[LeetCode] 147. Insertion Sort List

原题链接: https://leetcode.com/problems/insertion-sort-list/

1. 题目介绍

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

2. 解题思路

解决本题首先需要学会如何在一个有序链表中插入元素,并且保证插入元素后链表还是有序的。
一开始我采用函数来插入节点,代码如下:

class Solution {
    public ListNode insertionSortList(ListNode head) {
		if(head == null || head.next == null){
			return head;
		}
		
		ListNode ans = new ListNode(-1);
		ListNode cur = head;
		while(cur != null){
			ListNode next = cur.next;
			ans.next = insertNode(ans.next,cur);
			cur = next;
		}
		
        return ans.next;   
    }
    
    //为一个有序链表插入节点,插入后也要保证链表有序
    public ListNode insertNode(ListNode root , ListNode node){
    	//第1种情况,root为空
    	if(root == null){
    		root = new ListNode(node.val);
    		return root;
    	}
    	
    	//第2种情况,node.val 是最小的,需要排在第一个
    	if(root.val > node.val){
    		node.next = root;
    		root = node;
    		return root;
    	}
    	
    	//第3种情况,也是最一般的情况,
    	//node需要插在第一个比node.val 大的节点前面
    	ListNode cur = root.next;
    	ListNode curPre = root;
    	while(cur !=  null){
    		if(cur.val > node.val){
    			curPre.next = node;
    			node.next = cur;
    			return root;
    		}
    	   	curPre = cur;
    		cur = cur.next;
    	}
    	//如果没有节点比node.val大,那么node就排在最后面
    	curPre.next = node;
    	node.next = null;
    	
    	return root;
    }
}

虽然成功实现,但是代码还是比较长。我参考了 https://www.cnblogs.com/ganganloveu/p/3959331.html 的代码,重新写了一个更加简洁的版本。思路仍然是遍历链表、插入节点。

class Solution {
    public ListNode insertionSortList(ListNode head) {
		if(head == null || head.next == null){
			return head;
		}
		
		ListNode assist = new ListNode(-1);
		while(head != null){
			ListNode Cur = assist;
			ListNode next = head.next;
			
			//找到应该插入head节点的位置
			while(Cur.next != null && Cur.next.val < head.val ){
				Cur = Cur.next;
			}
			//插入head节点
			head.next = Cur.next;
			Cur.next = head;
            
			//下一个head节点预备上
			head = next;
		}
		
        return assist.next;   
    }
}

后来点开LeetCode上面耗时较少的答案,发现在 “寻找插入节点的位置” 这一步上,可以加入一个特判:当要插入的节点比有序链表的最后一个节点大的时候,就不用找插入节点的位置了,直接将其变为有序链表的最后一个节点即可。
具体实现代码如下:

class Solution {
    public ListNode insertionSortList(ListNode head) {
		if(head == null || head.next == null){
			return head;
		}
		
		ListNode assist = new ListNode(-1);
		assist.next = head;
		
		ListNode pre = head;//pre是已经排序好的链表的最后一个节点
		ListNode cur = pre.next;//cur是要插入的节点
		
		while(cur != null){
			ListNode temp = cur.next;
			
			//如果要插入的节点已经比有序链表的最后一个节点要大了
			//那么直接将其变为有序链表的最后一个节点			
			if(cur.val > pre.val){
				pre = cur;
				cur = temp;
			}else{
				//找到应该插入head节点的位置
				ListNode l = assist;
				
				while(l.next.val < cur.val ){
					l = l.next;
				}
				//插入cur节点
				cur.next = l.next;
				l.next = cur;
				pre.next = temp;
				cur = temp;
			}
		}
        return assist.next;   
    }
}

3. 参考资料

https://www.cnblogs.com/ganganloveu/p/3959331.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值