重启人生计划-浮舟沧海

news2024/9/22 21:33:50

🥳🥳🥳 茫茫人海千千万万,感谢这一刻你看到了我的文章,感谢观赏,大家好呀,我是最爱吃鱼罐头,大家可以叫鱼罐头呦~🥳🥳🥳

如果你觉得这个【重启人生计划】对你也有一定的帮助,加入本专栏,开启新的训练计划,漫长成长路,千锤百炼,终飞升巅峰!无水文,不废话,唯有日以继日,终踏顶峰! ✨✨欢迎订阅本专栏✨✨

❤️❤️❤️ 最后,希望我的这篇文章能对你的有所帮助! 愿自己还有你在未来的日子,保持学习,保持进步,保持热爱,奔赴山海! ❤️❤️❤️

🔥【重启人生计划】第零章序·大梦初醒🔥

🔥【重启人生计划】第壹章序·明确目标🔥

🔥【重启人生计划】第贰章序·勇敢者先行🔥

🔥【重启人生计划】第叁章序·拒绝内耗🔥

🔥【重启人生计划】第四章序·积蓄星火🔥

序言

大家好,我是最爱吃鱼罐头,距离离职已经过去一个月了,目前进度为4,打算重新找工作倒计时26天,当然这其中也会去投递面试。

没有信仰的人群川流不息,繁华的城市充斥着愚昧,因为生命存在着且有其独特之处。

今日回顾

今天早上大概回顾了下MySQL的面试题,后面就刷day5的算法题,难度适中,是需要理解链表的数据结构。

然后今天下午去了医院检查了下皮肤,也做一点手术换肤术、粉刺去除术,这一套下来脸部是又痒用疼的,尤其这个粉刺去除术,脸部基本都被扎烂了。。。闭着眼,偷偷扎你一下,还要硬挤你痘痘出来,这个挤是真疼,都已经疼出泪花了。。。

然后今天也没背诵,没有看视频,我决定明天补一下,然后再看一下视频。

算法回顾

反转链表 II

反转链表 II 📍

这道题和昨天的反转链表 📍类似,但又有些不同,不同在于反转的是局部,不是对整个链表进行操作,那这道题的关键在于**先找到局部区域的左结点,在左结点和右结点之间进行链表反转的操作即可。**并且这道题的另一个关键在于创建一个虚拟头结点,这样才能更好反转头结点。

主要步骤

  1. 创建一个虚拟头结点并指向head结点;
  2. 找到left位置的前一个结点preNode;
  3. 反转指定局部区间的链表;
  4. 在需要反转的区间里,每遍历到一个结点,让这个新结点来到反转部分的起始位置,一直反转到right位置;
    • preNode:永远指向待反转区域的第一个结点 left 的前一个结点;
    • curNode:指向待反转区域的第一个结点 left;
    • nextNode:指向curNode的next结点;
    • 需要做的操作:将curNode的下一个结点指向 nextNode 的下一个结点;把 pre 的下一个结点指向 next;最后把 nextNode 的下一个结点指向 pre的下一个结点;
  5. 最后返回虚拟头结点的下一个结点。

图解:

代码实现:

package com.ygt.day5;

import com.ygt.day4.ListNode;

/**
 * 92. 反转链表 II
 * https://leetcode.cn/problems/reverse-linked-list-ii/description/
 * 给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。
 * 请你反转从位置 left 到位置 right 的链表结点,返回 反转后的链表 。
 * 输入:head = [1,2,3,4,5], left = 2, right = 4
 * 输出:[1,4,3,2,5]
 * @author ygt
 * @since 2024/8/15
 */
public class ReverseBetween {
    public static void main(String[] args) {
        ListNode node5 = new ListNode(5);
        ListNode node4 = new ListNode(4, node5);
        ListNode node3 = new ListNode(3, node4);
        ListNode node2 = new ListNode(2, node3);
        ListNode node = new ListNode(1, node2);

        // 打印查看当前效果
        ListNode.print(node);

        ListNode listNode = new ReverseBetween().reverseBetween(node, 2, 4);
        System.out.println();

        // 打印查看当前效果
        ListNode.print(listNode);
    }

