代码随想录记录打卡2||链表||双指针解决链表问题

文章目录

  • 导入
  • 链表
  • 【例题】 707.设计链表
      • 题目
      • 代码展示
      • 小结
  • 【推荐题目】 203.移除链表元素
      • 题目
      • 代码展示
  • 【推荐题目】206. 反转链表
      • 题目
      • 代码展示
  • 【推荐题目】24. 两两交换链表中的节点
      • 题目
      • 代码思路
      • 代码展示
  • 【推荐题目】19. 删除链表的倒数第 N 个结点
      • 题目
      • 代码思路
      • 代码展示
  • 【推荐题目】面试题 02.07. 链表相交
      • 题目
      • 代码思路
      • 代码展示
  • 【推荐题目】142. 环形链表 II
      • 题目
      • 代码思路
      • 代码展示
  • 总结
  • 今日分享

导入

⭐数组在定义的时候,长度就是固定的,如果想改动数组的长度,就需要重新定义一个新的数组。

⭐链表的长度可以是不固定的,并且可以动态增删, 适合数据量不固定,频繁增删,较少查询的场景。

⭐双指针 + 链表挺有趣,链表的本质也还是考察指针操作,常考的也是这种题型。

链表

【例题】 707.设计链表

视频链接:代码随想录 707.设计链表
题目链接:一道题考完所有基本操作? 707.设计链表

题目

代码随想录记录打卡2||链表||双指针解决链表问题_第1张图片

代码展示

//首先要定义ListNode节点
class ListNode{
        int val;
        ListNode next;
        public ListNode(){

        }
        public ListNode(int val){
            this.val = val;
        }
        public  ListNode(int val,ListNode next){
            this.val = val;
            this.next = next;
        }
}
//我们操作第n个节点时,cur一定是在第n个节点之前,即cur.next才是第n个节点
//这样才能方便操作第n个节点
class MyLinkedList {
    //全局属性size和dummyHead
    int size;//节点长度
    ListNode dummyHead;//虚拟头节点

    public MyLinkedList(){
        size = 0;
        dummyHead = new ListNode(0);
    }
    //获取1下标为index的节点值
    public int get(int index) {
        //特判
        if(index < 0 || index >= size){
            return -1;
        }
        //cur表示当前节点,用来遍历
        ListNode cur = dummyHead;
        while(index != 0){
            cur = cur.next;
            index--;
        }
        return cur.next.val;
    }
    
    public void addAtHead(int val) {
        addAtIndex(0,val);
    }
    
    public void addAtTail(int val) {
        addAtIndex(size,val);
    }
    //在下标为index的节点 前 ,插入val节点
    public void addAtIndex(int index, int val) {
        if(index < 0) index = 0;
        if(index > size) return;
        ListNode cur = dummyHead;
        ListNode newNode = new ListNode(val);
        while(index != 0){
            cur = cur.next;
            index--;
        }
        newNode.next  = cur.next;
        cur.next = newNode;
        size++;
    }
    //删除下标为index的节点
    public void deleteAtIndex(int index) {
        //特判
        if(index < 0 || index >= size){
            return;
        }
        ListNode cur = dummyHead;
        while(index != 0){
            cur = cur.next;
            index--;
        }
        cur.next = cur.next.next;
        size--;
    }
}

小结

⭐设计链表这道题值得多看看,一方面,设计了常规操作,十分基础;另一方面,要学会手写ListNode类。因为力扣的题基本都会给ListNode类,但是机试、面试中,需要手写。

203.移除链表元素

