【LeetCode刷题笔记-79 92.反转链表Ⅱ】

在这里插入图片描述
今天这题需要注意的其实就是边界条件。

大体来说三步:
摘链 处理 归还

我自己的处理步骤用的是新建一个节点使用头插法。但是不知道为什么指针好像没有处理好,提交溢出了。但是在编译器里面确实能够做对。

题解的方法就是普通的反转链表,比我自己写的会简洁一些,这里两个版本都会贴上:

C++反转链表(附带测试)头插法:

#include<iostream>

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) {} 
};

void display(ListNode* head){
	head = head->next;
	while(head!=nullptr){
		cout<<head->val<<" ";
		head = head->next;
	}
	cout<<"endl"<<endl;
}

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
    	
    	ListNode *listhead = new ListNode(0,head);
    	ListNode *ptr = listhead;
        
        for (int i = 0; i < left - 1; i++) {
            ptr = ptr ->next;
        }
ListNode *leftptr = ptr;//记录左边界
ListNode *rightptr = leftptr;//记录右边界 

for (int i = 0; i < right - left + 1; i++) {
            rightptr = rightptr->next;
        }
		
ListNode *leftNode = leftptr->next;//保存摘链后的头 
ListNode *curr = rightptr->next;//保存摘链前的最后一个节点
 

ListNode *suplist = new ListNode(0);//辅助头节点
ListNode *suptr1 = suplist;//辅助指针,记录ptr的下一个
ListNode *suptr2 = leftNode;//辅助指针,记录链表尾部元素 
		while(leftNode!=nullptr){//使用头插法 
			suptr1 = leftNode->next;
			leftNode->next = suplist->next;
			suplist->next = leftNode;
			leftNode = suptr1; 
		}
		
        //归还链表
		leftptr->next = suplist->next;
		suptr2->next = curr;
		
        return listhead->next;
    }
};

int main(){
	int arr[5] = {1,2,3,4,5};
	ListNode *head = new ListNode(0);
	ListNode *ptr = head;//工作指针 
	for(int i=0;i<5;i++){
		ListNode *p1 = new ListNode(arr[i]);
		ptr->next = p1;
		ptr = ptr->next;
	}
	display(head);
	
	Solution solution;
	head = solution.reverseBetween(head->next,1,5);
	display(head);
}

普通的反转方法:

class Solution {
private:
    void reverseLinkedList(ListNode *head) {
        // 也可以使用递归反转一个链表
        ListNode *pre = nullptr;
        ListNode *cur = head;

        while (cur != nullptr) {
            ListNode *next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
    }

public:
    ListNode *reverseBetween(ListNode *head, int left, int right) {
        // 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
        ListNode *dummyNode = new ListNode(-1);
        dummyNode->next = head;

        ListNode *pre = dummyNode;
        // 第 1 步:从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点
        // 建议写在 for 循环里,语义清晰
        for (int i = 0; i < left - 1; i++) {
            pre = pre->next;
        }

        // 第 2 步:从 pre 再走 right - left + 1 步,来到 right 节点
        ListNode *rightNode = pre;
        for (int i = 0; i < right - left + 1; i++) {
            rightNode = rightNode->next;
        }

        // 第 3 步:切断出一个子链表(截取链表)
        ListNode *leftNode = pre->next;
        ListNode *curr = rightNode->next;

        // 注意:切断链接
        pre->next = nullptr;
        rightNode->next = nullptr;

        // 第 4 步:同第 206 题,反转链表的子区间
        reverseLinkedList(leftNode);

        // 第 5 步:接回到原来的链表中
        pre->next = rightNode;
        leftNode->next = curr;
        return dummyNode->next;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值