LeetCode [92] 反转链表 II

题目描述

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

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

示例:

输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL

题目分析

全链表反转是会用到三个指针的,而中间链表反转还需要一个表示其实节点,通俗的讲就是一头一尾一中间,标记了各个点,那他们的连接就只要用next来表示了。就以示例中的链表为例,假设我现在有个pre指针在2处,一个cur的指针在3处,一个next指针在4处,那么怎么反转他们呢,先解决中间的连接。next.next=cur cur.next=pre。这样中间的就反转好了,那么再处理两个头,把1记为head,那么就是head.next=next pre.next=next.next。这样就全连上啦。下面的也就是用这样的方法,先找这几个点,然后先解决中间的,再解决两个头。

源码

/**
* Definition for singly-linked list.
* public class ListNode {
*     int val;
*     ListNode next;
*     ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseBetween(ListNode head, int m, int n) {
    ListNode myHead = new ListNode(0);
    myHead.next = head;
    
    ListNode newHead = null;
    // 保留前一个结点
    ListNode curr = myHead;
    // 反转开始的结点,随着反转变化
    ListNode next = head;
    
    // 反转后的头
    ListNode begin = head;
    // 反转开始的结点, 不变
    ListNode pre = head;
   for(int i=1; i<m; i++){
       curr = curr.next;
       next = next.next;
       begin = begin.next;
       pre = pre.next;
   }
    //先反转中间的链表
    for(int i =0; i<n - m + 1;i++){
        next = next.next;
        begin.next = newHead;
        newHead = begin;
        begin = next;
    }
  //最后把头反转一下
    pre.next = next;
    curr.next = newHead;
    return myHead.next;
}
}

改进

这个指针太多了,容易晕怎么办,能不能有其他的方式,减少点指针呢,那么下面就要用到链表里的头插法了,不然指针一弄错就会形成死链。

改进代码

class Solution {
public ListNode reverseBetween(ListNode head, int m, int n) {
    ListNode dummy = new ListNode(0);
    dummy.next = head;
    ListNode pre = dummy;
    ListNode cur = dummy.next;
    for (int i = 1; i < m; i++) {
        pre = pre.next;
        cur = cur.next;
    }
    for (int i = 0; i < n - m; i++) {
        ListNode temp = cur.next;
        cur.next = temp.next;
        temp.next = pre.next;
        pre.next = temp;
    }
    return dummy.next;
}
}

分析

第一个时间复杂度为O(n)
第二个就是O(n)
空间复杂度都为O(1)

[1]https://leetcode-cn.com/problems/reverse-linked-list-ii/submissions/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值