力扣面试经典题

news2025/1/22 21:42:09

目录

前言

一、合并两个有序数组

二、移除元素

三、删除有序数组的重复项

四、删除有序数组的重复项Ⅱ

五、取数组中出现次数大于数组长度/2的元素

六、移动数组元素

七、计算数组中相差最大的值

八、字母异位词分组

九、最长连续序列

十、移动0

十一、盛水最多的容器


前言

自己的算法层面较为薄弱,希望能通过尝试做力扣的题能提升下自己,以下都是根据自己的方法做出来的,比较繁琐,有的方法结合了力扣里比较优秀的解答。

一、合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

//方法一
function merge(nums1: number[], m: number, nums2: number[], n: number): void {
    //拿到nums2裁剪后的数组
    nums2.splice(n);
    //裁剪掉只需要m个元素
    nums1.splice(m);
    nums2.forEach(number => {
        //给原数组后新增数据
        nums1.splice(m + 1, 0, number);
    });
    //给原数组排序
    nums1.sort((a,b)=>a-b);
};


//方法二
function merge(nums1: number[], m: number, nums2: number[], n: number): void {
            //从索引m开始(包括m)删除n个元素,然后添加nums2中的元素
            nums1.splice(m, n, ...nums2);
            //**注意:如果直接使用sort()不加函数体,此时如果有负数则会出现排序错误,因为默认是按照Unicode字符编码进行排序的。
            nums1.sort((a, b) => a - b);
        }

二、移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。

假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:

  • 更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
  • 返回 k
  //删除后会立即改变数组,所以原来索引为3的会变成索引为2,但由于循环已经执行了为2的所以会直接跳过,导致错误
        function removeElement(nums: number[], val: number): number {
            for (let j = 0; j < nums.length; j++) {
                if (nums[j] === val) {
                    nums.splice(j, 1);
                    //这一步是防止splice修改数组后能再次判断当前索引j的元素是否与val相等,如果被删除的元素后也是和val一致的值就会被跳过,则删除不全
                    j--;
                }
            }
            return nums.length;
        }

三、删除有序数组的重复项

给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

ps:发现for循环真是万能的= = 

function removeDuplicates(nums: number[]): number {
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] === nums[i + 1]) {
            nums.splice(i, 1);
            //防止后面还有重复的
            i--;
        }
    }
    return nums.length;
}

四、删除有序数组的重复项Ⅱ

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

ps:这一题需要连续重复起码3次及以上才会删除元素,所以可以根据这点结合快慢指针得到

function removeDuplicates(nums: number[]): number {
    //数组元素只有2个及以下时,此时直接返回数组长度
    if (nums.length <= 2) {
        return nums.length;
    } else {
        let slow = 2;
        for (let i = 2; i < nums.length; i++) {
            //如果连续三个或者三个以上相同则会存在索引-2值还一样
            if (nums[i] === nums[i - 2]) {
                nums.splice(i, 1);
                i--;
                //如果不一样,则说明不存在连续3个以上的数,则将索引值复制给slow
            } else {
                nums[slow] = nums[i];
                slow++;
            }
        }
        return slow;
    }
};

五、取数组中出现次数大于数组长度/2的元素

给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

 function majorityElement(nums: number[]): any {
            //次数超过数组长度/2也就是排序后出现次数最多的元素的索引需要为数组长度/2
            //先排序确保元素按照顺序排列
            nums.sort((a, b) => a - b);
            //向下取整 如7/2则为3,索引值为3的地方就是数组中出现次数最多的元素
            return nums[Math.floor(nums.length / 2)];
        }
        const a = majorityElement([1, 1, 1, 1, 1, 5, 5, 5]); //最终返回 1
        console.log(a);

六、移动数组元素

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

ps:刚开始实际上我使用的是时间复杂度为n平方的算法,但报超出时间限制,所以学习了他人的提交答案得到以下:

 function rotate(nums: number[], k: number): void {
            //k%nums.length 可以得到每一次需要移动到的实际位置,如k=1,则移动一次,如k=5,实际上和k=1移动到的位置一致,所以是整除数组长度
            //而实际上i%arr.length也得到每个索引值,所以移动后的索引值可以使用(i+k)%nums.length得到
            const arr = [...nums];
            for (let i = 0; i < arr.length; i++) {
                nums[(i + k) % arr.length] = arr[i];
            }
        }

