Leetcode链表刷题总结(Java版)

链表

1、移除链表元素(考虑全情况)

问题需求:根据给定的val值,移除链表中值是这个val的节点

203. 移除链表元素 - 力扣(LeetCode)

这里有一个问题就是,如果需要被移除的节点不是中间的某个节点,而是头节点。就没法借助前一个节点了,而是直接将

head = head.next

所以有两种思路,要么是分类处理;要么是在原本的head节点前面增加一个虚拟头节点,这样头节点也有个前面的节点了

还有需要注意的是,这里的代码,不应该用if,因为我们是一直移除的一个过程,所以应该用while

  • 思路一:
public ListNode removeElements(ListNode head, int val) {
    while(head != null && head.val == val)  //之所以不用if,是因为可能从头结点开始有连续的等于val的节点
        head = head.next;
    ListNode cur = head;		//删除非头节点情况
    while(cur != null && cur.next != null){
        if(cur.next.val = val)
            cur.next = cur.next.next;
        else
            cur = cur.next;
    }
    return head;
}
  • 思路二:
ListNode dummyHead = new ListNode(0); // 设置⼀个虚拟头结点
dummyHead.next = head; 			// 将虚拟头结点指向head,这样⽅⾯后⾯做删除操作
ListNode cur = dummyHead;
while(cur.next != null){
    ...
}
return dummyHead.next;

2、设计链表【个人觉得想熟悉链表时可以练这个】

  • 707. 设计链表 - 力扣(LeetCode)

在这里插入图片描述

就是实现关于链表的各个操作,为了方便,还是用上了虚拟头节点

初始化中的0就是虚拟头节点了

3、反转链表(双指针)

206. 反转链表 - 力扣(LeetCode)

双指针法

遍历链表,按照头插法,将旧链表的一个个节点放到新链表的头节点,最后反转成功

public ListNode reverseList(ListNode head) {
    ListNode cur = head;
    ListNode first = null;
    while(cur!=null){
        ListNode tmp = cur.next;    // 保存⼀下 cur的下⼀个节点,因为接下来要改变cur->next
        cur.next = first;           //头部插入
        //更新双指针
        first = cur;
        cur = tmp;
    }
    return first;
}

4、两两交换链表中的节点(借助虚拟头节点)

24. 两两交换链表中的节点 - 力扣(LeetCode)

在这里插入图片描述

需要借助虚拟头节点,这样操作会简单一点

每次需要一个指针cur指向需要被交换的两个节点,的前一个节点

顺序就是,虚拟头节点先指向2,然后让2指向1,最后1指向3。而这里的“1”和“3”是需要两个临时节点记录一下

public ListNode swapPairs(ListNode head) {
    ListNode  dummyHead = new ListNode(0);
    dummyHead.next = head;
    ListNode cur = dummyHead;
    while(cur.next != null && cur.next.next != null){
        ListNode tmp = cur.next;
        ListNode tmp1 = cur.next.next.next;
        cur.next = cur.next.next;
        cur.next.next = tmp;
        cur.next.next.next = tmp1;
        cur = tmp;                  // 或者cur = cur.next.next;  cur移动两位,准备下⼀轮交换
    }
    return dummyHead.next;
}

5、删除链表倒数第N个节点(快慢指针)

19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)

  • 由于需要删除的是倒数第N个,所以可以用快慢指针

  • 双指针的经典应⽤,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了

  • 这里需要注意的就是,需要虚拟头节点,考虑到了如果链表只有一个元素,或者只有两个元素的情况

    这种时候,用到虚拟头节点,就很好的可以处理

    另外,最后返回的时候,不要返回head,而是返回dummyhead.next,因为如果只有一个节点的情况,删除后,就没有head,就知识null了,所以不能返回head

public ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode dummyhead = new ListNode(0);
    dummyhead.next = head;
    ListNode fast = dummyhead;
    ListNode slow = dummyhead;
    for(int i = 0; i < n; i++)
        fast = fast.next;
    fast = fast.next;			 // fast再提前⾛⼀步,因为需要让slow指向删除节点的上⼀个节点
    while(fast != null){      
        slow = slow.next;
        fast = fast.next;
    }
    slow.next = slow.next.next;
    return dummyhead.next;      //不能返回head,只能是dummyhead.next
}

