package buildingblock.sorting.merge.lc021_mergetwosortedlists;

import fundamentals.list.ListNode;

/**
 * Merge two sorted linked lists and return it as a new list.
 * The new list should be made by splicing together the nodes of the first two lists.
 */
public class Solution {

    // Recursive solution
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null || l2 == null)
            return l1 != null ? l1 : l2;
        if (l1.val < l2.val) {
            l1.next = mergeTwoLists(l1.next, l2);
            return l1;
        } else {
            l2.next = mergeTwoLists(l1, l2.next);
            return l2;
        }
    }

    // Jump out of loop if one list reach end, so more efficient
    public ListNode mergeTwoLists_iterative2(ListNode l1, ListNode l2) {
        ListNode dmy = new ListNode(0), prev = dmy;
        while (l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                prev.next = l1;
                l1 = l1.next;
            } else {
                prev.next = l2;
                l2 = l2.next;
            }
            prev = prev.next;
        }
        prev.next = (l1 != null) ? l1 : l2;
        return dmy.next;
    }

    // My 2nd: common iterative solution
    public ListNode mergeTwoLists_iterative(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(0);
        ListNode prev = dummy;
        while (l1 != null || l2 != null) {
            int val1 = (l1 != null) ? l1.val : Integer.MAX_VALUE;
            int val2 = (l2 != null) ? l2.val : Integer.MAX_VALUE;
            if (val1 < val2) {
                prev.next = l1;
                l1 = l1.next;
            } else {
                prev.next = l2;
                l2 = l2.next;
            }
            prev = prev.next;
        }
        return dummy.next;
    }

    // My 1st
    public ListNode mergeTwoLists1(ListNode l1, ListNode l2) {
        ListNode first = new ListNode(-1);
        ListNode prev = first;
        while (l1 != null || l2 != null) {
            int d1 = (l1 == null) ? Integer.MAX_VALUE : l1.val;
            int d2 = (l2 == null) ? Integer.MAX_VALUE : l2.val;

            if (d1 < d2) {     // error: l1, l2 would not be moved together!
                prev.next = l1;
                l1 = l1.next;
            } else {
                prev.next = l2;
                l2 = l2.next;
            }
            prev = prev.next;
        }
        return first.next;
    }

}

@@ -274,16 +274,461 @@
 tion %7B%0A%0A
+    // 3AC%0A    public ListNode mergeTwoLists3(ListNode l1, ListNode l2) %7B%0A        ListNode dmy = new ListNode(0), p = dmy;%0A        while (l1 != null && l2 != null) %7B%0A            if (l1.val %3C l2.val) %7B%0A                p = p.next = l1;%0A                l1 = l1.next;%0A            %7D else %7B%0A                p = p.next = l2;%0A                l2 = l2.next;%0A            %7D%0A        %7D%0A        p.next = (l1 != null) ? l1 : l2;%0A        return dmy.next;%0A    %7D%0A%0A
     // R

merge two sorted lists