    public ListNode reverseBetween(ListNode head, int left, int right) {
        // 1. 创建一个虚拟头结点并指向head结点;
        // 为避免出现left出现在第一个结点
        ListNode dummyNode = new ListNode(-1, head);

        // 2. 找到left位置的前一个结点preNode;
        ListNode preNode = dummyNode;
        for (int i = 0; i < left - 1; i++) {
            preNode = preNode.next;
        }

        // 3. 反转指定局部区间的链表;
        // 在找到left的前结点后,可以在left和right区间的链表进行反转了
        //  1 --> 2 --> 3 --> 4 --> 5 待反转区域为 2 --> 3 --> 4
        // 定义当前结点
        ListNode curNode = preNode.next;

        // 4. 在需要反转的区间里,每遍历到一个结点,让这个新结点来到反转部分的起始位置,一直反转到right位置;
        // 开始遍历反转
        for (int i = left; i < right; i++) {
            // 当前结点的next结点
            ListNode nextNode = curNode.next;
            // 将当前结点的next指向了 nextNode的next结点 即 2 --> 4
            curNode.next = nextNode.next;
            // 将nextNode的next指向了 preNode的next结点 即 3 --> 2
            nextNode.next = preNode.next;
            // 将preNode的next指向了 nextNode 即 1 --> 3
            preNode.next = nextNode;

        }
        // 5. 最后返回虚拟头结点的下一个结点。
        return dummyNode.next;
    }
}

最后注意虚拟头结点:

链表的一大问题就是操作当前结点必须要找前一个结点才能操作。这就造成了,头结点的尴尬,因为头结点没有前一个结点了。

每次对应头结点的情况都要单独处理,所以使用虚拟头结点的技巧,就可以解决这个问题。而且很多链表的题目中,都大多数需要用到虚拟头结点。

删除排序链表中的重复元素 II

删除排序链表中的重复元素 II📍

这道题和昨天的删除排序链表中的重复元素📍类似,但又有些不同,不同在于删除元素上,这道题删除的是全部重复元素,不能有保留,比昨天额外需要做的一步是,循环一直跳过当前结点,直到不同为止,并且为了避免第一个元素就是重复的情况下,所以也得创建一个虚拟头结点。

代码实现:

package com.ygt.day5;

import com.ygt.day4.ListNode;

/**
 * 82. 删除排序链表中的重复元素 II
 * https://leetcode.cn/problems/remove-duplicates-from-sorted-list-ii/description/
 * 给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的结点,只留下不同的数字 。返回 已排序的链表 。
 * 输入:head = [1,2,3,3,4,4,5]
 * 输出:[1,2,5]
 * @author ygt
 * @since 2024/8/15
 */
public class DeleteDuplicates {
    public static void main(String[] args) {

        ListNode node7 = new ListNode(5);
        ListNode node6 = new ListNode(4, node7);
        ListNode node5 = new ListNode(4, node6);
        ListNode node4 = new ListNode(3, node5);
        ListNode node3 = new ListNode(3, node4);
        ListNode node2 = new ListNode(2, node3);
        ListNode node = new ListNode(1, node2);

        // 打印查看当前效果
        ListNode.print(node);

        ListNode listNode = new DeleteDuplicates().deleteDuplicates(node);
        System.out.println();

        // 打印查看当前效果
        ListNode.print(listNode);
    }

    public ListNode deleteDuplicates(ListNode head) {
        // 1. 创建一个虚拟头结点并指向head结点;
        // 为避免出现第一个结点就重复的情况
        ListNode dummyNode = new ListNode(-1, head);

        // 前一个结点
        ListNode preNode = dummyNode;

        // 从虚拟头结点出发,为啥不直接 ListNode preNode = dummyNode.next;
        // 因为第一个结点有可能重复呀。
        while (preNode.next != null && preNode.next.next != null) {
            // 当前值
            int curVal = preNode.next.val;
            // next值
            int nextVal = preNode.next.next.val;

            // 两种情况,
            if(curVal != nextVal){
                // 当前值与next值不同
                // curNode.next可以正常指向,无需改变,也就是后移一位。
                preNode = preNode.next;
            }else{
                // 相同
                // 就得循环找到不同的值为止
                do {
                    // 跳过当前结点
                    preNode.next = preNode.next.next;
                }while (preNode.next != null && preNode.next.val == curVal);

            }
        }
        return dummyNode.next;
    }
}

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

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

