自己千辛万苦写出的循环:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1 == nullptr) return pHead2;
if(pHead2 == nullptr) return pHead1;
ListNode * pHeadNew = new ListNode(0);
ListNode * pNode = pHeadNew;
ListNode * pNode1 = pHead1, * pNode2 = pHead2;
if(pHead1->val <= pHead2->val) {
pNode->val = pHead1->val;
pNode1 = pHead1->next;
} else {
pNode->val = pHead2->val;
pNode2 = pHead2->next;
}
while(pNode1 != nullptr && pNode2 != nullptr) {
pNode->next = new ListNode(0);
pNode = pNode->next;
if(pNode1->val <= pNode2->val) {
pNode->val = pNode1->val;
pNode1 = pNode1->next;
} else {
pNode->val = pNode2->val;
pNode2 = pNode2->next;
}
}
ListNode * pRemain = nullptr;
if(pNode1 != nullptr) {
pRemain = pNode1;
} else if(pNode2 != nullptr) {
pRemain = pNode2;
}
if(pRemain != nullptr) {
while(pRemain != nullptr) {
pNode->next = new ListNode(0);
pNode = pNode->next;
pNode->val = pRemain->val;
pRemain = pRemain->next;
}
}
// pNode->next = nullptr;
return pHeadNew;
}
};
居然写了50+行,真是没sei了。
刚开始好几次没过,主要是因为struct新建节点不熟悉,用它的构造函数却不想有初始值,导致参数类型错误。再次提醒自己:c++中函数的参数及返回值的类型、顺序非常严格,一丝不苟。
编译通过以后又case通过率0%,原因是边界没处理好。刚开始写的是一个节点赋完值后,就new一个节点,再下一轮while循环,这样是不对的,因为不一定有下一个节点了。应该先检测有没有下一个节点再new。 所以改变new的位置后,发现第一个节点已经有了,就不用new了。但是再while循环中加if语句达不到目的,所以手动处理了第一个节点。以上就是我用循环写的全部过程,虽然代码量长,但也算逻辑清晰&无冗余。
然后参考了书上它说用递归!对啊!“这是典型的递归”!
于是自己又写递归,改进后的不改变原链表的答案如下:
// 递归解法
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1 == nullptr) return pHead2;
if(pHead2 == nullptr) return pHead1;
ListNode* pHeadNew = new ListNode(0);
if(pHead1->val <= pHead2->val) {
pHeadNew->val = pHead1->val;
pHeadNew->next = Merge(pHead1->next, pHead2);
} else {
pHeadNew->val = pHead2->val;
pHeadNew->next = Merge(pHead1, pHead2->next);
}
return pHeadNew;
}
};
这次代码简洁了不少。但是又看书上,发现它没有新建节点,但是改变了原链表,相当于把原链表中的指针擦除,按要求重新串起来了。我觉得呢,这种方法不一定就是好的,具体要看面试官的要求,有没有要求原链表保留,有没有要求不用额外的空间呢。所以,递归+不用额外空间的解法如下:
// 递归解法 不需要创建新节点,改变原链表指针即可
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1 == nullptr) return pHead2;
if(pHead2 == nullptr) return pHead1;
ListNode * pHeadNew;
if(pHead1->val <= pHead2->val) {
pHeadNew = pHead1;
pHeadNew->next = Merge(pHead1->next, pHead2);
} else {
pHeadNew = pHead2;
pHeadNew->next = Merge(pHead1, pHead2->next);
}
return pHeadNew;
}
};
反思:看到比较繁杂的题目,想想能不能用递归:
不用递归的情况:递归有大量重复计算,栈深度大
用递归:操作重复,但递归计算不重复。
啥也不说了,我要返回去把上一道题反转链表用递归做一下去 ~