6、链表相交:寻找两个链表(无环结构)重合结点

面试题 02.07. 链表相交 - 力扣(LeetCode)

  • 其实这个链表问题主要需要总结的就是那些经验及方法,而对于两个无环结构的链表,就是常规方法

    ​ 先是求出连两个链表的长度length1,length2,然后就是需要判断这两个链表的尾结点是不是一样的

    ​ 如果连尾结点都不一样,就说明两个链表连一个结点都没有重合,所以两个链表绝对不会重合

    如果尾结点一样的话,需要将两个链表的长度互减

    ​ 然后这个数num的绝对值就是这两个链表长度的差值,**让长链表提前走num步,然后两个链表再同时走,**直到遇见了相同的交点处停下来返回此结点,具体代码如下:

    public static Node noLoop(Node head1, Node head2) {
        if (head1 == null || head2 == null) {	return null;   }
        Node cur1 = head1;
        Node cur2 = head2;
        int n = 0;                      //这里为了简化以及节省空间,就设置了一个变量n,通过下面的两个while循环,一个自加,一个自减,最后求他的绝对值,就是两个链表的长度差值
        while (cur1.next != null) {
            n++;
            cur1 = cur1.next;}
        while (cur2.next != null) {
            n--;
            cur2 = cur2.next;}
        if (cur1 != cur2) {			   //如果最后一个结点都不一样,那么两个链表绝对不可能有交合的地方了
            return null;              
        }
        cur1 = n > 0 ? head1 : head2;			//谁长,谁的头变成cur1
        cur2 = cur1 == head1 ? head2 : head1;	 //谁短,谁的头变成cur2
        n = Math.abs(n);
        while (n != 0) {			  //先让长链表走了n步
            n--;
            cur1 = cur1.next;
        }
        while (cur1 != cur2) {		  //开始寻找相交结点
            cur1 = cur1.next;
            cur2 = cur2.next;
        }
        return cur1;
    }
    

7、环形链表

142. 环形链表 II - 力扣(LeetCode)

划分为两个问题:

  1. 判断有环无环
  2. 如果有环的话,找到环的起始节点

1)判断有环无环

判断链表是否有环,可以借助哈希表set,也可以用快慢指针,

**1)哈希表set:**将所有节点放进set中,每放进去一个节点都查查这个节点是不是在集合中,第一次查到这个节点在集合中的时候,就说明这个节点就是环的起点

2)快慢指针: 只要最后不会指向空【如果快指针指向空了,就说明没有环】,并且快慢指针重合,就说明该链表又环。判断有环之后,就要开始找环的起始点,看下面的描述

//哈希表set
public static boolean hasCycle(Node head){
    HashSet<Node> set = new HashSet<Node>();
    set.add(head);
    Node cur = head.next;
    while(true){
        if(set.contains(cur))
            return true;
        else{
            set.add(cur);
            cur=cur.next;
            if(cur==null)
                return false;
        }
    }
}
//快慢指针
public static boolean ifCycle(Node head){
	Node slow = head;
    Node fast = head.next;
    while(fast != slow){
        if(fast == null)
            return false;
        slow = slow.next;
        fast = fast.next.next;
    }
    return true;
}

2)找到环的起始节点

这里一开始还是借助快慢指针,先是判断有无环结构:

  1. 如果有环的话,也就是说快慢指针在环上的某一个结点上重合了。(这是第一个while循环)

  2. 此后就到了本方法的骚气处了【这是通过公式推导出来的规律!!记住这个结论!!!】

    • 将快指针转移到头结点的位置,慢节点还是在原来环上面两个指针相遇的位置
    • 快慢指针的的移动步长都变为一
    • 此时他们再相遇重合的那个位置就是环结点的起始处了(这是第二个while循环),直接上代码:
public ListNode detectCycle(ListNode head) {
    ListNode fast = head;
    ListNode slow = head;
    while(fast != null && fast.next != null){
        fast = fast.next.next;
        slow = slow.next;
        if(slow == fast)
            break;
    }
    if(fast == null || fast.next == null)  //跳出上面循环时有两种可能,一是没有环,另外就是slow == fast。所以需要判断如果										//无环的话,直接返回null
        return null;
    fast = head;
    while(fast != slow){
        fast = fast.next;
        slow = slow.next;
    }
    return fast;
}

