java算法day4

  • 删除链表的倒数第N个结点
  • 链表相交
  • 环形链表

删除链表的倒数第N个结点

解法:双指针(快慢指针)
首先一定要有删除结点的思想。所以这个题是用虚拟头结点比较方便。
先上模拟图,然后看流程:
请添加图片描述
这里后移根据不同的想法有不同的后移步数。
这里我比较喜欢移动对应的上的步数。这里图里面的解法是移动n+1步。其实移动n步也可以做。
我写一个移动n步的。
请添加图片描述
我比较喜欢这个图的做法。

流程:
1.初始化fast=dummyhead,slow=dummyhead。
2.先让fast走n步。
3.然后fast和slow一起走。
4.一起走的循环停止条件:fast.next!=null。
5.此时完成删除操作即可,slow.next = slow.next.next;

/**
 * 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) {
        ListNode dummyhead = new ListNode(0); //创建一个虚拟头结点
        dummyhead.next = head; //把虚拟头结点加在链表前面
        ListNode fast = dummyhead; //快慢指针都指向头结点
        ListNode slow = dummyhead;
        for(int i = 0;i<n;i++){ //让快的指针先走n步
            fast = fast.next;
        }
        while(fast.next!=null){ //两个一起走。注意这个终止条件,按图来。
            fast = fast.next;
            slow = slow.next;
        }

        slow.next = slow.next.next; //删除操作
        return dummyhead.next; //返回链表头结点。
    }
}

链表相交

这里进行一个小总结:虚拟头结点一般是需要做修改操作时才用到。查找一般不用

这个解法很特殊,建议记下来。
也是双指针解法,但是有数学规律。

请添加图片描述
解法总结一句话:

只要两个有相交,A,B同时往后走,A到底(null)后指回B,B到底后指回A。依然同时往后走,最终一定会相遇。

根据这句话代码很容易就写出来了。

/**
 * 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 a = headA;
        ListNode b = headB;
        //终止的条件就是二者相遇。
        while(a!=b){
            if(a==null){
                a = headB; //a走到底了就到B
            }else{
                a = a.next;
            }

            if(b==null){
                b = headA;//b走到底了就到A
            }else{
                b = b.next;
            }
        }
        return a; //最后a=b了。随便返回一个。
    }
}

如果不懂为什么这么干就可以得到相等。可以看看这个数学推导。
请添加图片描述
按刚刚的流程会发现,a走到相交结点走的步数就是a-c+c+b-c = a+b-c
b走到相交结点的步数是b-c+c+a-c = a+b-c
会发现其实a,b沿着这样的路线走到首个公共结点。走的步数是一样的。

所以就可以推出两个一直往后走,然后走到底了a到B开始,b到A开始。肯定会到首个公共结点相遇。因为走的步数是一样的。


环形链表Ⅱ

直接看这个题解:
https://leetcode.cn/problems/linked-list-cycle-ii/solutions/12616/linked-list-cycle-ii-kuai-man-zhi-zhen-shuang-zhi-

里面有一张图,看完我只能说就做出来了。

做法总结:

设置双指针,fast和slow。fast两次从head头结点出发。
第一次:
fast一次走两步,slow一次走一步。如果有环那slow和fast一定会相遇。
第二次:也就是slow和fast相遇了,fast回到head。之后,fast和slow同时走,两个都是每次只走一步。最终fast和slow一定会再相遇。而且相遇的这个点就是环的第一个点。

注意循环条件。
第一次两个相遇,这个循环必须要永真循环。因为这个循环还必须做一个特判。如果fast走下去走到了null。就必须直接return null了。
那么这里就要写个if判断,由于fast要走两步,所以就要判断fastnull || fast.nextnull。并且这样有一个短路的效果。

第二个相遇就是两个无脑后退,while的条件就是slow != fast。

/**
 * 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 fast = head; //起点都在head
        ListNode slow = head;
        while(true){ //第一个循环
            if(fast == null || fast.next == null){//而且还弄了个短路效果
                return null;  //特判,万一没有环。
                //由于每次都要走两步,这里还有个细节,还防止了head=null的情况,那么就要判断,fast==null,然后再判断下一步,如果fast.next=null。那么就也没必要走了。因为下一次一次走两步,会导致fast = null。所以逻辑是对的。
            }
            fast = fast.next.next; //fast一次走两步
            slow = slow.next;  //slow一次一步
            if(fast == slow){
                break;  //第一次相遇就停下来
            }
        }

        fast = head; //fast回到头结点。
        while(slow!=fast){ //下一次二者相遇的时候就是环的第一个结点
            slow = slow.next; //二者一次走一步
            fast = fast.next;
        }

        return fast; //返回fast和slow都行
        
    }
}

数学推导:
设:链表头部到环入口(不包括环的入口元素) 为a,环有b个结点,则链表总共有a+b个结点。

在第一轮。两个指针分别走了。f和s步。
fast走的步数是slow的两倍。即f=2s。
fast比slow多走了n个环的长度,即f=s+nb(这个自己多想想)。
两式相减得到s=nb。f =2nb。所以可得到。fast和slow分别走了2n和n个环的周长。

如果让指针从链表头部一直往前走并统计步数k,那么所有走到链表入口节点时的步数是k=a+nb,即先走a步到入口节点。之后每绕一圈环(b步)都会再次到入口节点。而目前slow指针走了nb步。因此,我们只要想办法slow再走a步停下来,就可以到环的入口了。

但是我们不知道这个到底是多少,那么此时仍然是双指针法,考虑构建一个指针,此指针需要有这样的性质:和slow同时往前走a步后,两者在入口节点重合。此时显而易见,从哪里走到入口节点需要a步?那就是head头节点。

所以第二次相遇的逻辑就来了。
1.令fast重新指向head。此时f = 0,s = nb。
2.slow和fast同时每轮往前走一步
3.当fast指针走到f = a步时,slow指针就走到了s = a+nb,此时fast和slow在环入口重合。返回slow指向的结点即可。

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

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

相关文章

java优先级队列(堆)详解

一、优先级概念 什么是优先级&#xff1a;比如女士优先&#xff0c;个子低的优先排到前面去&#xff0c;有一部分数据具备优先级&#xff0c;要以优先级的顺序将顺序存储起来。 前面介绍过队列&#xff0c;队列是一种先进先出(FIFO)的数据结构&#xff0c;但有些情况下&#…

OceanBase开发者大会2023届视频及PPT汇总

数据库技术趋势 我眼中的数据库技术 阳振坤OceanBase 首席科学家 观看视频 下载 PDF 未来&#xff0c;中国需要什么样的数据库&#xff1f; 周傲英华东师范大学副校长&#xff0c;CCF 会士 观看视频 下载 PDF 云原生技术趋势解读 Keith ChanCNCF 云原生计算基金会中国区总监 …

开发工具的使用

IDEA的安装与使用&常用快捷键 文章目录 IDEA的安装与使用&常用快捷键一、认识IntelliJ IDEA二、IDEA 的下载&卸载三、IEAD相关设置3.1 JDK的相关设置3.2 系统设置&#xff08;启动项/自动更新&#xff09;3.3 设置整体主题&#xff08;主题/字体/背景&#xff09;3…

Linux--链表 第二十五天

1. 链表 t1.next -> data t1.next->next->data .(点号)的优先级比->的大 所以 t1.next->data 就可以了 不用(t1.next)->data 2. 链表的静态增加和动态遍历 打印链表算法&#xff0c; void printLink(struct Test *head) { struct Te…

如何做一个优秀的系统工程师?

一、背景 做好一个优秀系统工程师的关键在于其在产品开发生命周期中对需求分析的有效把握与运用&#xff0c;这个过程直接影响到系统的整体架构设计、规格参数的明确设定以及业务流程的深度挖掘与优化。需求分析不仅是理解用户实际问题的核心环节&#xff0c;更是界定系统开发…

Java基础之JVM对象内存分配机制简介

一 对象内存分配 1.1 运行时数据区域 1.2 常见java应用启动JVM参数&#xff1a; -Xss&#xff1a;每个线程的栈大小(单位kb)-Xms&#xff1a;堆的初始大小&#xff0c;默认物理内存的1/64,示例&#xff1a;-Xms:4g -Xms:10m-Xmx&#xff1a;堆的最大可用大小&#xff0c;默认物…

LeetCode 热题 100 题解:普通数组部分

文章目录 题目一&#xff1a;最大子数组和&#xff08;No. 53&#xff09;题解 题目二&#xff1a;合并区间&#xff08;No. 56&#xff09;题解 题目三&#xff1a;轮转数组&#xff08;No. 189&#xff09;题解 题目四&#xff1a;除自身以外数组的乘积&#xff08;No. 238&a…

springSecurity用户认证和授权

一&#xff0c;框架介绍 Spring 是一个非常流行和成功的 Java 应用开发框架。Spring Security 基于 Spring 框架&#xff0c;提供了一套 Web 应用安全性的完整解决方案。一般来说&#xff0c;Web 应用的安全性包括用户认证&#xff08;Authentication&#xff09;和用户授权&am…

zig v0.12.0 发布 — x-cmd 提供 zig 快捷安装方法和 x zig 模块

文章目录 简介功能特点v0.12.0 新特性[重新设计 Autodoc 的工作原理](https://ziglang.org/download/0.12.0/release-notes.html#Redesign-How-Autodoc-Works)语法变更各类标准库变更构建系统变更 常见用法**使用案例**:竞品和相关项目进一步阅读 简介 Zig 是一种通用编程语言…

模电期末复习(五)集成运算放大电路

集成运算放大电路 5.1 集成放大电路的特点5.2 集成运放的主要技术指标5.3 集成运放的基本组成部分5.3.1 偏置电路5.3.2 差分放大输入级5.3.3 中间级5.3.4 输出级 5.4 集成运放的典型电路5.4.1 双极型集成运放LM741 5.5 各类集成运放的性能特点5.6 集成运放使用中的几个具体问题…

JAVAEE——IP协议

文章目录 IP协议IP协议报头格式IP协议报头的各个区段四位版本四位首部长度八位服务类型16位总长度16位标识&#xff0c;3位标志&#xff0c;13位片偏移八位生存时间八位协议 地址管理IP地址解决提议1&#xff1a;动态分配Ip地址解决提议2&#xff1a;NAT机制 IP协议 IP协议报头…

基于SpringBoot+Vue钢材销售管理系统的设计与实现

系统介绍 为了更好地发挥本系统的技术优势&#xff0c;根据钢材销售管理系统的需求&#xff0c;本文尝试以B/S经典设计模式中的Spring Boot框架&#xff0c;JAVA语言为基础&#xff0c;通过必要的编码处理、钢材销售管理系统整体框架、功能服务多样化和有效性的高级经验和技术…

分类神经网络3:DenseNet模型复现

目录 DenseNet网络架构 DenseNet部分实现代码 DenseNet网络架构 论文原址&#xff1a;https://arxiv.org/pdf/1608.06993.pdf 稠密连接神经网络&#xff08;DenseNet&#xff09;实质上是ResNet的进阶模型&#xff08;了解ResNet模型请点击&#xff09;&#xff0c;二者均是…

葡萄书--关系图卷积神经网络

异质图和知识图谱 同质图与异质图 同质图指的是图中的节点类型和关系类型都仅有一种 异质图是指图中的节点类型或关系类型多于一种 知识图谱 知识图谱包含实体和实体之间的关系&#xff0c;并以三元组的形式存储&#xff08;<头实体, 关系, 尾实体>&#xff0c;即异…

vlan的学习笔记1

vlan&#xff1a; 1.一般情况下:以下概念意思等同: 一个vlan一个广播域 一个网段 一个子网 2.一般情况下: &#xff08;1&#xff09;相同vlan之间可以直接通信&#xff0c;不同vlan之间不能直接通信! &#xff08;2&#xff09;vlan技术属于二层技术&…

三、Flask模型基础

ORM 创建模型 # exts.py:插件管理 # 扩展的第三方插件 # 1.导入第三方插件 from flask_sqlalchemy import SQLAlchemy # ORM插件 from flask_migrate import Migrate # 2. 初始化 db = SQLAlchemy() # ORM migrate = Migrate() # 数据迁移 # 3. 和app对象绑定 def init_ex…

基于Bootstrap 4的企业项目体验服务网站模板

目录 一.前言 二.展示 三.下载链接 一.前言 网页包含以下内容&#xff1a; 页面基本信息&#xff1a;设置页面的字符集、兼容性、视口等元数据。 网站标题和描述&#xff1a;定义了网站的标题为"Benten"&#xff0c;同时也设置了关键词和描述。 CSS样式表链接&a…

基于SpringBoot+Vue七匹狼商城系统的设计与实现

系统介绍 近年来随着社会科技的不断发展&#xff0c;人们的生活方方面面进入了信息化时代。计算机的普及&#xff0c;使得我们的生活更加丰富多彩&#xff0c;越来越多的人使用通过网络来购买各类的商品。早期商品的销售和购买都是通过实体店&#xff0c;这种购买方式需要耗费…

《苍穹外卖》Day03部分知识点记录

一、公共字段自动填充 业务表中的公共字段&#xff1a; 序号字段名含义数据类型操作类型1create_time创建时间datetimeinsert2create_user创建人idbigint3update_time修改时间datetimeinsert、update4update_user修改人idbigint 问题&#xff1a;代码冗余&#xff0c;不便于…

const成员函数 以及 取地址及const取地址操作符重载

目录 const成员函数 结论&#xff1a; 取地址及const取地址操作符重载 const成员函数 将const 修饰的 “ 成员函数 ” 称之为 const成员函数 &#xff0c; const 修饰类成员函数&#xff0c;实际修饰该成员函数的&#xff08;*this&#xff09; &#xff0c;表明在该成员函数…