上篇文章:力扣--分治(归并排序)算法题II:计算右侧小于当前元素的个数,翻转对(无痛通关困难题)
目录
1.两数相加
https://leetcode.cn/problems/add-two-numbers/description/


理解题意
在没有前置0并且是非空链表的前提下,将每个数字逆序存储,再将两个链表中的数字逆序相加,返回正常值的逆序。
算法原理
模拟两数相加的过程即可。逆序有助于我们完成代码。
先设计一个头结点,再创建一个变量用于存储进位值,再依次将每个链表节点中的数字通过尾插的方式进行相加即可。
代码
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) // t不为0时,证明还有进位
{
if(cur1)
{
t += cur1->val;
cur1 = cur1->next;
}
if(cur2)
{
t += cur2->val;
cur2 = cur2->next;
}
prev->next = new ListNode(t % 10);
prev = prev->next;
t /= 10;
}
prev = newhead->next;
delete newhead;
return prev;
}
};
2.两两交换链表中的节点
https://leetcode.cn/problems/swap-nodes-in-pairs/

理解题意
在不改变节点内部的值的情况下,进行链表中的两两交换。
算法原理
先创建一个空的头结点,这样方便后续的记录与交换。

之后的代码如上图所示,将prev的next与next相连,cur的next与nnext相连,如此重复,并且注意截至条件为next为空。
代码
方式一:递归
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(head == nullptr || head->next == nullptr) return head;
auto tmp = swapPairs(head->next->next);
auto ret = head->next;
head->next->next = head;
head->next = tmp;
return ret;
}
};
方式二:循环
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* newhead = new ListNode(0);
newhead->next = head;
ListNode* prev = newhead;
while(prev->next != nullptr && prev->next->next != nullptr)
{
ListNode* cur = prev->next;
ListNode* next = cur->next;
ListNode* nnext = next->next;
prev->next = next;
next->next = cur;
cur->next = nnext;
prev = cur;
}
prev = newhead->next;
delete newhead;
return prev;
}
};
3.重排链表
https://leetcode.cn/problems/reorder-list/description/

理解题意
进行实际的节点交换,给定单链表,将最后一个链表尾插在第一个链表之后,依次类推。
算法原理
使用快慢双指针找链表中点,再通过头插法进行对后半段链表逆序,最终合并两链表即可。
由于链表有奇偶数之分,根据画图分析,将slow->next往后的链表节点进行逆序更方便,见下图:



代码
class Solution {
public:
void reorderList(ListNode* head) {
if(head == nullptr || head->next == nullptr || head->next->next == nullptr) return;
// 快慢双指针找中间节点
ListNode* slow = head, *fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
// 双指针将后半段指针逆序(头插法)
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;
}
// 双指针合并两段指针
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;
}
};
本章完。