(3条消息) 力扣题库--2.两数相加 c++解法_dreamxian的博客-CSDN博客
一、LeetCode21合并两个有序链表
题目描述:将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
解法1迭代: 设一个虚拟头结点;比较两个链表的头结点,将数值小的(list1)放到虚拟指针后面;虚拟指针和list1的指针向后移;继续比较,直到某个链表为空,将另一个链表加入到虚拟指针后。
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode *head=new ListNode(0);//虚拟头结点
ListNode *p=head;//虚拟指针
while(list1&&list2)//有链表为空时退出循环
{
if(list1->val<=list2->val)
{
p->next=list1;//将数值小的节点接到虚拟指针处
list1=list1->next;//继续遍历该节点的下一个节点
}else
{
p->next=list2;
list2=list2->next;
}
p=p->next;//加进了一个节点,虚拟指针后移
}
if(!list1)p->next=list2;//将未遍历完的链表直接加到虚拟链表后面
else p->next=list1;
return head->next;//返回时抛掉虚拟头结点
}
};
解法2递归: 终止条件:其中一个参数链表为空,返回另一个链表; 比较两个链表,将数值小的节点返回,该链表的剩下节点和另一个链表再次进行合并;返回的节点接到现有节点的后面。
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
//其中一个为空,另一个直接返回
if(!list1)return list2;
if(!list2)return list1;
if(list1->val<=list2->val)
{
//保留两个链表中的较小节点,剩下的和另一条链表继续合并
list1->next=mergeTwoLists(list1->next,list2);
//返回每一层的最小节点(接到上一层的后面)
return list1;
}
else
{
list2->next=mergeTwoLists(list1,list2->next);
return list2;
}
}
};
二、LeetCode24交换相邻节点
题目描述:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例:
解法:
递归:每两个节点分为一组,每一层将这两个节点交换;返回交换后的排在前面的节点,接到上一层末尾结点的后面。
代码:
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
//若无节点或只有一个节点;不需交换
if(head==nullptr||head->next==nullptr)return head;
//保存2节点的地址
ListNode* p=head->next;
//1的后面接交换完成的3,4节点
head->next=swapPairs(p->next);
//2放在1前面
p->next=head;
//返回2(交换后的头结点)
return p;
}
};
三、LeetCode83删除重复节点
题目描述:给定一个已排序的链表的头 head
, 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
示例:
解法:定义一个指针p,指向链表的头节点;判断p的元素和下一个节点元素是否相等,相等则删掉下一个节点后重新判断;不相等则p后移。
代码:
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode* p=head;
//p位置和p的下一个位置不为空
while(p&&p->next)
{
//p的数值和p的下一个节点的数值相等时,删掉p的下一个节点
if(p->val==p->next->val)
{
ListNode* pp=p->next;
p->next=pp->next;
delete(pp);
pp=nullptr;
//删完进入下一个循环,再次判断p和p.next的数值
continue;
}
//p和p.next数值不相等,p后移
p=p->next;
}
return head;
}
};
四、LeetCode328分离奇偶链表
题目描述:给定单链表的头节点 head ,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表。
第一个节点的索引被认为是 奇数 , 第二个节点的索引为 偶数 ,以此类推。
请注意,偶数组和奇数组内部的相对顺序应该与输入时保持一致。
你必须在 O(1) 的额外空间复杂度和 O(n) 的时间复杂度下解决这个问题。
示例:
解法:链表的头结点为奇链表的头,头结点的下一个节点为偶链表的头;设两个变量分别指向奇偶链表的头;遍历链表,将奇数位的节点接到奇链表的后面,偶数位的节点接到偶链表的后面;最后把偶链表接到奇链表后面。
代码:
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
//链表为空或只有一个节点,返回链表
if(!head||!head->next)return head;
//nehead是偶链表的头
ListNode* nehead=head->next;
//用于遍历的指针
ListNode* one=head,*two=nehead;
//用于判断当前遍历到链表的奇数位还是偶数位
int a=1;
while(one&&two)
{
if(a)//奇数位
{
one->next=two->next;
one=one->next?one->next:one;
a--;
}
else//偶数位
{
two->next=one->next;
two=two->next;
a++;
}
}
one->next=nehead;
return head;
}
};
五、LeetCode19删除倒数第n个节点
题目描述:给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
示例:
解法:
法1:快慢指针:快指针比慢指针先走n步,当快指针的下一个节点是空时,慢指针的下一个节点就是待删除的节点。
法2:先遍历一次链表得出链表长度L,再遍历一次,删除第L-n+1个节点。
法3:入栈出栈
法1代码:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
//定义一个哑结点
ListNode* dm=new ListNode(0,head);
//定义快慢指针
ListNode* one=dm,*two=dm;
//快指针先走n步
while(n--)
{
one=one->next;
}
//快指针的下一个节点不为空时,两个指针向后移动
while(one->next)
{
one=one->next;
two=two->next;
}
//快指针的下一个节点为空,删除慢指针的下一个节点
two->next=two->next->next;
//返回哑结点的下一个节点(避免删除头结点或链表为空)
return dm->next;
}
};