小彩笔的痛苦刷题日记 —— 反转链表Ⅱ

反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

说明:
1 ≤ m ≤ n ≤ 链表长度。

输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
一、使用递归地思路解决 —— 题解来自labuladong
1、递归反转整个链表
ListNdoe reverse(ListNode head){
	if(head.next == null) return head;
	ListNode last = reverse(head.next);
	head.next.next = head;
	head.next = null;
	return last;
}
  • 输入一个结点head,将[以head为起点]的链表反转,并返回反转之后的头节点。
  • 注意:
    ①递归函数的终止条件if(head.next == null) return head; ,当链表只有一个结点,返回它本身。
    ②当链表递归反转之后,新的头节点是last,而之前的head变成了最后一个节点,链表的末尾要指向Null head.next = null
2、反转链表前N个节点
  • 将链表的前n个结点反转(n <= 链表长度)
  • 有一个后驱结点来记录n位置的下一个结点
ListNode successor = null; // 后驱结点
// 反转以 head 为起点的 n 个节点,返回新的头结点
ListNode reverseN(ListNode head, int n){
	if(n == 1){
		// 记录第n+1个节点
		successor = head.next;
		return head;
	}
	// 以 head.next 为起点,需要反转前n-1个结点
	ListNode last = reverseN(head.next, n-1);
		
	head.next.next = head;
	// 让反转之后的head节点和后面的结点连接起来
	head.next = successor;
	return last;
}
  • 注意:
    ①终止条件变为n==1,之反转一个元素,同时记录后驱结点
    ②反转链表后原本的head不一定是最后一个结点,所以要使用后驱结点,反转之后将head连接上。
3、反转链表的一部分

给一个索引区间[m,n],仅反转区间中的链表元素。
如果m==1,就相当于反转链表开头的n个元素,就跟第二部分是一样的
m!=1时,将head的索引看作1,是要从第m个元素开始反转; 若head.next的索引作为1的话,则是要从m-1个元素开始反转;head.next.next就是从m-2开始…

ListNode reverseBetween(ListNode head, int m, int n){
	// 终止条件
	if(m == 1){
		return reverseN(head, n);
	}
	// 递归,直到m==1
	head.next = reverseBetween(head.next, m-1, n-1);
	return head;
}
二、迭代遍历思路——题解来自力扣官方题解

思路:在需要反转的区间里,每遍历到一个节点,就让这个新节点来到反转部分的起始位置
使用三个指针变量pre、curr、next来记录反转过程中需要的变量

  • cur:指向待反转区域的第一个结点left
  • next:永远指向cur的下一个结点,在循环中,next会随着cur不断变化
  • pre: 永远指向待反转区域的第一个节点left的前一个节点,在循环中过程中不变
public ListNode reverseBetween(ListNode head, int left, int right){
	// 设置一个傀儡节点
	ListNode dummyNode = new ListNode(-1);
	dummyNode.next = head;
	ListNode pre = dummyNode;
	for(int i = 0; i < left - 1; i++){ // 找到要反转位置的前一个位置
		pre = pre.next;
	}
	ListNode cur = pre.next;
	ListNode next;
	for(int i = 0; i < right - left; i++){
		next = cur.next;         // next时cur的下一个节点
		cur.next = next.next;    // 将cur的next指向next的下一个节点(next);相当于跳过了next位置
		next.next = pre.next;	 // next应该去开始反转的第一个位置
		pre.next = next;         // next应该去开始反转的第一个位置
	    }
	return dummyNode.next;  
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值