BM2 链表内指定区间反转,为什么链表要new一个结点?

链表内指定区间反转_牛客题霸_牛客网 (nowcoder.com)

思路就是,把需要反转的结点放入栈中,然后在弹出来。

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
 #include<stack>
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head ListNode类 
     * @param m int整型 
     * @param n int整型 
     * @return ListNode类
     */
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        stack<int>s;
        int cnt=1;
        ListNode* pre = head;//前一个结点
        ListNode* cur = head;//当前节点
        ListNode* res = head;//如果从头节点开始反转,需要重新弄一个头节点以便返回i
        ListNode* tmp = head;//临时结点
        ListNode T(0);
        if (m == 1)
        {
            while (cnt <= n)
            {
                s.push(cur->val);
                cnt++;
                cur = cur->next;
            }
            ListNode*T = new ListNode(s.top());
            res = T;
            tmp = res;
            s.pop();
            while (!s.empty())
            {
                ListNode*T = new ListNode(s.top());
                tmp->next = T;
                s.pop();
                tmp = tmp->next;
            }
            while (cur)
            {
                tmp->next = cur;
                tmp=cur;
                cur = cur->next;
            }
            return res;
        }
        else
        {
           while (cnt != m)//这个while世找到m
            {
                cnt++;
                pre = cur;
                cur = cur->next;
            }
            while (cnt <=  n)//入栈
            {
                s.push(cur->val);
                cnt++;
                cur = cur->next;
            }
            //cout<<cur->val<<endl;
            while (!s.empty())//重新连接
            {
                //cout<<s.top()<<endl;
                ListNode*T = new ListNode(s.top());
                pre->next = T;
                s.pop();
                pre = pre->next;
                //cout<<pre->val<<endl;
            }
            //cout<<pre->val<<endl;
            while (cur)//连n之后的
            {
                pre->next = cur;
                pre=cur;
                //cout<<pre->val<<endl;
                cur = cur->next;
            }
            return head;
        }
        // write code here
    }
};

循环中重复定义相同变量名不报错的问题_循环语句中名称有重复_喂一天鱼的博客-CSDN博客 

下面有一个错误代码,与上面不一的地方在于

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        stack<int>s;
        int cnt=1;
        ListNode* pre = head;
        ListNode* cur= head;
        ListNode *res=head;
        ListNode* tmp=head;
        if (m == 1)
        {
            while (cnt <= n)
            {
                s.push(cur->val);
                cnt++;
                cur = cur->next;
            }
            res = &ListNode(s.top());
            tmp = res;
            s.pop();
            while (!s.empty())
            {
                tmp->next = &ListNode(s.top());
                s.pop();
                tmp = tmp->next;
            }
            while (cur)
            {
                tmp->next = cur;
                cur = cur->next;
            }
            return res;
        }
        else
        {
            while (cnt != m)
            {
                cnt++;
                pre = cur;
                cur = cur->next;
            }
            while (cnt <= n)
            {
                s.push(cur->val);
                cnt++;
                cur = cur->next;
            }
            while (!s.empty())
            {
                pre->next = &ListNode(s.top());
                s.pop();
                pre = pre->next;
            }
            while (cur)
            {
                tmp->next = cur;
                cur = cur->next;
            }
            return head;
        }
        // write code here
    }
}
/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
 #include<stack>
ListNode T(0);
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head ListNode类 
     * @param m int整型 
     * @param n int整型 
     * @return ListNode类
     */
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        stack<int>s;
        int cnt=1;
        ListNode* pre = head;
        ListNode* cur = head;
        ListNode* res = head;
        ListNode* tmp = head;
        //ListNode T(0);
        if (m == 1)
        {
            while (cnt <= n)
            {
                s.push(cur->val);
                cnt++;
                cur = cur->next;
            }
            T=ListNode(s.top());
            res = &T;
            tmp = res;
            s.pop();
            while (!s.empty())
            {
                T=ListNode(s.top());
                tmp->next = &T;
                s.pop();
                tmp = tmp->next;
            }
            while (cur)
            {
                tmp->next = cur;
                cur = cur->next;
            }
            return res;
        }
        else
        {
            while (cnt != m)
            {
                cnt++;
                pre = cur;
                cur = cur->next;
            }
            while (cnt <= n)
            {
                s.push(cur->val);
                cnt++;
                cur = cur->next;
            }
            //cout<<cur->val<<endl;
            while (!s.empty())
            {
                //cout<<s.top()<<endl;
                T=ListNode(s.top());
                pre->next = &T;
                s.pop();
                pre = pre->next;
                //cout<<pre->val<<endl;
            }
            //cout<<pre->val<<endl;
            while (cur)
            {
                pre->next = cur;
                pre=cur;
                //cout<<pre->val<<endl;
                cur = cur->next;
            }
            
            return head;
        }
        // write code here
    }
};

