大多数题目是在链表上实现的排序算法,或者运用部分排序算法中的部分思想解题。 单链表适合用归并排序,双向链表适合用快速排序,时间复杂度O(nlogn) & 空间复杂度O(1)
147 Insertion Sort List Medium
Sort a linked list using insertion sort. A graphical example of insertion sort. The partial sorted list (black) initially contains only the first element in the list. With each iteration one element (red) is removed from the input data and inserted in-place into the sorted list Algorithm of Insertion Sort: Insertion sort iterates, consuming one input element each repetition, and growing a sorted output list. At each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there. It repeats until no input elements remain. Example 1: Input: 4->2->1->3 Output: 1->2->3->4 Example 2: Input: -1->5->3->4->0 Output: -1->0->3->4->5
题意:链表的插入排序 思路:初始时,sorted list是空,把一个元素插入sorted list中。然后,在每一次插入过程中,都是找到最合适位置进行插入。 因为是链表的插入操作,需要维护pre,p和q 3个指针。 pre始终指向sorted list的dummy,p指向当前需要被插入的元素,q指向下一个需要被插入的元素。 当sortedlist为空以及pre.next所指向的元素比cur指向的元素值要大时,需要把cur元素插入到pre.next所指向元素之前。否则,pre指针后移。最后返回dummy的next即可。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode insertionSortList(ListNode head) {
if(head == null || head.next == null) {
return head;
}
ListNode dummy = new ListNode(-1);
ListNode p = head;
while(p != null) {
ListNode pre = dummy, q = p.next;
while(pre.next != null && pre.next.val<p.val) {
pre = pre.next;
}
p.next = pre.next;
pre.next = p;
p = q;
}
return dummy.next;
}
}
23 Merge k Sorted Lists Hard
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. Example: Input: [ 1->4->5, 1->3->4, 2->6 ] Output: 1->1->2->3->4->4->5->6
题意:归并k个有序链表 思路:先两个链表归并,剩下的所有链表再每两个链表做归并,递归,与归并排序类似。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if(lists == null || lists.length == 0) {
return null;
}
return merge(lists,0,lists.length-1);
}
private ListNode merge(ListNode[] lists, int low, int high) {
if(low<high) {
int mid = low+(high-low)/2;
ListNode left = merge(lists,low,mid);
ListNode right = merge(lists,mid+1,high);
return mergeTwoLists(left, right);
}
return lists[low];
}
private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
// 两个有序链表的归并
ListNode p = l1, q = l2;
ListNode dummy = new ListNode(-1);
ListNode r = dummy;
while(p!=null || q!=null) {
if(p == null) {
r.next = q;
break;
} else if(q == null) {
r.next = p;
break;
} else if(p.val < q.val) {
r.next = p;
p = p.next;
r = r.next;
} else {
r.next = q;
q = q.next;
r = r.next;
}
}
return dummy.next;
}
}
148 Sort List Medium
Sort a linked list in O(n log n) time using constant space complexity. Example 1: Input: 4->2->1->3 Output: 1->2->3->4 Example 2: Input: -1->5->3->4->0 Output: -1->0->3->4->5
题意:单链表的归并排序 思路:找链表的中点,用最经典的faster和slower方法,faster速度是slower的两倍,当faster到链尾时,slower就是中点,slower的next是下一半的开始点。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
if(head == null || head.next == null) {
return head;
}
ListNode slow = head, fast = head;
while(fast.next!=null && fast.next.next!=null) {
slow = slow.next;
fast = fast.next.next;
}
ListNode firstHalf = head, secondHalf = slow.next;
slow.next = null;
ListNode leftList = null, rightList = null;
if(firstHalf!=secondHalf) {
leftList = sortList(firstHalf);
rightList = sortList(secondHalf);
}
return mergeTwoLists(leftList, rightList);
}
private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
// 两个有序链表的归并
ListNode p = l1, q = l2;
ListNode dummy = new ListNode(-1);
ListNode r = dummy;
while(p!=null || q!=null) {
if(p == null) {
r.next = q;
break;
} else if(q == null) {
r.next = p;
break;
} else if(p.val < q.val) {
r.next = p;
p = p.next;
r = r.next;
} else {
r.next = q;
q = q.next;
r = r.next;
}
}
return dummy.next;
}
}
215 Kth Largest Element in an Array Medium
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element. Example 1: Input: [3,2,1,5,6,4] and k = 2 Output: 5 Example 2: Input: [3,2,3,1,2,4,5,5,6] and k = 4 Output: 4 Note: You may assume k is always valid, 1 ≤ k ≤ array's length.
题意:求一个乱序数组中第k大的数 方法1:基于Partition方法。 方法2:最小堆。
class Solution {
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> minHeap = new PriorityQueue<>(k);
for(int num:nums) {
if(minHeap.size()<k) {
minHeap.add(num);
} else {
if(minHeap.peek() < num) {
minHeap.poll();
minHeap.add(num);
}
}
}
return minHeap.peek();
}
}