题目

原题:https://leetcode-cn.com/problems/reverse-linked-list-ii/

image.png

题解

反正某一部分的节点,当反正的节点如果从头结点开始,会存在复杂的判断,所以一般会构造一个虚拟节点,来避免这种问题的讨论。

另外还要注意的是,链表的更改下一节点数据时,要考虑用临时节点来做,以免丢失节点数据。

LeetCode 上的这道题,一开始连解题思路都没有,看答案有些步骤有种根本想不到的感觉,感觉他们是有上帝视角,不然有些步骤都想不到可以这么做,在多抄了几遍答案后,思考这个问题的本质其实就是两个变量交换值,a=1,b=2,那么需要变量 c 来暂存下,不然不能完成交换,只不过这两个变量挂在了链表上。同理,要把链表 a:

5-4-3-2-1

反正部分节点,得到链表 b:

5-2-3-4-1

那么我们需要链表 c 来暂存下,因此这道题,首先我们要开辟两个新的内存空间,但是这也的好处就是只要遍历链表一次就行。

  1. public ListNode reverseBetween(ListNode head, int left, int right) {
  2. // 设置 dummyNode 是这一类问题的一般做法
  3. ListNode dummyNode = new ListNode(-1);
  4. dummyNode.next = head;
  5. ListNode pre = dummyNode;
  6. // 找到要反转的头结点
  7. for (int i = 0; i < left - 1; i++) {
  8. pre = pre.next;
  9. }
  10. // 用临时节点操作,防止节点丢失,cur是要反转的头结点
  11. ListNode cur = pre.next;
  12. ListNode next;
  13. // right - left 表示要反转的节点个数
  14. // 这里链表中的节点交换位置,可以理解为两个变量交换位置,那么
  15. // 需要一个临时变量来暂存要交换的数据
  16. for (int i = 0; i < right - left; i++) {
  17. // 开始反转操作,pre 原始数据,cur和next都是用来暂存临时节点,
  18. // cur当前节点数据,next下一个要反转的节点数据
  19. // 每次调换一个节点,例如: 5-4-3-2-1 => 5-3-4-2-1 => 5-2-3-4-1
  20. // 不好理解需要画个图
  21. next = cur.next;
  22. cur.next = next.next;
  23. // 将已经反转的节点赋值到新的节点
  24. next.next = pre.next;
  25. pre.next = next;
  26. }
  27. return dummyNode.next;
  28. }

总结

如果不知道怎么做,可以多看别人的解题思路,多抄几遍代码,我就是这样,一开理解不了,拆了好多遍后,能模仿,然后在思考下,为什么这么做。总之,不会的情况,多模仿。