题目描述:
将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度 O(n),空间复杂度 O(1)。
例如:
输入
{1,2,3,4,5},2,4输出
{1,4,3,2,5}
解题思路:
要先找到了第m个位置才能开始反转链表,而反转的部分就是从第m个位置到第n个位置,并连接好整个链表。
解体步骤:
- step 1:我们可以在链表前加一个表头(虚拟头节点),后续返回时去掉就好了,因为如果要从链表头的位置开始反转,在多了一个表头的情况下就能保证第一个节点永远不会反转,不会到后面去。
- step 2:使用两个指针,一个指向当前节点,一个指向前序节点。
- step 3:依次遍历链表,到第m个的位置。
- step 4:对于从m到n这些个位置的节点,依次断掉指向后续的指针,反转指针方向。
- step 5:返回时去掉我们添加的表头。
具体过程(包含代码解释):
首先,创建一个链表类:
class ListNode {
int val; //数据域
ListNode next = null; //指针域
//构造函数,用于初始化
ListNode(int val) {
this.val = val;
}
}
然后编写具体实现类及方法:
public class TwoReverseBetween {
/**
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
public ListNode reverseBetween (ListNode head, int m, int n) {
//加一个表头(虚拟头节点)
ListNode res = new ListNode(-1);
res.next = head;
//前序节点
ListNode pre = res;
//当前节点
ListNode cur = head;
//找到m
for (int i = 1; i < m; i++) {
pre = cur;
cur = cur.next;
}
//反转区间
for (int i = m; i < n; i++) {
ListNode temp = cur.next;
cur.next = temp.next;
temp.next = pre.next;
pre.next = temp;
}
//输出去掉虚拟头节点后的链表
return res.next;
}
}
分析:
我们首先有一个链表如下,
加入虚拟头节点,并设置前序节点(指针)和当前节点(指针)之后,
然后移动指针,找到第m个节点,
对m-n这个区间的元素进行反转,首先,用一个临时链表指向cur.next(建议分屏对照代码理解)
然后,让cur.next指向temp.next;
然后让temp.next指向pre.next
然后pre.next指向temp
重复上述步骤,直到整个区间反转