算法学习day29

一、乘法表中第k小的数(和有序矩阵中第k小的数类似)

题意:

乘法表是大小为 m x n 的一个整数矩阵,其中 mat[i][j] == i * j(下标从 1 开始)。

给你三个整数 mn 和 k,请你在大小为 m x n 的乘法表中,找出并返回第 k 小的数字。

输入:m = 3, n = 3, k = 5
输出:3
解释:第 5 小的数字是 3 。
思路:

如何在乘法表中寻找第K小的数字?

我们可以想象这些数字都在一维数组中,最小值是1,最大值是m*n(行*列)。

要在这里面寻找第k小的数字,可以使用二分法,每次选取中间值,然后判断中间值在乘法表中是第几小的数字,然后跟k作比较

如果mid>=k,说明第k小的元素是在左边的,此时更新right;right=mid;


如果mid<k,说明第k小的元素是在右边的,此时更新left;  left=mid+1;

为什么index<k而不是index<=k? 当index=k的时候,left=mid+1;可能会使left错失正确值。如果mid==k,那么最后的结果是left=right=mid;

此时选择mid>=k,刚好是right=mid;

如果选择mid<=k,那么left会+1;

注意:如何寻找num在乘法表中是第几小的?

因为乘法表是从左往右、从上往下依次递增的。可以以列为单位去寻找

1.以列为单位,从最后一行的第一列开始寻找。x=nums.length-1 y=0;if(nums[x][y]<=k)index+=x;

else x--;

代码:
class Solution {public int findKthNumber(int m, int n, int k) {int left=1,right=m*n;while(left<right){int mid=left+(right-left)/2;int count=getIndexOfNum(m,n,mid);System.out.println("mid: "+mid+" count: "+count);if(count<k){left=mid+1;}else{right=mid;}}return left;}//该函数是寻找mid是在m*n乘法表中的第几小的数字public int getIndexOfNum(int m,int n,int mid){int x=m;int y=1;int res=0;while(x>=1&&y<=n){if(x*y<=mid){res+=x;y++;}else{x--;}}return res;}
}

二、任务调度器(贪心算法)

给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表,用字母 A 到 Z 表示,以及一个冷却时间 n。每个周期或时间间隔允许完成一项任务。任务可以按任何顺序完成,但有一个限制:两个 相同种类 的任务之间必须有长度为 n 的冷却时间。返回完成所有任务所需要的 最短时间间隔 。

输入:tasks = ["A","A","A","B","B","B"], n = 2
输出:8
解释:A -> B -> (待命) -> A -> B -> (待命) -> A -> B在本示例中,两个相同类型任务之间必须间隔长度为 n = 2 的冷却时间,而执行一个任务只需要一个单位时间,所以中间出现了(待命)状态。 
思路:

为了在更短的时间之内完成调度任务。我们就要在待命期间安排上其它种类的任务。待命期间的长短是由n来决定的。然后要进行多少次这样的操作是由任务数量最多的种类决定的。 就算我们不执行其它任务,我们也要去等冷却时间完毕之后执行该任务。

数量最多的任务max 和 冷却时间n 以及和 同样拥有最.

多数量的种类type 决定了一个范围,(max-1)*n+type

如果在这个范围里面,其他种类的任务不足够执行完,那么结果就是tasks.length;

代码:
class Solution {public int leastInterval(char[] tasks, int n) {Map<Character,Integer> map=new HashMap<>();for(Character ch:tasks){map.put(ch,map.getOrDefault(ch,0)+1);}//1.计算出某个任务的数量最多是多少int max=0;int count=0;Set<Character> set=map.keySet();for(Character ch:set){max=Math.max(max,map.get(ch));}//2.计算出和该任务相同数量的任务有多少for(Character ch:set){if(map.get(ch)==max)count++;}System.out.println("任务数量最多的是:"+max+"相同任务:"+count);return Math.max((max-1)*(n+1)+count,tasks.length);}
}

三、最大数

给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。

注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。

输入nums = [3,30,34,5,9]
输出:"9534330"
思路:

我们要做的就是将第一位数字放到最前面,这样拼接形成的数字也是最大的。我们可以使用字符串的compareTo()方法,eg:"abc".compareTo("acc");在比较第二个字符bc的时候,b<c所以返回负数(-1)。那我们就可以自定义一个排序规则,使得拼接更大的数字在前面(降序排列)。

Arrays(strs,(a,b)->{

    return (b+a).compareTo(a+b);

});

注意:

如果第一个数字是0的话,那么后面的数字都是0,此时按照正常逻辑拼接的话,会返回“00”;因此该种情况直接返回“0”;

代码: 
class Solution {public String largestNumber(int[] nums) {StringBuilder sb=new StringBuilder();String[] strs=new String[nums.length];for(int i=0;i<nums.length;i++){strs[i]=String.valueOf(nums[i]);}Arrays.sort(strs,(a,b)->{return (b+a).compareTo(a+b);});if(strs[0].equals("0")){return "0";}for(String str:strs){sb.append(str);}return sb.toString();}
}

四、合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6]
思路:

