Leetcode 147.对链表进行排序

对链表进行插入排序

对链表进行插入排序。

插入排序算法:

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

   

示例 1:

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

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

到了链表,我们发现一个问题,那就是链表不能从后往前遍历,这就很尴尬了。我本来是尝试找到一个需要移动的节点(即该节点的值比前驱节点的值小),从前往后遍历,直到找到一个节点值比它大时插入到这个节点前面,然而实现了很久发现代码又臭又长,关键是还总有测试用例不通过,最后还是放弃了。

看了答案发现思路应该是创建一个辅助的新链表,并且使用一个指针遍历原链表,每次将原链表中的一个节点插入到新链表的合适位置(即该节点的值大于新链表上的节点的值,又小于后一节点的值)。最后将新链表的头部返回即可。代码如下,做了详细的注释,应该很容易看懂。



 1 class ListNode {
 2     int val;
 3     ListNode next;
 4     ListNode(int x) {
 5         val = x;
 6     }
 7 }
 8     /**
 9      * 链表插入排序
10      * */
11     public ListNode insertionSortList(ListNode head) {
12         //边界条件判断
13         if(head==null || head.next == null)
14             return head;
15 
16         //创造一个新的链表头部
17         ListNode pre = new ListNode(-1);
18         //用一个临时变量保存头节点
19         ListNode ans = pre;
20         //cur是原链表上的指针
21         ListNode cur = head;
22         while (cur != null) {
23             //每次循环前重置pre为头结点,这样保证每次都从头往后遍历
24             pre = ans;
25 
26             //当pre.next.val大于cur.val时停止循环
27             while (pre.next != null && pre.next.val < cur.val) {
28                 pre = pre.next;
29             }
30 
31             //pre.next.val 大于 cur.val,此时应该把cur插入到pre后
32             //保存原链表当前节点的下一节点
33             ListNode tmp = cur.next;
34             //把cur插入到pre之后
35             cur.next = pre.next;
36             pre.next = cur;
37 
38             //cur指针后移一位
39             cur = tmp;
40         }
41         return ans.next;
42     }

 

 

原文地址:https://www.cnblogs.com/kexinxin/p/10195970.html