学习记录:js算法(二十八):删除排序链表中的重复元素、删除排序链表中的重复元素II

news/2024/9/16 23:36:03/ 标签: 学习, javascript, 算法

文章目录

    • 删除排序链表中的重复元素
      • 我的思路
        • 解法一:循环
        • 解法二:递归
      • 网上思路
    • 删除排序链表中的重复元素 II
      • 我的思路
      • 网上思路
    • 总结

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

给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。

图一
在这里插入图片描述

图二
在这里插入图片描述

示例 1:(图一)
输入:head = [1,1,2]
输出:[1,2]示例 2:(图二)
输入:head = [1,1,2,3,3]
输出:[1,2,3]

我的思路
两个思路,一个是循环,一个是递归
网上思路
双指针

我的思路

解法一:循环
var deleteDuplicates = function(head) {let current = head;while (current && current.next) {if (current.val === current.next.val) {current.next = current.next.next; } else {current = current.next;}}return head;
};

讲解

  1. 初始化指针:创建一个指针 current 指向链表的头节点。
  2. 遍历链表:遍历链表直到 current.next 为空。
  3. 检查重复:如果当前节点 current 的值与下一个节点 current.next 的值相同,则跳过下一个节点,即将 current.next 设置为 current.next.next
  4. 继续遍历:如果当前节点 current 的值与下一个节点 current.next 的值不同,则将 current 指针移动到下一个节点。
  5. 返回结果:遍历完成后返回链表的头节点。
解法二:递归
var deleteDuplicates = function (head) {if (head === null || head.next === null) return head;if (head.next.val === head.val) {head.next = head.next.next;return deleteDuplicates(head);} else {head.next = deleteDuplicates(head.next);return head;}
};

讲解

  1. 如果链表为空(head === null) 或只有一个节点 (head.next === null),则返回头节点,因为没有重复节点需要删除。
  2. 如果当前节点的值与下一个节点的值相同**(head.next.val === head.val)**,则说明存在重复节点。
  3. 通过 head.next = head.next.next,我们将当前节点的 next 指向下一个节点的下一个节点,从而跳过了重复节点。
  4. 然后递归调用 deleteDuplicates(head),继续检查当前节点**(head)**的下一个节点。
  5. 如果当前节点的值与下一个节点的值不相同,说明没有重复节点。
  6. 递归调用 deleteDuplicates(head.next) 处理下一个节点,并将返回的结果赋值给 head.next,以确保链表的结构保持正确。

网上思路

var deleteDuplicates = function (head) {if (!head) return head;let prev = head;let current = head.next;while (current) {if (current.val === prev.val) {prev.next = current.next;} else {prev = current;}current = current.next;}return head;
};

讲解

  1. 初始化指针:
    prev 指向链表的头节点。
    current 指向头节点的下一个节点。
  2. 遍历链表:
    使用 while (current) 来遍历整个链表
  3. 检查重复:
    如果 current.val 和 prev.val 相同,说明存在重复。
    prev.next = current.next:通过调整 prevnext 指针,跳过重复的节点。
  4. 移动指针:
    如果当前节点和前一个节点的值不同,则移动 prev 指针到当前节点。
    无论是否有重复,current 指针始终向前移动。

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

给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。

图三
在这里插入图片描述

图四
在这里插入图片描述

示例 1:(图三)
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]示例 2:(图四)
输入:head = [1,1,1,2,3]
输出:[2,3]

我的思路
双指针
网上思路
递归

我的思路

var deleteDuplicates = function (head) {let dummy = new ListNode(0, head);let prev = dummy;let curr = head;while (curr && curr.next) {if (curr.val === curr.next.val) {while (curr.next && curr.val === curr.next.val) {curr = curr.next;}prev.next = curr.next;} else {prev = prev.next;}curr = curr.next;}return dummy.next;
};

讲解

  1. 创建哑节点:为了方便处理头节点可能被删除的情况,我们可以在链表前面添加一个哑节点。
  2. 初始化指针:创建一个指针 prev 指向哑节点,创建一个指针 curr 指向链表的头节点。
  3. 遍历链表:遍历链表直到 curr 到达末尾。
  4. 检查重复:如果当前节点 curr 的值与下一个节点 curr.next 的值相同,则继续向前遍历直到找到一个不同的节点。
  5. 连接不同节点:一旦找到不同的节点,将 prev.next 设置为这个不同的节点。
  6. 更新指针:如果没有重复节点,则将 prevcurr 都移动到下一个节点。
  7. 返回结果:遍历完成后返回哑节点的下一个节点作为新的头节点。

网上思路

