您的位置:首页 > 其它

LeetCode [92] 反转链表 II

2019-03-27 17:29 281 查看

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/

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: