代码随想录算法训练营第四天|24、19、面试题 02.07、142、92(寄了)

news2025/1/17 1:02:31

Leecode24. 两两交换链表中的节点

链接:https://leetcode.cn/problems/swap-nodes-in-pairs/

其实这道题的思路和203比较相似,因为若是不设置虚拟头结点的话,处理头结点的方式和处理非头结点的方式会不一样,所以还是设置虚拟头结点

其实思路也是比较简单的,但是链表问题难就难在:有很多的指针都指向同一位置,牵一发而动全身,更改链表的指针需要非常的细心和谨慎

画图演示过程:
在这里插入图片描述

  1. 我们从虚拟头结点开始操作,三步之后可以交换相邻两结点
  2. 第二轮其实交换的是3和4,如同交换2和1的时候需要虚拟头结点一样,交换3和4的时候需要3之前的元素1,所以每次循环后需要将此次循环的“头结点”向前移动两次(例如交换3和4的时候操作的是1而不是dummy_head)
  3. 但是循环也是有条件的, 每次交换两个元素,肯定需要保证循环时的“头结点”后有两个元素存在呀,就拿第一次交换举例,必须满足:v->next!=NULL及v->next->next!=NULL才可以开始循环
  4. 循环开始之前定义的dummy_head是用来返回head的,循环中需要另外定义一个cur指针,此指针是随着循环进行而移动的
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        // 其实就是相邻节点的指针交换,设计一个虚拟头结点就很方便
        // 首先要明白只有一个节点或者没有节点的情况一定是非法的
        // 直接返回就可
        if (head == NULL || head->next == NULL) return head;

        ListNode *dummy_head = new ListNode(0);
        // 做一次循环判断一次,每次操作至少都需要两个元素
        // 第一次参与到循环中的最前面的节点是虚拟头结点,循环结束之后变成dummy—>next->next
        // 我们在循环结束就将dummy变成dummy->next->next,然后while中判断,若dummy->next!=NULL(两个元素的情况)且dummy->next->next!=NULL再进行循环
        dummy_head->next = head;
        // 应该定义一个循环变量,dummy_head的值肯定是不可以变的,但是在循环中必需有一个不断改变的“头指针”
        ListNode *cur = dummy_head;
        while (1) // 估计是被一起改变了
        {
            ListNode *temp1 = cur->next; // temp1指向1
            cur->next = cur->next->next; // dummy_head->next指向2

            ListNode *temp2 = temp1->next; // temp2指向2
            ListNode *temp3 = temp2->next;
            temp2->next = temp1; // temp2的next指向1

            ListNode *temp4 = cur->next->next;
            temp4->next = temp3;
            // 02134
            // 应该在这里退出,而不是在循环开始的时候退出  
            cur = cur->next->next;
            if (cur->next == NULL || cur->next->next == NULL) break;
        }
        head = dummy_head->next;
        delete dummy_head;
        return head;
    }
};

Leecode19.删除链表的倒数第N个节点

链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/

快慢指针,很容易就可以A,但是要想清楚逻辑

看图:
在这里插入图片描述

开始的时候我们定义快慢指针,假设经过移动后快指针指向NULL而慢指针指向的是3(此时n = 2,所以慢指针指向的是要删除元素的前面一个元素),但是为什么要指向欲删除元素的前面一个元素呢?因为删除此元素后要连接前面元素和后面元素,如果不是从前面开始删除的话会找不到目标元素前面的元素

往前倒推,开始的时候让p指向的是虚拟头结点dummy_head,q指向的是后面n+1个节点,然后让两个指针一起向后移动,若q == NULL,那么此时p已经移动到了目标元素的前面位置,删除即可

class Solution {
public:
	ListNode* removeNthFromEnd(ListNode* head, int n) {
		// 首先生成两个节点,都指向head,也就是head之前的空节点
		// 然后另其中一个节点向前移动n+1次
		ListNode* vir = new ListNode(0);
        vir -> next = head;
        ListNode *p = vir;
        ListNode *q = vir;
		for (int i = 0; i < n + 1; i++) q = q->next;
		
		// 然后令q和p一起移动,直到q为空为止
		while (q != NULL)
		{
			p = p->next;
			q = q->next;
		}
		ListNode * tar = p->next;
		p->next = p->next->next;
		delete tar;

        ListNode * res = vir->next;
        delete vir;
		return res;
	}
};

