传送门:
https://leetcode.cn/problems/merge-two-sorted-lists/description/
题目要求;
给你两个有序的链表,将这两个链表按照从小到大的关系,合并两个链表为一个新的链表。
解:
看到两个合成一个的,我们就可以利用二路归并的思想来解决,这道题也是如此。
关于顺序表和链表的二路归并可以看我之前发表的一篇博客:
顺序表和单链表的二路归并问题
我们本节主要讨论如何利用递归来求解合并两个单链表的问题?
设计递归:
过程:以1 2 4 — 1 3 4两个链表为例子。
代码示例:
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
if (list1==nullptr)
{
return list2;
}
if (list2==nullptr)
{
return list1;
}
//每一次找到节点值小的链表进入递归
if (list1->val>=list2->val)
{
list2->next=mergeTwoLists(list1,list2->next);
return list2;
}
list1->next=mergeTwoLists(list1->next,list2);
return list1;
}
};
传送门:
https://leetcode.cn/problems/reverse-linked-list/description/
题目要求:把一个单链表的所有节点原地翻转。
我们可以利用迭代来求解这个问题:
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pTemp=nullptr;
ListNode* pCur=head;
//前一个节点置空,可以在第一步就断开链表
ListNode* pPre=nullptr;
while (pCur)
{
//1. 保存下一个节点位置
pTemp=pCur->next;
//2. 当前节点指向前一个节点
pCur->next=pPre;
//3. 前一个节点指向当前节点
pPre=pCur;
//4. 继续遍历下一个节点
pCur=pTemp;
}
return pPre;
}
};
迭代的方式很简单,自己画图就可以理解,重点要理解第二步与第三步。
接下来我们看递归:
设定一个pNew节点为我们的结果,最后返回pNew即可。
递去: 当节点为空或者next为空时,返回此节点,
代码如下:
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (head==nullptr || head->next==nullptr)
{
return head;
}
ListNode* pNew=reverseList(head->next);
head->next->next=head;
head->next=nullptr;
return pNew;
}
};
传送门:
https://leetcode.cn/problems/remove-nodes-from-linked-list/
题目要求:
给你一个链表的头节点 head 。
对于列表中的每个节点 node ,如果其右侧存在一个具有 严格更大 值的节点,则移除 node 。
返回修改后链表的头节点 head 。
这道题利用非递归可以更加有效,非递归的空间复杂度是O(1),利用非递归可以首先将链表逆转,然后依次遍历每个节点,删除,最后再翻转回来。这里不再多说。
递归过程:
class Solution {
public:
ListNode* removeNodes(ListNode* head) {
if (head==nullptr || head->next==nullptr)
{
return head;
}
ListNode* pNew=removeNodes(head->next);
if (pNew->val>head->val)
{
return pNew;
}
head->next=pNew;
return head;
}
};