当前位置: 首页 > news >正文

每日5题Day5 - LeetCode 21 - 25

每一步向前都是向自己的梦想更近一步,坚持不懈,勇往直前!

第一题:21. 合并两个有序链表 - 力扣(LeetCode)

class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {//讨论特殊情况if (list1 == null) {return list2;}if (list2 == null) {return list1;}//头节点ListNode node;if (list1.val <= list2.val) {node = new ListNode(list1.val);list1 = list1.next;} else {node = new ListNode(list2.val);list2 = list2.next;}//给一个dummy,用来最后定位ListNode dummy = new ListNode(-1, node);while (list1 != null || list2 != null) {//分类讨论ListNode curnode;if (list1 != null && list2 != null) {if (list1.val <= list2.val) {curnode = new ListNode(list1.val);list1 = list1.next;} else {curnode = new ListNode(list2.val);list2 = list2.next;}}else{if(list1 != null){curnode = new ListNode(list1.val);list1 = list1.next;}else{curnode = new ListNode(list2.val);list2 = list2.next;}}node.next = curnode;node = node.next;}return dummy.next;}
}

上面的代码用了太多的额外空间了,如果考虑使用递归呢?

如果对于链表(树的节点同样如此)使用递归的话,专注于每一个具体节点的行为,我们可以发现当list1为空的时候返回list2,反之亦然,因此这是一个边界情况;否则两者都存在时,当前node的next的next其实应该是返回比较小的那个值(为什么是返回?因为要与上面画横线的地方相对应)我们可以得到:

这样写清爽得多,在子递归中我们也表明了方向。

完整代码如下:

class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {// 如果其中一个链表为空,直接返回另一个链表if (list1 == null) {return list2;}if (list2 == null) {return list1;}// 递归地选择较小的节点作为合并后的头节点if (list1.val <= list2.val) {list1.next = mergeTwoLists(list1.next, list2);return list1;} else {list2.next = mergeTwoLists(list1, list2.next);return list2;}}
}

虽然递归也要使用空间,但至少空间消耗比原来低一些,代码则简单太多了。所以我们对于链表、树节点的处理,尽量要考虑递归。


第二题:22. 括号生成 - 力扣(LeetCode)

class Solution {List<String> res = new ArrayList<>();List<Character> path = new ArrayList<>();public List<String> generateParenthesis(int n) {int[] flag = new int[2];traversal(0, n, flag);return res;}private void traversal(int startindex, int n, int[] flag){if(startindex == n * 2){StringBuilder sb = new StringBuilder();for(char ch : path){sb.append(ch);}res.add(sb.toString());return;}if(flag[0] < n){// 讨论加入左括号的情况path.add('(');flag[0]++;traversal(startindex + 1, n, flag);flag[0]--;path.remove(path.size() - 1);}if(flag[0] > flag[1]){//只有在左边括号存在的数量大于右边的时候,//才可以考虑加入右括号,否则不匹配了path.add(')');flag[1]++;traversal(startindex + 1, n, flag);flag[1]--;path.remove(path.size() - 1);}}
}

第三题:23. 合并 K 个升序链表 - 力扣(LeetCode)

这道题不好处理,咱们直接考虑使用优先级队列来做,反正是升序,具体过程交给优先级队列来做,我们就负责把所有的值添加进去

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {ListNode mergeKLists(ListNode[] lists) {if (lists.length == 0) return null;// 虚拟头结点ListNode dummy = new ListNode(-1);ListNode p = dummy;// 优先级队列,最小堆PriorityQueue<ListNode> pq = new PriorityQueue<>(new Comparator<ListNode>(){@Overridepublic int compare(ListNode o1, ListNode o2){return (o1.val) - (o2.val);}});// 将 k 个链表的头结点加入最小堆for (ListNode head : lists) {if (head != null)pq.add(head);}while (!pq.isEmpty()) {// 获取最小节点,接到结果链表中ListNode node = pq.poll();p.next = node;if (node.next != null) {pq.add(node.next);}// p 指针不断前进p = p.next;}return dummy.next;}}

第四题:24. 两两交换链表中的节点 - 力扣(LeetCode)

class Solution {public ListNode swapPairs(ListNode head) {//特殊情况if(head == null || head.next == null){return head;}//dummy头节点ListNode dummyhead = new ListNode(-1, head);ListNode cur = dummyhead;//注意这里为什么是判断第二三个节点存在?while(cur.next != null && cur.next.next != null){//用变量名指代一下,不然看起来太复杂了ListNode A = cur.next, B = cur.next.next;cur.next = B;A.next = B.next;B.next = A;cur = cur.next.next;}return dummyhead.next;}
}


 第五题:25. K 个一组翻转链表 - 力扣(LeetCode)

class Solution {public ListNode reverseKGroup(ListNode head, int k) {if (head == null || head.next == null) {return head;}ListNode tail = head;for (int i = 0; i < k; i++) {//剩余数量小于k的话,则不需要反转。if (tail == null) {return head;}tail = tail.next;}// 反转前 k 个元素ListNode newHead = reverse(head, tail);//下一轮的开始的地方就是tailhead.next = reverseKGroup(tail, k);return newHead;}// 左闭右开区间private ListNode reverse(ListNode head, ListNode tail) {ListNode pre = null;ListNode next = null;while (head != tail) {next = head.next;head.next = pre;pre = head;head = next;}return pre;}
}

相关文章:

  • jiebaNET中文分词器
  • 水平垂直居中的六种方法
  • 添加webpack.config.js配置
  • 三分钟学会视频号卖货,真的太简单了!
  • webgl three 模型操作
  • 【C++】特殊类设计 | 单例设计模式
  • 一、QGroundControl地面站使用介绍
  • 【python】使用函数名而不加括号是什么情况?
  • LeetCode刷题之HOT100之比特位计数
  • PHP在线制作表白网源码
  • 电脑usb数据线共享网络给手机
  • 必应崩了?
  • 高校网络安全管理运维赛WP
  • Springboot+Vue项目-基于Java+MySQL的游戏交易系统(附源码+演示视频+LW)
  • JVM(7):虚拟机性能分析和故障解决工具之jstat工具
  • 【Amaple教程】5. 插件
  • 〔开发系列〕一次关于小程序开发的深度总结
  • 2017年终总结、随想
  • 78. Subsets
  • C++回声服务器_9-epoll边缘触发模式版本服务器
  • CEF与代理
  • E-HPC支持多队列管理和自动伸缩
  • HTTP中的ETag在移动客户端的应用
  • JAVA 学习IO流
  • Java教程_软件开发基础
  • MySQL数据库运维之数据恢复
  • UMLCHINA 首席专家潘加宇鼎力推荐
  • web标准化(下)
  • yii2权限控制rbac之rule详细讲解
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 免费小说阅读小程序
  • 实现菜单下拉伸展折叠效果demo
  • 详解NodeJs流之一
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • 1.Ext JS 建立web开发工程
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • #include
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (42)STM32——LCD显示屏实验笔记
  • (Redis使用系列) Springboot 使用redis的List数据结构实现简单的排队功能场景 九
  • (solr系列:一)使用tomcat部署solr服务
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (论文阅读笔记)Network planning with deep reinforcement learning
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • (自适应手机端)响应式服装服饰外贸企业网站模板
  • .Net IOC框架入门之一 Unity
  • .NET Standard 的管理策略
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • .NET企业级应用架构设计系列之技术选型
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具
  • [2544]最短路 (两种算法)(HDU)
  • [C#][DevPress]事件委托的使用
  • [C++] 如何使用Visual Studio 2022 + QT6创建桌面应用