当前位置:   article > 正文

链表之指定区间反转_链表指定区间反转

链表指定区间反转

描述

将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度O(n),空间复杂度 O(1)。
例如:
给出的链表为 1→2→3→4→5→NULL, m=2,n=4,
返回 1→4→3→2→5→NULL.
 

数据范围: 链表长度 0<size≤1000,0<m≤n≤size,链表中每个节点的值满足 ∣val∣≤1000

要求:时间复杂度 O(n) ,空间复杂度 O(n)

进阶:时间复杂度 O(n),空间复杂度 O(1)

示例1

输入:

{1,2,3,4,5},2,4

返回值:

{1,4,3,2,5}

示例2

输入:

{5},1,1

返回值:

{5}


基本思路:

1.遍历整个链表

2.将从第m个结点开始到第n个结点的结点都倒置

既然要倒置从m到n的结点,所以可以想到之前的链表之反转链表

这里有个疑问:如果正好从第一个开始倒置怎么办?

当时我没注意到这个点,所以写完后发现,有例子出错了。那么如果我们想要保证原来的链表的任何位置都保持相同处理逻辑,那么最好引入一个头结点

  1. import java.util.*;
  2. /*
  3. * public class ListNode {
  4. * int val;
  5. * ListNode next = null;
  6. * }
  7. */
  8. public class Solution {
  9. /**
  10. *
  11. * @param head ListNode类
  12. * @param m int整型
  13. * @param n int整型
  14. * @return ListNode类
  15. */
  16. public ListNode reverseBetween (ListNode head, int m, int n) {
  17. //1.判空或只有一个结点
  18. if (head == null || head.next == null) {
  19. return head;
  20. }
  21. //2.需要设置一个头结点 (非常重要)
  22. ListNode dummyNode = new ListNode(0);
  23. dummyNode.next = head;
  24. ListNode leftNode = null;
  25. ListNode rightNode = null;
  26. ListNode preNode = null;
  27. ListNode curNode = dummyNode;
  28. int location = 0;
  29. //3.找到需要反转的结点的头和尾
  30. while (curNode != null) {
  31. if (location == m - 1) {
  32. preNode = curNode;
  33. }
  34. if (location == m) {
  35. leftNode = curNode;
  36. }
  37. if (location == n) {
  38. rightNode = curNode;
  39. }
  40. // 在第n个结点的后一个位置,进行调整
  41. if (location == n + 1) {
  42. break;
  43. }
  44. location++;
  45. curNode = curNode.next;
  46. }
  47. //4.切断反转链表的对前后的连接
  48. preNode.next = null;
  49. rightNode.next = null;
  50. //5.反转m到n个结点
  51. preNode.next = reverse(leftNode);
  52. leftNode.next = curNode;
  53. return dummyNode.next;
  54. }
  55. public ListNode reverse(ListNode head) {
  56. ListNode newHead = null;
  57. ListNode cur = head;
  58. ListNode next = null;
  59. while (cur != null) {
  60. System.out.println("curNode = " + cur.val);
  61. //先定位到下一个节点的位置
  62. next = cur.next;
  63. //将当前节点的下一个节点指向新链表的表头
  64. cur.next = newHead;
  65. //再将新链表的表头重新定位到当前节点
  66. //此时已经实现的当前结点指向前一个节点的操作
  67. newHead = cur;
  68. //将当前结点指向下一个节点,为下一次循环作准备
  69. cur = next;
  70. }
  71. return newHead;
  72. }
  73. }

是否还能再简约一些呢?

  1. import java.util.*;
  2. /*
  3. * public class ListNode {
  4. * int val;
  5. * ListNode next = null;
  6. * }
  7. */
  8. public class Solution {
  9. /**
  10. *
  11. * @param head ListNode类
  12. * @param m int整型
  13. * @param n int整型
  14. * @return ListNode类
  15. */
  16. public ListNode reverseBetween (ListNode head, int m, int n) {
  17. //1.设置虚拟头节点
  18. ListNode dummy =new ListNode(0);
  19. dummy.next=head;
  20. ListNode pre=dummy;
  21. //2.将pre指针移动到m前一个位置
  22. for(int i=0;i<m-1;i++){
  23. pre=pre.next;
  24. }
  25. //3.获取m位置
  26. ListNode cur=pre.next;
  27. ListNode next;
  28. for(int i=0;i<n-m;i++){
  29. next=cur.next;
  30. cur.next=next.next;
  31. //注意这里不能是next.next=cur,因为cur一直指的是最开始时m位置的节点
  32. next.next=pre.next;
  33. pre.next=next;
  34. }
  35. return dummy.next;
  36. }
  37. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/209586
推荐阅读
相关标签
  

闽ICP备14008679号