七、计算数组中相差最大的值

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

 //找到两者差最大的两个元素
        function maxProfit(prices: number[]): number {
            //最低买入
            let min = prices[0];
            //最大利润
            let max = 0;
            for (let i = 1; i < prices.length; i++) {
                //找到两者之间较小的值
                min = Math.min(min, prices[i]);
                //找到两者之间较大的利润
                max = Math.max(max, prices[i] - min);
            }
            return max;
        }
        //第一轮prices[0]为4,4<5,min=4,max1=5-4=1
        //第二轮prices[0]为4,4<7,min=4,max1=7-4=3
        //第一轮prices[0]为4,4>1,min=1,max0=1-1=0,3>0,max1=3
        //第一轮prices[0]为4,1<2,min=1,max0=2-1=1,3>1,max1=3

八、字母异位词分组

字母异位词‌是指由相同的字母组成,但字母排列顺序不同的单词。例如,"cat"和"act"就是一对字母异位词

 //字母异位词:字符串组合的字母都是相同的,只是顺序不同。如abc,cba,bac,互为字母异位词
        function groupAnagrams(strs: string[]): string[][] {
            const map = new Map();
            //遍历出数组中的每一项
            for (let str of strs) {
                //将字符串转换为数组后将数组排序,如果位异位词那么得到的数组一定是相同的
                const arr = Array.from(str);
                arr.sort();
                let key = arr.toString();
                if (map.has(key)) {
                    map.set(key, map.get(key).concat([str]));
                } else {
                    map.set(key, [str]);
                }
            }
            //获取可迭代对象的值转换为数组
            const list = [...map.values()];
            return list;
        }
        groupAnagrams(['abc', 'cba', 'abs']);//[['abc','cba'],['abs']]

九、最长连续序列

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

 //求有序列的最大连续值,其实就是先去重,再判断每个数是不是有序列的第一个值,如果不是,则说明他前面还有其他的值,如果是,则往后走
        //这道题首先,先将数组去重,因为重复的值是没有意义的,其次遍历去重后的数组,对遍历出的每个值都进行判断,
        //这个值是否为序列最开始,也就是没有当前值 - 1,如果是则最长序列为当前值,且判断当前值 + 1是否存在这个数组内,如果存在则最长序列再 + 1,这样循环判断
        function longestConsecutive(nums: number[]): number {
            const setList = new Set(nums);
            let max = 0;
            for (let num of setList) {
                //如果去重后的数组中不存在当前值-1,说明当前值就是序列开头,如果存在则不进入,直到找到当前序列的最小
                if (!setList.has(num - 1)) {
                    let currentNum = num;
                    let cureentLength = 1;
                    //赋值当前值,防止while循环重复循环,需要有个跳出循环的条件
                    //如果存在当前值后面的值,则说明序列还能增加
                    while (setList.has(currentNum + 1)) {
                        currentNum++;
                        cureentLength++;
                    }
                    //找到每一次循环时较长的序列
                    max = Math.max(max, cureentLength);
                }
            }
            return max;
        }
        longestConsecutive([9, 1, 4, 7, 3, -1, 0, 5, 8, -1, 6]); // [3,4,5,6,7,8,9] //最长序列为7

十、移动0

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

 自己想的一个不规范的方法,用到了删除:

/**
 Do not return anything, modify nums in-place instead.
 */
function moveZeroes(nums: number[]): void {
    let count = 0;
    for (let i = 0; i < nums.length; i++) {
        //如果数值为0就计数
        if (!nums[i]) {
            //删除当前0
            nums.splice(i, 1);
            //删除后后面的元素会往前移,所以需要i--重新遍历当前元素
            i--;
            count++;
        }
    }
    //删除了多少个0就在末尾加多少个0
    nums.push(...new Array(count).fill(0));
};

规范的方法: 

 //所有0移动到数组末尾,其余数按照原始顺序排列
        //使用双指针,fast快指针遍历数组,slow慢指针用于储存不为0的数,当fast指针指向的值不为0,则赋值给slow,最后slow前的值都不为0,slow后的都为0
        function moveZeroes(nums: number[]): void {
            let fast = 0;
            let slow = 0;
            while (fast < nums.length) {
                //所有不为0的都位于[0,slow-1]中
                if (nums[fast] !== 0) {
                    nums[slow] = nums[fast];
                    //最后一个不为0的值的索引值为slow-1
                    slow++;
                }
                fast++;
            }
            //第一个while循环执行完后,再执行第二个while循环
            //这个while循环用于判断除去不为0的数的索引其余都应该填充为0
            while (slow < nums.length) {
                nums[slow] = 0;
                slow++;
            }
            console.log(nums);
        }
        moveZeroes([0, 0, 3, 1, 5, 2, 8, 0]); //[3,1,5,2,8,0,0,0]

十一、盛水最多的容器

