链表交换

已知一个正整数序列,序列元素个数未知,但至少有两个元素,你的任务是建立一个单链表用于存储这个正整数序列。然后实现交换此链表中任意指定的两段,第一段为[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函数来简化记录节点的过程

posted @   是应该不应该  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示