Skip to content

Latest commit

 

History

History
369 lines (286 loc) · 15.3 KB

LinkedList.md

File metadata and controls

369 lines (286 loc) · 15.3 KB

LinkedList(25/34)

No. Title Difficulty Solved Date
2 Add Two Numbers Medium yes 2018-12-28
19 Remove Nth Node From End of List Medium yes 2019-01-07
21 Merge Two Sorted Lists Easy yes 2019-01-07
23 Merge k Sorted Lists Hard yes 2019-05-21
24 Swap Nodes in Pairs Medimu yes 2019-01-09
25 Reverse Nodes in k-Group Hard yes 2019-05-21
61 Rotate List Meidum yes 2019-01-09
82 Remove Duplicates from Sorted List II Medium yes 2019-01-09
83 Remove Duplicates from Sorted List Easy yes 2019-01-09
86 Partition List Medium yes 2019-05-21
92 Reverse Linked List II Medium yes 2019-01-11
109 Convert Sorted List to Binary Search Tree Medium yes 2019-01-03
138 Copy List with Random Pointer Medium yes 2019-01-11
141 Linked List Cycle Easy yes 2019-01-09
142 Linked List Cycle II Medium yes 2019-05-21
143 Reorder List Medium yes 2019-01-12
147 Insertion Sort List Medium yes 2019-01-14
148 Sort List Medium yes 2019-01-18
160 Intersection of Two Linked Lists Easy yes 2019-01-18
203 Remove Linked List Elements Easy yes 2019-01-23
206 Reverse Linked List Easy yes 2019-01-10
234 Palindrome Linked List Easy yes 2019-01-10
237 Delete Node in a Linked List Easy yes 2019-01-10
328 Odd Even Linked List Medium yes 2019-01-28
430 Flatten a Multilevel Doubly Linked List Medium yes 2019-01-05
445 Add Two Numbers II Medium yes 2019-01-10
707 Design Linked List Easy yes 2019-01-17
725 Split Linked List in Parts Medium yes 2019-05-21
817 Linked List Components Medium yes 2019-01-23
876 Middle of the Linked List Easy yes 2019-01-09
1019 Next Greater Node in LinkedList Medium yes 2019-05-21

  1. Add Two Numbers

链表的数据结构,使用两个指针同时向前移动,可以解决。需要注意的是,最后结果是否需要进位。

  1. Remove Nth Node From End of List

链表遍历的问题。可以采用一次遍历或是二次遍历。问题较为简单,不要将所有节点都存储到临时数组中。

  1. Merge Two Sorted Lists

双指针遍历即可。

  1. Merge K Sorted Lists

最简单的思路,参考题目21. K个链表,先用第一个和第二个进行合并,然后再和第三个进行合并。

高级一些的思路是,1和2合并,3和4合并。。,完成第一次遍历后,然后再1和3合并,5和7合并。。使用归并的思路,每次遍历一遍之后,问题的规模变为原来的1/2。

  1. Swap Nodes in Pairs

两个节点为一组,交换两个节点的位置。为了便于处理,可以设置一个哨兵节点。

  1. Reverse Nodes in K-Groups

k个节点为一组进行倒序,当不满足k个节点的时候,就不再继续处理。每组链表倒序完成后,需要和原来的链表组合起来。

  1. Rotate List

计算链表的长度,用k对len求余后,就是需要移动到链表头部的节点的个数.

  1. Remove Duplicates from Sorted List II

一次遍历。在遍历的过程中,保存当前节点的前一个节点。

  1. Remove Duplicates from Sorted List

和82比较相似。可以递归的进行处理。从头节点开始,remove(head, head.next) => remove(head.next, head.next) | remove(head,head.next.next)

  1. Partition List

遍历链表,遇到值比x大的节点,就拼接到链表的末尾,并从当前位置删除。

public ListNode partition(ListNode head, int x) {
        ListNode h1 = new ListNode(0);
        ListNode h2 = new ListNode(0);
        ListNode temp1  = h1;
        ListNode temp2 = h2;
        ListNode temp = head;
        while (temp != null) {
            ListNode next = temp.next;
            if (temp.val < x) {
                temp1.next = temp;
                temp.next = null;
                temp1 = temp;
            } else {
                temp2.next = temp;
                temp.next = null;
                temp2 = temp;
            }
            temp = next;
        }
        temp1.next = h2.next;
        return h1.next;      
    }
  1. Reverse Linked List II

可以先计算出需要反转的节点的前一个节点和后一个节点。然后将中间的链表进行反转。最后连接起来即可。

  1. Convert Sorted List to Binary Search Tree

一个比较朴素的处理思路是将链表处理成数组。然后就转变成为排序后的数组生成二叉查找树的问题。不过这种题目的考核点明显不在这个地方。应该存在更好的办法。

查看资料,可以使用快慢指针法。慢指针一次移动一个位置,快指针一次移动两个位置。这样当筷子真到链表末尾的时候,慢指针指向中间位置。同事,还需要断开中间位置左右两个链表。

  1. Copy List with Random Pointer

可以递归的进行解决。由于有random节点的存在,复制的时候,需要考虑此节点是否已经创建完成。

  1. Linked List Cycle

快慢指针法.

public boolean hasCycle(ListNode head) {
        if (head == null) return false;
        ListNode slow = head;
        ListNode fast =head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                return true;
            }
        }
        return false;
    }
  1. Linked List Cycle II

