代码随想录刷题笔记(DAY3)

news2024/11/24 4:28:45

今日总结:虽然之前刷过链表,但这次做的是有些费力的,也有了更深的理解。整理完今天的 Vue 笔记就睡。。。

DAY 3

01. 移除链表元素(No. 203)

题目链接:https://leetcode.cn/problems/remove-linked-list-elements/description/

代码随想录题解:https://programmercarl.com/0203.%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8%E5%85%83%E7%B4%A0.html

1.1 题目

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回新的头节点 。

示例 1:

img

输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

示例 2:

输入:head = [], val = 1
输出:[ ]

示例 3:

输入:head = [7,7,7,7], val = 7
输出:[ ]

1.2 笔记

我们要删除一个节点就是让这个节点的上一个节点指向这个节点的下一个节点,如下图所示:

但我们的链表是一个单向链表,我们无法使得这个节点找到它的上一个节点,所以这里我们只能去寻找这个节点的下一个节点是不是要去除的,然后将这个节点的的 next 指向它的下下个节点,同时我们要保证这个节点绝对不能是要去删除的节点,那应该如何保证呢?

如果头节点是要删除的节点,我们直接让头节点向前移动即可,如果是其他节点,我们要保证它的下一个节点不能是要删除的节点,才进行 p = p.next 的操作,这是为了避免连续出现删除元素的情况,如果我们不判断就会出现漏删的情况:

也就是我们节点指向的绝对不能是要删除的节点。

另外要注意的是保证本身和 next 不为空即可,next.next 为空是有意义的。

