目录
一、两数相加
1. 题目链接:2. 两数相加
2. 题目描述:
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
输入:l1 = [2,4,3], l2 = [5,6,4] 输出:[7,0,8] 解释:342 + 465 = 807.示例 2:
输入:l1 = [0], l2 = [0] 输出:[0]示例 3:
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9] 输出:[8,9,9,9,0,0,0,1]
3. 解法
🎈算法思路:
两个链表都是逆序存储数字的,即两个链表的个位数、十位数等都已经对应,可以直接相加。
在相加过程中,我们要注意是否产生进位,产生进位时需要将进位和链表数字一同相加。如果产生进位的位置在链表尾部,即答案位数比原链表位数长一位,还需要再 new 一个结点储存最高位。
🎈算法代码:
/**
* 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* addTwoNumbers(ListNode* l1, ListNode* l2)
{
ListNode* cur1 = l1, *cur2 = l2;
ListNode* newhead = new ListNode(0);// 创建虚拟头节点
ListNode* prev = newhead;// 尾指针
int t = 0;
while(cur1 || cur2 || t)
{
// 1.先加上第一个链表
if(cur1)
{
t += cur1->val;
cur1 = cur1->next;
}
// 2.再加上第二个链表
if(cur2)
{
t += cur2->val;
cur2 = cur2->next;
}
prev->next = new ListNode(t % 10);
prev = prev->next;
t = t / 10;
}
prev = newhead->next;
delete newhead;
return prev;
}
};
二、两两交换链表中的节点
1. 题目链接:24. 两两交换链表中的节点
2. 题目描述:
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例 1:
输入:head = [1,2,3,4] 输出:[2,1,4,3]示例 2:
输入:head = [] 输出:[]示例 3:
输入:head = [1] 输出:[1]提示:
- 链表中节点的数目在范围
[0, 100]
内0 <= Node.val <= 100
3. 解法
🎈算法思路:
画图画图画图,重要的事情说三遍!!!
🎈算法代码:
- 循环 + 迭代
/**
* 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* swapPairs(ListNode* head)
{
if(head == nullptr || head->next == nullptr) return head;
ListNode* newhead = new ListNode(0);// 定义虚拟头节点
newhead->next = head;
ListNode* prev = newhead, *cur = prev->next, *next = cur->next, *nnext = next->next;
while(cur && next)
{
// 交换节点
prev->next = next;
next->next = cur;
cur->next = nnext;
// 修改指针
prev = cur;
cur = nnext;
if(cur) next = cur->next;
if(next) nnext = next->next;
}
cur = newhead->next;
delete newhead;
return cur;
}
};
- 递归
/**
* 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* swapPairs(ListNode* head)
{
if(head == nullptr || head->next == nullptr) return head;
ListNode* newhead = head->next;
head->next = swapPairs(newhead->next);
newhead->next = head;
return newhead;
}
};
三、重排链表
1. 题目链接:143. 重排链表
2. 题目描述:
给定一个单链表
L
的头节点head
,单链表L
表示为:L0 → L1 → … → Ln - 1 → Ln请将其重新排列后变为:
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
输入:head = [1,2,3,4] 输出:[1,4,2,3]示例 2:
输入:head = [1,2,3,4,5] 输出:[1,5,2,4,3]提示:
- 链表的长度范围为
[1, 5 * 104]
1 <= node.val <= 1000
3. 解法
🎈算法思路:
模拟:
- 找到链表的中间节点(快慢双指针)
- 中间部分往后的逆序(头插法)
- 合并两个链表
🎈算法代码:
/**
* 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) {
// 处理边界情况
if (head == nullptr || head->next == nullptr ||
head->next->next == nullptr)
return;
// 1.找到中间节点
ListNode *slow = head, *fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
// 2.将链表的后半部分进行逆转 -- 头插法
ListNode* head2 = new ListNode(0);
ListNode* cur = slow->next;
slow->next = nullptr;
while (cur) {
ListNode* next = cur->next;
cur->next = head2->next;
head2->next = cur;
cur = next;
}
// 3.合并两个链表 -- 双指针
ListNode* ret = new ListNode(0);
ListNode* prev = ret;
ListNode *cur1 = head, *cur2 = head2->next;
while (cur1) {
// 先放第一个链表
prev->next = cur1;
cur1 = cur1->next;
prev = prev->next;
// 再放第二个链表
if (cur2) {
prev->next = cur2;
cur2 = cur2->next;
prev = prev->next;
}
}
delete head2;
delete ret;
}
};