快慢指针。

  1. Reorder List

快慢指针法,取得后半段的链表,然后反转后半段的链表。

在反转之后,可以遍历后半段链表,依次插入即可。需要注意的从后半段的链表长度可能比长半段的长度大1.需要注意不要清空了可能存在的最后一个节点。

public void reorderList2(ListNode head) {
        if (head == null || head.next == null || head.next.next == null) return;
        ListNode prev = null;
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            prev = slow;
            slow = slow.next;
            fast = fast.next.next;
        }
        if (prev != null) {
            prev.next = null;
        }
        slow = reverse(slow);
        ListNode h = head;
        while (slow != null) {
            ListNode next = h.next;
            ListNode next2 = slow.next;
            h.next = slow;
            if (next == null) break;
            slow.next = next;
            h = next;
            slow = next2;
        }
        
    }
  1. Insertion Sort List

插入排序。可以使用递归方法解决,也可以使用迭代方法解决。

public ListNode insertionSortList(ListNode head) {
        if (head == null) return null;
        ListNode h = new ListNode(0);
        h.next = head;
        ListNode cur = head.next;
        head.next = null;
        // tail node
        ListNode prev2 = head;
        while (cur != null) {
            ListNode prev = h;
            ListNode current = h.next;
            while (current != null) {
                if (current.val <= cur.val) {
                    prev = current;
                    current = current.next;
                } else {
                    break;
                }
            }
            if (current == null) {
                prev.next = cur;
                prev2 = cur;
                cur = cur.next;
                prev2.next = null;
            } else {
                ListNode temp = cur.next;
                prev.next = cur;
                cur.next = current;
                cur = temp;
            }
            
        }
        return h.next;
    }
  1. Sort List

可以使用147中的插入排序。

  1. Intersection of Two Linked Lists

计算链表的长度差,然后将长链表的指针提前向前移动长度差个距离。

  1. Remove Linked List Elements

简单。相对而言,迭代的方式更加直接。

递归的写法如下

 public ListNode removeElements(ListNode head, int val) {
        if (head == null) return null;
        if (head.val == val) {
            return removeElements(head.next, val);
        } else {
            remove(head, head.next, val);
            return head;
        }
    }
    
    private void remove(ListNode prev, ListNode current, int val) {
        if (current == null) return;
        if (current.val == val) {
            prev.next = current.next;
            remove(prev, current.next, val);
        } else {
            remove(current, current.next, val);
        }
    }
  1. Reverse Linked List

可以使用递归或者迭代来进行求解.

  1. Palindrome Linked List

首先去求链表的中间节点

然后将后半段链表反转

最后遍历去比较两个链表的节点。需要注意的是两个链表可能长度不一致,存在一个节点的长度差。在遍历比较节点值的时候,只需要比较存在的节点即可。

public boolean isPalindrome(ListNode head) {
        if (head == null || head.next == null) return true;
        ListNode prev = null;
        // locate to the middle node
        ListNode slow = middle(head);
        ListNode fast = head;
        /// reverse the linkedlist
        slow = reverse(slow);
        while (fast != null || slow != null) {
            if (fast == null || slow == null) {
                return true;
            }
            if (fast.val != slow.val) {
                return false;
            }
            fast = fast.next;
            slow = slow.next;
        }
        return true;
    }
  1. Delete Node in a Linked List

遍历过程中,将下一个节点的值赋给前一个节点。同时修改尾指针。

  1. Odd Even Linked List

这个题目不错。值得反复思考一下。

  1. Flatten a Multilevel Doubly Linked List

节点有next指针、prev指针和child指针,要求将链表展开。在节点同时有next节点和child节点的时候,优先排列child,然后再排列next。 很容易想到使用递归的方式。最简单的方式是使用临时存储,在遍历链表的时候,不处理各个节点之间指针的指向关系,先将所有的节点存储到一个List中。 然后使用二次遍历,按照list中存储的顺序,来来处理指针的指向。需要注意的是需要将child指针置空。

不使用临时存储的话,同样使用递归的方式,在一次遍历的过程中,处理好指针引用。针对当前节点,如果节点child指针为空,可以处理下一个节点。如果节点的child不为空,则以child节点为当前节点,递归的执行。child节点处理完成后,处理next节点。

class Solution {
    public Node flatten(Node head) {
        flatten(null, head);
        return head;
    }
    private Node flatten(Node prev, Node current) {
        if (current == null) return prev;
        Node next = current.next;
        Node child = current.child;
        if (prev != null) {
            prev.next = current;
        }
        current.prev = prev;
        if (child == null) {
            return flatten(current, current.next);
        } else {
            current.child = null;
            Node c = flatten(current, child);
            c.next = next;
            if (next != null) {
                next.prev = c;
            }
            return flatten(c, next);
        }
    }
}
  1. Add Two Numbers II

反转链表之后进行求解.

  1. Design Linked List

简单的题目,不过测试用例有些坑。

  1. Linked List Components

可以使用Map来存储每个节点在链表中的序号。然后,即可根据节点的序号值来判断是否相连。

  1. Middle of the Linked List

快慢指针.快指针是慢指针的两倍速度。当快指针到末尾的时候,慢指针到中间位置。

public ListNode middleNode(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;   
    }
  1. Next Greater Node in linkedList