reverse linked list: http://lintcode.com/en/problem/reverse-linked-list/

  1. two pointers: prev, curr
  2. keep a copy of original next for iteration
  3. 改变结构
  4. move forward
  • 当需要遍历链表且其结构变化时 通常在变化前(usually first step) 记录下original next node for iteration.

  • 注意 return prev 而不是 curr

// test case: 1 -> 2 -> 3 -> 4 -> null, return 4 -> 3 -> 2 -> 1 -> null
public ListNode reverse(ListNode node) {

    ListNode prev = null;
    ListNode curr = node;

    while (curr != null) {
        ListNode next = curr.next;
        curr.next = prev;
        prev = curr;
        curr = next;
    }

    return prev;
}

find middle in linked list

  • two pointers: fast, slow
  • fast != null && fast.next != null
// test case 1: 1 -> 2 -> 3 -> 4, return 2
// test case 2: 1 -> 2 -> 3 -> 4 -> 5, return 3
// test case 3: 1, return 1
public ListNode findMiddle(ListNode node) {

    if (node == null) return node;

    ListNode slow = node;
    ListNode fast = node.next;

    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }

    return slow;    
}

merge two sorted linked list: http://lintcode.com/en/problem/merge-two-sorted-lists/

  • since need to return original dummy.next, so need a proxy of dummy node which walks through the list. 目的是不影响 dummy的值

  • i.e. ListNode newNode = dummy;

  • 类似的 curr1, curr2 是 node1, node2 的 proxy

// test case: 1->3->8->11->15->null, 2->null , return 1->2->3->8->11->15->null.
public ListNode merge(ListNode node1, ListNode node2) {

    ListNode curr1 = node1;
    ListNode curr2 = node2;
    ListNode dummy = new ListNode(0);
    ListNode newNode = dummy;

    while (curr1 != null && curr2 != null) {
        if (curr1.val <= curr2.val) {
            newNode.next = curr1; 
            curr1 = curr1.next;
        } else {
            newNode.next = curr2;
            curr2 = curr2.next;
        }
        newNode = newNode.next;    
    }

    if (curr1 == null) {
        dummy.next = curr2;
    }

    if (curr2 == null) {
        dummy.next = curr1;
    }

    return dummy.next;
}

sort list: http://www.lintcode.com/en/problem/sort-list/

  1. find middle
  2. divide and conquer
  3. merge (left, right)
  • head == null || head.next == null: 终止条件为 当前的head为空 或者 只有一个元素。 i.e. 无法继续分割. 换言之 至少有两个元素才能开始后面 否则 middle.next 会报错 (1 -> null)

    • head == null 针对 init input = null

    • head.next == null 针对 有两个元素

  • middle.next = null: sort left时 需要断开链接

  • Time: O(nlogn), Space: O(n)

// test case 1: 1 -> 3 -> 2, return 1 -> 2 -> 3
// test case 2: 1 -> 5 -> 3 -> 7, return 1 -> 3 -> 5 -> 7
// test case 3: 1, return 1
public ListNode sortList(ListNode head) {

    if (head == null || head.next == null) {
        return head
    }

    ListNode middle = findMiddle(head);
    ListNode right = sortList(middle.next);
    middle.next = null;
    ListNode left = sortList(head);

    return merge(left, right);
}

reorder list: http://www.lintcode.com/en/problem/reorder-list/

  1. find middle
  2. reverse right
  3. merge (left, right)
  • head == null || head.next == null: 终止条件为 当前的head为空 或者 只有一个元素。 i.e. 无法继续分割. 换言之 至少有两个元素才能开始 否则 middle.next 会报错 (1 -> null)

  • middle.next = null: 断开链接

  • reverse(middle.next): 传到reverse()里的middle.next是一个copy(proxy) 不影响original middle node, so middle.next = null中的middle是original middle

// test case 1: 1 -> 2 -> 3 -> 4, return 1 -> 4 -> 2 -> 3
// test case 2: 1 -> 2 -> 3 -> 4 -> 5, return 1 -> 5 -> 2 -> 4 -> 3
// test case 3: 1 -> null
public ListNode reorderList(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }

    ListNode middle = findMiddle(head);
    ListNode right = reverse(middle.next);
    middle.next = null

    return merge(head, right);        
}

reverse linked list ii (m to n reverse): http://www.lintcode.com/en/problem/reverse-linked-list-ii/

  1. find m - 1
  2. reverse (m, n)
  3. handle m - 1, n + 1

need dummy node since head may change

ListNode curr = dummy: need a proxy for dummy since return dummy.next

m <= n

// test case 1: 1 -> 2 -> 3 -> 4 -> 5, m = 2, n = 4, return: 1 -> 4 -> 3 -> 2 -> 5
// test case 2: 1 -> 2 -> 3 -> 4 -> 5, m = 1, n = 2, return: 2 -> 1 -> 3 -> 4 -> 5
public ListNode reverseBetween(ListNode head, int m, int n) {

        ListNode dummy = new ListNode(0);
        dummy.next = head;

        ListNode prev = dummy;
        ListNode curr = head;

        for (int i = 0; i < m-1; i++) {
            prev = curr;
            curr = curr.next;
        }

        ListNode prevStub = prev;

        while (curr != null && m <= n) {
            ListNode next = curr.next;
            curr.next = prev;
            prev = curr; 
            curr = next;
            m++;
        }

        prevStub.next.next = curr;
        prevStub.next = prev;

        return dummy.next;
}

