再看LeetCode92

题目:
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

说明:
1 ≤ m ≤ n ≤ 链表长度。

示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL

代码演示:(注释很清楚,还有之前自己弄混的知识点)

public static ListNode reverseBetween(ListNode head, int m, int n) {
 //注意踩坑,判断不符合条件的都给返回了,尤其注意m=n的时候,这个时候也不需要交换
 //如果在这里不把这个踢出的话,下面的判断条件里i<n也是满足的
    if(head==null||head.next==null||m==n)return head;
 /**
  * 这里的整体思路是:让head在m的位置直接等于n后面位置 
  * 意思就是让head直接把m,n位置删除了 
  * 然后m--n位置保存起来
  * 从head本来是m位置的元素开始进行头插法删除掉的那部分,就实现了那部分的反转
  */
    ListNode p=head;
    int i=1;
    //这里找到m的前一个元素
    while(i+1<m) {
    p=p.next;
    i++;
    }
    ListNode temp=null;
/**
* 这里的临时变量temp保存的是从m位置开始的所有元素
* p此时表示的m位置节点的前一个节点,
* 因为即将从p之后一直到n位置的节点都将从head中清除
* ---
* ---
* 这里插入几句链表知识
* 不管new出来多少个结点,它指向的都是某个结点的内存地址,这个时候你对这个节点进行操作的话
* 就会影响到和这个节点相关的所有链表,但是如果只对变量操作(设为null)即不指向这个节点了而已
* 并不会影响到这个节点和其他指向该节点的元素(除非这个 节点没有被指向了就会清空)
* ---
* --
* 这时候从内存上分析,p指向的依旧是head这个链表对应的 某个元素
* 同样的temp指向的也是某个元素,
* 而这个temp需要判断,因为一开始如果m=1的话,本来需要从head清除的是1-n
* 因为正常情况下p是指向m的前一个节点的,m=1这个时候没有前一个节点
* 那么 这个时候,本来需要从head清除的是1--n
* 现在由于p没有移动,那么找出的temp就是1位置的下一个元素节点了
* 所以这个时候需要判断,以保证temp指向的就是m--n的节点
*/
    if(m==1) {
        temp=p;
    }else {
        temp=p.next;
    }
        //这里定义一个新指针q是因为p要记录当前m的前一个位置,
        //后续head是需要从p位置开始,跳过m--n连接到n的下一个节点
    ListNode q=temp;
    i++;
    while(i<n) {
        q=q.next;
        i++;
    }
/**
* 这个时候q就到了n的位置,那么就可以连接p--q之间的节点了
* 
* (如果m==1的时候q到了n的前一个位置,因为在循环开始之前i++了
*     这里i++的原本意思是找到m的前一个节点p的时候,i++继续去判断q的位置
*     但是m==1的时候,没有找到这个p,所以这个i就多+了一次,对应的q就少走一次)
*     
* (清除了m--n)
* 所以这个时候无论对m--n之间的节点怎么操作都不会影响到head的某个节点了
*因为head已经不指向它们了
* 而m之后的节点是temp在保存,所以不会被删除
* 我们要的是m--n之间的节点
* 这个时候可以让q节点之后为null
* 
*/
    if(m==1) {
    //上面已经解释了这里为啥q还要.next一次才让head指向
    //为什么单独判断下面一条注释说明了
    //----
    //无论是这个条件还是下一个条件,其意义都是:
    //在与在消除m--n节点之后的head链表里p位置之后头插法插入m--n之间的节点(头插法得到的是逆序)
        q=q.next;
        head=q.next;
        q.next=null;
        while(temp!=null) {
             q=temp.next;
             temp.next=head;
             head=temp;
             temp=q;
        }
        return head;
    }
        //上面需要对m==1单独操作是因为但m==1的时候,head不需要从p位置连接
        //清除m--n之间节点的时候,head就直接指向n的下一个节点了
    p.next=q.next;
    q.next=null;
    while(temp!=null) {
        q=temp.next;
         temp.next=p.next;
         p.next=temp;
        temp=q;
    }
    return head;
}

//题目里给的节点类
class ListNode{
	int val;
	ListNode next;
	ListNode(int x) { val = x; }
}

之前做这个题的时候被卡了好长时间,尝试过很多次怎么就是不对,于是就放一边了,可能是思路局限了,想后续不再局限于这个思路的时候再回头做,这次总算是做出来了,看看之前的提交记录:(不忍直视)
在这里插入图片描述
用到三个指针,所以空间复杂度还行吧。时间复杂度虽然代码看起来是有三个while循环,但由于是同一个变量i,因此时间复杂度也说得过去:
在这里插入图片描述

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页