面试题 02.07. 链表相交

链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/

其实这类思维题,就是观察并且理解题目的特点,对症下药

在这里插入图片描述

规律就是两个相交的链表,在相交之后的长度一定都是相等的!

那么,对于较长的链表B而言,判断B中比A多出来的前一个的元素,是完全没有意义的,他们只会在最后三个元素相交(或者根本就不相交)

所以,我们可以先让两个链表底部对齐,并且从相对较短的链表的第一个元素开始判断,判断和其位置相同的另一个链表中的指针是不是和它指向同一个位置,若不是,二者同时向前挪动一个位置···

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    // 开始的时候先计算链表A和链表B的长度
        ListNode *curA = headA;
        ListNode *curB = headB;
        int len_A = 0,len_B = 0;
        // 先得到二者的长度
        while(curA != NULL) {curA = curA ->next;len_A++;}
        while(curB != NULL) {curB = curB ->next;len_B++;}
		
        // 为了方便默认A的长度大于B的长度,如果不是,就把较长的B赋给A(AB交换,指针也一起)
        curA = headA;
        curB = headB;
        if(len_B > len_A){swap(len_A,len_B);swap(curA,curB);}

        // 将A和B移动到相同的索引,其实只要移动A就OK
        int len = (len_A - len_B);
        while(len--) {curA = curA->next;}

        while(curA!=NULL) 
        {
            if(curA == curB) 
            return curA;curA = curA->next;curB = curB->next;
        }
        return nullptr;
    }
};

Leecode142.环形链表II

链接:https://leetcode.cn/problems/linked-list-cycle-ii/description/

还是快慢指针,理解了思路就很容易A

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        // 开始的时候分别定义快指针和慢指针,
        // 其中快指针每次走两步,慢指针每次走一步,循环的判断条件是fast!=NULL及fast->next!=NULL
        // 直至两个指针相遇,再次进入一个循环
        // 在第二个循环开始的时候定义一个指针从头开始遍历,另外一个指针就是接着慢指针往前走
        // 在这个循环中相遇的点,就是环的入口处,此时直接返回就OK

        // 否则直接返回null
        ListNode* slow = head;
        ListNode* fast = head;
        while(fast!= NULL && fast->next!= NULL) // 虽然循环里面有fast->next->next,但是只要保证fast和fast->next!=NULL即可,也就是说不出现空指针的next就可以
        {
            slow = slow ->next;
            fast = fast ->next ->next;
            if(slow == fast)
            {
                ListNode *start = head;
                while(start!=slow)
                {
                    start = start->next;
                    slow = slow->next;
                }
                return start;
            }
        }
        return NULL;
    }
};

Leecode92. 反转链表 II(寄了)

主要是记录错点,本来想把反转链表①中的结论直接套到这里面来,但是有大坑!坑死我了!

其中反转链表①中的核心代码如下:(双指针)

while(now != NULL) // 改成beh->next就报错
        {
            ListNode * temp = now->next; // temp 现在是5,然后now是4,pree是3

            now -> next = pree; 

            pree = now;
            now = temp;
        }

循环中的NULL及其关键,改成非NULL的其他有效指针就很容易错,比如将其改为“now!=beh->next”,那么非常amazing的事情就会发生在循环中——当now == beh的时候,对now的操作会连beh一起改变,这样死都不知道是怎么死的(我真的,被哭死)

指针真的太危险了

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

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

相关文章

LeetCode力扣刷题——指针三剑客之三:图

图 一、数据结构介绍 作为指针三剑客之三&#xff0c;图是树的升级版。图通常分为有向&#xff08;directed&#xff09;或无向&#xff08;undirected&#xff09;&#xff0c;有 循环&#xff08;cyclic&#xff09;或无循环&#xff08;acyclic&#xff09;&#xff0c;所有…