partition list: http://www.lintcode.com/en/problem/partition-list/

  • Approach 1: two list (Exceed memory limit, Space O(n), Time O(n))

  • create dummy left, dummy right to link <=x and >x

  • merge dummy left

public ListNode partition(ListNode head, int x) {

        ListNode leftDummy = new ListNode(0);
        ListNode rightDummy = new ListNode(0);

        ListNode left = leftDummy;
        ListNode right = rightDummy;

        ListNode curr = head;

        while (curr != null) {
            if (curr.val < x) {
                left.next = curr;
                left = left.next;
            } else {
                right.next = curr;
                right = right.next;
            }

            curr = curr.next;
        }

        left.next = rightDummy.next;

        return leftDummy.next;
    }

remove duplicates from sorted list ii: http://www.lintcode.com/en/problem/remove-duplicates-from-sorted-list-ii/

    public static ListNode deleteDuplicates(ListNode head) {
        // write your code here
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode curr = dummy;

        while (curr.next != null && curr.next.next != null) {

            if (curr.next.val == curr.next.next.val) {
                int val = curr.next.val;
                while (curr.next != null && curr.next.val == val) {
                    curr.next = curr.next.next;
                }
            } else {
                curr = curr.next;
            }
        }

        return dummy.next;
    }

linked list cycle: http://www.lintcode.com/en/problem/linked-list-cycle/

  • fast-slow pointers

rotated list: http://www.lintcode.com/en/problem/rotate-list/

merge k sorted list (k路归并): http://www.lintcode.com/en/problem/merge-k-sorted-lists/

  • approach 1: heap
  • approach 2: divide & conquer
  • approach 3: merge list 2 by 2
  • related: merge k sorted arrays, merge 2 sorted list
    // heap
   private Comparator<ListNode> comparator = new Comparator<ListNode>() {
         public int compare(ListNode left, ListNode right) {
             return left.val - right.val;
         }
     };

    public ListNode mergeKLists(List<ListNode> lists) {  
        if (lists == null || lists.size() == 0) return null;

        ListNode dummy = new ListNode(0);
        ListNode curr= dummy;

        Queue<ListNode> heap = new PriorityQueue<>(lists.size(), comparator);

        for (ListNode head : lists) {
            if (head != null)
                heap.add(head);
        }

        while (!heap.isEmpty()) {
            ListNode node = heap.poll();
            curr.next = node;
            curr = curr.next;
            if (node.next != null)
                heap.add(node.next);

        }

        return dummy.next;
    }
    // two by tow merge, divide and conquer 
    public ListNode mergeKLists(List<ListNode> lists) {  
        // write your code here
        if (lists == null || lists.size() == 0) { return null; }

        return mergeHelper(lists, 0, lists.size() - 1);
    }

    private ListNode mergeHelper(List<ListNode> lists, int start, int end) {

        if (start == end) {
            return lists.get(start);
        }

        int mid = start + (end - start) / 2;
        ListNode left = mergeHelper(lists, start, mid);
        ListNode right = mergeHelper(lists, mid + 1, end);

        return merge(left, right);
    }

    private ListNode merge(ListNode left, ListNode right) {
        ListNode dummy = new ListNode(0);
        ListNode curr = dummy;
        ListNode leftCurr = left;
        ListNode rightCurr = right;

        while (leftCurr != null && rightCurr!= null) {

            if (leftCurr.val < rightCurr.val) {
                curr.next = leftCurr;
                leftCurr = leftCurr.next;
            } else {
                curr.next = rightCurr;
                rightCurr = rightCurr.next;
            }

            curr = curr.next;
        }

        if (leftCurr == null) {
            curr.next = rightCurr;
        }

        if (rightCurr == null) {
            curr.next = leftCurr;
        }

        return dummy.next;
    }
    // merge two by two
    public ListNode mergeKLists(List<ListNode> lists) {  
        // write your code here
        if (lists == null || lists.size() == 0) { return null; }

        while (lists.size() > 1) {

            List<ListNode> mergedList = new ArrayList<>();
            for (int i = 0; i < lists.size() - 1; i += 2) {
                ListNode mergedNode = merge(lists.get(i), lists.get(i+1));
                mergedList.add(mergedNode);
            }

            if (lists.size() % 2 == 1) {
                mergedList.add(lists.get(lists.size() - 1));
            }

            lists = mergedList;
        }

        return lists.get(0);
    }

copy list with random pointer: http://www.lintcode.com/en/problem/copy-list-with-random-pointer/

  • approach 1: hash map
  • approach 2: no extra space

http://www.lintcode.com/problem/convert-sorted-list-to-balanced-bst/

http://www.lintcode.com/problem/reverse-nodes-in-k-group/

http://www.lintcode.com/problem/delete-node-in-the-middle-of-singly-linked-list/

http://www.lintcode.com/problem/convert-binary-search-tree-to-doubly-linked-list/

https://leetcode.com/problems/remove-nth-node-from-end-of-list/

https://leetcode.com/problems/odd-even-linked-list/

https://leetcode.com/problems/swap-nodes-in-pairs/

results matching ""

    No results matching ""