逆序链表从m到n位置

1 逆置整个链表

#include<stdio.h>

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

class Solution{
	public:
		ListNode* reverseList(ListNode *head){
			ListNode *new_head = NULL;	//指向新链表头结点指针
			while(head){
				ListNode *next = head->next;	//备份head->next 
				head->next = new_head;			//更新head->next 
				new_head = head;				//移动new_head 
				head = next; 					//遍历链表 
			} 
			return new_head;					//返回新链表结点 
		}
		
		ListNode* reverseList2(ListNode *head){
			ListNode *left = NULL;
			ListNode *right = head->next;
			while(head){
				head->next = left;
				left = head;
				head = right;
				if(right)
					right = right->next;
			} 
			return left;
		}
}; 

int main(){
	ListNode a(1);
	ListNode b(2);
	ListNode c(3);
	ListNode d(4);
	ListNode e(5);
	
	a.next = &b;
	b.next = &c;
	c.next = &d;
	d.next = &e;
	
	Solution solve;
	ListNode *head = &a;
	printf("Before reverse: \n");
	
	while(head){
		printf("%d\n",head->val);
		head = head->next;
	}
	
	head = solve.reverseList2(&a);
	printf("After reverse:\n");
	while(head){
		printf("%d\n",head->val);
		head = head->next;
	}		
}

2 逆置一个链表的m到n位的元素,返回逆置后的头结点

核心步骤

1.如何找到逆置段的开始和结束位置?

逆置段长度 :len=n-m+1
逆置段开始位置:while(head && –m) head移动m-1个位置

2.几个关键位置

1.逆置前 逆置段开始位置的前一个结点位置: pre_head
2.逆置前 逆置段结束位置的后一个结点位置: modify_list_tail

3.如何连接逆置后的逆置段

分类讨论
逆置段是否包括逆置前链表的头结点?

如果包括头结点,则 pre_head为空,逆置前的头结点变成逆置段逆置后的尾结点

如果不包括头结点,则pre_head不为空,逆置前后整个链表头结点还是链表的头结点,即result指向的位置

if(pre_head){							//如果pre_head不空,说明不是从第一个结点开始逆置的m>1, 就是逆置段不包括头结点result的情况
				pre_head->next = new_head;			//将逆置链表开始的结点前驱与逆置后的头结点连接  
			} 
			else{									//如果逆置段包括了头结点,头结点元素成了逆置段 逆置后的尾元素 
				result = new_head;					//result为逆置前链表头结点的位置,如果pre_head为空,说明 m==1,
													//从链表第一个结点开始逆置,链表头结点变为逆置段逆置后的尾结点,逆置前逆置段的尾结点成了逆置后整个链表头结点 
			} 
#include<stdio.h>

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

class Solution{
	public:
		ListNode* reverse_b(ListNode *head,int m,int n){
			if(m<1 && m>n){
				printf("error data\n");  
			}
			
			int change_len = n-m+1;		//需要逆置的结点个数 
			ListNode *pre_head = NULL;	//初始化开始逆置的结点的前驱
			ListNode *result = head;	//最终转换后的链表头结点,非特殊情况即为head
			while(head && --m){			//将head向前移动m-1个位置,注意如果m=1,pre_head还是为NULL,while循环不执行 
				pre_head = head;		//记录head的前驱 
				head = head->next; 	
			} 
			
			ListNode *modify_list_tail = head;		//将modify_list_tail指向当前的head,即逆置段逆置后的链表尾 
			ListNode *new_head = NULL; 
			while(head && change_len){				//逆置change_len个结点 
				ListNode *next = head->next;
				head->next = new_head;
				new_head = head;
				head = next; 
				change_len--;						//每完成一个结点逆置,change_len-- 
			}
			
			modify_list_tail->next = head;			//连接逆置后链表尾 与 逆置段的后一个结点 
			if(pre_head){							//如果pre_head不空,说明不是从第一个结点开始逆置的m>1, 就是逆置段不包括头结点result的情况
				pre_head->next = new_head;			//将逆置链表开始的结点前驱与逆置后的头结点连接  
			} 
			else{									//如果逆置段包括了头结点,头结点元素成了逆置段 逆置后的尾元素 
				result = new_head;					//result为逆置前链表头结点的位置,如果pre_head为空,说明 m==1,
													//从链表第一个结点开始逆置,链表头结点变为逆置段逆置后的尾结点,逆置前逆置段的尾结点成了逆置后整个链表头结点 
			} 
			return result; 							
		} 
}; 

int main(){
	ListNode a(1);
	ListNode b(2);
	ListNode c(3);
	ListNode d(4);
	ListNode e(5);
	
	a.next = &b;
	b.next = &c;
	c.next = &d;
	d.next = &e;
	
	Solution solve;
	ListNode *head = &a;
	printf("Before reverse: \n");
	
	while(head){
		printf("%d\n",head->val);
		head = head->next;
	}
	
	printf("Please Input m and n:\n");
	int m,n;
	scanf("%d%d",&m,&n);
	head = solve.reverse_b(&a,m,n);
	printf("After reverse:\n");
	while(head){
		printf("%d\n",head->val);
		head = head->next;
	}		
}

学习地址

https://www.bilibili.com/video/BV1F4411b7qE?t=2010

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值