Golang入门笔记(15)—— 数组和切片

编程的世界中&#xff0c;或许是因为一次一次的定义变量&#xff0c;维护管理起来都太费劲了&#xff0c;所以推出了数组&#xff0c;将数据用数组的形式管理起来。 Go的数组和Java的实现机制是不同的&#xff0c;Go语言的数组是作为基本数据类型存在的。所以数组是开辟在栈帧中…

Golang Web开发一键生成各层级模板代码

文章目录go_project_quickstart快速开始要求安装项目实现架构设计代码逻辑统一的调用逻辑代码复用每次写web项目&#xff0c;模板都是统一的&#xff0c;每次都要写大量冗余的代码会很烦&#xff0c;在Java中有很多逆向生成的工具&#xff0c;而Go语言我找了很久&#xff0c;也…

手把手搭建springboot项目,并测试springDataJPA

这篇文章记录了搭建springboot项目并测试springDataJPA的过程&#xff0c;接下来一起看看吧。 1.访问阿里云java脚手架网站 点击访问 2.按照下图勾选并获取代码 3.将获取到的代码解压到idea工作空间。 下图的JPAdemo就是我的项目 4.打开idea&#xff0c;导入项目 5.在pom…

【Redis】| 01 | Redis 可视化工具RedisInsight

目录1 RedisInsight 简介2 RedisInsight 安装2.1 安装2.1.1 软件安装2.1.1.1 下载 RedisInsight 软件包2.1.1.2 安装命令2.1.1.3 配置环境变量2.1.1.4 启动服务2.1.2 Kubernetes 安装2.1.2.1 创建 RedisInsight 的 yaml 文件2.1.2.2 启动3.RedisInsight 使用3.1 安装redis3.1.1…

Jacobi迭代的MPI进阶——计算通信重叠和虚拟进程的使用

1:条形分割的几种策略 这里先放Makefile和run.slurm Makefile CC = mpicc FLAGS = -O3 -Wall OBJ = *.o EXE = hang hangstartall Ihang xunihang qipan srqipan Isrqipan qipanendall: ${EXE}hang: hang.c $(CC) -o $@ $^ $(FLAGS)

信息安全结业复习题(选择 + 填空 + 简答 + 计算 + 设计 )含历年考题

这里写目录标题客观题知识点简答题计算题设计题客观题知识点 考过填空 密码学是保障信息安全的核心、信息安全是密码学研究和发展的目标 保证数字信息机密性的最有效方法是使用密码算法对其进行加密&#xff08;对称和非对称&#xff09; 保证信息完整性的有效方法是利用hash…

SQL Server全套教程(基于SQL语句----续更中)

SQL Server全套教程全程干货1. 数据库的基础操作1.1.0 创建数据库1.1.1 查看及修改数据库1.1.3 分离、附加和删除数据库2.数据库表的相关操作2.1.0 常用数据类型2.1.1 表结构的创建2.1.2 表结构的查看及修改1. 数据库的基础操作 1.1.0 创建数据库 数据库创建语法 -- 创建数据…

MicroPython-On-ESP8266——8x8LED点阵模块(2)使用74HC595驱动

MicroPython-On-ESP8266——8x8LED点阵模块&#xff08;2&#xff09;使用74HC595驱动 1. 使用74HC595驱动的原理 1.1. 基础回顾 上篇我们学习了8x8LED点阵屏的电路基础知识和驱动的原理&#xff0c;见 8x8LED点阵模块&#xff08;1&#xff09;驱动原理 里面也提到了&…

基于ssm+Javaweb的OA小型企业资源管理系统-计算机毕业设计

小型OA企业资源管理系统基于SSM(SpringSpringMVCMyBatis)框架,适用于毕业设计&#xff0c;采用javaweb,基于B/S模式,Myeclipse或者eclipse idea为开发工具,mysql数据库,主要包括登录模块、人事管理模块、公告管理模块、产品管理模块、和退出模块等多个模块。 本系统主要包含了…

