Leetcode——Swapping Nodes in a Linked List

这篇博客介绍了如何在给定一个链表头结点和整数k的情况下,交换链表从头开始的第k个节点和从尾部开始的第k个节点的值。博主首先提供了一个解决方案,通过两次遍历找到目标节点并交换其值,然后展示了更简洁的代码实现,通过一次遍历同时定位到两个目标节点并交换它们的值。文章提供了多个测试样例以验证算法的正确性,并强调了代码的简洁性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述
  • You are given the head of a linked list, and an integer k.

  • Return the head of the linked list after swapping the values of the kth node from the beginning and the kth node from the end (the list is 1-indexed).

  • 现给出一个链表的头结点,以及一个整数k

  • 将从头往尾数第k个结点和从尾往头数第k个结点进行交换之后,返回新的链表的头节点

测试样例
  • example1
    在这里插入图片描述

  •   Input: head = [1,2,3,4,5], k = 2
      Output: [1,4,3,2,5]
    
  • example2

      Input: head = [7,9,6,6,7,8,3,0,9,5], k = 5
      Output: [7,9,6,6,8,7,3,0,9,5]
    
  • example3

      Input: head = [1], k = 1
      Output: [1]
    
  • example4

      Input: head = [1,2], k = 1
      Output: [2,1]
    
  • example5

      Input: head = [1,2,3], k = 2
      Output: [1,2,3]
    
  • constraints

    • The number of nodes in the list is n.
      1 <= k <= n <= 105
      0 <= Node.val <= 100
思路分析
  • 定位到某一个具体结点,就要找到对应的前一个结点,主要还是对于链表的查询遍历,整体的难度不大。

  • 根据之前那道题的经验,一次遍历就可以实现。传送门
    请添加图片描述

  • 主要是两种思路

    • 找到目标结点,单纯的交换值就行了
    • 找到目标节点的前一个结点,是交换节点
  • 我是通过交换目标结点的值实现的

具体实现
#include<iostream>
#include<sstream>
#include<vector>

using namespace std;

//定义轻型线性表
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 {
private:
    //头节点之前的结点
    ListNode priorHead;
public:

    /*
     * 描述:从末向头数第n个结点
     * 返回:返回当前结点的前一个结点的索引
     */
    ListNode* findLastNode(ListNode* head,int k){

        //初始化头节点之前的结点,将之指向指针
        priorHead.next = head;

        //初始化两个指针,left和right,left指向目标节点的前一个结点,right遍历向尾结点
        ListNode* left = &priorHead;
        ListNode* right = head;

        //right进行调整,调整间距
        for (int i = 1; i < k && right ; ++i) {
            right = right->next;
        }

        //如果是指向第一个结点,直接返回,right为空
        if(!right || !right->next){
            return left;
        }

        //将right和left同时向后进行遍历,知道最后一个结点
        while(right->next){
            right = right->next;
            left = left->next;
        }

        //调整之后,返回首结点
        return left;
    }

    /*
     * 描述:交换对应序列的两个结点,并将交换之后的链表返回
     * 参数:head是指头结点
     *      k是需要交换的结点的序列
     * 返回:交换之后的链表的头节点
     * 原理:找到两个目标节点,然后进行交换值
     */
    ListNode* swapNodes(ListNode* head, int k) {

        //找到目标结点,初始化两个指针,用于搜寻目标节点
        ListNode* left = head;
        ListNode* right;

        //左边的结点,是当前的结点
        for (int i = 1; i < k; ++i) {
            left = left->next;
        }

        //右边的结点的前一个结点
        right =  findLastNode(head,k);

        //交换对应的值
        int temp = left->val;
        left->val = right->next->val;
        right->next->val = temp;

        //返回最终结果
        return head;
    }
};

int main(int argc, char const *argv[])
{
    //声明vector用来保存数组
    vector<int> number;

    //处理输入,形成对应的链表
    string a = "";
    getline(cin,a);

    //去除开头和结尾
    a = a.erase(0,1);
    a = a.erase(a.size()-1,1);

    //将分割之后的结果进行输出
    stringstream sstr(a);
    string token;
    while(getline(sstr,token,',')){
        number.push_back(atoi(token.c_str()));
    }

    //生成对应的链表
    ListNode head(number.at(0));
    ListNode *temp = &head;
    for (int i = 1; i < number.size(); ++i)
    {
        temp->next = new ListNode(number.at(i));
        temp = temp->next;
    }

    //目标节点
    int n;
    cin>>n;
    Solution solution;
    ListNode* result = solution.swapNodes(&head,n);

    while(result){
        cout<<result->val<<endl;
        temp = result->next;
        delete(result);
        result = temp;
    }

    return 0;
}
事故现场
第一次提交

在这里插入图片描述

借鉴他人
ListNode* swapNodes(ListNode* head, int k) {
	
	//n1指向从头往尾数第n个结点
	//n2指向从尾往头数第n个结点
    ListNode *n1 = nullptr, *n2 = nullptr;

	//一次遍历完成的,p最终指向尾结点的后一个结点,p用来遍历整个过程
    for (auto p = head; p != nullptr; p = p->next) {
		
		//当n2和P之间形成了间距,n2就开始和p一块向后进行遍历
        n2 = n2 == nullptr ? nullptr : n2->next;
		
		//正向遍历的过程,也是形成间距的过程
        if (--k == 0) {
            n1 = p;
            n2 = head;
        }
    }
	
	//交换对应的结点的值
    swap(n1->val, n2->val);
    return head;
}
  • 不得不说,人家的代码,比我的简洁多了,思想虽然差不多,但是我就不连贯,是分段解决得。
  • 在找寻从尾结点向头结点数第n个结点时候,已经遍历到了正向第n个结点,所以,这完全是一个过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值