• labuladong刷题——第一章(1) 双指针技巧秒杀七道链表题目


    双指针技巧秒杀七道链表题目


    1.合并两个有序链表 LeetCode21

    输入两个链表,合并成一个新的有序链表。很简单,注意头结点的使用即可。

    1. ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    2. /*
    3. 关键在于这个头指针dummy,他创造了一个空指针指向堆头
    4. */
    5. ListNode dummy = new ListNode(-1), p = dummy;
    6. ListNode p1 = l1, p2 = l2;
    7. while (p1 != null && p2 != null) {
    8. // 比较 p1 和 p2 两个指针
    9. // 将值较小的的节点接到 p 指针
    10. if (p1.val > p2.val) {
    11. p.next = p2;
    12. p2 = p2.next;
    13. } else {
    14. p.next = p1;
    15. p1 = p1.next;
    16. }
    17. // p 指针不断前进
    18. // 实际上这个链表是由p指针完成的.
    19. p = p.next;
    20. }
    21. if (p1 != null) p.next = p1;
    22. if (p2 != null) p.next = p2;
    23. return dummy.next;
    24. }


    2.单链表的分解 LC86

    在合并两个有序链表时让你合二为一,而这里需要分解让你把原链表一分为二。具体来说,我们可以把原链表分成两个小链表,一个链表中的元素大小都小于 x,另一个链表中的元素都大于等于 x,最后再把这两条链表接到一起,就得到了题目想要的结果。

    1. class Solution {
    2. public ListNode partition(ListNode head, int x) {
    3. /*
    4. 还是注意头结点的应用,这里用了两个dummy
    5. p负责遍历原来的链表 p1和p2用来生成结果链表
    6. 如果val小于x,用p1指向它,如果val大于x就用p2指向它
    7. 创建两个新的链表,最后将他们连在一起即可
    8. */
    9. ListNode dummy1 = new ListNode(-1);
    10. ListNode dummy2 = new ListNode(-1);
    11. ListNode p1 = dummy1;
    12. ListNode p2 = dummy2;
    13. ListNode p = head;
    14. while (p != null) {
    15. if (p.val < x) {
    16. p1.next = p;
    17. p1 = p1.next;
    18. } else {
    19. p2.next = p;
    20. p2 = p2.next;
    21. }
    22. /**
    23. * 这一段是为了让原来的链表断开
    24. * 保证每一次p都指向一个单独的,只有后继结点的链表
    25. * 为了断开原有的指针
    26. * 比如p1指向第一个结点 p2指向第二个节点 如果没有断开
    27. * 那么p1就会同时指向第三个节点和第二个节点,会出错
    28. * 当然也可以创建新的链表
    29. */
    30. ListNode temp = p.next;
    31. p.next = null;
    32. p = temp;
    33. }
    34. p1.next = dummy2.next;
    35. return dummy1.next;
    36. }
    37. }


    3.合并 k 个有序链表 LC23

     这里要用到PriorityQueue这个数据结构。

    PriorityQueue(优先队列) 采用的是堆排序
    实际上是一个堆(不指定Comparator时默认为最小堆)
    队列既可以根据元素的自然顺序来排序,也可以根据 Comparator来设置排序规则。

    由于是一个队列,操作的时候可以用offer()、poll()、remove() 、add() 方法。offer和add都是添加元素,remove和poll都是删除元素。peek方法是找到头元素但是不删除。

    可以自己指定排序方法

    1. PriorityQueue queue = new PriorityQueue(
    2. 10, //容量
    3. new Comparator(){
    4. public int compare(Integer a, Integer b){
    5. return a-b; //if a>b 则交换,so这是递增序列
    6. }
    7. });

    总体思路:将每个队列的头结点(因为已经排好序)放到小顶堆中,然后每次从其中取出一个来加入新的链表,之后将拿出来的这个节点的next加入到小顶堆中即可。

    1. class Solution {
    2. public ListNode mergeKLists(ListNode[] lists) {
    3. /**
    4. * 注意最小堆PriorityQueue的用法
    5. * 就是把链表的头结点塞进去
    6. */
    7. if(lists.length==0) return null;
    8. ListNode dummy = new ListNode(-1);
    9. ListNode p = dummy;
    10. // lambda表达式,表示构造函数的时候按照从小到大排列
    11. // 如果a.val-b.val>0 那么a就在b的前面
    12. PriorityQueue pq = new PriorityQueue<>(lists.length,
    13. new Comparator(){ //比较器比较的是ListNode
    14. public int compare(ListNode a,ListNode b){
    15. return a.val-b.val;
    16. //if a>b 则交换,so这是小顶堆
    17. }
    18. });
    19. for (ListNode head:lists){
    20. if(head!=null){
    21. pq.add(head);
    22. }
    23. //注意 这里加入的只是头结点
    24. //为什么捏?看后面
    25. }
    26. //开始从pq里面取值
    27. while(!pq.isEmpty()){
    28. ListNode node = pq.poll();
    29. p.next = node;
    30. if(node.next!=null){
    31. pq.add(node.next);
    32. }
    33. p = p.next;
    34. }
    35. return dummy.next;
    36. }
    37. }

    4.两个链表是否相交

    其实很简单,从a1开始和从b2开始,两个点走完全长以后从另一个结点开始就可以了。

     

    1. //leetcode submit region begin(Prohibit modification and deletion)
    2. /**
    3. * Definition for singly-linked list.
    4. * public class ListNode {
    5. * int val;
    6. * ListNode next;
    7. * ListNode(int x) {
    8. * val = x;
    9. * next = null;
    10. * }
    11. * }
    12. */
    13. public class Solution {
    14. public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    15. ListNode dummy1 = headA;
    16. ListNode dummy2 = headB;
    17. while(headA!=headB){
    18. if(headA==null) headA = dummy2;
    19. else headA = headA.next;
    20. if(headB==null) headB = dummy1;
    21. else headB = headB.next;
    22. }
    23. return headA;
    24. }
    25. }
    26. //leetcode submit region end(Prohibit modification and deletion)

  • 相关阅读:
    JAVA卓越导师双选系统计算机毕业设计Mybatis+系统+数据库+调试部署
    Zabbix-企业级监控系统
    三菱FX5U PLSV指令-可变速度输出
    请求与响应以及REST风格
    如何使用数字化系统赋能企业营销?数字化系统对于企业的作用?
    eclipse配置maven,安装lombok,导入和创建springboot项目
    C语言常识
    RISC-V声名鹊起,究竟为何?
    园子的商业化努力-行行AI人才培养「常青藤计划」
    Matlab .m脚本文件
  • 原文地址:https://blog.csdn.net/qq_37772958/article/details/126830180