• 链表知识点总结


    1. Linked List Cycle(判断链表是否有环)

    思路:设置slow和fast两个指针,初始化为head和head.next。遇到slow == fast说明有环,遇到fast == null || fast.next == null说明无环。模版程序如下。

     1 public class Solution {
     2     public boolean hasCycle(ListNode head) {
     3         if (head == null) {
     4             return false;
     5         }
     6         ListNode slow = head;
     7         ListNode fast = head.next;
     8         while (fast != slow) {
     9             if (fast == null || fast.next == null) {
    10                 return false;
    11             }
    12             fast = fast.next.next;
    13             slow = slow.next;
    14         }
    15         return true;
    16     }
    17 }
    View Code

    2. Intersection of Two Linked Lists(两个链表相交的开始节点)

    思路:把第一个链表的尾节点连到第二个链表的头节点,然后判断环的入口节点。

     1 public class Solution {
     2     public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
     3         if (headA == null || headB == null) {
     4             return null;
     5         }
     6         ListNode node = headA;
     7         while (node.next != null) {
     8             node = node.next;
     9         }
    10         node.next = headB;
    11         ListNode intersection = listCycle(headA);
    12         node.next = null;
    13         return intersection;
    14     }
    15     public ListNode listCycle(ListNode head) {
    16         ListNode slow = head;
    17         ListNode fast = head.next;
    18         while (fast != slow) {
    19             if (fast == null || fast.next == null) {
    20                 return null;
    21             }
    22             fast = fast.next.next;
    23             slow = slow.next;
    24         }
    25         slow = head;
    26         fast = fast.next;
    27         while (slow != fast) {
    28             slow = slow.next;
    29             fast = fast.next;
    30         }
    31         return slow;
    32     }
    33 }
    View Code

    3. Sorted List

    (1)快速排序

    思路:先找到中间节点(模版程序,详细见代码里的getMiddlle()函数),然后建立三个dummy分别用来组成比中间节点值小于、等于和大于的节点,注意最后一定要把末尾节点的next域置为null!!!因为末尾节点不一定是原list里的最后一个节点,其next域可能空可能不空。然后递归的排序left和right链表,最后把left、mid和right这三条链表合并。

    (2)归并排序链表

    思路:先找到中点节点,然后分治思想先排序右边list,再让中间节点的next域为null,再排序左边的list,最后merge。注意该算法空间复杂度为O(1)而不是给数组归并排序时的O(n),因为merge过程植新建了一个dummy node而并没有像数组的归并排序那样开辟了O(n)的临时数组。

     1 public class Solution {
     2     public ListNode sortList(ListNode head) {
     3         if (head == null || head.next == null) {
     4             return head;
     5         }
     6         ListNode mid = getMiddle(head);
     7         ListNode right = sortList(mid.next);
     8         mid.next = null;
     9         ListNode left = sortList(head);
    10         return merge(left, right);
    11     }
    12     public ListNode getMiddle(ListNode head) {
    13         ListNode slow = head;
    14         ListNode fast = head.next;
    15         while (fast != null && fast.next != null) {
    16             fast = fast.next.next;
    17             slow = slow.next;
    18         }
    19         return slow;
    20     }
    21     public ListNode merge(ListNode head1, ListNode head2) {
    22         ListNode dummy = new ListNode(0);
    23         ListNode cur = dummy;
    24         while (head1 != null && head2 != null) {
    25             if (head1.val < head2.val) {
    26                 cur.next = head1;
    27                 head1 = head1.next;
    28             } else {
    29                 cur.next = head2;
    30                 head2 = head2.next;
    31             }
    32             cur = cur.next;
    33         }
    34         if (head1 != null) {
    35             cur.next = head1;
    36         }
    37         if (head2 != null) {
    38             cur.next = head2;
    39         }
    40         return dummy.next;
    41     }
    42 }
    View Code

     4. Convert Binary Search Tree to Doubly Linked List

    Convert a binary search tree to doubly linked list with in-order traversal.
    
    Example
    Given a binary search tree:
    
        4
       / 
      2   5
     / 
    1   3
    return 1<->2<->3<->4<->5
    题目

    思路:分治思想,以root为根的BST,利用ResultType类记录其值最小的节点和值最大的节点,然后建立值为root.val的链表节点,它的prev与值最大节点相连(相互连接),它的next与值最小节点相连(相互连接)。

     1 /**
     2  * Definition of TreeNode:
     3  * public class TreeNode {
     4  *     public int val;
     5  *     public TreeNode left, right;
     6  *     public TreeNode(int val) {
     7  *         this.val = val;
     8  *         this.left = this.right = null;
     9  *     }
    10  * }
    11  * Definition for Doubly-ListNode.
    12  * public class DoublyListNode {
    13  *     int val;
    14  *     DoublyListNode next, prev;
    15  *     DoublyListNode(int val) {
    16  *         this.val = val;
    17  *         this.next = this.prev = null;
    18  *     }
    19  * }
    20  */
    21 class ResultType {
    22     DoublyListNode first;
    23     DoublyListNode last;
    24     public ResultType(DoublyListNode first, DoublyListNode last) {
    25         this.first = first;
    26         this.last = last;
    27     }
    28 }
    29 public class Solution {
    30     /**
    31      * @param root: The root of tree
    32      * @return: the head of doubly list node
    33      */
    34     public DoublyListNode bstToDoublyList(TreeNode root) {
    35         // Write your code here
    36         return helper(root).first;
    37     }
    38     public ResultType helper(TreeNode root) {
    39         if (root == null) {
    40             return new ResultType(null, null);
    41         }
    42         ResultType left = helper(root.left);
    43         ResultType right = helper(root.right);
    44         DoublyListNode node = new DoublyListNode(root.val);
    45         ResultType result = new ResultType(null, null);
    46         if (root.left == null) {
    47             result.first = node;
    48         } else {
    49             result.first = left.first;
    50             node.prev = left.last;
    51             left.last.next = node;
    52         }
    53         if (root.right == null) {
    54             result.last = node;
    55         } else {
    56             result.last = right.last;
    57             node.next = right.first;
    58             right.first.prev = node;
    59         }
    60         return result;
    61     }
    62 }
    View Code

    5. Merge k Sorted Lists

    Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

    思路I:分治法,将问题归结到合并两个有序链表的问题上。

     1 /**
     2  * Definition for singly-linked list.
     3  * public class ListNode {
     4  *     int val;
     5  *     ListNode next;
     6  *     ListNode(int x) { val = x; }
     7  * }
     8  */
     9 public class Solution {
    10     public ListNode mergeKLists(ListNode[] lists) {
    11         //Divide Conquer
    12         if (lists == null || lists.length == 0) {
    13             return null;
    14         }
    15         return mergeHelper(lists, 0, lists.length - 1);
    16     }
    17     public ListNode mergeHelper(ListNode[] lists, int start, int end) {
    18         if (start == end) {
    19             return lists[start];
    20         }
    21         int mid = start + (end - start) / 2;
    22         ListNode left = mergeHelper(lists, start, mid);
    23         ListNode right = mergeHelper(lists, mid + 1, end);
    24         return mergeTwoLists(left, right);
    25     }
    26     public ListNode mergeTwoLists(ListNode left, ListNode right) {
    27         ListNode dummy = new ListNode(0);
    28         ListNode cur = dummy;
    29         while (left != null && right != null) {
    30             if (left.val < right.val) {
    31                 cur.next = left;
    32                 left = left.next;
    33             } else {
    34                 cur.next = right;
    35                 right = right.next;
    36             }
    37             cur = cur.next;
    38         }
    39         if (left != null) {
    40             cur.next = left;
    41         }
    42         if (right != null) {
    43             cur.next = right;
    44         }
    45         return dummy.next;
    46     }
    47 }
    View Code

    思路II:小根堆

     1 /**
     2  * Definition for singly-linked list.
     3  * public class ListNode {
     4  *     int val;
     5  *     ListNode next;
     6  *     ListNode(int x) { val = x; }
     7  * }
     8  */
     9 public class Solution {
    10     public ListNode mergeKLists(ListNode[] lists) {
    11         // Minimum Heap
    12         if (lists == null || lists.length == 0) {
    13             return null;
    14         }
    15         PriorityQueue<ListNode> pq = new PriorityQueue<>(lists.length, new Comparator<ListNode>() {
    16             public int compare(ListNode a, ListNode b) {
    17                 return a.val - b.val;
    18             }
    19         });
    20         for (int i = 0; i < lists.length; i++) {
    21             //remove empty list
    22             if (lists[i] != null) {
    23                 pq.offer(lists[i]);
    24             }
    25         }
    26         ListNode dummy = new ListNode(0);
    27         ListNode cur = dummy;
    28         while (!pq.isEmpty()) {
    29             ListNode node = pq.poll();
    30             cur.next = node;
    31             cur = cur.next;
    32             if (node.next != null) {
    33                 pq.offer(node.next);
    34             }
    35         }
    36         //此句多余,应为到最后一个元素,其next指针一定为空。
    37         //因为都是有序链表,最后一个元素一定是某一条链表的末尾节点,其next域为空
    38         //cur.next = null;
    39         return dummy.next;
    40     }
    41 }
    View Code

    6. Insertion Sort List

    Sort a linked list using insertion sort.

    思路:pre指针指向每次要插入的元素的前一个位置,依次遍历节点插入即可。注意pre不必每次从头开始移动到插入位置,只需要当待插入元素比pre.next节点的值大才返回到头开始选择插入位置。

     1 /**
     2  * Definition for singly-linked list.
     3  * public class ListNode {
     4  *     int val;
     5  *     ListNode next;
     6  *     ListNode(int x) { val = x; }
     7  * }
     8  */
     9 public class Solution {
    10     public ListNode insertionSortList(ListNode head) {
    11         if (head == null || head.next == null) {
    12             return head;
    13         }
    14         ListNode dummy = new ListNode(0);
    15         ListNode pre = dummy;
    16         ListNode cur = head;
    17         while (cur != null) {
    18             ListNode next = cur.next;
    19             // 避免pre指针每次都从头开始移动
    20             if (pre.next == null || pre.next.val > cur.val) {
    21                 pre = dummy;
    22             }
    23             while (pre.next != null && pre.next.val <= cur.val) {
    24                 pre = pre.next;
    25             }
    26             cur.next = pre.next;
    27             pre.next = cur;
    28             cur = next;
    29         }
    30         return dummy.next;
    31     }
    32 }
    View Code
  • 相关阅读:
    软件工程课堂二
    大二下学期第三周总结
    大二第二个学期的自我介绍
    如何将非ARC的项目转换成ARC
    UIScrollView
    关于nil和 null和NSNull的区别及相关问题
    提高iOS开发效率的第三方框架等--不断更新中。。。
    iOS中常见的设计模式(MVC/单例/委托/观察者)
    TCP/IP、Http、Socket的区别
    iOS使用AVFoundation实现二维码扫描
  • 原文地址:https://www.cnblogs.com/choumeng/p/6410247.html
Copyright © 2020-2023  润新知