链表交换
已知一个正整数序列,序列元素个数未知,但至少有两个元素,你的任务是建立一个单链表用于存储这个正整数序列。然后实现交换此链表中任意指定的两段,第一段为[s1,t1],第二段[s2,t2]。s1、t1、s2、t2代表链表的第几个节点,且满足s1<=t1,s2<=t2,t1<s2,s2一定小于等于链表节点的总个数。正整数的输入用-1作为结束标志,注意-1不算这个正整数序列中的元素(不要统计-1)。最后将链表的全部节点释放。
输入
输入一个正整数序列,以输入“-1”结束,序列中元素个数未知,但输入“-1”前至少输入两个正整数。然后是四个整数,即为s1、t1、s2、t2。
输出
经过处理后的新链表,每个元素后有一个空格,注意最后一个元素后只有换行符。
数据最多的测试用例节点数在100这个数量级,所有整数可以用int型存储。
请注意输入输出格式。
样例输入 Copy
1 2 3 4 5 6 7 8 9 10 -1
1 1 4 7
样例输出
The new list is:4 5 6 7 2 3 1 8 9 10
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
class Solution {
public:
ListNode* findnode(ListNode *head,int x)
{
ListNode* p=head;
for(int i=0;i<x;i++) p=p->next;
return p;
}
ListNode* swapSegments(ListNode* head, int s1, int t1, int s2, int t2) {
ListNode* dummy = new ListNode(0);
dummy->next = head;
ListNode* pre = dummy;
ListNode* pre1=findnode(dummy,s1-1);//第一段的前一个节点
ListNode* pre2=findnode(dummy,s2-1);//第二段的前一个节点
ListNode* end1=findnode(dummy,t1);//第一段的尾节点
ListNode* end2=findnode(dummy,t2);//第二段的尾节点
// // 找到第一个段的前一个节点 pre1 和第二个段的前一个节点 pre2
// for (int i = 0; i < s1 - 1; ++i) {
// pre = pre->next;
// }
// ListNode* pre1 = pre;
// for (int i = 0; i < t1 - s1 + 1; ++i) {
// pre = pre->next;
// }
// ListNode* end1 = pre;
// for (int i = 0; i < s2 - t1 - 1; ++i) {
// pre = pre->next;
// }
// ListNode* pre2 = pre;
// for (int i = 0; i < t2 - s2 + 1; ++i) {
// pre = pre->next;
// }
// ListNode* end2 = pre;
ListNode* start1 = pre1->next;//第一段的头节点
ListNode* start2 = pre2->next;//第二段的头节点
ListNode* post1 = end1->next;//第一段后的下一个节点
ListNode* post2 = end2->next;//第二段后的下一个节点
if(s2-t1!=1){
pre1->next = start2;
end2->next = post1;
pre2->next = start1;
end1->next = post2;
}
else{
end2->next=start1;
end1->next=post2;
pre1->next=start2;
}
return dummy->next;
}
void printLinkedList(ListNode* head) {
while (head) {
cout << head->val;
if (head->next) {
cout << " ";
}
head = head->next;
}
}
void releaseLinkedList(ListNode* head) {
while (head) {
ListNode* temp = head;
head = head->next;
delete temp;
}
}
};
int main() {
Solution solution;
int num;
ListNode* dummy = new ListNode(0);
ListNode* current = dummy;
while (true) {
cin >> num;
if (num == -1) {
break;
}
current->next = new ListNode(num);
current = current->next;
//current->next=NULL;
}
ListNode* head = dummy->next;
delete dummy;
int s1, t1, s2, t2;
cin >> s1 >> t1 >> s2 >> t2;
head = solution.swapSegments(head, s1, t1, s2, t2);
cout << "The new list is:";
solution.printLinkedList(head);
solution.releaseLinkedList(head);
return 0;
}
注意当s2=t1+1时是特殊情况,end1和pre2两节点重合,需要特殊讨论:先将第一段接到第二段的末尾,然后在讲整个一段接入原链表
可以使用findnode函数来简化记录节点的过程
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理