这道题有两个关键点:

  1. 必须要有虚拟头结点,避免删除结点刚好是第一个的情况;
  2. 如何确定链表的倒数第 N 个结点呢?首先要确定删除某个结点话,一般是找到待删除结点的前一个结点,所以思路如下:
    • 让一个指针fast先走N步,然后创建一个指针slow和fast一起走,直到fast遇到了null,这时slow就是倒数第 N 个结点的前一个结点
    • 接着进行删除操作即可。

代码实现:

package com.ygt.day5;

import com.ygt.day4.ListNode;

/**
 * 19. 删除链表的倒数第 N 个结点
 * https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/
 * 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
 * 输入:head = [1,2,3,4,5], n = 2
 * 输出:[1,2,3,5]
 * @author ygt
 * @since 2024/8/15
 */
public class RemoveNthFromEnd {
    public static void main(String[] args) {
        // 测试反转链表
        ListNode node5 = new ListNode(5);
        ListNode node4 = new ListNode(4, node5);
        ListNode node3 = new ListNode(3, node4);
        ListNode node2 = new ListNode(2, node3);
        ListNode node = new ListNode(1, node2);

        // 打印查看当前效果
        ListNode.print(node);

        ListNode list = new RemoveNthFromEnd().removeNthFromEnd(node, 2);
        System.out.println();

        // 打印查看当前效果
        ListNode.print(list);
    }

    public ListNode removeNthFromEnd(ListNode head, int n) {
        if (head == null) {
            return null;
        }

        // 1. 创建一个虚拟头结点并指向head结点;
        // 为避免出现 删除结点刚好是第一个的情况
        ListNode dummyNode = new ListNode(-1, head);

        // 主要思路:让一个指针fast先走N步,然后创建一个指针slow和fast一起走,直到fast遇到了null,
        // 这时slow就是倒数第 N 个结点的前一个结点;

        ListNode fastNode = dummyNode;
        // 在移动过程中,必须额外判断是否有为空的情况。
        for (int i = 0; i < n && fastNode.next != null; i++) {
            fastNode = fastNode.next;
        }

        ListNode slowNode = dummyNode;
        while (fastNode.next != null) {
            // 一起移动,直到fast遇到null
            slowNode = slowNode.next;
            fastNode = fastNode.next;
        }

        // 删除
        slowNode.next = slowNode.next.next;

        return dummyNode.next;
    }
}

移除链表元素

移除链表元素 📍

最后这道题,就很简单了吧,主要关键点:

  1. 必须要有虚拟头结点,避免删除结点刚好是第一个的情况;
  2. 遍历过程遇到与题目要求的值相同时,直接删除。

代码实现:

package com.ygt.day5;

import com.ygt.day4.ListNode;

/**
 * 203. 移除链表元素
 * https://leetcode.cn/problems/remove-linked-list-elements/description/
 * 给你一个链表的头结点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的结点,并返回 新的头结点 。
 * 输入:head = [1,2,6,3,4,5,6], val = 6
 * 输出:[1,2,3,4,5]
 * @author ygt
 * @since 2024/8/15
 */
public class RemoveElements {
    public static void main(String[] args) {
        ListNode node6 = new ListNode(6);
        ListNode node5 = new ListNode(5, node6);
        ListNode node4 = new ListNode(4, node5);
        ListNode node3 = new ListNode(3, node4);
        ListNode node22 = new ListNode(6, node3);
        ListNode node2 = new ListNode(2, node22);
        ListNode node = new ListNode(1, node2);

        // 打印查看当前效果
        ListNode.print(node);

        ListNode list = new RemoveElements().removeElements(node, 6);
        System.out.println();

        // 打印查看当前效果
        ListNode.print(list);
    }

    public ListNode removeElements(ListNode head, int val) {
        if (head == null) {
            return null;
        }

        // 1. 创建一个虚拟头结点并指向head结点;
        // 为避免出现 删除结点刚好是第一个的情况
        ListNode dummyNode = new ListNode(-1, head);

        // 前一个结点
        ListNode preNode = dummyNode;

        while (preNode.next != null) {
            // 开始判断
            if(preNode.next.val == val) {
                // 相同
                preNode.next = preNode.next.next;
            }else {
                // 不同
                preNode = preNode.next;
            }
        }
        return dummyNode.next;
    }
}

不是,这它写的跟我有什么不同吗。。。。。我1ms,它0ms。这不区别对待?

小结算法

今天的算法还是相对比较简单,很好刷,认真思考下,就可以完成的,但是前提得要有链表的基础。

