【Leetcode 2273 】 移除字母异位词后的结果数组 —— 三种版本,时间击败100%,空间击败100%

本文主要是介绍【Leetcode 2273 】 移除字母异位词后的结果数组 —— 三种版本,时间击败100%,空间击败100%,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

给你一个下标从 0 开始的字符串 words ,其中 words[i] 由小写英文字符组成。

在一步操作中,需要选出任一下标 i ,从 words 中 删除 words[i] 。其中下标 i 需要同时满足下述两个条件:

  1. 0 < i < words.length
  2. words[i - 1] 和 words[i] 是 字母异位词 。

只要可以选出满足条件的下标,就一直执行这个操作。

在执行所有操作后,返回 words 。可以证明,按任意顺序为每步操作选择下标都会得到相同的结果。

字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。例如,"dacb" 是 "abdc" 的一个字母异位词。

示例 1:

输入:words = ["abba","baba","bbaa","cd","cd"]
输出:["abba","cd"]
解释:
获取结果数组的方法之一是执行下述步骤:
- 由于 words[2] = "bbaa" 和 words[1] = "baba" 是字母异位词,选择下标 2 并删除 words[2] 。现在 words = ["abba","baba","cd","cd"] 。
- 由于 words[1] = "baba" 和 words[0] = "abba" 是字母异位词,选择下标 1 并删除 words[1] 。现在 words = ["abba","cd","cd"] 。
- 由于 words[2] = "cd" 和 words[1] = "cd" 是字母异位词,选择下标 2 并删除 words[2] 。现在 words = ["abba","cd"] 。
无法再执行任何操作,所以 ["abba","cd"] 是最终答案。

示例 2:

输入:words = ["a","b","c","d","e"]
输出:["a","b","c","d","e"]
解释:
words 中不存在互为字母异位词的两个相邻字符串,所以无需执行任何操作。

提示:

  • 1 <= words.length <= 100
  • 1 <= words[i].length <= 10
  • words[i] 由小写英文字母组成

第一版本 

执行用时:97 ms, 在所有 Typescript 提交中击败了 - %的用户
内存消耗:59.62 MB, 在所有 Typescript 提交中击败了 - %的用户

/*
第一版本
https://leetcode.cn/u/cshappyeveryday/
执行用时:97 ms, 在所有 Typescript 提交中击败了 - %的用户
内存消耗:59.62 MB, 在所有 Typescript 提交中击败了 - %的用户
时间复杂度:O(n*m)
2024年8月30日 
*/
function removeAnagrams(words: string[]): string[] {const OFFSET = "a".charCodeAt(0);let sucP = 1;//二维数组存储每个字符的charCodeconst twoDimension = new Array(words.length).fill([]).map(() => new Array(26).fill(0));for (let i = 0; i < words.length; i++) {for (const char of words[i]) {twoDimension[i][char.charCodeAt(0) - OFFSET]++;}}for (let i = 1; i < words.length; i++) {//判断两个内容是否完全相等const diff = twoDimension[i].filter((n, j) => n === twoDimension[i - 1][j]);if (diff.length === twoDimension[i].length) continue;//在原数组上保存结果数据words[sucP++] = words[i];}return words.slice(0, sucP);
}

第二版本


执行用时:75 ms, 在所有 Typescript 提交中击败了 60.00 %的用户
内存消耗:55.16 MB, 在所有 Typescript 提交中击败了 100.00 %的用户 

