[关闭]
@xmruibi 2015-02-13T04:22:39.000000Z 字数 4060 阅读 835

Linked List Problem

Algorithm


Idea Tips:

1. No buffer, constant memory
Using assignments to modify the orginal input, like pointer;
2. Two pointers
(Runner and walker)
Using two pointers, for locating some special position;
this idea also fit for finding a loop;
3. Recursion or iteration
These two are alternative. For recursion, it may be easy to get reversal list or element. But sometime interviewer may require to think in iteration method; 

Content:

 * 求单链表中结点的个数: getListLength 
 * 将单链表反转: reverseList(遍历),reverseListRec(递归) 
 * 查找单链表中的倒数第K个结点(k > 0): reGetKthNode 
 * 查找单链表的中间结点: getMiddleNode 
 * 去除重复节点 (Remove Duplicate, from Sorted or unsorted) 
 * 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序: mergeSortedList, mergeSortedListRec 
 * 判断一个单链表中是否有环: hasCycle & 已知一个单链表中存在环,求进入环中的第一个节点: getFirstNodeInCycle, getFirstNodeInCycleHashMap 
 * 判断两个单链表是否相交: isIntersect  &  求两个单链表相交的第一个节点: getFirstCommonNode 
 * 给出一单链表头指针pHead和一节点指针pToBeDeleted,O(1)时间复杂度删除节点pToBeDeleted: delete 

1. Reverse Method:

  1. 1. Get Head Node and Tail Node;
  2. Get Current Node;
  3. while(Current!=Tail(or null)):
  4. Node temp = current.next;
  5. Current.next = head.next;
  6. Head.next = current;
  7. current = temp;
  8. 2. Node newHead = null;
  9. Node cur = head;
  10. while(cur!=null):
  11. Node preCur = cur;
  12. cur = cur.next;
  13. preCur.next = newHead;
  14. newHead = preCur;
  15. 3. reverse(head): !!!!!
  16. if head == null||head.next == null;
  17. return head;
  18. newHead = reverse(head.next);
  19. head.next.next = head;
  20. head.next = null;
  21. return newHead;

2. Get Kth Node from rear:

TIPS: Two Pointer: runner and walker, runner go fast n steps, then go together to the end when the runner stop.
  1. ListNode runner = head;
  2. ListNode walker = head;
  3. int i = 0;!!!
  4. while(i<n):
  5. runner = runner.next;
  6. i--;
  7. if(runner==null) return // check runner valid!!!
  8. while(runner.next!=null):
  9. runner = runner.next;
  10. walker = walker.next;

3. Get Middle of List

TIPS: Doesn't need two pointer: change the given node's val as the next node's val and change the next node of given node which point to the next.next.
  1. ListNode tmp = node.next;
  2. node.val = tmp.val;
  3. node.next = next.next;

4. Remove Duplicate:

4.1 for Unsorted:!!!
  1. ListNode pre = head;
  2. ListNode cur = pre.next;
  3. while(cur!=null):
  4. ListNode runner = head; // a moving pointer for comparison
  5. while(runner!=null):
  6. if(runner.val == cur.val):
  7. ListNode tmp = cur.next;
  8. pre.next = tmp;
  9. cur = tmp;
  10. break;
  11. else:
  12. runner = runner.next;
  13. if(cur == runner):
  14. pre = cur;
  15. cur = cur.next;
4.2 for Sorted:
  1. (1) ListNode p1 = head;
  2. ListNode p2 = head;
  3. while(p2!=null):
  4. if(p1.val==p2.val):
  5. p1.next = p2.next;
  6. else
  7. p1 = p2;
  8. p2 = p2.next;
  9. (2) ListNode fakeHead = new ListNode(0);
  10. fakeHead.next = head;
  11. ListNode pre = fakeHead;
  12. ListNode cur = pre.next;
  13. while(cur!=null):
  14. while(cur.next!=null&&cur.next.val==cur.val):
  15. cur = cur.next;
  16. if(pre.next == cur) // not duplicate!
  17. pre = pre.next;
  18. else
  19. pre.next = cur.next;
  20. cur = cur.next;
  21. return fakeHead.next;

5. Merge Two Sorted List:

  1. (1)
  2. ListNode dummy = new ListNode(0);
  3. dummy.next = head1;
  4. ListNode pre = dummy;
  5. while(l1!=null&&l2!=null):
  6. if(l1.val>l2.val):
  7. ListNode tmp = l2.next;
  8. l2.next = pre.next;
  9. pre.next = l2;
  10. l2 = tmp;
  11. else
  12. l1 = l1.next;
  13. pre = pre.next;
  14. if(l2!=null)
  15. pre.next = l2;
  16. return helper.next;
  17. (2)
  18. Node mergeHead = null;
  19. if (head1.val < head2.val):
  20. mergeHead = head1;
  21. // 连接已解决的子问题
  22. mergeHead.next = mergeSortedListRec(head1.next, head2);
  23. else:
  24. mergeHead = head2;
  25. mergeHead.next = mergeSortedListRec(head1, head2.next);
  26. return mergeHead;

6. Check Cycle:

  1. ListNode walker = head;
  2. ListNode runner = head;
  3. while(runner.next!=null):
  4. // please assign first, then check equivalent
  5. runner = runner.next.next;
  6. walker = walker.next;
  7. if(runner==walker):
  8. break;
  9. if(runner.next == null)
  10. return null;
  11. ListNode checker = head;
  12. while(checker!=walker):
  13. checker = checker.next;
  14. walker = walker.next;
  15. return checker;

7. Find Intersection:

  1. // check each length
  2. // make two equivalent
  3. // start new iteration to find interaction point
  4. ListNode dummy1 = l1;
  5. ListNode dummy2 = l2;
  6. int len1 = 0;
  7. int len2 = 0;
  8. while(dummy1!=null):
  9. dummy1 = dummy1.next;
  10. len1++;
  11. while(dummy2!=null):
  12. dummy2 = dummy2.next;
  13. len2++;
  14. dummy1 = l1;
  15. dummy2 = l2;
  16. while(len1>len2):
  17. dummy1 = dummy1.next;
  18. len1--;
  19. while(len2>len1):
  20. dummy2 = dummy2.next;
  21. len2--;
  22. while(dummy1!=null&&dummy2!=null):
  23. if(dummy1==dummy2)
  24. return dummy1;
  25. dummy1 = dummy1.next;
  26. dummy2 = dummy2.next;
  27. return null;

8. (LeetCode) Add Two Number:

    ListNode result = new ListNode(0);
    ListNode resultHead = result;
    int carry = 0;

    while(n1!=null||n2!=null||carry!=0):
        int cur = 0;
        if(n1!=null):
            cur+= n1.val;
            n1 = n1.next; // don't forget

        if(n2!=null):
            cur+= n2.val;
            n2 = n2.next; // don't forget

        cur += carry;
        carry = cur/10;
        cur %= 10;
        ListNode node = new ListNode(cur);
        result.next = node;
        result = result.next; // don't forget

    return resultHead.next;
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注