8、判断回文结构

借助栈

public static boolean isPalindrome1(Node head) {
	Stack<Node> s = new Stack<Node>();
    Node cur = head;
    while(cur != null){
        s.push(cur);
        cur = cur.next;
    }
    cur = head;
    while(head != null){
        if(head.val != s.pop().val)
            return false;
        head = head.next;
    }
   return true; 
}

本文是基于学习代码随想录,以及自刷leetcode总结链表方面的笔记,不仅仅限于代码随想录笔记,是一些自己的思考和整理。并且是Java版本

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/518399.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【蓝桥杯嵌入式】六、真题演练(二)-1研究篇:第 13 届真题-第二部分

温馨提示&#xff1a; 真题演练分为模拟篇和研究篇。本专栏的主要作用是记录我的备赛过程&#xff0c;我打算先自己做一遍&#xff0c;把遇到的问题和不同之处记录到演练篇&#xff0c;然后再返回来仔细研究一下&#xff0c;找到最佳的解题方法记录到研究篇。题目在&#xff1a…

【CSS】浮动笔记及案例

CSS浮动 1. 认识浮动 float属性可以指定一个元素沿着左侧或者是右侧放置&#xff0c;允许文本和内联元素环绕它 float属性最初只使用文字环绕图片但却是早起CSS最好用的左右布局方案 绝对定位、浮动都会让元素脱标&#xff0c;以达到灵活布局的目的可以通过float属性让元素脱…

SSM实战项目——哈哈音乐(二)后台模块开发

1、项目准备 ① 引入后台模块&#xff08;hami-console&#xff09;需要的依赖 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0…

【Qt】:常用控件(五:显示类控件)

常用控件 一.ProgressBar二. Calendar Widget 一.ProgressBar 使⽤ QProgressBar 表⽰⼀个进度条 代码⽰例:设置进度条按时间增⻓ 设置定时器&#xff0c;每个0.1秒&#xff0c;让进度条1 在实际开发中&#xff0c;进度条的取值&#xff0c;往往是根据当前任务的实际进度来进行…

创意绘图画画小程序:融合白板黑板功能,开启绘画新纪元

创意绘图画画小程序&#xff1a;融合白板黑板功能&#xff0c;开启绘画新纪元 在数字化时代的浪潮下&#xff0c;艺术创作正逐渐摆脱传统形式的束缚&#xff0c;以更加多元、便捷的方式走进人们的生活。其中&#xff0c;创意绘图画画小程序以其独特的白板画、黑板画功能&#…

蓝桥杯真题:k倍区间

import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();int k sc.nextInt();int[] a new int[n];long[] v new long[200000];long…

【注册中心】ZooKeeper

文章目录 概述Zookeeper的应用场景Zookeeper的角色Zookeeper 的数据模型zookeeper客户端常用命令Zookeeper的核心功能Zookeeper的架构与集群规则Zookeeper的工作模式Zookeeper如何实现分布式锁Zookeeper JavaAPI&#xff08;Curator&#xff09;来源 概述 Zookeeper 是一个开源…

手写防抖节流、手写深拷贝、事件总线

一、防抖 手写防抖--基本实现&#xff08;面试&#xff09; 手写防抖并且绑定this和event 添加取消功能 添加立即执行状态&#xff0c;默认不立即执行 underscore库介绍&#xff0c;lodash更轻量级 二、节流 用underscore库&#xff0c;调用throttle函数 手写基础版节流-&#…

Spring重点知识(个人整理笔记)

目录 1. 为什么要使用 spring&#xff1f; 2. 解释一下什么是 Aop&#xff1f; 3. AOP有哪些实现方式&#xff1f; 4. Spring AOP的实现原理 5. JDK动态代理和CGLIB动态代理的区别&#xff1f; 6. 解释一下什么是 ioc&#xff1f; 7. spring 有哪些主要模块&#xff1f;…

数据结构系列-队列的结构和队列的实现

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 队列 队列的概念及结构 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFO&#xff0c;…

Python | Leetcode Python题解之第10题正则表达式匹配

