用这样的方法,我解决了leetcode的大部分的这种题型!
点个赞,看一看,好习惯!本文 GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了 3 个月总结的一线大厂 Java 面试总结,本人已拿腾讯等大厂 offer。
另外,原创文章首发在我的个人博客:blog.ouyangsihai.cn,欢迎访问。
今天介绍一种解决常规的贪心策略或者字典排序的题目的通用解题方法。
第一题,leetcode中等难度题目
先来一道简单的字典序排列的问题,这个题目我这里不会用最优解来解决这个问题,这个是leetcode的中等难度的题目,最优解还是需要再思考一下的,这道题目作为文章开头只是为了介绍我想要介绍的贪心的解题的一种思路而已,大佬请勿喷!!
看到这个题目,我就是想用暴力的方法解决,以便更好的理解这种解题思路。
先给出我的答案,非常暴力,但是非常好理解。
public List<Integer> lexicalOrder(int n) {List<String> list = new ArrayList<>();for(int i = 1; i <= n; i++){list.add(i + "");}Collections.sort(list,(o1,o2)->{return o1.compareTo(o2);});List<Integer> iList = new ArrayList<>();list.stream().forEach((str)->{iList.add(Integer.parseInt(str));});return iList;}
这个解题方法很简单,用的就是Collections.sort()方法的排序,然后重写一下Comparator类而已,这里用的是lambda表达式,使得代码更加的简洁。
最优解大家可以去leetcode看看哈,自己动手,丰衣足食。
所以,通过这个题目我想给出的信息就是:通常涉及到字符串排序,字典序,数字排序等等的题目,都是可以用这种思路来解决问题的
。
不信,我们再看看其他题目。
第二题,leetcode中等难度题目
这是一道常见的topk问题,最优解也不是我给出的答案,目的只是为了阐述这种解题方法。
我的解题方法:用优先级队列,维护一个大小为k小顶堆,每次堆的元素到达k时,先弹出堆顶元素,这样就堆总是维持着k个最大值,最终可以的到前k高的元素。
下面看看我的解答(注意:我的答案绝对不是最优解,只是为了阐述这种方法)
class Solution {public int[] topKFrequent(int[] nums, int k) {Queue<Obj> queue = new PriorityQueue<>(k,(o1,o2)->{return o2.num - o1.num;});HashMap<Integer,Integer> map = new HashMap<>();for(int i = 0; i < nums.length; i++){map.put(nums[i],map.getOrDefault(nums[i],0) + 1);}for(int key : map.keySet()){queue.offer(new Obj(key,map.get(key)));}int[] ans = new int[k];int i = 0;while(i < k){ans[i] = queue.poll().target;i++;}return ans;}class Obj {public int target;public int num;public Obj(int target, int num){this.target = target;this.num = num;}}
}
这种方法没有维护k的最大的堆。
class Solution {public List<Integer> topKFrequent(int[] nums, int k) {HashMap<Integer, Integer> map = new HashMap();for (int n: nums) {map.put(n, map.getOrDefault(n, 0) + 1);}PriorityQueue<Integer> heap =new PriorityQueue<Integer>((n1, n2) -> map.get(n1) - map.get(n2));for (int n: map.keySet()) {heap.add(n);if (heap.size() > k)heap.poll();}List<Integer> top_k = new LinkedList();while (!heap.isEmpty())top_k.add(heap.poll());Collections.reverse(top_k);return top_k;}
}
这种方法维护k的最大的堆。
对比发现:不管维护k的最大堆还是不维护,核心的思想都是
Queue<Obj> queue = new PriorityQueue<>(k,(o1,o2)->{return o2.num - o1.num;});
和这段代码
PriorityQueue<Integer> heap =new PriorityQueue<Integer>((n1, n2) -> map.get(n1) - map.get(n2));
对比第一题中的
Collections.sort(list,(o1,o2)->{return o1.compareTo(o2);});
用的都是内部类:Comparator
,然后进行构建符合题意的排序规则。
第三题,更复杂点的
这个题目就更能明白什么是构建符合题意的排序规则。
因为很多题目不止让你根据一个字段进行排序,可能是两个字段进行排序,或者三个字段进行排序,所以就需要进行“构建”。
这个题目的解题思路:先排序再插入
- 排序规则:按照先H高度降序,K个数升序排序
- 遍历排序后的数组,根据K插入到K的位置上
核心思想:高个子先站好位,矮个子插入到K位置上,前面肯定有K个高个子,矮个子再插到前面也满足K的要求。
再看看解答
public int[][] reconstructQueue(int[][] people) {// [7,0], [7,1], [6,1], [5,0], [5,2], [4,4]// 再一个一个插入过程// [7,0]// [7,0], [7,1]// [7,0], [6,1], [7,1]// [5,0], [7,0], [6,1], [7,1]// [5,0], [7,0], [5,2], [6,1], [7,1]// [5,0], [7,0], [5,2], [6,1], [4,4], [7,1]Arrays.sort(people, (o1, o2) -> o1[0] == o2[0] ? o1[1] - o2[1] : o2[0] - o1[0]);LinkedList<int[]> list = new LinkedList<>();for (int[] i : people) {//在i位置,插入数:i[1]是[7,0], [7,1], [6,1], [5,0], [5,2], [4,4]的第一个数,表示前面有几个比我高的。list.add(i[1], i);}return list.toArray(new int[list.size()][2]);}
你会发现,核心代码还是跟第一题和第二题一样,只是复杂一点点。
Arrays.sort(people, (o1, o2) -> o1[0] == o2[0] ? o1[1] - o2[1] : o2[0] - o1[0]);
这是什么意思呢:o1和o2是一个类似这样[7,0]
的一位数组,当第一个数相等时,再比较一维数组的第二个数的大小,不相等,当然先比较第一个数了。
这个就是多个字段比较的例子,是不是还是跟前面的思路是一样的。
总结
最后发现,关于排序的,不管是,数组的排序,数字的排序,字符串的排序,还是优先级队列的排序,我们都是可以用Java的Comparator来解决的。
就说这么多,只是思路,不要死磕最优解!!!
最后,再分享我历时三个月总结的 Java 面试 + Java 后端技术学习指南,这是本人这几年及春招的总结,已经拿到了大厂 offer,整理成了一本电子书,拿去不谢,目录如下:
现在免费分享大家,在下面我的公众号 程序员的技术圈子 回复 面试 即可获取。
有收获?希望老铁们来个三连击,给更多的人看到这篇文章
1、老铁们,关注我的原创微信公众号「程序员的技术圈子」,专注于 Java、数据结构和算法、微服务、中间件等技术分享,保证你看完有所收获。
2、给俺点个赞呗,可以让更多的人看到这篇文章,顺便激励下我继续写作,嘻嘻。
3、另外,原创文章首发在我的个人博客:blog.ouyangsihai.cn,欢迎访问。
点赞是对我最大的鼓励
↓↓↓↓↓↓
用这样的方法,我解决了leetcode的大部分的这种题型!相关推荐
- shiro和Spring整合使用注解时没有执行realm的doGetAuthorizationInfo回调方法的解决
shiro和Spring整合使用注解时没有执行realm的doGetAuthorizationInfo回调方法的解决 from :http://blog.csdn.net/babys/article/ ...
- js获取url地址栏参数的方法,解决中文乱码问题,能支持中文参数
js获取url地址栏参数的方法,解决中文乱码问题,能支持中文参数 参考文章: (1)js获取url地址栏参数的方法,解决中文乱码问题,能支持中文参数 (2)https://www.cnblogs.co ...
- linux 下 设置 MySQL8 表名大小写不敏感方法,解决设置后无法启动 MySQL 服务的问题
linux 下 设置 MySQL8 表名大小写不敏感方法,解决设置后无法启动 MySQL 服务的问题 参考文章: (1)linux 下 设置 MySQL8 表名大小写不敏感方法,解决设置后无法启动 M ...
- html5新特性:利用history的pushState等方法来解决使用ajax导致页面后退和前进的问题
html5新特性:利用history的pushState等方法来解决使用ajax导致页面后退和前进的问题 参考文章: (1)html5新特性:利用history的pushState等方法来解决使用aj ...
- eclipse中用maven多模块管理,然后主项目无法调用其他被依赖项目里的方法,解决办法
eclipse中用maven多模块管理,然后主项目无法调用其他被依赖项目里的方法,解决办法 参考文章: (1)eclipse中用maven多模块管理,然后主项目无法调用其他被依赖项目里的方法,解决办法 ...
- cad2014卡顿的解决方法_升级iOS14.1后出现卡顿、闪退?这3种方法可以解决
随着iOS14.1正式版的推出,大家对于该版本有着很高的关注度,毕竟这是iOS14版本第一次正式的小版本更新,同时也将是新机iPhone12系列的预搭载版本. 但是,随着体验了几天的iOS14.1之后 ...
- [react] 路由切换时同一组件无法重新渲染的有什么方法可以解决?
[react] 路由切换时同一组件无法重新渲染的有什么方法可以解决? componentWillReceiveProps 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放弃很容易, 但坚持一定很酷 ...
- mysql mysqld.sock_MySQL笔记-最简单的方法来解决找不到mysqld.sock文件的问题
首先,环境:ubuntu 14.04,采用apt-get的方式安装的,手动安装可能路径设置稍有区别. 1.安装MySQL后,用命令行首次启动时发现找不到Mysqld.sock文件,提示: ERROR ...
- IntelliJ IDEA 乱码:全网最全 4 种方法完美解决 IntelliJ IDEA 控制台中文乱码问题
文章目录 前言 一.修改当前 Web 项目 Tomcat Server 的虚拟机输出选项 二.修改 IntelliJ IDEA 全局编码.项目编码.属性文件编码 三.IntelliJ IDEA 中自定 ...
最新文章
- Understanding The React Source Code
- java 环境变量 locale,修改locale把语言环境变量改为英文
- SQL搜索转为XML搜索
- DDNS For RHEL5
- javascript调试常用工具讲解
- 一文纵览EMAS 到底内含多少阿里核心技术能力
- web.config中httpRunTime的属性
- Flask笔记-session安全问题(避免任务重复提交)
- 自动驾驶路径规划论文解析(5)
- ubuntu更改屏幕界面大小和中文
- java - 抽象类、接口、内部类
- 国行ps4服务器维护,不能登录其地区的PSN代表什么
- 确认无疑,.NET 6是迄今为止最快的.NET
- 使用 HTTPS 方式登录防火墙USG6000设备
- Linux 用户的 3 个命令行小技巧
- EasyUI - Layout 布局控件
- python微信语音转发方法_微信怎么转发语音(想要转到别的群或者人这样做)
- 主要空间数据挖掘方法
- 学习单片机系列(一)单片机选型
- java 汉字转拼音缩写_用JAVA实现汉字转拼音缩写