问题描述:
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
代码实现
- 两种算法 递归和迭代
package com.leetcode.链表;
/**
* Author:markusZhang
* VM Args:
* Date:Create in 2020/2/4 14:18
*/
public class 反转链表II {
static class ListNode{
int val;
ListNode next;
public ListNode(){}
public ListNode(int val){
this.val = val;
}
}
private boolean stop; //用于终止递归的条件
private ListNode left;
public ListNode reverseBetween(ListNode head, int m, int n) {
this.left = head;
this.stop = false;
this.recurseAndReverse(head,2,4);
return head;
}
public void recurseAndReverse(ListNode right,int m,int n){
//最基本的终止递归的条件
if(n==1){
return ;
}
//同时移动两个指针
right = right.next;
if(m>1){
this.left = this.left.next;
}
//递归,直到两个指针到达各自相应的位置
this.recurseAndReverse(right,m-1,n-1);
//当两个指针位于一个节点上或者左指针已经越过了右指针,把stop改为true,然后结束
if(this.left==right || right.next == this.left){
this.stop = true;
}
//不是停止条件时,交换两个指针的所指向节点的值
if(!stop){
int t = this.left.val;
this.left.val = right.val;
right.val = t;
//然后将左指针向右移动一个位置,通过回溯,右指针向左移动一个位置
this.left = this.left.next;
}
}
public ListNode reverseBetween1(ListNode head, int m, int n) {
//鲁棒
if(head==null){
return null;
}
//定义两个指针 prev curr
ListNode prev = null;
ListNode curr = head;
//移动指针到第m个节点的前一个节点
while(m>1){
prev = curr;
curr = curr.next;
m--;
n--;
}
//System.out.println(n);
//定义 con tail指针 con的指针指向第m节点的前一个节点
// tail的指针指向当前需要进行反转的链表的最后一个节点
ListNode con = prev;
ListNode tail = curr;
ListNode third = null;
while(n>0){
third = curr.next;
curr.next = prev;
prev = curr;
curr = third;
n--;
}
//连接不发生反转的节点与发生反转的节点,确保整个链表不发生丢失
if(con!=null) {
con.next = prev;
}else{
head = prev;
}
tail.next = curr;
return head;
}
public static void main(String[] args) {
ListNode p = new ListNode(1);
ListNode p1 = new ListNode(2);
p.next = p1;
ListNode p2 = new ListNode(3);
p1.next = p2;
ListNode p3 = new ListNode(4);
p2.next = p3;
ListNode p4 = new ListNode(5);
p3.next = p4;
ListNode head = new 反转链表II().reverseBetween1(p,2,4);
while(head!=null){
System.out.print(head.val+" ");
head = head.next;
}
}
}