明日内容

算法

在有链表的基础上进行链表的算法题,可以事半功倍。

需要有链表以及双指针的基础。

  • 链表的中间结点 📍
  • 环形链表 📍
  • 环形链表 II 📍
  • 相交链表📍

🌸 完结

最后,相关算法的代码也上传到gitee或者github上了。

乘风破浪会有时 直挂云帆济沧海

希望从明天开始,一起加油努力吧,成就更好的自己。

🥂 虽然这篇文章完结了,但是我还在,永不完结。我会努力保持写文章。来日方长,何惧车遥马慢!✨✨✨

💟 感谢各位看到这里!愿你韶华不负,青春无悔!让我们一起加油吧! 🌼🌼🌼

💖 学到这里,今天的世界打烊了,晚安!🌙🌙🌙

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VIM复合命令

VIM提供了很多 复合命令&#xff0c;可以把两个动作合并为一次按键。极大提高了编辑效率。以下是一些具体的例子&#xff1a; 复合命令等效的长命令说明Cc$删除光标到行尾scl删除光标位置的字符S^C删除整行I^i光标移动到行首A$a光标移动到行尾oA 回车光标下方开启一行Oko光标…

一文掌握SOP搭建步骤方法

如果你正在阅读这篇文章&#xff0c;那么你很可能在寻找如何为你的企业编写标准操作程序&#xff08;SOP&#xff09;的指导&#xff0c;以确保更好的流程被传达给你的团队并且得到遵循。 为什么SOPs很重要 SOPs必须清晰地传达你的业务流程&#xff0c;以标准化操作并确保盈利性…

Vue2 消息订阅与发布

1.pubsub-js 第三方库实现 实现任何框架的消息订阅发布 npm i pubsub-js <template><div class"student"><h2>展示学生的名称:{{ name }}</h2><h2>展示学生的性别:{{ sex }}</h2></div> </template><script>…

浏览器插件利器--allWebPluginV2.0.0.16-Stable版发布

allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品&#xff0c;致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX控件直接嵌入浏览器&#xff0c;实现插件加载、界面显示、接口调用、事件回调等。支持Chrome、Firefo…

ollama使用llama3.1案例

ollama安装和运行llama3.1 8b conda create -n ollama python3.11 -y conda activate ollama curl -fsSL https://ollama.com/install.sh | sh ollama run songfy/llama3.1:8b 就这么简单就能运行起来了. 我们可以在命令行中与他交互. 当然我们也可以用接口访问: curl http:…

在IDEA中用自带的数据库 连接 redis 失败(JedisAccessControlException)

文章目录 1、问题出现的背景2、分析问题出现的原因3、解决办法不用输入用户名直接输入密码即可 1、问题出现的背景 redis.clients.jedis.exceptions.JedisAccessControlException: WRONGPASS invalid username-password pair or user is disabled.2、分析问题出现的原因 查看…

智慧水务项目(六)PyScada学习一,初步建立项目并测试

一、说明 Pyscada是scada的python实现&#xff0c;需要学习一下&#xff0c;以备不时之需&#xff0c;目前我的想法是用他来模拟opc数据&#xff0c;毕竟我准备做的项目需要系统与scada通过opc进行通信&#xff0c;正好做一个简单的scada系统 是一个开源的SCADA&#xff08;S…

记录|C#主界面设计【Web风格】

目录 前言一、页面效果二、布局设计2.1 左边菜单栏搭建框架Step1. panelMenu &#xff1a;Step2. panelLogoStep3. button模板Step4. 复制buttonStep5. 微调Button 2.2 界面颜色变换Step1. ThemeColor类Step2. From1.csStep3. 更换按钮点击颜色效果 2.3 按钮点击事件2.4 顶部ti…

十、Linux二进制安装ClickHouse集群(含rpm安装)

