剑指offer系列10:合并两个排序的链表
我拿到这个题的时候举的例子是链表1:1、3、5、7和链表2:2、4、6、8.我的思路是以:1为基础,将表2的每个结点插入表1。也就是说我一次性是要给新建立的链表中加入两个元素,分别是两个原始链表的头结点。这个思路我做了半天头脑一片混乱,中间指针实在不知道怎么弄了。于是我去睡了一觉,哈哈,我大概是这个世界上最会逃避的人了……
看了答案使用了递归的方法,其实我做的时候我有想到要用递归,但是没用的原因是我一般写代码不喜欢用递归,原因有两个,一个是递归容易死循环,一个是递归的复杂度太高。但这道题真的太适合用递归了,用递归做太简单了。而且在排序的时候,答案的方法是没次只排一个数,然后把剩下的两个长短也许不等的链表再拿去递归调用。看了答案思路瞬间清晰了,代码很快就写了:
1 #include<iostream> 2 using namespace std; 3 struct ListNode { 4 int val; 5 struct ListNode *next; 6 ListNode(){} 7 }; 8 class Solution { 9 public: 10 ListNode* Merge(ListNode* pHead1, ListNode* pHead2) 11 { 12 if (pHead1 == NULL)//这个特殊数据处理也很全面 13 return pHead2; 14 else 15 if (pHead2 == NULL) 16 return pHead1; 17 ListNode*p = NULL; 18 if (pHead1->val < pHead2->val)//如果第一个链表的数据更小,则把第一个链表的第一个结点拿出来作为新的链表,把第一个链表的剩下加点和链表二放进递归函数继续算 19 { 20 p = pHead1; 21 p->next = Merge(pHead1->next, pHead2); 22 } 23 else//反之同理 24 { 25 p = pHead2; 26 p->next = Merge(pHead1, pHead2->next); 27 } 28 return p; 29 } 30 }; 31 int main() 32 { 33 Solution so; 34 struct ListNode list[4]; 35 list[0].val = 1; 36 list[0].next = &list[1]; 37 list[1].val = 3; 38 list[1].next = &list[2]; 39 list[2].val = 5; 40 list[2].next = &list[3]; 41 list[3].val = 7; 42 list[3].next = NULL; 43 struct ListNode list1[4]; 44 list1[0].val = 2; 45 list1[0].next = &list1[1]; 46 list1[1].val = 4; 47 list1[1].next = &list1[2]; 48 list1[2].val = 6; 49 list1[2].next = &list1[3]; 50 list1[3].val = 8; 51 list1[3].next = NULL; 52 ListNode *re = so.Merge(list,list1); 53 while(re!=NULL) 54 { 55 cout << re->val << endl; 56 re= re->next; 57 } 58 return 0; 59 }
总结一下今天这道题:
1.遇见任何一个题目不要死脑筋的一个劲的想,一个题目不值得你费那么长时间,如果一道编程题1个小时没做出来,快点去看答案。剑指offer上的题目难度不是很大,尽量提高效率去做更多的题,而不是跟一个题死较劲。
2.遇见复杂的问题学会去分解问题,比如这个题。在我思路不通的时候我为什么还要一次性拿出两个结点去排序呢?完全可以一个一个来这样不就是标准答案了吗。这招在算法上讲叫分治法。
3.乐观乐观乐观,天生我材必有用。
4.今天有点感性,emmmmmm,虽然是工科生,但是我想随心随性的生活。
最后,我在博客园上发的博客超过两位数啦,开心。