剑指Offer(十六)——合并两个排序的链表(非递归有图)

题目描述:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

设计思想:把一个链表pHead2的所有元素逐个插入到另一链表pHead1中。

最外层是一个while循环遍历pHead2的所有节点。

 
推荐直接阅读一开始的四张图片,了解一般情况下的插入

1.先考虑一般情况:

设定node1为pHead1当前节点,node2为pHead2当前节点。

情况一:若node1的val  小于等于  node2的val

 此时又有两种情况

  a.node2在node1和temp1之间

对于该情况我们相当于node1后尾部插入节点node2先转移节点完后要调整新的指向。所以转移节点指向前要保存node1->next和node2->next。

具体代码:

 1  //保存下一节点
 2 temp1 = node1->next;
 3 temp2 = node2->next;
 4 //转移节点指向
 5 node1->next = node2;
 6 node2->next = temp1;
 7  //更新变量
 8 node1 = temp1;
 9 pre1 = node2;
10 node2 = temp2;
View Code

b.node2大于node1也大于node1的下一节点

 

 

 此时我们就要对上面的代码进行if判断时候temp1小于node2进入到本情况

//新加判断,我们要找到node1 的下一节点比node2大的位置。找到后就回到了尾部插入的情况。                          (若找到phead1的结尾也没找到,下面再讨论。)

 1  //保存下一节点
 2 temp1 = node1->next;
 3 temp2 = node2->next;
 4 
 5 //新加判断,我们要找到node1 的下一节点比node2大的位置
 6 while (temp1 != NULL && temp1->val <= node2->val)
 7 {
 8     node1 = temp1;
 9     temp1 = temp1->next;
10 }
11 
12 //转移节点指向
13 node1->next = node2;
14 node2->next = temp1;
15 //更新变量
16 node1 = temp1;
17 pre1 = node2;
18 node2 = temp2;
19                 
View Code

 

 

若node1的val  大于  node2的val

头部插入,需要用到node1的前一节点pre。

 1 if (node1->val <= node2->val)
 2 {
 3 temp1 = node1->next;
 4 temp2 = node2->next;
 5 
 6 //新增一个找到满足node2位于temp1和node1之间的状态
 7 while (temp1 != NULL && temp1->val <= node2->val)
 8 {
 9 node1 = temp1;
10 temp1 = temp1->next;
11 }
12 
13 node1->next = node2;
14 node2->next = temp1;
15 
16 node1 = temp1;
17 pre1 = node2;
18 node2 = temp2;
View Code

 

 

2.针对特殊情况的考虑:

情况一可能出现问题:pHead1到头了,node1->next是空。

保存完,在节点指向转移前,就是还没有下面的红线的时候,我们要判断temp1==NULL吗?

 

 

 若为空

此时我们pHead2的node2后的节点(包括node2)都大于pHead1的node1后的节点

因为pHead1遍历完最后一个元素值node1小于phead2的某一节点,那phead2之后的所有节点都大于phead1的最后一个节点了。

所以我们直接把所有node2后所有的节点都插入到node1后就ok了。直接node1-》next=node2;

 

 

 

 

 1 temp1 = node1->next;
 2 temp2 = node2->next;
 3 
 4 while (temp1 != NULL && temp1->val <= node2->val)
 5 {
 6     node1 = temp1;
 7     temp1 = temp1->next;
 8 }
 9 
10 
11 if (temp1 == NULL)
12 {
13     //链表pHead1完了,把所有的pHead2剩下节点尾部插入node1后面;
14     node1->next = node2;
15     break;
16 }    
17 node1->next = node2;
18 node2->next = temp1;
19 
20 node1 = temp1;
21 pre1 = node2;
22 node2 = temp2;
View Code

 

 

情况2可能出现问题:循环一开始node1=pHead1,pre=null;

 

 

此时我们要再节点指向修改前加判断

if(pre==NULL)

{node2->next=node1;pre=node2;pHead1=pre;}

具体代码:

 1  //保存信息
 2                 temp2=node2->next;
 3                 //修改节点指向       
 4                 if(pre1==NULL)
 5                 {
 6                     node2->next=node1;
 7                     pre1=node2;
 8                     pHead1=pre1;
 9                     
10                 }   
11                 else
12                 {
13                     //修改指向
14                     node2->next=node1;
15                     pre1->next=node2;
16                     //更新变量
17                     pre1=node2;
18                     node2=temp2;               
19                 }
View Code

 

 

3. 将上面代码写到while循环里即我们的最终代码

 1 /*
 2 struct ListNode {
 3 int val;
 4 struct ListNode *next;
 5 ListNode(int x) :
 6 val(x), next(NULL) {
 7 }
 8 };*/
 9 class Solution {
10 public:
11 static ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
12 {
13 //对特殊输入处理
14 if (pHead1 == NULL) { return pHead2; }
15 if (pHead2 == NULL) { return pHead1; }
16 
17 
18 //我们把pHead2插入到pHead1中
19 ListNode* node1 = pHead1, *node2 = pHead2;
20 ListNode* pre1 = NULL;//node1的前一节点,初始为空
21 ListNode* temp1, *temp2;
22 while (node2 != NULL)
23 {
24 if (node1->val <= node2->val)
25 {
26 //保存下一节点
27 temp1 = node1->next;
28 temp2 = node2->next;
29 while (temp1 != NULL && temp1->val <= node2->val)
30 {
31 node1 = temp1;
32 temp1 = temp1->next;
33 }
34 if (temp1 == NULL)
35 {
36 //链表pHead1完了,把所有的pHead2剩下节点尾部插入node1后面;
37 node1->next = node2;
38 break;
39 }    
40 //转移节点指向
41 node1->next = node2;
42 node2->next = temp1;
43 //更新变量
44 node1 = temp1;
45 pre1 = node2;
46 node2 = temp2;
47 
48 }
49 else
50 {
51 temp2 = node2->next;
52 node2->next = node1;
53 if (pre1 == NULL)
54 {
55 pre1 = node2;
56 }
57 else
58 {
59 pre1->next = node2;
60 pre1 = pre1->next;
61 node2 = temp2;
62 }
63 }
64 }
65 return pHead1;
66 
67 }
68 };
69 
70  
View Code

 

 

牛客网运行截图:

 

 


 

 PS:补充查到的一个递归解法感觉比较清晰

 

附上递归代码:这个不是C++应该是java或C#的代码

public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1 == null && list2 == null)
            return null;
        if(list1 == null)
            return list2;
        if(list2 == null)
            return list1;

        if(list1.val <= list2.val){
            list1.next = Merge(list1.next, list2);
            return list1;
        }else{
            list2.next = Merge(list1, list2.next);
            return list2;
        }
    }
}

  

 

 

 

 

 

 

 

---恢复内容结束---

posted @ 2019-10-16 19:51  碎梦残阳  阅读(106)  评论(0)    收藏  举报