ps:其实这道题的重点 //其实这道题就是找到(索引值相减*索引值对应整数的较小值)得到的最大值,遍历两次拿到每一次的较大者,最终输出最大值

 这个方法在力扣上不对:超出时间执行范围了

 //其实这道题就是找到(索引值相减*索引值对应整数的较小值)得到的最大值
        function maxArea(height: number[]): number {
            let max = 0;
            //j永远是i的下一个索引开头,索引为i+1
            for (let i = 0; i < height.length; i++) {
                for (let j = i + 1; j < height.length; j++) {
                    const num = (j - i) * Math.min(height[i], height[j]);
                    //每次比较取到最大值
                    max = Math.max(max, num);
                }
            }

            return max;
        }
        maxArea([1, 8, 6, 2, 5, 4, 8, 3, 7]);//49

使用官方方法:重点是左右两个指针,左指针指向开头索引为0,右指针指向末尾,比较左右两个指针对应的值的大小,如果左指针指向的值偏小则左指针偏右,如果右指针指向的值偏小则右指针偏左,这样可以确保是找最大面积 **注意:如果左指针指向的值偏小移动右指针此时宽度是减小1的且高度也只会比原来小或者不变,因为是以小的值为准,一个桶能装多少水,取决于短板

 function maxArea(height: number[]): number {
            //使用双指针,左指针指向索引为0,右指针指向height.length-1,此时如果height[i]>height[j],则移动较小者,因为最大面积就是高度的较小者决定的
            //如果移动较高者,不管怎么移动在宽度变小的情况下,结果只会比原来小或者不变,所以我们来移动较小者
            let left = 0;
            let right = height.length - 1;
            let maxArea = 0;
            while (left < right) {
                let currentArea = (right - left) * Math.min(height[left], height[right]);
                maxArea = Math.max(maxArea, currentArea);
                //移动值较小者,才有可能得到较大面积
                if (height[left] < height[right]) {
                    left++;
                } else {
                    right--;
                }
            }
            return maxArea;
        }
        maxArea([1, 8, 6, 2, 5, 4, 8, 3, 7]);//49

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

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

相关文章

【RabbitMq】RabbitMq高级特性-延迟消息

延迟消息 什么是延迟消息死信交换机延迟消息插件-DelayExchange其他文章 什么是延迟消息 延迟消息&#xff1a;发送者发送消息时指定一个时间&#xff0c;消费者不会立刻收到消息&#xff0c;而是在指定时间之后才收到消息。 延迟任务&#xff1a;设置在一定时间之后才执行的任…

抖音小程序一键获取手机号

前端代码组件 <button v-if"!isFromOrderList"class"get-phone-btn" open-type"getPhoneNumber"getphonenumber"onGetPhoneNumber">一键获取</button>// 获取手机号回调onGetPhoneNumber(e) {var that this tt.login({f…

CSS:语法、样式表、选择器

目录 一、语法 二、创建 外部样式表 内部样式表 内联样式 三、选择器 ID选择器 类选择器 伪类选择器 :hover a:link a:active a:visited 属性选择器 伪元素选择器 ::first-letter ::first-line ::selection ::placeholder ::before 和::after 通配选择器 标…

配电自动化中的进线监控技术

进线监控技术是配电网自动化中的一项关键技术&#xff0c;它主要用于对配电网进线变电站的开关状态以及母线电压、电流、有功功率、无功功率及电度量等参数进行实时监测。以下是对进线监控技术的详细介绍&#xff1a; 一、技术原理 进线监控技术基于传感器技术、数据采集技术、…

【三维分割】Gaga:通过3D感知的 Memory Bank 分组任意高斯

文章目录 摘要一、引言二、主要方法2.1 3D-aware Memory Bank2.2 三维分割的渲染与下游应用 三、实验消融实验应用: Scene Manipulation 地址&#xff1a;https://www.gaga.gallery 标题&#xff1a;Gaga: Group Any Gaussians via 3D-aware Memory Bank 来源&#xff1a;加利福…

《王者荣耀》皮肤爬虫源码

1.爬取网页 https://pvp.qq.com/web201605/herolist.shtml 2.python代码 import requests from bs4 import BeautifulSoup import os import threading from queue import Queuedef mul(x):if not os.path.exists(x):os.mkdir(x)print("目录创建成功")else:pass h…

iconfont等图标托管网站上传svg显示未轮廓化解决办法

打开即时设计 即时设计 - 可实时协作的专业 UI 设计工具 导入图标后拖入画板里面&#xff0c;右键选择轮廓化 将图标导出

【Linux系列】查看服务器是否使用了 SSD 的多种方法

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【AIGC】ChatGPT 的 Prompt Hacker 技巧:让简历轻松通过 AI 筛选

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;背景简化简历格式 &#x1f4af;简化 Prompt Hacker 的逻辑使用 Prompt Hacker 技巧**示例 Prompt&#xff1a;引导 AI 筛选简历**如何利用 Prompt 优化简历筛…