视频链接:代码随想录 203.移除链表元素
题目链接:基础题 203.移除链表元素`

【推荐题目】 203.移除链表元素

题目

代码随想录记录打卡2||链表||双指针解决链表问题_第2张图片

代码展示

 public class ListNode{
     int val;
     ListNode next;
     public ListNode(){

     }
     public ListNode(int val){
         this.val = val;
     }
     public ListNode(int val,ListNode next){
         this.val = val;
         this.next =  next;
     }
 }
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        //虚拟头结点的主要目的是为了避免对头结点的特殊处理。所以可以这样:涉及到对链表修改(如插入,删除,移动)的,都加个dummy,只是遍历取点就可以不用加
        ListNode dummyNode = new ListNode(-1,head);//虚拟头节点
        ListNode cur = dummyNode;//当前节点。用来遍历
        while(cur.next != null){
            if(cur.next.val == val){
                cur.next = cur.next.next;
            }
            else cur = cur.next;
        }
        return dummyNode.next;
    }
}

【推荐题目】206. 反转链表

视频链接:代码随想录 206. 反转链表
题目链接:双指针完成 206. 反转链表

题目

代码随想录记录打卡2||链表||双指针解决链表问题_第3张图片

代码展示


 public class ListNode {
     int val;
     ListNode next;
     ListNode() {}
     ListNode(int val) { this.val = val; }
     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 }

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode cur = head;//当前节点
        ListNode pre = null;//前一个节点
        ListNode temp = cur;//临时节点
        while(cur != null){
            temp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }
}

【推荐题目】24. 两两交换链表中的节点

视频链接:代码随想录 24.两两交换链表中的节点
题目链接:考察基础 24.两两交换链表中的节点

题目

代码随想录记录打卡2||链表||双指针解决链表问题_第4张图片

代码思路

代码随想录记录打卡2||链表||双指针解决链表问题_第5张图片

代码展示


 public class ListNode {
     int val;
     ListNode next;
     ListNode() {}
     ListNode(int val) { this.val = val; }
     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 }
class Solution {
    public ListNode swapPairs(ListNode head) {
        //首先要明确,如果要对节点4和节点5进行操作,那么cur要在节点3上(提前一个节点)
        //其次,因此,cur在一次遍历后,要到下下一个节点(后移2个节点)
        ListNode dummyNode = new ListNode(-1,head);
        ListNode cur = dummyNode;
        //
        while(cur.next != null && cur.next.next != null){
            ListNode t1 = cur.next;
            ListNode t2 = cur.next.next.next;
            cur.next = cur.next.next;
            cur.next.next = t1;
            t1.next = t2;
            cur = cur.next.next;
        }
        return dummyNode.next;
    }
}

【推荐题目】19. 删除链表的倒数第 N 个结点

视频链接:代码随想录 19. 删除链表的倒数第 N 个结点
题目链接:快慢指针 19. 删除链表的倒数第 N 个结点

题目

代码随想录记录打卡2||链表||双指针解决链表问题_第6张图片

代码思路

⭐ 思路:利用快慢指针fast、slow。fas、slow起初都在dummyNode上。
⭐我们知道,链表的一大问题就是操作当前节点必须要找前一个节点才能操作. 删除倒数第n个节点,也就是slow要在倒数n + 1的位置上。
⭐即:终止条件应该是slow在倒数第n + 1的位置,fast在null的位置。
⭐此时,slow与fast相隔n个位置。所以,fast要比slow快n+1步。

代码展示


 public class ListNode {
     int val;
     ListNode next;
     ListNode() {}
     ListNode(int val) { this.val = val; }
     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 }

 思路:利用快慢指针fast、slow。fas、slow起初都在dummyNode上。
 我们知道,链表的一大问题就是操作当前节点必须要找前一个节点才能操作.
 删除倒数第n个节点,也就是slow要在倒数n + 1的位置上。
 即:终止条件应该是slow在倒数第n + 1的位置,fast在null的位置。
 此时,slow与fast相隔n个位置。所以,fast要比slow快n+1步。
  */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummyNode = new ListNode(-1,head);
        ListNode fast = dummyNode;
        ListNode slow = dummyNode;
        //让fast先走n+1步
        n += 1;
        while(n -- > 0){
            fast = fast.next;
        }
        //fast、slow同时移动,知道fast到null 同时 slow到倒数第n+1位置。
        while(fast != null){
            fast = fast.next;
            slow = slow.next;
        }
        //删除倒数第n个节点
        slow.next = slow.next.next;
        return dummyNode.next;
    }
}

【推荐题目】面试题 02.07. 链表相交

题目链接:脑筋急转弯? 链表相交

题目

代码随想录记录打卡2||链表||双指针解决链表问题_第7张图片

代码随想录记录打卡2||链表||双指针解决链表问题_第8张图片
代码随想录记录打卡2||链表||双指针解决链表问题_第9张图片

代码思路

代码随想录记录打卡2||链表||双指针解决链表问题_第10张图片

⭐如果有相交的结点D的话,每条链的头结点先走完自己的链表长度,然后回头走另外的一条链表,那么两结点一定为相交于D点,因为这时每个头结点走的距离是一样的,都是AD + BD + DC,而他们每次又都是前进1,所以距离相同,速度又相同,固然一定会在相同的时间走到相同的结点上,即D点

代码展示

public class ListNode {
     int val;
     ListNode next;
     ListNode(int x) {
         val = x;
         next = null;
     }
 }
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode t1 = headA;
        ListNode t2 = headB;
        while(t1 != t2){
        //如果t1为空,那就让t1走headB
            if(t1 != null){t1 = t1.next;}
            else{t1 = headB;}
        //如果t2为空,那就让t2走headA
            if(t2 != null){t2 = t2.next;}
            else{t2 = headA;}
        }
        return t1;
    }
}

【推荐题目】142. 环形链表 II

视频链接:代码随想录 142. 环形链表 II
题目链接:数学题?明白a=c,完胜环形链表 II

题目

代码随想录记录打卡2||链表||双指针解决链表问题_第11张图片

代码思路

代码随想录记录打卡2||链表||双指针解决链表问题_第12张图片

已知a = c后,设相遇点为l1,l2 = head,长度一样长,那么就同时一直走,l1和l2相遇点,则为入口

代码展示

class ListNode {
    int val;
    ListNode next;
    ListNode(int x) {
        val = x;
        next = null;
    }
}

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        //为什么是&&,因为如果没有环,对于奇偶个数,退出while条件不同
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            //有环
            if(fast == slow){//如果相遇
                ListNode l1 = fast;//相遇点为l1(也是l2)
                ListNode l2 = head;//l2是头节点
                //l1和l2同时走,此时a = c派上用场
                while(l1 != l2){
                    l1 = l1.next;
                    l2 = l2.next;
                }
                return l1;//l1=l2,都是入口点
            }
        }
        return null;
    }
}

总结

代码随想录记录打卡2||链表||双指针解决链表问题_第13张图片

⭐这个图是 代码随想录知识星球 成员:海螺人 所画,总结的非常好,分享给大家。

⭐考察链表的操作其实就是考察指针的操作,是面试中的常见类型。

今日分享

读研的经历,不仅仅是做好实验认真听课就行,读研的三年,就是要一边又一遍地打磨你的性格,要对权威者绝对服从,要时刻谦卑,处事谨言慎行,要学会圆滑。年少时打出的子弹啊,最终还是正中了眉心。

你可以选择躲在角落里沉默,但是不要嘲笑,甚至诋毁比你勇敢的人。因为他们争取到的光明也会照耀到你!

你可能感兴趣的:(代码随想录记录,链表,数据结构)