题目链接:Insertion Sort List
Sort a linked list using insertion sort.
这道题的要求是对链表进行插入排序。
插入排序,就是和玩扑克差不多,每次拿到一张新牌,会从一侧向另一侧查找,直到找到合适位置,将其插进去,并保证手中的牌仍有续。
-
直接插入
而对于链表,采用同样的操作。将链表分为2部分:已排好序的部分和未排序的剩余rem部分。接下来,对每一个剩余节点,都在已排好序的部分中从左往右第查找,直到链表尾或者出现大于rem节点数值的节点停止查找。然后将rem指向的节点插入,并将rem后移一位。
时间复杂度:O(n2)
空间复杂度:O(1)
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
29
30
31
32
33
34
class Solution
{
public:
ListNode *insertionSortList(ListNode *head)
{
if(head == NULL || head -> next == NULL)
return head;
// 加头,便于后续操作
ListNode *h = new ListNode(0);
h -> next = head;
// 将链表在第一个节点后面切割,从第二个节点开始为剩余部分rem
ListNode *rem = h -> next -> next;
h -> next -> next = NULL;
// 执行插入操作,直到剩余部分rem没有节点
while(rem != NULL)
{
// 找到要插入节点的位置
ListNode *p = h;
while(p -> next != NULL && p -> next -> val < rem -> val)
p = p -> next;
// 插入节点
ListNode *temp = rem -> next;
rem -> next = p -> next;
p -> next = rem;
rem = temp;
}
return h -> next;
}
};
-
利用Hash
上面链表插入排序的时间复杂度为O(n2),其中每次找到需要插入的位置时的复杂度为O(n),因此,可以用hash进行快速找到要插入位置。由于c++中的map是由红黑树实现的,已经按key值进行排序了,因此,就可以用map在O(logn)时间复杂度找到要插入位置。
- 如果map中没有要插入节点,将其放入map中,然后找到其迭代器it,令it自减(如果it已经指向头节点,那么前一节点就是h了),这样就指向其前一节点了,就可以插入了。
- 如果map中已存在要插入节点,那么对应的value就是要插入位置的前一节点,然后再重新将该节点放到map中即可。
这样排序还是稳定的。。。
时间复杂度:O(nlogn)
空间复杂度:O(n)
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Solution
{
public:
ListNode *insertionSortList(ListNode *head)
{
if(head == NULL || head -> next == NULL)
return head;
// 加头,便于后续操作
ListNode *h = new ListNode(0);
h -> next = head;
// 将链表在第一个节点后面切割,从第二个节点开始为剩余部分rem
ListNode *rem = h -> next -> next;
h -> next -> next = NULL;
map<int, ListNode *> hash;
hash[h -> next -> val] = h -> next;
// 执行插入操作,直到剩余部分rem没有节点
while(rem != NULL)
{
ListNode *p = NULL;
// 找到要插入节点的位置p
auto it = hash.find(rem -> val);
if(it == hash.end())
{
hash[rem -> val] = rem;
it = hash.find(rem -> val);
p = it == hash.begin() ? h : (-- it) -> second;
}
else
{
p = it -> second;
hash[rem -> val] = rem;
}
// 插入节点
ListNode *temp = rem -> next;
rem -> next = p -> next;
p -> next = rem;
rem = temp;
}
return h -> next;
}
};