When the head of the target list we want to return may be different from the original given list, we can use a dummy node linked to the result so that we can get what we want by calling dummy.next.
ListNode dummy = new ListNode(0); ListNode pre = dummy; ListNode cur = head; int dup = Integer.MIN_VALUE;
while(cur != null && cur.next != null) { if(cur.val == cur.next.val) { dup = cur.val; while(cur.val == dup) { cur = cur.next; // if the rest of elements are all the same if(cur == null) { return dummy.next; } } } else { pre.next = cur; pre = pre.next; cur = cur.next; // add null to pre.next: in case the rest of elements are the same and returned above pre.next = null; } } // add the last element (since cur.next != null skip this element) pre.next = cur;
publicclassSolution{ public ListNode reverseBetween(ListNode head, int m, int n){ if(head == null) { return head; }
// find the m position node int count = 1; ListNode dummy = new ListNode(0); dummy.next = head; ListNode pre = dummy; while(count < m) { pre = pre.next; count++; }
// do the reverse: pre-> reverse[first->cur->next] ... ListNode first = pre.next; ListNode cur = pre.next.next; while(count < n) { ListNode next = cur.next; cur.next = pre.next; pre.next = cur; cur = next; count++; if(count == n) { first.next = next; } }
Sort List: Define a ListNode separate(ListNode head) and a ListNode merge(ListNode l1, ListNode l2) and do a merge sort. In the return statement (return merge(separate(head1), separate(head2))) of the separate method, we do the recursion until there is only one element left, do the merge method so that we can get sorted lists.
Find the middle of a linked list: Use a fast pointer and a slow pointer to find the middle element. It is also used in finding list cycle, or Reorder List.
We maintain a heap (ATTENTION: compare(o1, o2), return neg(o1 < o2), 0 (o1 == o2) or pos(o1 > o2)). The top of the heap will be the smallest element in the heap. This method will cost O(nk) for traverse all elements and O(logk) time to insert it into heap, so O(nklogk), O(k) space cost for the heap.
publicclassSolution{ public ListNode mergeKLists(ArrayList<ListNode> lists){ PriorityQueue<ListNode> heap = new PriorityQueue<ListNode>(11, new Comparator<ListNode>() { @Override publicintcompare(ListNode l1, ListNode l2){ return l1.val - l2.val; } }); for(int i = 0; i < lists.size(); i++) { // !!! PriorityQueue DOES NOT allow null element !!! if(lists.get(i) != null) { heap.offer(lists.get(i)); } } ListNode dummy = new ListNode(0); ListNode cur = dummy; while(heap.size() > 0) { ListNode node = heap.poll(); cur.next = node; cur = cur.next; // !!! PriorityQueue DOES NOT allow null element !!! if(node.next != null) { heap.offer(node.next); } } return dummy.next; } }
Solution 2: Divide & Conquer(Merge Sort)
Do merge sort the lists of linked list and merge each pair of them. Cost: Merge Sort costs O(klogk) * O(n)Merge = O(nklogk), space O(logk) for the recursion stack.
Comments