Nameless Site

But one day, you will stand before its decrepit gate,without really knowing why.

0%

对链表进行插入排序

来自Leetcode第147题对链表进行插入排序

对链表进行插入排序。

img
插入排序的动画演示如上。从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示)。
每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中。

插入排序算法:

  1. 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
  2. 每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
  3. 重复直到所有输入数据插入完为止。

示例 1:

1
2
输入: 4->2->1->3
输出: 1->2->3->4

转换成列表后排序

最简单思路,转换成数组(列表)后直接sort,最后转回链表即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public ListNode insertionSortList(ListNode head) {
if(head == null || head.next == null)
return head;
ListNode p1 = head;
List<Integer> list = new ArrayList<>();
while (p1 != null){
list.add(p1.val);
p1 = p1.next;
}
Collections.sort(list);
Iterator<Integer> it = list.iterator();
p1 = head;
while (it.hasNext()){
head.val = it.next();
head = head.next;
}
head.next = null;
return p1;
}

插入排序

先假定一个伪头结点,并把尾结点tail设置为伪头结点,接着依次比较当前结点cur与tai的值,如果tail的值大于等于cur,则说明cur应该插入tail之前,先记录下cur.next,并将tail.next设置为cur.next,从伪头结点开始遍历,直到找到一个结点下一个结点的值大于cur,这样就找到了cur结点的插入位置,修改对应结点的位置即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public ListNode insertionSortList(ListNode head) {
if(head == null || head.next == null)
return head;
ListNode p1 = new ListNode(Integer.MIN_VALUE); //傀儡头结点
ListNode pre = p1, tail = p1, cur = head;
while(cur != null){
if(tail.val < cur.val){
tail.next = cur;
tail = cur;
cur = cur.next;
}else{
ListNode tmp = cur.next;
tail.next = tmp;
//不加这一句,当前面是已经排好序的1->2->3->4这种情况时,
//如果要再把5插入里面,会造成后面的while语句一直循环
//tail.next后面接的就是cur,然后cur.next = pre.next;
//pre.next = cur;就成环了,因为成环接下来会一直困在主while循环
//找到适当的插入位置
while (pre.next != null && pre.next.val < cur.val)
pre = pre.next;
cur.next = pre.next;
pre.next = cur;
pre = p1;
cur = tmp;
}
}
return p1.next;
}