MySQL高级篇知识点——主从复制

目录1.主从复制概述1.1.如何提升数据库并发能力1.2.主从复制的作用2.主从复制的原理2.1.原理剖析2.2.复制的基本原则3.一主一从架构搭建3.1.准备工作3.2.主机配置文件3.3.从机配置文件3.4.主机&#xff1a;建立账户并授权3.5.从机&#xff1a;配置需要复制的主机3.6.测试3.7.停…

tensorflow2.x --------------------DenseNet-----------------------------

用tensorflow2.4实现了DenseNet-121,训练基于ImageNet图像数据集&#xff0c;图片输入大小为 224x224 。网络结构采用包含4个DenseBlock的DenseNet-BC&#xff0c;每个DenseNet-BC由若干个 BNReLU1x1 ConvBNReLU3x3 Conv&#xff08;Dense_layer)且每个DenseBlock的特征图大小分…

听我劝,自学游戏建模真的很难

我的个人建议一直是偏向不要自学建模的&#xff08;特别是零基础&#x1f923;&#xff09;&#xff0c;学习3D游戏建模除了单纯需要为爱发电还需要能够自行✅掌握软件操作技巧和✅纠错改正&#xff0c;后者都是自学非常❌难做到的&#x1f62d; 除此之外&#xff0c;还有以下…

详解Unity中的Nav Mesh新特性|导航寻路系统 (二)

前言 第一篇我们简要概述了新版NavMesh的一些新增功能&#xff0c;以及旧版的对比。本篇我们来讲一讲NavMeshSurface、NavMeshLink这两个组件的参数以及如何应用&#xff0c;接下来就进入正题吧。 本系列提要 Unity新版NavMesh专题博客共分成三篇来讲解&#xff1a; 【本篇为…

Golang入门笔记(最后一章 17 封版)—— 映射map

映射 (map) 作为一个常用的类型&#xff0c;Go语言已为我们开发者内置了map类型。 基本语法&#xff1a; var 变量名 map [keyT类型] valueT类型 这里T就是一个类型代表&#xff08;我这么写&#xff0c;有点受到了Java的泛型影响&#xff09;&#xff0c;key的类型通常为str…

【20-业务开发-基础业务-商品模块-分类管理-前端展示后端具有层级关系的目录数据-商品系统三级分类的逻辑删除前后端代码实现】

一.知识回顾 【0.三高商城系统的专题专栏都帮你整理好了&#xff0c;请点击这里&#xff01;】 【1-系统架构演进过程】 【2-微服务系统架构需求】 【3-高性能、高并发、高可用的三高商城系统项目介绍】 【4-Linux云服务器上安装Docker】 【5-Docker安装部署MySQL和Redis服务】…

JUC线程池——newSingleThreadExecutor源码解析JDK提供线程池ThreadPoolExecutor执行任务流程解析

newSingleThreadExecutor源码解析&&JDK提供线程池ThreadPoolExecutor执行任务流程解析测试代码核心代码解析ThreadPoolExecutor内部类&#xff1a;Worker解析调试台线程切换到执行异步任务的线程ThreadPoolExecutor&#xff1a;getTask()LinkedBlockingQueue&#xff1…

shell-函数

函数介绍 shell中有系统函数&#xff0c;也可以自定义函数 系统函数 basename basename [pathname] [suffix] 返回完整路径最后的/的部分&#xff0c;常用于获取文件名 basename命令会删掉所有的前缀包括最后一个/字符&#xff0c;然后将字符串显示出来 suffix为后缀&#…

java计算机毕业设计专业招聘网站(附源码、数据库)

java计算机毕业设计专业招聘网站&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技…

从零搭建个人博客项目并通过github部署上线

文章目录一、环境准备二、创建hexo博客项目1.全局安装hexo-cil工具2.新建hexo项目3.启动项目三、部署上线1.新建github仓库2.修改配置项3.部署项目一、环境准备 1.Node.js (版本需不低于 10.13) 2.Git https://hexo.io/zh-cn/ hexo博客官方文档 二、创建hexo博客项目 1.全局安…