147. 对链表进行插入排序
- 插入排序的动画演示如上。从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示)。
- 每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中。
插入排序算法:
- 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
- 每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
- 重复直到所有输入数据插入完为止。
分析
将原链表分为两个部分:已排好序和未排好序,pre指针代表已排好序链表的哑节点,cur为未排序链表的头节点。进行插入操作时,cur指针依次遍历原链表,pre指针遍历黑色表示的元素,找到正确的插入位置,将cur节点插入,然后cur指针指向下一个待排序的元素。
public ListNode insertionSortList(ListNode head) {
if (head == null) {
return head;
}
ListNode dummyHead = new ListNode(0);
ListNode cur = head; // 待排序/插入的节点
ListNode pre = dummyHead; // 正确插入位置的指针
ListNode next; // 下一个插入结点
while (cur != null) {
next = cur.next;
while (pre.next != null && pre.next.val < cur.val) { // 插入查找
pre = pre.next;
}
// 断开现有结点
cur.next = pre.next;
pre.next = cur;
pre = dummyHead;
cur = next;
}
return dummyHead.next;
}
148. 排序链表
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
分析
归并排序的时间复杂度是 O( n n log),将数组的归并排序修改成链表的归并排序即可。
我的代码
public ListNode sortList(ListNode head) {
ListNode cur = head;
int i = 0;
while (cur != null) {
cur = cur.next;
i ++;
}
return sort(head, 0, i - 1);
}
public ListNode sort(ListNode head, int l, int r) {
if (l >= r) {
return head;
}
int mid = l + (r-l) / 2;
ListNode cur = head;
int i = 0;
while (cur != null && i < mid - l) {
cur = cur.next;
i ++;
}
ListNode tmp = cur.next;
cur.next = null;
ListNode left = sort(head, l, mid);
ListNode right = sort(tmp, mid + 1, r);
ListNode merge = merge(left, right);
return merge;
}
public ListNode merge(ListNode a, ListNode b) {
ListNode dummyHead = new ListNode(0);
ListNode cur = dummyHead;
while (a != null || b != null) {
if (a == null) {
cur.next = b;
break;
}
else if (b == null) {
cur.next = a;
break;
}
else if (a.val < b.val) {
cur.next = new ListNode(a.val);
cur = cur.next;
a = a.next;
}
else {
cur.next = new ListNode(b.val);
cur = cur.next;
b = b.next;
}
}
return dummyHead.next;
}
其中merge这一步,我这里是创建新的节点,其实也可以直接使用原链表的节点。每移动一个节点,就选两个链表中较小的节点接到结果链表中,直到其中一个链表遍历完,将另一个链表余下的节点接到最后即可。
public ListNode merge(ListNode l1, ListNode l2) {
ListNode l = new ListNode(0), p = l;
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
p.next = l1;
l1 = l1.next;
} else {
p.next = l2;
l2 = l2.next;
}
p = p.next;
}
if (l1 != null)
p.next = l1;
if (l2 != null)
p.next = l2;
return l.next;
}
如果文章里有说得不对的地方请前辈多多指正~ 与君共勉~