AI News(1/21/2025):OpenAI 安全疏忽:ChatGPT漏洞引发DDoS风险/OpenAI 代理工具即将发布

1、OpenAI 的安全疏忽&#xff1a;ChatGPT API 漏洞引发DDoS风险 德国安全研究员 Benjamin Flesch 发现了一个严重的安全漏洞&#xff1a;攻击者可以通过向 ChatGPT API 发送一个 HTTP 请求&#xff0c;利用 ChatGPT 的爬虫对目标网站发起 DDoS 攻击。该漏洞源于 OpenAI 在处理…

windows下使用docker执行器并配置 hosts 解析

本篇目录 1. 问题背景2. 环境准备2.1 云上开通windows 2022 英文版机器2.1.1 安装 git2.1.2 安装 runner2.1.3 装docker2.1.4 注册runner并使用docker执行器 3. 项目信息3.1 编写window bat脚本3.2 项目.gitlab-ci.yml文件 4. 测试结论4.1 运行流水线 5. troubleshooting问题1&…

centos9编译安装opensips 二【进阶篇-定制目录+模块】推荐

环境&#xff1a;centos9 last opensips -V version: opensips 3.6.0-dev (x86_64/linux) flags: STATS: On, DISABLE_NAGLE, USE_MCAST, SHM_MMAP, PKG_MALLOC, Q_MALLOC, F_MALLOC, HP_MALLOC, DBG_MALLOC, CC_O0, FAST_LOCK-ADAPTIVE_WAIT ADAPTIVE_WAIT_LOOPS1024, MAX_RE…

靶机复现-pikachu靶机文件包含漏洞

本篇文章旨在为网络安全渗透测试靶机复现学习。通过阅读本文&#xff0c;读者将能够对渗透pikachu靶场文件包含漏洞复现有一定的了解 原文学习链接 CSDN博主&#xff1a;One_Blanks主页地址 靶机资源下载 PHPStudy pikachu 一、前言 文件包含漏洞是编程中的一种安全隐患&a…

【机器学习实战高阶】基于深度学习的图像分割

机器学习项目图像分割 你可能已经注意到&#xff0c;大脑如何快速高效地识别并分类眼睛感知到的事物。大脑以某种方式进行训练&#xff0c;以便能够从微观层面分析所有内容。这种能力有助于我们从一篮子橙子中分辨出一个苹果。 计算机视觉是计算机科学的一个领域&#xff0c;…

【Elasticsearch 】 聚合分析:桶聚合

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

Skyeye 云 VUE 版本 v3.15.5 发布

Skyeye 云智能制造&#xff0c;采用 Springboot winUI 的低代码平台、移动端采用 UNI-APP。包含 30 多个应用模块、50 多种电子流程&#xff0c;CRM、PM、ERP、MES、ADM、EHR、笔记、知识库、项目、门店、商城、财务、多班次考勤、薪资、招聘、云售后、论坛、公告、问卷、报表…

TCP如何保证安全可靠?

TCP如何保证安全可靠&#xff1f; TCP&#xff08;传输控制协议&#xff09;是一种面向连接的、可靠的传输层协议。为了保证数据传输的安全性和可靠性&#xff0c;TCP 采用了多种机制&#xff0c;包括确认和重传、数据校验、数据分片和排序、流量控制以及拥塞控制。 1. 确认和…

高等数学学习笔记 ☞ 定积分的积分方法

1. 定积分的换元积分法 1. 换元积分公式&#xff1a;设函数在闭区间上连续&#xff0c;令&#xff0c;若满足&#xff1a; ①&#xff1a;当时&#xff0c;&#xff1b;当时&#xff0c;。 此时的大小关系不一定&#xff0c;但与最好对应着写&#xff0c;否则就要留意变号的问…

Alluxio 联手 Solidigm 推出针对 AI 工作负载的高级缓存解决方案

作者&#xff1a;Wayne Gao, Yi Wang, Jie Chen, Sarika Mehta Alluxio 作为全球领先的 AI 缓存解决方案供应商&#xff0c; 提供针对 GPU 驱动 AI 负载的高速缓存。其可扩展架构支持数万个节点&#xff0c;能显著降低存储带宽的消耗。Alluxio 在解决 AI 存储挑战方面的前沿技…

Docker Load后存储的镜像及更改镜像存储目录的方法

Docker Load后存储的镜像及更改镜像存储目录的方法 Docker Load后存储的镜像更改镜像存储目录的方法脚本说明注意事项Docker作为一种开源的应用容器引擎,已经广泛应用于软件开发、测试和生产环境中。通过Docker,开发者可以将应用打包成镜像,轻松地进行分发和运行。而在某些场…