首先将二维数组按照升序排序---->自定义一个排序规则。Arrays.sort(intervals,(a,b)->{

return a[0]-b[0];});

排好序之后,对数组进行遍历,使用临时数组cur指向前一个集合(方便合并)

if(intervals[i][0]<=cur[1])说明下一个范围和上一个范围有重合的地方。此时我们更新cur[1]=Math.max(cur[1],intervals[i][1]);为什么不用更新cur[0]呢。 因为我们按照升序排列,cur[0]一定是小于Intervals[i][0]的

else 直接把cur加入到集合中 cur=intervals[i];

代码:
class Solution {public int[][] merge(int[][] intervals) {if(intervals.length==1)return intervals;//对数组进行升序排Arrays.sort(intervals,(a,b)->{return a[0]-b[0];});List<int[]> list=new ArrayList<>();int[] cur=intervals[0];for(int i=1;i<intervals.length;i++){if(intervals[i][0]<=cur[1]){cur[1]=Math.max(intervals[i][1],cur[1]);}else{list.add(cur);cur=intervals[i];}}list.add(cur);int[][] res=new int[list.size()][2];for(int i=0;i<list.size();i++){res[i]=list.get(i);}return res;}
}

五、插入区间

题意:

给你一个 无重叠的 ,按照区间起始端点排序的区间列表 intervals,其中 intervals[i] = [starti, endi] 表示第 i 个区间的开始和结束,并且 intervals 按照 starti 升序排列。

样给定一个区间 newInterval = [start, end] 表示另一个区间的开始和结束。

在 intervals 中插入区间 newInterval,使得 intervals 依然按照 starti 升序排列,且区间之间不重叠(如果有必要的话,可以合并区间)。

思路:

这个题就是让我们把一个区间插入到区间数组里一个合适的地方。

我们可以先将重合部分的左边加入到res中,然后加入重叠部分合成的区域、然后加入右边部分的区域。

代码:
class Solution {public int[][] insert(int[][] intervals, int[] newInterval) {// 分三种情况讨论 重叠左边 重叠部分 重叠右边// 1.左边int index = 0, size = intervals.length;List<int[]> list = new ArrayList<>();while (index < size && intervals[index][1] < newInterval[0]) {list.add(intervals[index]);index++;}// 2.中间while (index < size && intervals[index][0] <= newInterval[1] && newInterval[0] <= intervals[index][1]) {newInterval[0] = Math.min(newInterval[0], intervals[index][0]);newInterval[1] = Math.max(newInterval[1], intervals[index][1]);index++;}list.add(newInterval);// 3.右边while (index < size && intervals[index][0] > newInterval[1]) {list.add(intervals[index++]);}// 转换为int[][]数组int[][] res = new int[list.size()][2];for (int i = 0; i < list.size(); i++) {res[i] = list.get(i);}return res;}
}

六、最长数对链(贪心)

给你一个由 n 个数对组成的数对数组 pairs ,其中 pairs[i] = [lefti, righti] 且 lefti < righti 。

现在,我们定义一种 跟随 关系,当且仅当 b < c 时,数对 p2 = [c, d] 才可以跟在 p1 = [a, b] 后面。我们用这种形式来构造 数对链 。

思路:

有题目可知,要使数对链最长。我们就要使每次结尾的尾部是最小的,这样我们成为最长的可能就最大。

1.那我们就应该对数组进行排序Arrays.sort(pairs,(a,b)->{return a[1]-b[1]});

2.排序完之后,对数组进行遍历就可。

class Solution {public int findLongestChain(int[][] pairs) {Arrays.sort(pairs,(a,b)->{return a[1]-b[1];});int count=1;int[] cur=pairs[0];for(int i=1;i<pairs.length;i++){if(pairs[i][0]>cur[1]){count++;cur=pairs[i];}}return count;}
}

七、摆动排序II

给你一个整数数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]... 的顺序。

思路:

从排列中我们可以看出 小大小大...。我们可以将数组分成两部分:小数部分和大数部分。

eg:123456 小数部分123 大数部分456 小数放一个大数放一个 142536

但是如果正序放的话,会遇到这种情况 eg:1336 13/36  1336 这样中间两个值就相同了。

注意:

为了防止中间值相同的情况,倒序交叉排序:1336  13/36  3661 从后往前选择

为什么倒序可以?如果倒序所选的两个值还相同的话,倒序中间最少差一个 也就是axb,这样三个值都相同了,而且一共四个值。题目不会出现这样的输入的。

代码:
class Solution {public void wiggleSort(int[] nums) {int[] clone=nums.clone();Arrays.sort(clone);int N=nums.length-1;for(int i=1;i<clone.length;i+=2){nums[i]=clone[N--];}for(int i=0;i<clone.length;i+=2){nums[i]=clone[N--];}}
}

八、参议院

题意:
给你一串字符串,其中包括R阵营\D阵营(R参议员和D参议员);参议员有禁止一名参议员的权利,如果在某轮投票中发现参议院都是一方的。那么就宣布该阵营胜利
思路:

遍历数组

1.当我们遇到R的时候,我们需要判断前面是否有还未使用权利的D;

2.在遇到D的时候,也要判断前面是否有未使用权利的R;

我们使用一个int整数类型的flag变量来记录。如果flag<0,说明前面有D;如果flag>0,说明前面有R.

其次,我们需要判断所有的参议院中是否只有一个阵营的或者两个阵营都有。

boolean D;boolean R。true代表某个阵营存在。

注意:

比较不只是一轮,直到比出结果,循环才会结束。因此在最外层有while循环。

代码:
class Solution {public String predictPartyVictory(String senate) {// 1.禁止权利2.如果有权利投票的参议员都是一个阵营的 胜利// R 天辉 D 夜魇boolean R = true, D = true;int flag = 0;// 如果flag<0说明在这个R前面有D;flag>0说明在这个D前面有Rchar[] senates = senate.toCharArray();while (R && D) {R = false;D = false;for (int i = 0; i < senates.length; i++) {char ch = senates[i];if (ch == 'R') {if (flag < 0)senates[i]='0';else R=true;flag++;}else if(ch=='D'){if (flag > 0)senates[i]='0';else D=true;flag--; }}}return R==true?"Radiant":"Dire";}
}

九、有效的括号字符串(双栈)

给你一个只包含三种字符的字符串,支持的字符类型分别是 '('')' 和 '*'。请你检验这个字符串是否为有效字符串,如果是 有效 字符串返回 true 。

*可以代替(或者) 或者"";

思路:

左括号的数量为:a;*的数量为:b;右括号的数量为:c

利用双栈,一个栈用来存储左括号、另一个栈用来存储*。(栈里面是存放该字符的下标)

1.遍历字符串,遇到左括号就入栈1,遇到*就入栈2;

如果遇到右括号,先判断栈1是否为空;再去判断栈2是否为空。如果栈1栈2都为空直接return false;a>b+c; 无法匹配

如果左括号为空,那么就去判断*,a>b 但是a<b+c;

2.遍历结束之后,如果left栈为空,此时 a=b+c 直接返回true;如果left栈不为空,可能存在a<b的情况,此时就需要*还消除(;但是只有下标在(左边的*才能起到消除作用;

while(!left.isEmpty()){

int a=left.pop();

int b=star.pop();

此时a是最靠近右边的左括号 b是最靠近右边的*号

if(a>b)return false;栈顶的*号都匹配不到,那么其他的也匹配不到

}

代码:
class Solution {public boolean checkValidString(String s) {Stack<Integer> left=new Stack<>();Stack<Integer> star=new Stack<>();for(int i=0;i<s.length();i++){char ch=s.charAt(i);if(ch=='(')left.push(i);else if(ch=='*')star.push(i);else{if(!left.isEmpty()){left.pop();continue;}if(!star.isEmpty()){star.pop();continue;}return false;}}while(!left.isEmpty()){if(star.isEmpty())return false;else{int i=left.pop();int j=star.pop();if(i>j)return false;}}return true;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/392420.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

可视化图表与源代码显示的动态调整

可视化图表与源代码显示的动态调整 页面效果描述&#xff1a;本篇代码实现了通过拖动一个可调整大小的分隔符&#xff0c;用户可以动态地调整图表显示区域和源代码显示区域的大小。通过监听鼠标事件&#xff0c;当用户拖动分隔符时&#xff0c;会动态计算并更新两个区域的大小 …

Vue项目学习(1)

1、进入cmd命令行——> vue ui ——>等等操作 2、 3、src目录下 4、vue项目的启动 &#xff08;1&#xff09; &#xff08;2&#xff09; 5、如何更改前端vue项目的端口号&#xff1f;——>去vue.config.js里配置应一个对象

mprpc框架的应用示例

一、注册 有一个本地服务&#xff0c;我想把它发布成远程服务&#xff0c;首先在user.proto中定义rpc方法的描述&#xff0c;定义参数和响应的消息类型 然后在userservice.cc文件中通过继承UserServiceRpc这个类&#xff0c;重写一下响应的方法&#xff08;打四个动作&#xf…

shell函数的基本知识

文章目录 shell函数定义函数调用函数函数参数返回值 Shell 输入/输出重定向输入重定向输出重定向 Shell 函数是 Shell 脚本编程中的一个非常有用的特性&#xff0c;它允许你将一段代码封装起来&#xff0c;给它一个名字&#xff08;函数名&#xff09;&#xff0c;然后在脚本的…

低代码: 开发难点分析,核心技术架构设计

开发难点分析 1 &#xff09;怎样实现组件 核心问题&#xff1a;编辑器 和 页面其实整个就是一系列元素构成的这些元素的自然应该抽象成组件&#xff0c;这些组件的属性应该怎样设计在不同的项目中怎样做到统一的使用 2 &#xff09;跨项目使用 在不同的项目中怎样做到统一的…

【Linux】线程互斥

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

C# Unity 面向对象补全计划 七大原则 之 依赖倒置原则 (DIP)难度:☆☆ 总结:多抽象,多接口,少耦合

本文仅作学习笔记与交流&#xff0c;不作任何商业用途&#xff0c;作者能力有限&#xff0c;如有不足还请斧正 本系列作为七大原则和设计模式的进阶知识&#xff0c;看不懂没关系 请看专栏&#xff1a;http://t.csdnimg.cn/mIitr&#xff0c;查漏补缺 1.依赖倒置原则 (DIP) 这…

「队列」实现FIFO队列(先进先出队列|queue)的功能 / 手撕数据结构(C++)

概述 队列&#xff0c;是一种基本的数据结构&#xff0c;也是一种数据适配器。它在底层上以链表方法实现。 队列的显著特点是他的添加元素与删除元素操作&#xff1a;先加入的元素总是被先弹出。 一个队列应该应该是这样的&#xff1a; --------------QUEUE-------------——…

骨传导耳机哪个牌子好?五款业界高性能机型推荐,让你选购不迷茫!

骨传导耳机哪个牌子好&#xff1f;哪款耳机值得入手&#xff1f;作为一名资深的数码设备测评师&#xff0c;我极力推荐大家尝试下骨传导耳机&#xff0c;它无需直接堵塞耳道&#xff0c;既能起到保护听力的作用&#xff0c;又能在使用中保持对外界的环境感知。然而&#xff0c;…

OD C卷 - 园区参观路径

园区参观路径&#xff08;100&#xff09; 有一个矩形园区&#xff0c;从左上角走到右下角&#xff0c;只能向右、向下走&#xff1b;共有多少条不同的参观路径&#xff1b; 输入描述&#xff1a; 第一行输入长度、宽度 后续每一行表示 对应位置是否可以参观&#xff0c;0可…

poetry配置镜像

1.简介 poetry 是一个包管理和打包的工具。 在 Python 中&#xff0c;对于初学者来说&#xff0c;打包系统和依赖管理是非常复杂和难懂的。即使对于经验丰富的开发者&#xff0c;一个项目总是要同时创建多个文件&#xff1a; setup.py ,requirements.txt,setup.cfg , MANIFES…

【数据结构与算法】十大经典排序算法深度解析:冒泡排序、选择排序、插入排序、归并排序、快速排序、希尔排序、堆排序、计数排序、桶排序、基数排序

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法》 期待您的关注 ​ 目录 引言 一、排序算法概述 排序算法简介 排序算法的分类 性能指标 二、十大排序算法…

Unity Rigidbody 踩坑记录

1&#xff1a;两个带有刚体的物体碰撞会一直不停的弹 把被动受力的刚提的 Freeze Position 的勾选 去掉&#xff08;碰到过一次&#xff0c;有一种受力无法释放又返回给目标的 所以一直弹跳的感觉&#xff09; 2&#xff1a;子物体 和父物体 都有刚体的情况下 子物体 Freeze R…

zdpy+vue3+onlyoffice文档系统实战上课笔记 20240805

上次 上次计划 1、最近文档表格完善 2、实现登录功能 3、新建文件&#xff0c;复制文件&#xff0c;删除文件 4、其他 目前任务&#xff1a;最近文档表格完善 1、在名称前面&#xff0c;渲染这个文档的图标 2、大小的基本的单位是kb&#xff0c;超过1024kb则换成mb&#xff0…

Java | Leetcode Java题解之第318题最大单词长度乘积

题目&#xff1a; 题解&#xff1a; class Solution {public int maxProduct(String[] words) {Map<Integer, Integer> map new HashMap<Integer, Integer>();int length words.length;for (int i 0; i < length; i) {int mask 0;String word words[i];in…

Mysql中事务的读一致性问题,以及如何用MVCC解决

事务四大特性的实现&#xff1a; 原子性事务具有回滚的能力&#xff0c;InnoDB引擎使用undo log日志表来进行回滚操作。 持久性InnoDB引擎使用redo log日志表来保证数据的持久性。 事务的隔离性产生的问题&#xff1a; 脏读&#xff1a;一个事务读取到了另一个事务未提交的数…

Linux系统驱动(五)

文章目录 一、实现机制二、字符设备驱动分布实现流程三、添加自己的系统调用函数1. 找到系统调用文件2. 找到 一、实现机制 应用层 vfs层 驱动层 字符设备按照字节流顺序访问&#xff0c;但是实际它提供了无序访问的功能 vi -t sys_open 内核中通过inode号可以唯一的找到一…

请转告HPC计算AI计算单位,选对存储事半功倍

U.2 NVMe全闪混合统一存储GS 5000U是Infortrend产品中一款高性能机型。得益于搭载强劲的第五代IntelXeon处理器&#xff0c;以及支持PCIe 5.0、NVMe-oF、100GbE等多种特点&#xff0c;GS 5000U单台块级性能可达50 GB/s的读、20 GB/s的写&#xff0c;以及1300K的IOPS&#xff1b…

Xshell安装图文

1.下载 通过百度网盘分享的文件&#xff1a;Xshell安装图文 链接&#xff1a;https://pan.baidu.com/s/1k4ShbhUVQmdxpM9H8UYOSQ 提取码&#xff1a;kdxz --来自百度网盘超级会员V3的分享 2.安装 3.连接与使用 见下载

论文辅导 | 基于二次分解和BO-BiLSTM组合模型采煤工作面瓦斯涌出量预测方法研究

辅导文章 模型描述 结合变分模态分解&#xff08;VMD&#xff09;、自适应噪声完备经验模态分解&#xff08;CEEMDAN&#xff09;、贝叶斯优化算法&#xff08;BO&#xff09;和双向长短期记忆神经网络&#xff08;BiLSTM&#xff09;这4种时间序列处理方法&#xff0c;建立了…