题目
原题:https://leetcode-cn.com/problems/reverse-linked-list-ii/
题解
反正某一部分的节点,当反正的节点如果从头结点开始,会存在复杂的判断,所以一般会构造一个虚拟节点,来避免这种问题的讨论。
另外还要注意的是,链表的更改下一节点数据时,要考虑用临时节点来做,以免丢失节点数据。
LeetCode 上的这道题,一开始连解题思路都没有,看答案有些步骤有种根本想不到的感觉,感觉他们是有上帝视角,不然有些步骤都想不到可以这么做,在多抄了几遍答案后,思考这个问题的本质其实就是两个变量交换值,a=1,b=2,那么需要变量 c 来暂存下,不然不能完成交换,只不过这两个变量挂在了链表上。同理,要把链表 a:
5-4-3-2-1
反正部分节点,得到链表 b:
5-2-3-4-1
那么我们需要链表 c 来暂存下,因此这道题,首先我们要开辟两个新的内存空间,但是这也的好处就是只要遍历链表一次就行。
public ListNode reverseBetween(ListNode head, int left, int right) {
// 设置 dummyNode 是这一类问题的一般做法
ListNode dummyNode = new ListNode(-1);
dummyNode.next = head;
ListNode pre = dummyNode;
// 找到要反转的头结点
for (int i = 0; i < left - 1; i++) {
pre = pre.next;
}
// 用临时节点操作,防止节点丢失,cur是要反转的头结点
ListNode cur = pre.next;
ListNode next;
// right - left 表示要反转的节点个数
// 这里链表中的节点交换位置,可以理解为两个变量交换位置,那么
// 需要一个临时变量来暂存要交换的数据
for (int i = 0; i < right - left; i++) {
// 开始反转操作,pre 原始数据,cur和next都是用来暂存临时节点,
// cur当前节点数据,next下一个要反转的节点数据
// 每次调换一个节点,例如: 5-4-3-2-1 => 5-3-4-2-1 => 5-2-3-4-1
// 不好理解需要画个图
next = cur.next;
cur.next = next.next;
// 将已经反转的节点赋值到新的节点
next.next = pre.next;
pre.next = next;
}
return dummyNode.next;
}
总结
如果不知道怎么做,可以多看别人的解题思路,多抄几遍代码,我就是这样,一开理解不了,拆了好多遍后,能模仿,然后在思考下,为什么这么做。总之,不会的情况,多模仿。