反转链表(非递归,哨兵,递归)

92. 反转链表 II

给你单链表的头节点 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

反转链表

在这里插入图片描述

非递归解法
  1. ​ 反转cur.next

    cur.next = pre ;
    pre = cur;
    cur = next
    next = cur.next;
    
  2. 新建一个头结点,头插法(哨兵法)

head.next = cur;
cur = cur.next;

return head.next;
递归解法

思路:将两个结点间的指针换个方向

递归到底部:

在这里插入图片描述

递归回根:
在这里插入图片描述

void reverse(ListNode head)
{
	if(head.next = null) return head;
	ListNode last = reverse(head);
	head.next.next = head;
	head.next=null;
}

本题解法

1.基于非递归
  1. 由于翻转指定区间,反转区间外的两个指针无论是否空都不处理,所以要做好判断。
public ListNode reverseBetween(ListNode head, int left, int right) {
        
        if(left==right||left>right) return head;
        int now = 1;
        ListNode ppre = null,p=head;
        while(now!=left){   
            //确定反转区间和反转指针前的第一个指针
            ppre = p;
            p = p.next;
            now++;
        }
        
        ListNode pre = p, cur = p.next, next = cur.next, tail = p;
        while(cur!=null){
            cur.next = pre;
            pre = cur;
            cur = next;
            if(now>=right-1){ 
                //最后一步,处理反转区间外的连接
                tail.next = next;   //反转区间的头指针被处理到区间的末尾了
                if(ppre!=null)ppre.next = pre;
                break;
            }
            next = cur.next;
            now++;    
        }
        return ppre==null?pre:head;   //left为1 ppre为空,head被处理了
        
    }
2.基于递归
    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;
    }    

    public ListNode reverseBetween(ListNode head, int m, int n) {
        // base case
        if (m == 1) {
            return reverseN(head, n);
        }
        // 前进到反转的起点触发 base case
        head.next = reverseBetween(head.next, m - 1, n - 1);
        return head;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值