代码随想录算法训练营day4 | 链表(2)

一、LeetCode 24 两两交换链表中的节点

题目链接:24.两两交换链表中的节点icon-default.png?t=N7T8https://leetcode.cn/problems/swap-nodes-in-pairs/

思路:设置快慢指针,暂存节点逐对进行交换。

代码优化前:

/**
 * Definition for singly-linked list.
 * 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) {
        if(head == null || head.next == null){
            return head;
        }
        //头部结点交换
        ListNode cur = head;         //cur存储节点1
        ListNode now = cur.next;    //now存储节点2
        ListNode temp_n = now;       //暂存节点2
        ListNode temp_c = now.next;  //暂存下一轮的节点_1
        now.next = cur;              //节点2 → 节点1
        head = now;                  //head - 节点2
        now = cur;                   //now - 节点1
        cur.next = temp_c;           //节点1 → 节点_1
        cur = temp_c;                //cur - 节点_1
        //while循环中逻辑与上同
        while(cur != null && cur.next != null){
            temp_n = now;
            now = cur.next;
            temp_n.next = now;
            temp_c = now.next;
            now.next = cur;
            now = cur;
            cur.next = temp_c;
            cur = temp_c;
        }
        return head;
    }
}

代码优化后:

二、LeetCode 19 删除链表的倒数第N个节点

题目链接:19.删除链表的倒数第N个节点icon-default.png?t=N7T8https://leetcode.cn/problems/remove-nth-node-from-end-of-list/

思路:考虑使用快慢指针。先处理特殊情况(单节点链表或删除头结点);快慢指针同时后移、找到要删除节点的前一个节点做删除处理。

/**
 * Definition for singly-linked list.
 * 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 removeNthFromEnd(ListNode head, int n) {
        //单个元素
        if(head.next == null){
            return null;
        }
        ListNode slow = head;
        ListNode fast = head;
        //删除倒数第n个节点、快指针先行n步
        while(fast != null && n > 0){
            fast = fast.next;
            n--;
        }
        //fast先行n步到链表末尾,说明要删除第一个节点
        if(fast == null){
            return head.next;
        }
        //slow指针与fast指针同时后移,找到要删除节点的前一个节点
        //(所以是fast.next!=null 而不是fast != null)
        while(fast.next != null){
            slow = slow.next;
            fast = fast.next;
        }
        //删除节点
        slow.next = slow.next.next;
        return head;
    }
}

 三、LeetCode 面试题 02 07 链表相交

题目链接:面试题02.07.链表相交icon-default.png?t=N7T8https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/

思路:

计算链表A、B长度、并把指针移动到链表结尾;利用链表A、B长度差,调整较长链表的遍历指针到剩余长度与较短链表的长度相同的位置;A、B遍历指针同步后移,找到相交位置。

/**
 * Definition for singly-linked list.
 * 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 index_a = headA;
        ListNode index_b = headB;
        //处理链表A、B为空的情况
        if(index_a == null || index_b == null){
            return null;
        }
        //计算链表A、B长度、并把指针移动到链表结尾
        int len_a = 1,len_b = 1;
        while(index_a != null && index_a.next != null){
            index_a = index_a.next;
            len_a++;
        }
        while(index_b != null && index_b.next != null){
            index_b = index_b.next;
            len_b++;
        }
        //结尾指针指向的节点不同,说明不相交
        if(index_a != index_b){
            return null;
        }
        //指针回到头部
        index_a = headA;
        index_b = headB;
        //利用链表A、B长度差,调整较长链表的遍历指针到剩余长度与较短链表的长度相同的位置
        //A、B遍历指针同步后移,找到相交位置
        if(len_a > len_b){
            int num = len_a - len_b;
            while(num > 0){
                index_a = index_a.next;
                num--;
            }
            while(index_a != index_b){
                index_a = index_a.next;
                index_b = index_b.next;
            }
        }else{
            int num = len_b - len_a;
            while(num > 0){
                index_b = index_b.next;
                num--;
            }
            while(index_a != index_b){
                index_a = index_a.next;
                index_b = index_b.next;
            }
        }
        return index_a;
    }
}

 四、LeetCode 142 环形链表II

题目链接:142.环形链表IIicon-default.png?t=N7T8https://leetcode.cn/problems/linked-list-cycle-ii/description/

思路:

        先判断是否有环:设置快慢指针fast、slow。在每个循环中,fast后移2次、slow后移1次,作图可知,若链表有环,则fast与slow必然能够相遇且必定在环内相遇。

        再确定环入口:设head到环入口的长度为x,环入口到fast、slow相遇点的长度为y,相遇点到换入口的长度为z,fast在环内转了n圈才遇到slow;又因为fast的移动距离是slow的2倍,则可列: x+y+n*(y+z) = 2*(x+y) → x = (n-1)*(y+z)+z。

        当n = 1时,x = z,设置指针index_1 = head,index_2 = slow/fast(即相遇位置),易知index_1与index_2以相同的速度后移再相遇的位置即为环入口。

示意图:

代码如下:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while(fast != null && fast.next != null){
            //fast指针移速是slow指针的2倍
            fast = fast.next.next;
            slow = slow.next;
            //fast与slow相遇
            if(slow == fast){
                ListNode index_1 = head;
                ListNode index_2 = slow;
                //由思路中的数学分析进行同步后移操作
                while(index_1 != index_2){
                    index_1 = index_1.next;
                    index_2 = index_2.next;
                }
                return index_1;
            }
        }
        //fast最终指向null,链表无环
        return null;
    }
}

五、今日小结

        链表知识果然难呜呜呜,好在坚持写完了~ 24、19两题有待优化,142不熟练过几天需要回顾。最近休息不太好很影响效率和状态,明天出门运动、调整作息,加油!

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

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

相关文章

435. 无重叠区间 - 力扣(LeetCode)

题目描述 给定一个区间的集合 intervals ,其中 intervals[i] [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 。 题目示例 输入: intervals [[1,2],[2,3],[3,4],[1,3]] 输出: 1 解释: 移除 [1,3] 后,剩下的区间没有重…

Django模型(一)

一、介绍 模型,就是python中的类对应数据库中的表 1.1、ORM ORM 就是通过实例对象的语法,完成关系型数据库的操作的技术,是"对象-关系映射"(Object/Relational Mapping) 的缩写 ORM 把数据库映射成对象 1.2、示例 1.2.1、模型 from django.db import models…

海康实时监控预览视频流接入web

我们采取的方案是后端获取视频流返回给前端,然后前端播放 海康开放平台海康威视合作生态致力打造一个能力开放体系、两个生态圈,Hikvision AI Cloud开放平台是能力开放体系的核心内容。它是海康威视基于多年在视频及物联网核心技术积累之上,…

我们应该怎样定义 BTC Layer2?

撰文:Jademont,水滴资本创始人 原文来自Techub News:我们应该怎样定义 BTC Layer2? 广义的 BTC Layer2: 只要消耗 BTC 作为 gas,以 BTC 为底层资产,可以做为 dapp 平台,性能又远优…

【2024】Docker部署Redis

1.说明: 因为容器实例的运行是有生命周期的,一些redis的备份、日志和配置文件什么的最好还是放在服务器本地。这样当容器删除时,我们也可以保留备份和日志文件。所以先在本地服务器安装redis并配置文件设置。下面是安装步骤: 2.安装步骤 1…

人脸识别 FaceNet人脸识别(一种人脸识别与聚类的统一嵌入表示)

人脸识别 FaceNet人脸识别(一种人脸识别与聚类的统一嵌入表示) FaceNet的简介Facenet的实现思路训练部分 FaceNet的简介 Facenet的实现思路 import torch.nn as nndef conv_bn(inp, oup, stride 1):return nn.Sequential(nn.Conv2d(inp, oup, 3, stride…

什么是RBAC

什么是RBAC 概述:RBAC:Role-Based Access Control详解:什么是基于⻆⾊的访问控制具体实现:如何设计RABC模型其他介绍:RBAC支持三个著名的安全原则 概述:RBAC:Role-Based Access Control RBAC&a…

【网站项目】基于SSM的228图书商城网站

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…

数据监控-Prometheus/Grafana

一、数据监控Prometheus 1、什么是Prometheus Prometheus是由SoundCloud开源监控告警解决方案,从2012年开始编写代码,到2015年github上开源以来,吸引不少用户以及公司的使用。Prometheus作为新一代的开源解决方案,很多理念与Google SRE的运维之道不谋而合。 2、Promet…

YOLO自制数据集及训练

使用 Make Sense 网站进行标注 https://www.makesense.ai/可以让AI帮你先标一下 一定要点一下 + ,不然不会加进去 导出标签

【第五天】蓝桥杯备战

1、金币 https://www.lanqiao.cn/problems/357/learning/ 解法:暴力 import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) {Scanner scan new Scanner(System.in);//在此输入…

蓝牙----蓝牙GAP层

蓝牙协议栈----GAP GAP的角色连接过程连接参数 GAP:通用访问配置协议层 gap的角色发现的模式与过程连接模式与过程安全模式与过程 CC2640R2F的GAP层抽象 GAP的角色 Broadcaster 广播电台 -不可连接的广播者。Observer 观察者 -扫描广播者但无法启动连接。Periphe…

SpringBoot系列之JPA实现按年月日查询

SpringBoot系列之JPA实现按年月日查询 通过例子的方式介绍Springboot集成Spring Data JPA的方法,进行实验,要先创建一个Initializer工程,如图: 选择,需要的jdk版本,maven项目 选择需要的maven配置&#x…

了解维特比算法:通信系统和自然语言处理中解码的基石

一、介绍 在数字通信和信号处理领域,维特比算法是一种革命性的纠错和解码方法。该算法以 1967 年推出的 Andrew Viterbi 的名字命名,已成为数字通信和自然语言处理领域的基础。本文旨在深入研究维特比算法的复杂性,探讨其理论基础、实际应用以…

【JavaEE进阶】 数据库连接池与MySQL企业开发规范

文章目录 🌴数据库连接池🎋数据库连接池的使用🎄MySQL企业开发规范⭕总结🌴数据库连接池 数据库连接池负责分配、管理和释放数据库连接,它允许应⽤程序重复使⽤⼀个现有的数据库连接,⽽不是再重新建⽴⼀个. 没有使⽤数据库连接池的情况:每次执⾏SQL语句,要先创建⼀…

数据库 sql select *from account where name=‘张三‘ 执行过程

select *from account where name张三分析上面语句的执行过程 用到了索引 由于是根据 1.name字段进行查询,所以先根据name张三’到name字段的二级索引中进行匹配查 找。但是在二级索引中只能查找到 Arm 对应的主键值 10。 2.由于查询返回的数据是*&#xff0c…

排序(1)——直接插入排序、希尔排序

目录 一、直接插入排序 1.简介 2.思路与代码 3.复杂度与稳定性分析 (1)时间复杂度 (2)空间复杂度 (3)稳定性 二、希尔排序 1.简介 2.思路与代码 (1)分组排序 &#xff08…

python222网站实战(SpringBoot+SpringSecurity+MybatisPlus+thymeleaf+layui)-帖子管理实现

锋哥原创的SpringbootLayui python222网站实战: python222网站实战课程视频教程(SpringBootPython爬虫实战) ( 火爆连载更新中... )_哔哩哔哩_bilibilipython222网站实战课程视频教程(SpringBootPython爬虫实战) ( 火…

Go的基准测试

基准测试(Benchmark)是一项用于测量和评估软件性能指标的方法,主要用于评估你写的代码的性能。 基准测试的代码文件必须以_test.go结尾基准测试的函数必须以Benchmark开头,必须是可导出的基准测试函数必须接受一个指向Benchmark类…

Blender教程-初始用户界面-01

开始第一天的Blender学习、也是业余学习。希望记录下这一份学习的过程、并且分享给大家。今天带大家认识Blender这一款软件,先说说我为什么选择了Blender,我在软件市场找了好久,市场上其他雷同软件都是要么收费要么不好用,最终决定…