var deleteDuplicates = function (head) {if (!head || !head.next) return headif (head.val === head.next.val) {while (head.next && head.next.val === head.val) head.next = head.next.nextreturn deleteDuplicates(head.next)} else {head.next = deleteDuplicates(head.next)}return head
};

讲解

  1. 基本情况检查:
    if (!head || !head.next) return head:如果链表为空**(head 为 null)或者只有一个节点(head.next 为 null)**,则直接返回 head。这是递归的基本情况,表示链表已经处理完成。
  2. 检查当前节点与下一个节点的值:
    if (head.val === head.next.val):检查当前节点的值是否与下一个节点的值相同。如果相同,说明存在重复节点。
  3. 跳过重复节点:
    while (head.next && head.next.val === head.val) head.next = head.next.next:使用 while 循环,继续跳过所有与当前节点值相同的节点, 直到找到一个不同的节点或到达链表末尾。
  4. 递归调用:
    return deleteDuplicates(head.next):在跳过所有重复节点后,递归调用 deleteDuplicates 处理下一个节点,并返回处理后的链表。
  5. 处理不同的节点:
    else { head.next = deleteDuplicates(head.next) }:如果当前节点的值与下一个节点的值不同,递归调用 deleteDuplicates 处理下一个节点,并将返回的结果赋值给 head.next
  6. 返回处理后的头节点:
    return head:最后,返回处理后的链表头节点。

总结

链表的题目写了这么多天,好像都可以用递归来解题,今天尝试了一下,还是不错的,后面可以再多尝试尝试。


http://www.ppmy.cn/news/1522656.html

相关文章

在js渲染的dom中的事件中传递对象

在某些情况下&#xff0c;可能需要将整个对象或部分对象嵌入到 HTML 元素的属性中&#xff0c;可以将对象数据序列化为 JSON 字符串&#xff0c;存储在 data-* 自定义属性中。这样可以在事件中取出并解析对象数据&#xff1a; <!DOCTYPE html> <html lang"en&qu…

Docker | Win10 安装

环境准备 1. 开启 WSL 环境配置 Docker 在 Windows 中&#xff0c;可以依赖于两种环境&#xff0c;分别是&#xff1a;Hyper-V、WSL。 Hyper-V&#xff1a;是一个虚拟环境&#xff0c;也就是虚拟机。WSL&#xff1a;是 Windows 的 Linux 子系统(系统要求不低于 Window10 的 …

八,SpringBoot Web 开发访问静态资源(附+详细源码剖析)

八&#xff0c;SpringBoot Web 开发访问静态资源(附详细源码剖析) 文章目录 八&#xff0c;SpringBoot Web 开发访问静态资源(附详细源码剖析)1. 基本介绍2. 快速入门2.1 准备工作 3. 改变静态资源访问前缀&#xff0c;定义为我们自己想要的4. 改变Spring Boot当中的默认的静态…

为何iPhone 16系列的发布对苹果至关重要?

即将发布的iPhone 16系列对苹果来说将是至关重要的时刻&#xff0c;特别是在快速发展的AI智能手机市场背景下。随着Android制造商在集成先进AI功能方面领先一步&#xff0c;苹果正处于一个关键的转折点——赶上竞争对手不仅仅是选择&#xff0c;而是必须完成的任务。 AI竞赛&am…

【深度学习详解】Task3 实践方法论-分类任务实践 Datawhale X 李宏毅苹果书 AI夏令营

前言 综合之前的学习内容&#xff0c; 本篇将探究机器学习实践方法论 出现的问题及其原因 &#x1f34e; &#x1f34e; &#x1f34e; 系列文章导航 【深度学习详解】Task1 机器学习基础-线性模型 Datawhale X 李宏毅苹果书 AI夏令营 【深度学习详解】Task2 分段线性模型-引入…

正则表达式--python

正则表达式 1、简介 概述 正确的, 符合特定规则的 字符串. 英文名叫: Regular Expression, 简称叫: re, RegExp 作用 主要是校验数据 细节 学正则, 主要是学正则的规则. 即: 哪个符号表示什么含义. 关于正则, 要求很简单, 只要能用规则, 看懂别人写的式子, 且能简单修改即可,…

springboot、flowable 生成图片发布到Docker乱码问题

flowable自带的方法生成图片时&#xff0c;如设置字体为宋体&#xff0c;则本地测试没有问题&#xff0c;因为windows自带宋体字体库&#xff0c;但是如果发布到Docker&#xff0c;则会出现乱码问题&#xff0c;因为大部分Docker并不包含宋体字体库&#xff1b; 通过Java代码&a…

VitePress 路由重写:自定义目录结构与页面生成

