目录
学习计划链接
题目解析
1. 剑指 Offer II 024. 反转链表
1) 问题描述
2) 思路分析
- 法1:使用递归;
- 法2:三指针
① 用prev、cur、next指向三个连续的节点,用于更改连接关系
② 迭代更改cur的next指向,直到最后更改到链表结束,更新头节点。
3) leetcode链接
4) 代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
//法1:使用递归;
//法2:三指针
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==nullptr||head->next==nullptr){
return head;
}
ListNode *cur = reverseList(head->next);
head->next->next=head;
head->next=nullptr;
return cur;
}
ListNode* reverseList1(ListNode* head) {
if(head==nullptr||head->next==nullptr)
{
return head;
}
//用prev、cur、next指向三个连续的节点,用于更改连接关系
ListNode *prev=nullptr;
ListNode *cur=head;
ListNode *next=head->next;
while(cur)
{
cur->next=prev;
prev=cur;
cur=next;
//判断当前更改关系是否为最后一个
if(next)
next=next->next;
else
head=prev;
}
return head;
}
};
2. 剑指 Offer II 025. 链表中的两数相加
1) 问题描述
2) 思路分析
逆置链表(由于加法运算是从低位到高位相加,故逆置链表,模拟加法,每一位的值等于sum%10 ———— sum=b1+b2+carry——其中b1,b2分别为r1、r2对应为的数值、carry为低位向上的进位,本位向上一高位的进位为sum/10)
- 逆置两链表;
- 求和,并插入新链表;
- 逆置新链表得结果。
3) leetcode链接
4) 代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* l)
{
if(l==nullptr || l->next==nullptr)
return l;
ListNode *prev=nullptr;
ListNode *cur=l;
ListNode *next=l->next;
while(cur)
{
cur->next=prev;
prev=cur;
cur=next;
if(next)
{
next=next->next;
}
}
return prev;
}
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
//1.逆置链表。(由于加法运算是从低位到高位相加,故逆置链表,模拟加法,每一位的值等于sum%10 ———— sum=b1+b2+carry——其中b1,b2分别为r1、r2对应为的数值、carry为低位向上的进位,本位向上一高位的进位为sum/10)
ListNode *r1 = reverseList(l1);
ListNode *r2 = reverseList(l2);
int sum=0;
int carry=0;
ListNode *rhead = nullptr; //逆置两链表之后的结果。
ListNode *rtail = nullptr; //指向rhead的尾节点,方便尾插
while(r1||r2)
{
//1. 取r1和r2对应值
int n1=0;
if(r1)
{
n1= r1->val;
r1=r1->next;
}
int n2=0;
if(r2)
{
n2=r2->val;
r2=r2->next;
}
//2.求两数之和。
sum=n1+n2+carry;
//3.得出当前位的进位和当前位的值。判断当前节点是否为链表第一个节点,若为第一个,则更新头指针;否则,将当前位的值插入rhead尾部中,并更新尾节点。
carry=sum/10;
ListNode *newNode=new ListNode(sum%10);
if(rhead==nullptr) //判断当前节点是否为链表第一个节点,若为第一个,则更新头指针
{
rhead=newNode;
}
else
rtail->next=newNode;
rtail=newNode;
}
//遍历完链表,若进位非0,则向链表尾部再插入一个值为进位的节点。
if(carry)
{
ListNode *newNode=new ListNode(carry);
rtail->next=newNode;
}
//逆置链表,即得到结果。
ListNode* head = reverseList(rhead);
return head;
}
//结果超过long long范围,溢出
// long long toNumber(ListNode *l)
// {
// ListNode *cur=l;
// long long ret=0;
// while(cur)
// {
// ret=ret*10+cur->val;
// cur=cur->next;
// }
// return ret;
// }
// ListNode* addTwoNumbers1(ListNode* l1, ListNode* l2) {
// if(l1->val==0 &&l2->val==0)
// return l2;
// //1.将两个链表转为数字并相加
// long long n1=toNumber(l1);
// long long n2=toNumber(l2);
// long long add=n1+n2;
// //2.将结果连起来
// ListNode *nextNode=nullptr;
// long long tmp=add;
// ListNode *newNode=nullptr;
// while(tmp)
// {
// newNode=new ListNode(tmp%10);
// newNode->next=nextNode;
// nextNode=newNode;
// tmp/=10;
// }
// return newNode;
// }
};
3. 剑指 Offer II 026. 重排链表
1) 问题描述
2) 思路分析
队列和栈辅助实现
- 记录链表个数,前n/2个插入队列中,后n/2个插入栈中。
- 如果当前位置为链表偶数位,则从队列中取数据,否则,从栈中取数据。
注意:尾指针的next一定要置为空,否则,会出现带环链表
3) leetcode链接
4) 代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
void reorderList(ListNode* head) {
queue<ListNode *> q;
stack<ListNode *> s;
int i=0;
int n=0;
//1. 记录链表个数,前n/2个插入队列中,后n/2个插入栈中。
ListNode *cur=head;
while(cur)
{
n++;
cur = cur->next;
}
cur=head;
while((n%2==0 && i<n/2)||(n%2!=0 && i<n/2+1))
{
i++;
q.push(cur);
cur=cur->next;
}
while(i<n)
{
s.push(cur);
cur=cur->next;
i++;
}
ListNode *tail=nullptr; //记录新链表尾部
//ListNode *newhead=nullptr; //记录新链表头部
head=nullptr;
i=0;
//如果当前位置为链表偶数位,则从队列中取数据,否则,从栈中取数据。
while(!q.empty()||!s.empty())
{
if(i%2==0)
{
ListNode *x=q.front();
q.pop();
if(head==nullptr)
{
head=x;
}
else
{
tail->next=x;
}
tail=x;
}
else
{
ListNode *x=s.top();
s.pop();
tail->next=x;
tail=x;
}
i++;
}
tail->next=nullptr; //注意尾指针的next一定要置为空,否则,会出现带环链表
//head=newhead;
}
};