题目&#xff1a; 题解&#xff1a; class Solution:def isMatch(self, s: str, p: str) -> bool:m, n len(s), len(p)dp [False] * (n1)# 初始化dp[0] Truefor j in range(1, n1):if p[j-1] *:dp[j] dp[j-2]# 状态更新for i in range(1, m1):dp2 [False] * (n1) …

【C++】排序算法 --快速排序与归并排序

目录 颜色分类&#xff08;数组分三块思想&#xff09;快速排序归并排序 颜色分类&#xff08;数组分三块思想&#xff09; 给定⼀个包含红⾊、⽩⾊和蓝⾊、共 n 个元素的数组 nums &#xff0c;原地对它们进⾏排序&#xff0c;使得相同颜⾊ 的元素相邻&#xff0c;并按照红⾊、…

【面试八股总结】传输控制协议TCP(一)

参考资料 &#xff1a;小林Coding、阿秀、代码随想录 一、什么是TCP协议 TCP是传输控制协议Transmission Control Protocol TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。 面向连接的&#xff1a;每条TCP连接杜只能有两个端点&#xff0c;每一条TCP连接只能是点对…

js中的事件循环

浏览器进程模型 在理解什么叫事件循环前&#xff0c;我们需要先知道浏览器的进程模型 现代浏览器的功能极度复杂&#xff0c;为了能确保各个部分独立运行互不影响&#xff0c;浏览器会在启动之时开启多个进程&#xff0c;具体而言可以分为以下三种 浏览器进程 负责浏览器的用…

Pulsar服务端处理消费者请求以及源码解析

引言 处理读写是Pulsar服务端最基本也是最重要的逻辑&#xff0c;今天就重点看看服务端是如何处理的读请求也就是消费者请求 正文 Pulsar服务端处理消费者请求的流程大致如下图所示 消费者通过TCP向服务端发起消息拉取请求Broker会根据请求中携带的ID来获取在服务端对应的…

Lua 和 Love 2d 教程 二十一点朴克牌 (上篇lua源码)

GitCode - 开发者的代码家园 Lua版完整原码 规则 庄家和玩家各发两张牌。庄家的第一张牌对玩家是隐藏的。 玩家可以拿牌&#xff08;即拿另一张牌&#xff09;或 停牌&#xff08;即停止拿牌&#xff09;。 如果玩家手牌的总价值超过 21&#xff0c;那么他们就爆掉了。 面牌…

WIFI|软体 茶凳浅谈 高通WIN QSDK - IPQ6000 与 88Q2112 的相遇

Qualcomm IPQ 系列的Ethernet IC 搭配的有 QCA8075, QCA8081 … 等等Qualcomm自家出产的芯片。QSDK中内建可以支持的3rd party芯片&#xff0c;却寥寥可数。日前&#xff0c;客户使用车载以太网 - 88Q2112 - Marvell与IPQ6000做搭配。将之记录下来&#xff0c;以供参考。 方…

传输层 --- TCP (下篇)

目录 1. 超时重传 1.1. 数据段丢包 1.2. 接收方发送的ACK丢包 1.3. 超时重传的超时时间如何设置 2. 流量控制 3. 滑动窗口 3.1. 初步理解滑动窗口 3.2. 滑动窗口的完善理解 3.3. 关于快重传的补充 3.4. 快重传和超时重传的区别 4. 拥塞控制 4.1. 拥塞控制的宏观认识…

2024年华为OD机试真题-推荐多样性-Java-OD统一考试(C卷)

题目描述&#xff1a; 推荐多样性需要从多个列表中选择元素&#xff0c;一次性要返回N屏数据&#xff08;窗口数量&#xff09;&#xff0c;每屏展示K个元素&#xff08;窗口大小&#xff09;&#xff0c;选择策略&#xff1a; 1. 各个列表元素需要做穿插处理&#xff0c;即先从…

新版HI3559AV100开发注意事项(三)

新版HI3559AV100开发注意事项&#xff08;三&#xff09; 十九、用的sdk是Hi3559V200_MobileCam_SDK_V1.0.1.5 播放AAC音频文件&#xff0c;adec->ao;adec的初始化里面包括了aaclc解码器的注册&#xff0c;可是在HI_MPI_ADEC_RegisterDecoder(&s32Handle, &stAac);…