1.3 代码
/**
 * 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 removeElements(ListNode head, int val) {
        // 先去处理头节点的情况,保证 p 一开始指向的不是要删除的元素
        while (head != null && head.val == val ) {
            head = head.next;
        }
        if (head == null) {
            return null;
        }
        ListNode p = head; // 指向头节点的指针
        while (p.next != null) { // 隐式的包含了 p != null
            if (p.next.val == val) {
                // 删除节点的逻辑
                p.next = p.next.next;
            } else {
                // 保证 p.next 不是要删除的元素才能执行这个操作
                p = p.next;
            }            
        }
        return head;
    }
}
1.4 拓展 —— 虚拟头节点

虚拟头节点是思想很简单,就是多加一个头节点,这样让我们对头节点的处理和对正常节点的处理是相同的,唯一需要注意的就是返回值应该是虚拟头节点的 下一个 节点。

代码:

/**
 * 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 removeElements(ListNode head, int val) {
        ListNode listNode = new ListNode(); // 虚拟头节点
        listNode.next = head;
//        while (head != null && head.val == val ) {
//            head = head.next;
//        }
//        if (head == null) {
//            return null;
//        }
        ListNode p = listNode; //指向头节点的指针
        while (p.next != null) {
            if (p.next.val == val) {
                p.next = p.next.next;
            } else {
                p = p.next;
            }
        }
        return listNode.next;
    }
}

02. 设计链表(No. 707)

题目链接:https://leetcode.cn/problems/design-linked-list/description/

代码随想录题解:https://programmercarl.com/0707.%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8.html

1.1 题目

你可以选择使用单链表或者双链表,设计并实现自己的链表。

单链表中的节点应该具备两个属性:valnextval 是当前节点的值,next 是指向下一个节点的指针/引用。

如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。

实现 MyLinkedList 类:

  • MyLinkedList() 初始化 MyLinkedList 对象。
  • int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1
  • void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
  • void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。
  • void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。
  • void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。
1.2 笔记

这里采用上面的虚拟头节点进行设计,这样设计对我们修改真正的头节点来说非常便利

先来设计一个节点类

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

这里引进一个 size 变量,当指定的 index 值没有意义的时候可以很快的返回,先来确定 index 错误的时机:index < 0 或者 index >= size (下标从 0 开始),每次执行和 index 有关的操作的时候都先判断一次。

这里比较重点的是 get() 方法和 addAtIndex() 方法,因为上面 size 的约束,不用在考虑越界的问题,那思考一下,从虚拟头节点到我们需要处理的下标的前一个元素需要走多少个 .next 呢?需要 size - 1 步,这样就写出了我们的方法:

public void addAtIndex(int index, int val) {
    if (index > size || index < 0) {
        return;
    }
    size++;
    //找到要插入节点的前驱
    ListNode pred = virtualHeadNode;
    for (int i = 0; i < index; i++) {
        pred = pred.next;
    }
    ListNode toAdd = new ListNode(val);
    toAdd.next = pred.next;
    pred.next = toAdd;
}

注意这里的边界条件要放宽成 index > size 因为题目告诉我们可以设置最后一个元素的后一个元素的值。

接下来是 get() 方法的实现:

public int get(int index) {
    if (index < 0 || index >= size) {
        return -1;
    }
    ListNode currentNode = virtualHeadNode;
    //包含一个虚拟头节点,所以查找第 index+1 个节点
    for (int i = 0; i <= index; i++) {
        currentNode = currentNode.next;
    }
    return currentNode.val;
}

这里需要注意的还是需要前进的步数。

1.3 代码
class MyLinkedList {
    ListNode virtualHeadNode = new ListNode(); // 虚拟头节点
    int size;
    public MyLinkedList() {
    }

    public int get(int index) {
        if (index < 0 || index >= size) {
            return -1;
        }
        ListNode currentNode = virtualHeadNode;
        //包含一个虚拟头节点,所以查找第 index+1 个节点
        for (int i = 0; i <= index; i++) {
            currentNode = currentNode.next;
        }
        return currentNode.val;
    }

    public void addAtHead(int val) {
        addAtIndex(0, val);
    }

    public void addAtTail(int val) {
        addAtIndex(size, val);
    }

    public void addAtIndex(int index, int val) {
        if (index > size || index < 0) {
            return;
        }
        size++;
        //找到要插入节点的前驱
        ListNode pred = virtualHeadNode;
        for (int i = 0; i < index; i++) {
            pred = pred.next;
        }
        ListNode toAdd = new ListNode(val);
        toAdd.next = pred.next;
        pred.next = toAdd;
    }

    public void deleteAtIndex(int index) {
        if (index < 0 || index >= size) {
            return;
        }
        size--;
        if (index == 0) {
            virtualHeadNode = virtualHeadNode.next;
	    return;
        }
        ListNode pred = virtualHeadNode;
        for (int i = 0; i < index ; i++) {
            pred = pred.next;
        }
        pred.next = pred.next.next;
    }
    public ListNode getNodeByIndex(int index) {
        ListNode p = virtualHeadNode.next;
        while (index-- > 0 && p != null) {
            p = p.next;
        }
        return p;
    }
}

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

03. 反转链表(No. 206)

题目链接:https://leetcode.cn/problems/reverse-linked-list/description/

代码随想录题解:https://programmercarl.com/0206.%E7%BF%BB%E8%BD%AC%E9%93%BE%E8%A1%A8.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE

3.1 题目

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

img

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

img

输入:head = [1,2]
输出:[2,1]

示例 3:

输入:head = []
输出:[]
3.2 笔记

第一种是使用双指针来做这个题,很容易想到用 cur 指针指向需要改变的节点,用 pre 指针指向前一个节点,再循环更新 curpre 指向的节点

这时候遇到一个问题就是 curnext 这时候已经写给了 pre 节点,那再怎么找到原本的 next 呢?所以这里也需要定义一个 tempNode 来协助更新 cur

下面来考虑初始化,pre 初始化为 nullcur 初始化为 headtemp 也初始化为 null

最重要的是 while 循环的终点,容易犯的错误是在 cur 指向最后一个节点时返回 cur 的值,这时候返回的是只有最后一个元素的链表,因为最后一个元素还未更新,应该再进行一次循环,也就是 cur 指向 null 的时候,我们返回的是 pre

3.3 代码
/**
 * 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 reverseList(ListNode head) {
        // 如果只有一个元素直接返回
        if (head == null || head.next == null) {
            return head;
        }
        // 初始化
        ListNode currentNode = head;
        ListNode preNode = null;
        ListNode tempNode = null;
        
        while (currentNode != null) { 
            tempNode = currentNode.next;          
            currentNode.next = preNode;
            preNode = currentNode;
            currentNode = tempNode;           
        }
        return preNode;
    }
}

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

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

相关文章

UE4开发BIM程序 的 流程

某机构BIM设计研究中心主任马晓龙&#xff0c;他对编程颇有研究。今天他会用通俗易懂的语言来讲解基于游戏引擎UE4的BIM技术可视化应用。对于想要自己开发程序的设计师一定要读一下&#xff01; 1&#xff09;关于UE4——UE4是什么&#xff1f; 可以简单的理解为&#xff0c;一…

NXP MC17XS6500高边驱动芯片功能的介绍

简介 本文主要介绍了高边驱动芯片MC17XS6500 的功能、特性。世平集团基于 FlagChips FC7300 HV BMS 方案&#xff0c;高边驱动芯片MC17XS6500 被用于驱动继电器的断开和闭合。在本文中介绍了 MC17XS6500 在正常模式和故障模式下&#xff0c;是如何控制 OUT 的输出。 1、功能…

【软件测试】为bug而生

为什么定位问题如此重要&#xff1f; 可以明确一个问题是不是真的“bug” 很多时候&#xff0c;我们找到了问题的原因&#xff0c;结果发现这根本不是bug。原因明确&#xff0c;误报就会降低多个系统交互&#xff0c;可以明确指出是哪个系统的缺陷&#xff0c;防止“踢皮球”&…

彻底理解前端安全面试题(1)—— XSS 攻击,3种XSS攻击详解,建议收藏(含源码)

前言 前端关于网络安全看似高深莫测&#xff0c;其实来来回回就那么点东西&#xff0c;我总结一下就是 3 1 4&#xff0c;3个用字母描述的【分别是 XSS、CSRF、CORS】 一个中间人攻击。当然 CORS 同源策略是为了防止攻击的安全策略&#xff0c;其他的都是网络攻击。除了这…

mac安装k8s环境

安装kubectl brew install kubectl 确认一下安装的版本 kubectl version --client 如果想在本地运行kubernetes 需要安装minikube brew install minikube 需要注意安装minikube需要本地的docker服务是启动的 启动 默认连接的是google的仓库 minikube start 指定阿…

(2023,3D NeRF,无图像变分分数蒸馏,单步扩散)SwiftBrush:具有变分分数蒸馏的一步文本到图像扩散模型

SwiftBrush : One-Step Text-to-Image Diffusion Model with Variational Score Distillation 公众&#xff1a;EDPJ&#xff08;添加 VX&#xff1a;CV_EDPJ 或直接进 Q 交流群&#xff1a;922230617 获取资料&#xff09; 目录 0. 摘要 1. 方法 1.1 基础 1.2 SwiftBrus…

elasticsearch 笔记三:查询建议介绍、Suggester、自动完成

一、查询建议介绍 1. 查询建议是什么&#xff1f; 查询建议&#xff0c;为用户提供良好的使用体验。主要包括&#xff1a; 拼写检查&#xff1b; 自动建议查询词&#xff08;自动补全&#xff09; 拼写检查如图&#xff1a; 自动建议查询词&#xff08;自动补全&#xff09;…

Mybatis插件入门

专栏精选 引入Mybatis Mybatis的快速入门 Mybatis的增删改查扩展功能说明 mapper映射的参数和结果 Mybatis复杂类型的结果映射 Mybatis基于注解的结果映射 Mybatis枚举类型处理和类型处理器 再谈动态SQL Mybatis配置入门 Mybatis行为配置之Ⅰ—缓存 Mybatis行为配置…

【经典算法】有趣的算法之---蚁群算法梳理

every blog every motto: You can do more than you think. 0. 前言 蚁群算法记录 1. 简介 蚁群算法(Ant Clony Optimization, ACO)是一种群智能算法,它是由一群无智能或有轻微智能的个体(Agent)通过相互协作而表现出智能行为,从而为求解复杂问题提供了一个新的可能性…

JDK9及之后版本使用 jlink 生成定制化的 JRE

许多java软件的运行需要依赖jre&#xff0c;在 jdk8 之后&#xff0c;不再提供默认的 jre&#xff0c;后续如果项目中还是想用 jre 的形式发布软件&#xff0c;那么可以使用 jlink 工具生成 jre。 一、jlink 命令详解 jlink 二、查看jdk中包含的所有模块 如果在 jdk 安装文件夹…

css 用多个阴影做出光斑投影的效果 box-shadow

css 用多个阴影做出光斑投影的效果 box-shadow 你首先需要知道的一点是 box-shadow 可以接收多个值&#xff0c;也就是可以设置多个阴影&#xff0c;这样就可以做一个类似光斑投影的效果。 一、效果 二、代码 里面用到了我一些 scss 工具方法&#xff0c;不过不影响&#xf…

Android MVP 写法

前言 Model&#xff1a;负责数据逻辑 View&#xff1a;负责视图逻辑 Presenter&#xff1a;负责业务逻辑 持有关系&#xff1a; 1、View 持有 Presenter 2、Model 持有 Presenter 3、Presenter 持有 View 4、Presenter 持有 Model 辅助工具&#xff1a;ViewBinding 执行…

【华为机试】2023年真题B卷(python)-观看文艺汇演-计算演出场次

一、题目 题目描述&#xff1a; 一个人只能同时观看一场演出&#xff0c;且不能迟到早退&#xff0c;由于演出分布在不同的演出场地&#xff0c;所以连续观看的演出最少有15分钟的时间间隔&#xff0c;小明是一个狂热的文艺迷&#xff0c;想观看尽可能多的演出&#xff0c; 现给…

【并发设计模式】聊聊线程本地存储模式如何实现的线程安全

前面两篇文章&#xff0c;通过两阶段终止的模式进行优雅关闭线程&#xff0c;利用数据不变性的方式保证数据安全&#xff0c;以及基于COW的模式&#xff0c;保证读数据的安全。本篇我们来简述下如果利用线程本地存储的方式保证线程安全。 首先一个大前提就是并发问题&#xff…

八皇后问题(C语言)

了解题意 在一个8x8的棋盘上放置8个皇后&#xff0c;使得任何两个皇后都不能处于同一行、同一列或同一斜线上。问有多少种方法可以放置这8个皇后&#xff1f; 解决这个问题的目标是找到所有符合要求的皇后摆放方式&#xff0c;通常使用回溯算法来求解。回溯算法会尝试所有可能…

[蓝桥杯2022省赛] X 图形

X 图形 问题描述 给定一个字母矩阵。一个 X 图形由中心点和由中心点向四个 4545 度斜线方向引出的直线段组成&#xff0c;四条线段的长度相同&#xff0c;而且四条线段上的字母和中心点的字母相同。 一个 X 图形可以使用三个整数r,c,L 来描述&#xff0c;其中 r,c 表示中心点…

PiflowX组件-ReadFromKafka

ReadFromKafka组件 组件说明 从kafka中读取数据。 计算引擎 flink 有界性 Unbounded 组件分组 kafka 端口 Inport&#xff1a;默认端口 outport&#xff1a;默认端口 组件属性 名称展示名称默认值允许值是否必填描述例子kafka_hostKAFKA_HOST“”无是逗号分隔的Ka…

腾讯云标准型S5服务器4核8G配置优惠价格表

腾讯云4核8G服务器S5和轻量应用服务器优惠价格表&#xff0c;轻量应用服务器和CVM云服务器均有活动&#xff0c;云服务器CVM标准型S5实例4核8G配置价格15个月1437.3元&#xff0c;5年6490.44元&#xff0c;轻量应用服务器4核8G12M带宽一年446元、529元15个月&#xff0c;腾讯云…

malloc、calloc、realloc、free函数的使用及注意事项

malloc函数 malloc函数的返回值为void*类型 内存管理函数操作的内存是在堆区空间 malloc函数使用示例 free(p)相当于值传递&#xff0c;不能改变p本身。 free只是释放了空间&#xff0c;释放后p依然指向原地址&#xff0c;故需要手动置NULL。 calloc函数 calloc可以指定开辟n个…

【Week-P3】CNN天气识别

文章目录 一、环境配置二、准备数据三、搭建网络结构四、开始训练五、查看训练结果六、总结6.1 不改变学习率的前提下&#xff0c;将训练epoch分别增加到50、60、70、80、90&#xff08;1&#xff09;epoch 50 的训练情况如下&#xff1a;&#xff08;2&#xff09;epoch 60 …