• Java-数据结构-链表<三>


    承接上文 Java-数据结构-链表<一>

                   Java-数据结构-链表<二>

    一. 链表简单介绍 

            见 Java-数据结构-链表<一>

     

    二. 链表的代码实现

            见 Java-数据结构-链表<一>

     

    三. leetcode&牛客实例

     

    1-6 见 Java-数据结构-链表<一>

    7-13 见Java-数据结构-链表<二>

    14. leetcode2 两数相加

            给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

    输入:l1 = [2,4,3], l2 = [5,6,4]
    输出:[7,0,8]
    解释:342 + 465 = 807.

    1. class Solution {
    2. public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
    3. ListNode dummyhead = new ListNode(0);
    4. ListNode cur = dummyhead;
    5. int carry = 0;
    6. while(l1 != null || l2 != null){
    7. int L1_val = l1 == null ? 0 : l1.val;
    8. int L2_val = l2 == null ? 0 : l2.val;
    9. int sum = L1_val+L2_val+carry;
    10. carry = sum/10;
    11. sum = sum%10;
    12. cur.next = new ListNode(sum);
    13. cur = cur.next;
    14. if(l1 != null){
    15. l1 = l1.next;
    16. }
    17. if(l2 != null){
    18. l2 = l2.next;
    19. }
    20. }
    21. if(carry != 0){
    22. cur.next = new ListNode(1);
    23. }
    24. return dummyhead.next;
    25. }
    26. }

    15. leetcode24 两两相交链表中的节点

    给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

    输入:head = [1,2,3,4]
    输出:[2,1,4,3]

    1. class Solution {
    2. public ListNode swapPairs(ListNode head) {
    3. ListNode pre = new ListNode(0);
    4. pre.next = head;
    5. ListNode temp = pre;
    6. while(temp.next != null && temp.next.next != null) {
    7. ListNode start = temp.next;
    8. ListNode end = temp.next.next;
    9. temp.next = end;
    10. start.next = end.next;
    11. end.next = start;
    12. temp = start;
    13. }
    14. return pre.next;
    15. }
    16. }

    16. leetcode23 合并k个升序链表

    给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。

    输入:lists = [[1,4,5],[1,3,4],[2,6]]
    输出:[1,1,2,3,4,4,5,6]
    解释:链表数组如下:
    [
      1->4->5,
      1->3->4,
      2->6
    ]
    将它们合并到一个有序链表中得到。
    1->1->2->3->4->4->5->6

    暴力

    1. class Solution {
    2. public ListNode mergeKLists(ListNode[] lists) {
    3. List list = new ArrayList<>();
    4. for(int i = 0; i< lists.length; i++){
    5. ListNode temp = lists[i];
    6. while(temp != null){
    7. list.add(temp.val);
    8. temp = temp.next;
    9. }
    10. }
    11. ListNode head = new ListNode(0);
    12. ListNode first = head;
    13. Collections.sort(list);
    14. for(int i = 0; i < list.size(); i++){
    15. first.next = new ListNode(list.get(i));
    16. first = first.next;
    17. }
    18. return head.next;
    19. }
    20. }

    优先队列

    1. class Solution {
    2. class heap implements Comparator{
    3. public int compare(ListNode o1, ListNode o2){
    4. return o1.val - o2.val;
    5. }
    6. }
    7. public ListNode mergeKLists(ListNode[] lists) {
    8. PriorityQueue list = new PriorityQueue<>(new heap());
    9. for(ListNode cur : lists){
    10. while(cur != null){
    11. list.add(cur);
    12. cur = cur.next;
    13. }
    14. }
    15. ListNode dummyhead = new ListNode(0);
    16. ListNode cur = dummyhead;
    17. while(!list.isEmpty()){
    18. cur.next = list.poll();
    19. cur = cur.next;
    20. }
    21. cur.next = null;
    22. return dummyhead.next;
    23. }
    24. }

    两两合并【1】

    1. class Solution {
    2. public ListNode mergeKLists(ListNode[] lists) {
    3. if(lists==null || lists.length==0) {
    4. return null;
    5. }
    6. //将lists[0]作为最终合并的链表,然后将list[0]和lists[1]合并成lists[0-1]
    7. //再将lists[0-1]和lists[2]合并,如此反复最终lists[0]就是最终结果
    8. ListNode res = lists[0];
    9. for(int i=1;i
    10. res = merge(res,lists[i]);
    11. }
    12. return res;
    13. }
    14. //合并两个有序链表
    15. private ListNode merge(ListNode a, ListNode b) {
    16. if(a==null || b==null) {
    17. return (a==null) ? b : a;
    18. }
    19. if(a.val<=b.val) {
    20. a.next = merge(a.next,b);
    21. return a;
    22. } else {
    23. b.next = merge(a,b.next);
    24. return b;
    25. }
    26. }
    27. }

    分治【1】

    1. class Solution {
    2. public ListNode mergeKLists(ListNode[] lists) {
    3. if(lists==null || lists.length==0) {
    4. return null;
    5. }
    6. return helper(lists,0,lists.length-1);
    7. }
    8. //通过mid将数组一分为二,并不断缩小规模,当规模为1时返回并开始合并
    9. //通过合并两个链表,不断增大其规模,整体看就是不断缩小-最后不断扩大的过程
    10. private ListNode helper(ListNode[] lists, int begin, int end) {
    11. if(begin==end) {
    12. return lists[begin];
    13. }
    14. int mid = begin+(end-begin)/2;
    15. ListNode left = helper(lists,begin,mid);
    16. ListNode right = helper(lists,mid+1,end);
    17. return merge(left,right);
    18. }
    19. //合并两个有序链表
    20. private ListNode merge(ListNode a, ListNode b) {
    21. if(a==null || b==null) {
    22. return (a==null) ? b : a;
    23. }
    24. if(a.val<=b.val) {
    25. a.next = merge(a.next,b);
    26. return a;
    27. } else {
    28. b.next = merge(a,b.next);
    29. return b;
    30. }
    31. }
    32. }

    17. leetcode25 k个一组翻转链表

    给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。

    k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

    你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

    输入:head = [1,2,3,4,5], k = 2
    输出:[2,1,4,3,5]

    1. class Solution {
    2. public ListNode reverseKGroup(ListNode head, int k) {
    3. Deque stack = new ArrayDeque();
    4. ListNode dummy = new ListNode(0);
    5. ListNode p = dummy;
    6. while (true) {
    7. int count = 0;
    8. ListNode tmp = head;
    9. while (tmp != null && count < k) {
    10. stack.add(tmp);
    11. tmp = tmp.next;
    12. count++;
    13. }
    14. if (count != k) {
    15. p.next = head;
    16. break;
    17. }
    18. while (!stack.isEmpty()){
    19. p.next = stack.pollLast();
    20. p = p.next;
    21. }
    22. p.next = tmp;
    23. head = tmp;
    24. }
    25. return dummy.next;
    26. }
    27. }

     暴力

    1. public ListNode reverseKGroup(ListNode head, int k) {
    2. ListNode dummy = new ListNode(0);
    3. dummy.next = head;
    4. ListNode pre = dummy;
    5. ListNode end = dummy;
    6. while (end.next != null) {
    7. for (int i = 0; i < k && end != null; i++) end = end.next;
    8. if (end == null) break;
    9. ListNode start = pre.next;
    10. ListNode next = end.next;
    11. end.next = null;
    12. pre.next = reverse(start);
    13. start.next = next;
    14. pre = start;
    15. end = pre;
    16. }
    17. return dummy.next;
    18. }
    19. private ListNode reverse(ListNode head) {
    20. ListNode pre = null;
    21. ListNode curr = head;
    22. while (curr != null) {
    23. ListNode next = curr.next;
    24. curr.next = pre;
    25. pre = curr;
    26. curr = next;
    27. }
    28. return pre;
    29. }

     

    参考自:

    【1】leetcode 王尼玛 四种解法+多图演示 23. 合并K个排序链表

    【2】leetcode  画手大鹏 画解算法:24. 两两交换链表中的节点

    【3】leetcode 房建斌学算法 图解k个一组翻转链表 

    【4】leetcode powcai k 个一组翻转链表 ​​​​​​​

  • 相关阅读:
    大模型的背景与现状问题
    从核酸检测平台崩盘看性能工程的范围
    FPGA时序分析与约束(14)——虚拟路径
    iMazing2023永久免费版苹果iOS设备管理软件
    STL容器
    软件兼容性测试对软件产品起到什么作用?CMA、CNAS软件测评中心分享
    中文编程开发语言工具开发案例:多种称重方式编程实际例子
    工作几年还是悟不懂自动化测试的意义
    视觉SLAM第五讲
    板块概念相关(五)
  • 原文地址:https://blog.csdn.net/weixin_45532984/article/details/125661887