21. Merge Two Sorted Lists 合并两个有序链表
https://leetcode.com/problems/merge-two-sorted-lists/
题目:合并两个排序链接列表并将其作为新列表返回。新列表应该通过将前两个列表的节点拼接在一起来创建。
解答:
class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode dummy = new ListNode(-1); ListNode cur = dummy; while(l1 != null && l2 != null) { if(l1.val < l2.val) { cur.next = l1; l1 = l1.next; } else { cur.next = l2; l2 = l2.next; } cur = cur.next; } if(l1 != null) { cur.next = l1; } else { cur.next = l2; } return dummy.next; } }
143. Reorder List 重新排序链表
https://leetcode.com/problems/reorder-list/
题目:对于链表 L: L0→L1→…→Ln-1→Ln,重新排序为 L0→Ln→L1→Ln-1→L2→Ln-2→…
思路:采用快慢指针来找到链表的中点,将中点后面的链表翻转,然后间隔地插入到前半部分的链表中。后半段翻转部分:先记录cur的next,再讲cur的next指向pre,更新pre的指向为和cur相同,更新cur为之前记录的cur的next,每一步都相当于让最新的节点(cur)指向已经完成翻转的链表(pre)。拼接两段链表时:先记录Ln的下一项Ln-1,然后让Ln的next指向L1,L0的next指向Ln,最后更新我们的指针;这样做比先让L0的next指向Ln会方便一些,只用暂时记录Ln的next,不然Ln和L0的next都需要记录。
class Solution { public void reorderList(ListNode head) { if (head == null || head.next == null) { return; } ListNode slow = head, fast = head; while(fast.next != null && fast.next.next != null) { slow = slow.next; fast = fast.next.next; } ListNode cur = slow.next, pre = null, next = null; while(cur != null) { next = cur.next; cur.next = pre; pre = cur; cur = next; } slow.next = null; // 要注意翻转完成后需要将两部分断开 ListNode reHead = pre; ListNode tempHead = head; while(pre != null && tempHead != null) { // pre.next可以为null ListNode temp = pre.next; pre.next = tempHead.next; tempHead.next = pre; pre = temp; tempHead = tempHead.next.next; } } }
147. Insertion Sort List 链表插入排序
https://leetcode.com/problems/insertion-sort-list/
题目:使用插入排序对链表进行排序。
思路:将元素从链表中取出来,然后按顺序插入到新链表中。当pre的next大于等于cur或为null时退出while循环,就将cur插入到pre和pre.next之间,此时满足pre.val < cur.val < pre.next.val。
class Solution { public ListNode insertionSortList(ListNode head) { if(head == null || head.next == null) return head; ListNode dummy = new ListNode(-1000); ListNode pre = dummy; ListNode cur = head; while(cur != null) { while(pre.next != null && pre.next.val < cur.val) { pre = pre.next; } ListNode next = cur.next; cur.next = pre.next; pre.next = cur; cur = next; pre = dummy; } return dummy.next; } }
148. Sort List 链表排序
https://leetcode.com/problems/sort-list/
题目:使用常数空间复杂度对链接列表进行O(nlogn)时间排序。
思路:归并排序。将链表拆分,对每一部分应用mergeTwoLists即可得到结果。
class Solution { public ListNode sortList(ListNode head) { if(head == null || head.next == null) return head; ListNode fast = head, slow = head, pre = head; while(fast != null && fast.next != null) { pre = slow; slow = slow.next; fast = fast.next.next; } pre.next = null; return mergeTwoLists(sortList(head), sortList(slow)); } public ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode dummy = new ListNode(-1); ListNode cur = dummy; while(l1 != null && l2 != null) { if(l1.val < l2.val) { cur.next = l1; l1 = l1.next; } else { cur.next = l2; l2 = l2.next; } cur = cur.next; } if(l1 != null) { cur.next = l1; } else { cur.next = l2; } return dummy.next; } }