Document
链表的习题
-
将两个递增的有序链表合并为一个递增的有序链表。要求结果链表仍使用原来的两个链表的存储空间,不另外占用其他的存储空间,表中不允许有重复的数据。
为了方便不处理边界采用带哨兵的单链表形式
LIST-ORDERLY-MARGE(L1,L2)
1 p1=L1.nil.next
2 p2=L2.nil.next
//new tail=L.nil
3 while p1!=L1.nil and p2!=L2.nil
4 if p1.key<= p2.key < view>=>
5 if p1.key!=tail.key
6 temp=p1.next
7 p1.next=tail.next
8 tail.next=p1
9 tail=tail.next
10 p1=temp
11 else
12 p1=p1.next
13 else
14 if p2.key!=tail.key
15 temp=p2.next
16 p2.next=tail.next
17 tail.next=p2
18 tail=tail.next
19 p2=temp
20 else
21 p2=p2.next
22 while p1!=L1.nil
23 if p1.key!=tail.key
24 temp=p1.next
25 p1.next=tail.next
26 tail.next=p1
27 tail=tail.next
28 p1=temp
29 else
30 p1=p1.next
31 while p2!=L2.nil
32 if p2.key!=tail.key
33 temp=p2.next
34 p2.next=tail.next
35 tail.next=p2
36 tail=tail.next
37 p2=temp
38 else
39 p2=p2.next
- 根据题目描述,链表L1,L2是递增的,因此容易想到使用双指针p1和p2遍历两链表链表,根据L1.key和L2.key的大小关系确定添加结点顺序,两指针交替前进,直至遍历完毕
- 引入哨兵nil:由于初始状态合并链表中无结点,因此循环第一轮无法将结点添加到合并链表L中(边界问题),故初始化一个哨兵nil(哨兵请看List1-1)
- 为了方便在表尾添加数据,增加一个tail指针指向合并表L的表尾,由于开始无结点,故指向L.nil(哨兵).
算法流程:
初始化:哨兵L.nil,表尾tail=L.nil
循环合并:(在更新时候,此题注意边界查看表尾tail.key是否与添加的key相等)
- 当p1.key<=p2.key时,表尾tail.next指向p1,更新tail和p1< li>
- 当p2.key< p1.key时,表尾tail.next指向p2,更新tail和p2
=p2.key时,表尾tail.next指向p1,更新tail和p1<>
合并剩余尾部:跳出时有两种情况,即L1遍历完或L2遍历完
时间复杂度为:Ο(n+m)
剑指 Offer 25合并两个排序的链表
-
将两个非递减的有序链表合并为一个非递增的有序链表,要求结果链表仍使用原来的存储空间,允许有重复。与上题一样为了更容易处理边界采用哨兵且要求空间复杂度改为Ο(1)
LIST-Turn-ORDERLY-MARGE(L1,L2)
1 new L3.nil
2 p1=L1.nil.next
3 p2=L2.nil.next
4 while p1!=L1.nil and p2!=L2.nil.next
5 if(p1.key<=p2.key>)=p2.key>
6 temp=p1.next
7 p1.next=L3.nil.next
8 L3.nil.next=p1
9 p1=temp
10 if(p2.key< p1.key)
11 temp=p2.next
12 p2.next=L3.nil.next
13 L3.nil.next=p2
14 p2=temp
15 while p1!=L1.nil
16 temp=p1.next
17 p1.next=L3.nil.next
18 L3.nil.next=p1
19 p1=temp
20 while p2!=L2.nil
21 temp=p2.next
22 p2.next=L3.nil.next
23 L3.nil.next=p2
24 p2=temp
算法流程:
初始化:哨兵L3.nil
循环合并:(在使用头插法进行插入时记得保留待插入结点的next指针,不然会破坏链表的结构)
- 当p1.key<=p2.key时,在L3.nil与L3.nil.next(上一个较小的元素)之间插入p1< li>
- 当p2.key< p1.key时,在L3.nil与L3.nil.next(上一个较小的元素)之间插入p2
=p2.key时,在L3.nil与L3.nil.next(上一个较小的元素)之间插入p1<>
合并剩余尾部:跳出时有两种情况,即L1遍历完或L2遍历完。
1 L1没有遍历完,继续进行遍历进行头插.
2 L2没有遍历完,继续进行遍历进行头插.
最后得到一个非递增的有序链表(也就是递减的链表)
Author:
xiao chong
Permalink:
http://example.com/2021/09/17/List1-2/
License:
Copyright (c) 2019 CC-BY-NC-4.0 LICENSE
Slogan:
Do you believe in DESTINY?