开宗明义:本系列基于牛客网剑指offer,刷题小白,一天两道我快乐!旨在理解和交流,重在记录,望各位大牛指点!
牛客网-剑指offer
文章目录
1、反转链表
描述:输入一个链表,反转链表后,输出新链表的表头。
思路1:见代码注释;
测试代码:
#include <algorithm>
struct ListNode {
int val;
ListNode *next;
ListNode(int x) :val(x), next(nullptr) {}
};
class Solution {
public:
ListNode* ReverList(ListNode* pHead) {
//程序的鲁棒性
if (pHead == NULL)
return NULL;
//
ListNode* pNode = pHead; //当前头指针
ListNode* pReverseHead = NULL; //新链表的头指针
ListNode* pPrev = NULL; //当前指针的前一个节点
while (pNode!=NULL){ //当前结点不为空时才执行
ListNode* pNext = pNode->next; //链断开之前一定要保存断开位置后边的结点
if (pNext == NULL) {
pReverseHead = pNode; //当pNext为空时,说明当时结点为尾节点,也就是新链表的表头
}
pNode->next = pPrev; //只占反转
pPrev = pNode; //当前结点给上一个
pNode = pNext; //下一个给现在的
}
return pReverseHead;
}
};
思路2:递归方法
利用递归走到链表的末端,然后再更新每一个 node 的 next 值 ,实现链表的反转。而 newhead 的值没有发生改变,为该链表的最后一个结点,所以,反转后,我们可以得到新链表的 head。
测试代码:
#include <algorithm>
struct ListNode {
int val;
ListNode *next;
ListNode(int x):val(x),next(NULL){}
};
class Solution {
ListNode* ReverseList(ListNode* pHead) {
//如果链表为空或者链表中只有一个元素
if (pHead == NULL || pHead->next == NULL)
return pHead;
//先反转后面的链表,走到链表的末端结点
ListNode* pReverseNode = ReverseList(pHead->next);
//再将当前结点设置为后面节点的后续结点
pHead->next->next = pHead; //当前结点设为后一个结点连接方向
pHead->next = NULL; //体会这边的空,很6!
return pReverseNode;
}
};
2、合并可以排序的两个链表
描述:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
思路1:加一个辅助表,做交换存储用。
测试代码:
#include <algorithm>
struct ListNode{
int val;
ListNode *next;
ListNode(int x):val(x),next(NULL){}
};
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
ListNode *p1, *p2, *p3, *pre1;
pre1 = p1 = pHead1;
p2 = pHead2;
while (p1 && p2) { //p1与p2都不为空
if (p1->val > p2->val) { //值,P1大于P2
pre1->next = p2;
p3 = p2->next;
p2->next = p1;
p2 = p3;
}
//P1小于P2
pre1 = p1;
p1 = p1->next;
}
if (p2)
pre1->next = p2;
return pHead1;
}
};