在使用VitePress构建文档网站时&#xff0c;你可能会遇到项目结构复杂的情况&#xff0c;特别是当你的项目是一个包含多个包的monorepo时。为了更好地组织和管理文档&#xff0c;你可能希望将文档文件放置在源代码旁边。然而&#xff0c;VitePress默认会按照特定的目录结构生成…

springboot+mybatis+vue2分页功能开发

前端框架代码 <div class"block"><span class"demonstration">完整功能</span><el-paginationsize-change"handleSizeChange"current-change"handleCurrentChange":current-page"currentPage4":page-s…

Linux多线程——日志任务的线程池实现

文章目录 线程池日志系统完善线程池的实现线程数据线程池的实现完整代码 线程池 线程池可以说是把之前所有的内容全部串联起来的一个项目 我们这里实现一个简单的版本&#xff0c;可以对其进行扩展 线程池也是一种生产者消费者模型 生产者布置任务而消费者处理任务 主要运…

Android 存储之 SharedPreferences 编码模板(工具类编码)

一、SharedPreferences 1、基本介绍 SharedPreferences 是 Android 的一个轻量级存储工具&#xff0c;它采用 key - value 的键值对方式进行存储 它允许保存和读取应用中的基本数据类型&#xff0c;例如&#xff0c;String、int、float、boolean 等 保存共享参数键值对信息的…

html记账本改写:保存数据 localStorage。

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><title>记账本改写</title><style>table {user-select: none;/* width: 100%; */border-collapse: collapse;}table,th,td {border: 1px solid…

Hive服务部署及Datagrip工具使用

目录 Hive服务部署 Hiveserver2服务 1&#xff09;用户说明 2&#xff09;Hiveserver2部署 &#xff08;1&#xff09;Hadoop端配置 &#xff08;2&#xff09;Hive端配置 3&#xff09;测试 &#xff08;1&#xff09;启动Hiveserver2 &#xff08;2&#xff09;使用命…

tio websocket 客户端 java 代码 工具类

为了更好地组织代码并提高可复用性&#xff0c;我们可以将WebSocket客户端封装成一个工具类。这样可以在多个地方方便地使用WebSocket客户端功能。以下是使用tio库实现的一个WebSocket客户端工具类。 1. 添加依赖 确保项目中添加了tio的依赖。如果使用的是Maven&#xff0c;可以…

第四章 类和对象(2)

4.2 类 类是封装对象的属性和行为的载体&#xff0c;Java中定义类使用class关键字&#xff0c;其语法如下&#xff1a; class 类名称{// 成员变量// 成员方法()} 在Java语言中对象的属性以成员变量的形式存在&#xff0c;对象的方法以成员方法的形式存在。本节将对类与对象进行…

WordPress的安装与简单开发教程

WordPress是目前世界上最受欢迎的开源内容管理系统&#xff08;CMS&#xff09;&#xff0c;它以简便易用、扩展性强和庞大的生态系统著称。通过它&#xff0c;你可以轻松构建博客、企业网站、电子商务平台等多种类型的网站。本文将为你介绍WordPress的安装过程&#xff0c;以及…

如何规避SQL注入漏洞

1 引言 对于很多初学者而言&#xff0c;SQL注入攻击是一种很容易被忽略的安全漏洞&#xff0c;其原理很简单&#xff0c;在日常编码中需要注意规避&#xff0c;养成良好的系统安全意识。 2 原理 SQL注入漏洞产生的根本原因&#xff0c;就是在编码过程中手动拼接sql参数造成的…

IOS 18 发现界面(UITableView)Banner轮播图实现

发现界面完整效果 本文实现Banner轮播图效果 文章基于IOS 17 基于UITabBarController实现首页TabBar继续实现发现界面 实现逻辑 从发现界面的效果图可以看出&#xff0c;发现界面是一个列表&#xff0c;列表包含了不同的Item&#xff0c;我们可以将 banner部分看成是列表的一…

分享基于PDF.JS的移动端PDF阅读器代码

一、前言 在之前的文章《分享基于PDF.js的pdf阅读器代码》里提到了PC端基于PDF.js的阅读器&#xff0c;本文将提供针对移动端的版本。 二、pdfViewer 为了能够直接使用&#xff0c;这里分享一下经过简单修改后能直接使用的pdfViewer代码&#xff1a; pdfViewer代码目录&…

webpack - 五大核心概念和基本配置(打包一个简单HTML页面)

// 五大核心概念 1. entry&#xff08;入口&#xff09; 指示Webpack从哪个文件开始打包2. output&#xff08;输出&#xff09; 指示Webpack打包完的文件输出到哪里去&#xff0c;如何命名等3. loader&#xff08;加载器&#xff09; webpack本身只能处理js&#xff0c;json等…