#include<iostream>
using namespace std;
#include<stack>
#include<algorithm>
#include<bitset>
#include<cmath>


 struct ListNode {
 	int val;
 	struct ListNode *next;
 	ListNode(int x) : val(x), next(nullptr) {}
  };
 /**
  * struct ListNode {
  *  int val;
  *  struct ListNode *next;
  *  ListNode(int x) : val(x), next(nullptr) {}
  * };
  */

int main()
{

    
    ListNode* Node;
    ListNode* Head;
    ListNode T(1);
    Node = &T;
    Head = &T;
    T=ListNode(2);
    Node->next = &T;
    Node = Node->next;
    T=ListNode(3);
    Node->next = &T;
    Node = Node->next;
    /*
    循环输出3
    while (Head)
    {
        cout << Head->val << " ";
        Head = Head->next;
    }
    */
    if (Head->val == Head->next->val)
    {
        cout << "理解了吗" << endl;
    }
	system("pause");
	return 0;
}
	

 一个是new一个结点,另一个是建一个结点然后取地址,错误的代码在于,

就是错误代码,我想的是自己创的局部变量T,这个对象每次都是新的,结果在VS2022上调试,一步步发现,原来每次新建的T居然是一个地址!!因为链表里已经加入了之前的T的这个地址,这直接导致链表发生错误,以第一个用例为例,本意是想实现1-4-3-2,结果最后只有1-2

因为在循环时,首先是1-4,在创建3这个节点时,由于是4的地址,所以就把4覆盖了,输出1-3,而不是1-4-3.
链表申请新节点要new。这样每次地址都不一样就连起来了。


#include<iostream>
using namespace std;
#include<stack>
#include<algorithm>
#include<bitset>
#include<cmath>


 struct ListNode {
 	int val;
 	struct ListNode *next;
 	ListNode(int x) : val(x), next(nullptr) {}
  };
 /**
  * struct ListNode {
  *  int val;
  *  struct ListNode *next;
  *  ListNode(int x) : val(x), next(nullptr) {}
  * };
  */

int main()
{
    /*ListNode T1(1);
    ListNode T2(2);
    ListNode T3(3);
    ListNode *node;
    ListNode* head;
    node = &T1;
    head = &T1;
    node->next = &T2;
    node = node->next;
    node->next = &T3;
    node = node->next;
    while (head)
    {
        cout << head->val << " ";
        head = head->next;
    }*/
    /*
    报错 “T”: 重定义;多次初始化
    ListNode* Node;
    ListNode* Head;
    ListNode T(1);
    Node = &T;
    Head = &T;
    ListNode T(2);
    Node->next = &T;
    Node = Node->next;
    ListNode T(3);
    Node->next = &T;
    Node = Node->next;
    while (Head)
    {
        cout << Head->val << " ";
        Head = Head->next;
    }
    */
    /*
    报错 a”: 重定义;多次初始化
    int a = 10;
    int a = 5;
    cout << a << endl;
    */
	system("pause");
	return 0;
}
	



下面讲一种,加入一个虚拟节点(哨兵)的做法,之所以这样是可以当从头节点开始转变时,代码不用特判。

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head ListNode类 
     * @param m int整型 
     * @param n int整型 
     * @return ListNode类
     */
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        ListNode* res=new ListNode(0);//虚拟节点
        res->next=head;
        ListNode* pre=res;
        ListNode* cur=head;
        ListNode* beg=head;
        ListNode* en=head;
        ListNode* tmp;
        for(int i=1;i<m;i++)
        {
           pre=beg;
           beg=beg->next;
        }
        for(int i=1;i<n;i++)
        {
           en=en->next;
        }
        cur=beg->next;
        beg->next=en->next;
        pre->next=en;
        pre=beg;
        while(pre!=en)
        {
           tmp=cur->next;
           cur->next=pre;
           pre=cur;
           cur=tmp;
        }
        return res->next;
        // write code here
    }
};

第三个方法

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head ListNode类 
     * @param m int整型 
     * @param n int整型 
     * @return ListNode类
     */
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        ListNode* res=new ListNode(0);//虚拟节点
        res->next=head;
        ListNode* pre=res;
        ListNode* cur=head;
        ListNode* beg=head;
        ListNode* tmp;
       for(int i=1;i<m;i++)
       {
         pre=beg;
         beg=beg->next;
       }
       tmp=beg->next;
       for(int i=m+1;i<=n;i++)
       {
          cur=tmp;
          tmp=tmp->next;
          beg->next=tmp;
          cur->next=pre->next;
          pre->next=cur;
       }
       return res->next;
        // write code here
    }
};



 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值