目录 十、Linux二进制安装ClickHouse集群(含rpm安装&#xff0c;单机版使用rpm&#xff0c;集群使用tar包安装方式)1 部署前服务器配置&#xff08;集群的话三台都要配置&#xff09;1.2 配置hosts文件1.3 打开文件数限制1.4 取消 SELINUX1.5 禁用透明大页 2 下载所需文件2.1 t…

24/8/14算法笔记 复习_支持向量机svc

支持向量机&#xff08;Support Vector Machine, SVM&#xff09;是一种强大的监督学习模型&#xff0c;用于分类、回归甚至异常检测。它基于统计学习理论&#xff0c;特别关注找到数据的最佳分隔超平面。 import numpy as np import matplotlib.pyplot as pltfrom sklearn.sv…

vue3 antdv a-datepicker 修改datepicker 的panel宽度,初始弹出一些正常,但再次弹出,宽度就再次变小的解决

1、展示页面的框架结构&#xff1a; 2、然后&#xff0c;我们上二张图对比一下&#xff1a; 图1-1 需要的效果图&#xff1a; 图1-2 对比一下图1-1与图1-2&#xff0c;我们就会发现图1-1中的农历&#xff0c;换行显示了&#xff0c;第二张是有效的。 3、我们修改样式&#x…

秋招突击——8/15——知识补充——垃圾回收机制

文章目录 引言正文指针引用可达性分析算法垃圾回收算法标记清除算法标记整理算法复制分代收集 垃圾收集器Serial收集器ParNew并行收集器Parallel Scavenge吞吐量优先收集器Serial Old老年代收集器Parallel old收集器CMS收集器G1收集器&#xff08;Garbage First垃圾优先&#x…

关于堆的介绍

1.堆的概念及结构 如果有一个关键码的集合&#xff0c;把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中&#xff0c;并满足&#xff1a;且则称为小堆&#xff08;或大堆&#xff09;。将根节点最大的堆叫做最大堆或者大根堆&#xff0c;根节点最小的堆叫做最小…

【Linux】:进程控制(创建、终止、等待、替换)

目录 1.进程创建 2.进程终止&#xff08;退出&#xff09; 2.1 什么是进程终止 2.2 进程退出的场景&#xff08;原因&#xff09; 2.3 进程退出码 2.4 错误码errno 2.5 进程常见的退出方法 正常终止 从main函数返回 调用库函数exit 系统接口_exit 3.进程等待 3.1 …

【Linux】简易线程池项目

线程池是一个可以巩固一些线程相关接口 && 加强理解的一个小项目。 注意&#xff1a;这里的线程池使用的线程并不是Linux原生接口&#xff0c;而是经过封装的&#xff0c;具体请看线程封装&#xff0c;为什么不使用原生接口&#xff1f; 因为原生接口一旦进行pthread…

2024最新easyrecovery 14中文破解版图文教程

使用EasyRecovery易恢复进行数据恢复非常简单。首先&#xff0c;用户需要选择需要恢复的数据类型&#xff0c;如文档、图片、视频等。然后&#xff0c;软件会对选定的存储设备进行全面扫描&#xff0c;以寻找可恢复的数据。在扫描过程中&#xff0c;用户可以预览部分已找到的文…

成化瓷器“制字衣横少越刀”--还有例外

孙瀛洲先生关于成化款瓷器的名言非常经典&#xff0c;但是&#xff0c;凡事总有以外。 图1&#xff0c;本人收藏成化斗彩鸡缸杯底款&#xff0c;制字的衣横越过双勾刀。 下面是两件台北故宫成化瓷器底款&#xff0c;制字下面的衣横也是越过刀了。 所以&#xff0c;凡事总有例外…

mysql5.7安装

1.创建一个software文件 2.先下载mysql的repo源 wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm 3安装源包 rpm -ivh mysql-community-release-el7-5.noarch.rpm 可能会报错 改成命令 rpm -ivh mysql-community-release-el7-5.noarch.rpm --nodeps…

优化图像处理:从旋转与缩放到水印添加

1. 旋转与缩放的仿射变换 在 OpenCV 中&#xff0c;cv2.getRotationMatrix2D() 函数可以生成旋转矩阵&#xff0c;该矩阵用于对图像进行旋转和缩放变换。旋转矩阵的主要参数是&#xff1a; Center&#xff1a;旋转中心点的坐标 (x, y)。 Angle&#xff1a;旋转角度&#xff0…

数据结构与算法--图的应用

文章目录 回顾提要连通图生成树最小生成树构造最小生成树的算法普里姆(Prim)算法克鲁斯卡尔(Kruskal)算法 最短路径狄杰斯特拉 (Dijkstra) 算法当前最短路径的更新拓扑排序拓扑排序方法拓扑排序示例总结 回顾 图的遍历方法&#xff1a; 深度优先遍历 (DFS)&#xff1a;从任意…