/*
第二版本
https://leetcode.cn/u/cshappyeveryday/
执行用时:75 ms, 在所有 Typescript 提交中击败了 60.00 %的用户
内存消耗:55.16 MB, 在所有 Typescript 提交中击败了 100.00 %的用户
时间复杂度:O(n*m)
2024年8月30日 
*/
function removeAnagrams2(words: string[]): string[] {const OFFSET = "a".charCodeAt(0);let sucP = 1;for (let i = 1; i < words.length; i++) {let curWordCode = new Array(26).fill(0);let preWordCode = new Array(26).fill(0);//每一次都计算当前与上一次的charCodefor (const word of words[i]) {curWordCode[word.charCodeAt(0) - OFFSET]++;}for (const word of words[i - 1]) {preWordCode[word.charCodeAt(0) - OFFSET]++;}const isSame = curWordCode.every((n, j) => n === preWordCode[j]);if (isSame) continue;words[sucP++] = words[i];}return words.slice(0, sucP);
}

最终版本

执行用时:67 ms, 在所有 Typescript 提交中击败了 100.00 %的用户

内存消耗:54.29 MB, 在所有 Typescript 提交中击败了 100.00 %的用户

/*
最终版本
https://leetcode.cn/u/cshappyeveryday/
执行用时:67 ms, 在所有 Typescript 提交中击败了 100.00 %的用户
内存消耗:54.29 MB, 在所有 Typescript 提交中击败了 100.00 %的用户
时间复杂度:O(n * m)
2024年8月30日 
*/
function removeAnagrams3(words: string[]): string[] {const OFFSET = "a".charCodeAt(0);let sucP = 1; //成功指针,指向words,该指针前面的元素都是结果let curWordCode = new Array<number>(26).fill(0); //当前 wordCodelet preWordCode = new Array<number>(26).fill(0); //上一个wordCode// 初始化 preWordCodefor (const word of words[0]) {preWordCode[word.charCodeAt(0) - OFFSET]++;}for (let i = 1; i < words.length; i++) {//去除和上一个相同的,注意:这里的去重与 Set() 去重不同。Set会将所有相同的去除,这里只针对相邻的两个if (words[i] === words[i - 1]) continue;curWordCode = new Array<number>(26).fill(0);for (const word of words[i]) {curWordCode[word.charCodeAt(0) - OFFSET]++;}//判断上一次成功的值与本次是否为 字母内容相同的const isSame =curWordCode.length === preWordCode.length &&curWordCode.every((n, j) => n === preWordCode[j]);//   是则证明不是 字母异位词,跳过if (isSame) continue;// 不是,则证明是 字母异位词,则 preWordCode 变成本次wordpreWordCode = [...curWordCode];//修改 结果,将成功指针后移words[sucP++] = words[i];}//依据 sucP 的位置返回结果return words.slice(0, sucP);
}

这篇关于【Leetcode 2273 】 移除字母异位词后的结果数组 —— 三种版本,时间击败100%,空间击败100%的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1121907

相关文章

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

Tomcat版本与Java版本的关系及说明

《Tomcat版本与Java版本的关系及说明》:本文主要介绍Tomcat版本与Java版本的关系及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Tomcat版本与Java版本的关系Tomcat历史版本对应的Java版本Tomcat支持哪些版本的pythonJ

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

IDEA中Git版本回退的两种实现方案

《IDEA中Git版本回退的两种实现方案》作为开发者,代码版本回退是日常高频操作,IntelliJIDEA集成了强大的Git工具链,但面对reset和revert两种核心回退方案,许多开发者仍存在选择... 目录一、版本回退前置知识二、Reset方案:整体改写历史1、IDEA图形化操作(推荐)1.1、查看提

C语言实现两个变量值交换的三种方式

《C语言实现两个变量值交换的三种方式》两个变量值的交换是编程中最常见的问题之一,以下将介绍三种变量的交换方式,其中第一种方式是最常用也是最实用的,后两种方式一般只在特殊限制下使用,需要的朋友可以参考下... 目录1.使用临时变量(推荐)2.相加和相减的方式(值较大时可能丢失数据)3.按位异或运算1.使用临时

C++原地删除有序数组重复项的N种方法

《C++原地删除有序数组重复项的N种方法》给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度,不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(... 目录一、问题二、问题分析三、算法实现四、问题变体:最多保留两次五、分析和代码实现5.1、问题分析5.

Java终止正在运行的线程的三种方法

《Java终止正在运行的线程的三种方法》停止一个线程意味着在任务处理完任务之前停掉正在做的操作,也就是放弃当前的操作,停止一个线程可以用Thread.stop()方法,但最好不要用它,本文给大家介绍了... 目录前言1. 停止不了的线程2. 判断线程是否停止状态3. 能停止的线程–异常法4. 在沉睡中停止5

JDK多版本共存并自由切换的操作指南(本文为JDK8和JDK17)

《JDK多版本共存并自由切换的操作指南(本文为JDK8和JDK17)》本文介绍了如何在Windows系统上配置多版本JDK(以JDK8和JDK17为例),并通过图文结合的方式给大家讲解了详细步骤,具有... 目录第一步 下载安装JDK第二步 配置环境变量第三步 切换JDK版本并验证可能遇到的问题前提:公司常

查看Oracle数据库中UNDO表空间的使用情况(最新推荐)

《查看Oracle数据库中UNDO表空间的使用情况(最新推荐)》Oracle数据库中查看UNDO表空间使用情况的4种方法:DBA_TABLESPACES和DBA_DATA_FILES提供基本信息,V$... 目录1. 通过 DBjavascriptA_TABLESPACES 和 DBA_DATA_FILES