力扣面试经典150 —— 1-5题

  • 力扣面试经典150题
  • 在 VScode 中安装 LeetCode 插件即可使用 VScode 刷题,安装 Debug LeetCode 插件可以免费 debug
  • 本文使用 python 语言解题,文中 “数组” 通常指 python 列表;文中 “指针” 通常指 python 列表索引

文章目录

  • 1. [简单] 合并两个有序数组
    • 1.1 解法1:双指针
    • 1.2 解法2:逆向双指针
  • 2. [简单] 移除元素
    • 2.1 解法1:双指针
  • 3. [简单] 删除有序数组中的重复项
    • 3.1 解法1:双指针
  • 4. [中等] 删除有序数组中的重复项 II
    • 4.1 解法1:双指针+计数
    • 4.2 解法2:双指针
  • 5. [简单] 多数元素
    • 5.1 解法1:哈希表
    • 5.2 解法2:排序
    • 5.3 解法3:分治
    • 5.4 解法4:Boyer-Moore 投票算法

1. [简单] 合并两个有序数组

  • 题目链接
  • 标签:数组、双指针、排序
    在这里插入图片描述

1.1 解法1:双指针

  • 由于两个数组都已经有序,使用双指针分别遍历两个数组,每次将较小的元素加入结果数组。考虑到两个数组长度可能不一样,可以考察已经遍历的数组长度,只从未遍历完成的数组中取元素;也可以将已遍历完成数组中取的值设为 inf。下面给出后者代码
    class Solution:
        def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
            """
            Do not return anything, modify nums1 in-place instead.
            """
            res = []
            pos1 = pos2 = 0
            while len(res) < m + n:
            	# 已遍历完成的数组,取出的元素值设为无限大
                num1 = float('inf') if pos1 >= m else nums1[pos1]
                num2 = float('inf') if pos2 >= n else nums2[pos2]
                if num1 < num2:
                    res.append(num1)
                    pos1 += 1
                else:
                    res.append(num2)
                    pos2 += 1
            # 原地修改 nums1 的内容
            nums1[:] = res
    
  • 空间复杂度均为 O ( m + n ) O(m+n) O(m+n),前者时间复杂度 O ( m + n ) O(m+n) O(m+n),后者时间复杂度 O ( 2 max ⁡ ( m , n ) ) O(2\max(m,n)) O(2max(m,n))

1.2 解法2:逆向双指针

  • 解法1中使用辅助数组 res 增加了空间复杂度,由于题目中 nums1 尾部有空余空间,可以直接从两个数组元素的尾部开始反向遍历,总是把较大元素覆盖到 nums1 尾部。注意到当从 nums1 本身复制一个元素到最后占据一个空位时,nums1 前面又出现一个空位,因此 nums1 中永远有足够的空间容纳 nums2 的全部元素
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
            """
            Do not return anything, modify nums1 in-place instead.
            """
            pos1 = m - 1
            pos2 = n - 1
            tail = -1
            while pos1 >= 0 or pos2 >= 0:
                if pos1 == -1:
                    nums1[tail] = nums2[pos2]
                    pos2 -= 1
                elif pos2 == -1:
                    nums1[tail] = nums1[pos1]
                    pos1 -= 1
                elif nums1[pos1] > nums2[pos2]:
                    nums1[tail] = nums1[pos1]
                    pos1 -= 1
                else:
                    nums1[tail] = nums2[pos2]
                    pos2 -= 1
                tail -= 1
    
  • 时间复杂度 O ( m + n ) O(m+n) O(m+n),空间复杂度 O ( 1 ) O(1) O(1)

2. [简单] 移除元素

  • 题目链接
  • 难度:简单
  • 标签:数组、双指针
    在这里插入图片描述

2.1 解法1:双指针

  • 左右两个指针都初始化指向 0 索引位置,右指针遍历数组 nums,将不等于 val 的元素复制到左指针位置,并把左指针右移一格,当右指针遍历完成时,左指针索引位置即为新长度
    class Solution:
        def removeElement(self, nums: List[int], val: int) -> int:
            left = 0
            for right in range(len(nums)):
                if nums[right] != val:
                    nums[left] = nums[right]
                    left += 1
            return left
    
  • 时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( 1 ) O(1) O(1)

3. [简单] 删除有序数组中的重复项

  • 题目链接
  • 难度:简单
  • 标签:数组、双指针
    在这里插入图片描述

3.1 解法1:双指针

  • 左右两个指针都初始化指向 1 索引位置,由于数组 nums 有序,只需右指针遍历 nums,将 nums[right] != nums[right-1] 的元素复制到左指针位置,并把左指针右移一格,当右指针遍历完成时,左指针索引位置即为新长度。和上一题很类似
    class Solution:
        def removeDuplicates(self, nums: List[int]) -> int:
            left = 1
            for right in range(1, len(nums)):
                if nums[right] != nums[right-1]:
                    nums[left] = nums[right]
                    left += 1
            return left
    
  • 时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( 1 ) O(1) O(1)

4. [中等] 删除有序数组中的重复项 II

  • 题目链接
  • 标签:数组、双指针
    在这里插入图片描述

4.1 解法1:双指针+计数

  • 和上一题思路一致,但是增加一个计算器以允许保留一个重复元素
    class Solution:
        def removeDuplicates(self, nums: List[int]) -> int:
            left, cnt = 1, 1
            for right in range(1, len(nums)):
                if nums[right] != nums[right-1]:
                	# 元素值变化,重置计数器
                    nums[left] = nums[right]
                    left += 1
                    cnt = 1
                else:
                	# 元素值不变,计数器加1
                    cnt += 1
                    if cnt <= 2:
                    	# 允许保留一个重复元素
                        nums[left] = nums[right]
                        left += 1
            return left
    
  • 时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( 1 ) O(1) O(1)

4.2 解法2:双指针

  • 由于给定数组 nums 是有序的,所以相同元素必然连续。左右两个指针都初始化指向 2 索引位置,右指针遍历 nums,如果 nums[right] == nums[left-2] 意味着必有 nums[right] == nums[left-1] == nums[left-2],这时已经有两个相同值元素,右指针指示的元素应该舍去。因此,只需将 nums[right] != nums[left-2] 的元素复制到左指针位置,并把左指针右移一格。当右指针遍历完成时,左指针索引位置即为新长度
    class Solution:
        def removeDuplicates(self, nums: List[int]) -> int:
            left, right = 2, 2
            for right in range(2, len(nums)):
                if nums[right] != nums[left-2]:
                    nums[left] = nums[right]
                    left += 1
            return left
    
  • 时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( 1 ) O(1) O(1)

5. [简单] 多数元素

  • 题目链接
  • 标签:数组、哈希表、分治、计数、排序
    在这里插入图片描述

5.1 解法1:哈希表

  • 用哈希表记录数组中每个元素出现的次数,该哈希表的每个键值对中,键代表一个元素,值代表元素出现次数。在计数过程中,可以实时检查各个元素当前出现次数,并在找到满足条件的值时直接返回
    def majorityElement(self, nums: List[int]) -> int:
            cnts = {}
            limit = len(nums) // 2
            for num in nums:
                if num not in cnts:
                    cnts[num] = 1
                else:
                    cnts[num] += 1
                    if cnts[num] > limit:
                        break
            return num
    
  • 时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( n ) O(n) O(n)

5.2 解法2:排序

  • 利用众数的性质,当数组元素单调递增排序时,索引为 ⌊ n 2 ⌋ \lfloor\frac{n}{2}\rfloor 2n 的元素一定是众数
    def majorityElement(self, nums: List[int]) -> int:
        nums.sort()
        return nums[len(nums) // 2]
    
  • 时间复杂度和空间复杂度取决于排序算法

5.3 解法3:分治

  • 设 a 是数组的众数,那么将数组分成两部分时,a 必定是至少一部分的众数。这个结论可以用反证法证明,若数组众数 a 既不是左半边的众数也不是右半边的众数,那么它本身没法成为整个数组的众数。
  • 因此可以用分治法解决这个问题:将数组分成左右两部分,分别求出左半部分的众数 a1 以及右半部分的众数 a2,随后在 a1 和 a2 中选出正确的众数。递归边界是子数组长度为 1 的情况,这时数组元素就是众数
    def majorityElement(self, nums: List[int]) -> int:
        def _rec(lo, hi):
            # 递归边界:长度为1的列表中众数就是元素本身
            if lo == hi:
                return nums[lo]
            
            # 分治递归计算左右两部分的众数
            mid = (hi - lo) // 2 + lo
            left = _rec(lo, mid)
            right = _rec(mid + 1, hi)
    
            # 左右众数相等,则本段众数也一致
            if left == right:
                return left
    
            # 左右众数不等,则本段众数为出现更多的那个
            left_count = sum(1 for i in range(lo, hi + 1) if nums[i] == left)
            right_count = sum(1 for i in range(lo, hi + 1) if nums[i] == right)
            return left if left_count > right_count else right
            
        return _rec(0, len(nums)-1)
    
  • 时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn),空间复杂度 O ( log ⁡ n ) O(\log n) O(logn)

    在这里插入图片描述

5.4 解法4:Boyer-Moore 投票算法

  • 之前的方法都没法实现 O ( n ) O(n) O(n) 的时间复制度和 O ( 1 ) O(1) O(1) 的空间复杂度,为了实现这个要求,必须在常数次遍历过程中确定众数,并且不设置任何额外空间。一个巧妙的想法是,把数组元素想象成消消乐游戏,不同的元素就消除掉,这样最后剩下的就一定是众数
  • 为了在遍历过程中进行消除,可以在遍历过程中设置候选众数,并对其出现次数进行计数,如果遇到候选众数则计数加一,遇到其他数则计数减一(理解为消除了一对不同的元素),当计数减到0时,则设置新遇到的元素为新的候选众数。一个示例如下
    原始数组:   [7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 7, 7, 7, 7]
    候选众数:  	7  7  7  7  7  7   5  5   5  5  5  5   7  7  7  7
    众数计数:    1  2  1  2  1  0   1  0   1  2  1  0   1  2  3  4
    
    如此遍历之后,最后的候选众数就是真实众数
    def majorityElement(self, nums: List[int]) -> int:
            candidate = nums[0]
            cnt = 0
    
            for num in nums:
                if cnt == 0:
                    candidate = num    
                cnt = cnt + 1 if num == candidate else cnt - 1
    
            return candidate
    
  • 时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( 1 ) O(1) O(1)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TongWEB(东方通),部署WEB前后端项目步骤

我的系统: 银河麒麟桌面系统V10(SP1)(兆芯) 环境需要搭建好,什么redis,数据库等 1.准备项目前端war包 (我后端项目本就是war部署,jar转war自行百度一下吧) 进入前端打包好的dist文件夹,创建一个文件夹 WEB-INF ,再在 WEB-INF 里创建一个 web.xml 文件,文件内容: <web-…

谁说常量字符串不可修改

哈喽&#xff0c;我是子牙&#xff0c;一个很卷的硬核男人 深入研究计算机底层、Windows内核、Linux内核、Hotspot源码……聚焦做那些大家想学没地方学的课程。为了保证课程质量及教学效果&#xff0c;一年磨一剑&#xff0c;三年先后做了这些课程&#xff1a;手写JVM、手写OS、…

接口性能优化的小技巧

目录 1.索引 1.1 没加索引 1.2 索引没生效 1.3 选错索引 2. sql优化 3. 远程调用 3.1 并行调用 3.2 数据异构 4. 重复调用 4.1 循环查数据库 4.2 死循环 4.3 无限递归 5. 异步处理 5.1 线程池 5.2 mq 6. 避免大事务 7. 锁粒度 7.1 synchronized 7.2 redis分…

git 使用总结

文章目录 git merge 和 git rebasegit mergegit rebase总结 git merge 和 git rebase git merge git merge 最终效果说明&#xff1a; 假设有一个仓库情况如下&#xff0c;现需要进行 merge&#xff1a; merge 操作流程&#xff1a; merge 的回退操作&#xff1a; git reba…

ubuntu常见配置

ubuntu各个版本的安装过程大差小不差&#xff0c;可以参考&#xff0c;ubuntu20.04 其它版本换一下镜像版本即可 安装之后需要配置基本的环境&#xff0c;我的话大概就以下内容&#xff0c;后续可能有所删改 sudo apt-get update sudo apt-get install gcc sudo apt-get inst…

常见的芯片行业ERP:SAP Business One ERP系统

在现代企业管理中&#xff0c;企业资源规划(ERP)系统已成为不可或缺的工具。特别是在高度复杂和竞争激烈的芯片行业中&#xff0c;一款高效、全面的ERP系统更是助力企业实现精细管理、提升竞争力的关键。SAP Business One ERP系统便是其中一款备受推崇的选择。 SAP Business On…

2023 龙蜥操作系统大会演讲实录:《兼容龙蜥的云原生大模型数据计算系统——πDataCS》

本文主要分三部分内容&#xff1a;第一部分介绍拓数派公司&#xff0c;第二部分介绍 πDataCS 产品&#xff0c;最后介绍 πDataCS 与龙蜥在生态上的合作。 杭州拓数派科技发展有限公司&#xff08;简称“拓数派”&#xff0c;英文名称“OpenPie”&#xff09;是国内基础数据计…

alist修改密码(docker版)

rootarmbian:~# docker exec -it [docker名称] ./alist admin set abcd123456 INFO[2024-02-20 11:06:29] reading config file: data/config.json INFO[2024-02-20 11:06:29] load config from env with prefix: ALIST_ INFO[2024-02-20 11:06:29] init logrus..…

bilibili尚硅谷周阳老师JUC并发编程与源码分析课程笔记第十一章——Synchronized与锁升级

文章目录 先从阿里及其它大厂面试题说起本章路线总纲阿里手册对锁使用的强制要求Synchronized锁优化的背景Synchronized锁的升级过程Synchronized锁的升级标志 Synchronized的性能变化Java5以前&#xff0c;只有Synchronized&#xff0c;这个是操作系统级别的重量级锁为什么每一…

C# .Net 发布后,把dll全部放在一个文件夹中,让软件目录更整洁

PublishFolderCleaner – Github 测试环境: .Net 8 Program.cs 代码 // https://github.com/dotnet-campus/dotnetcampus.DotNETBuildSDK/tree/master/PublishFolderCleanerusing System.Diagnostics; using System.Text;// 名称, 不用写 .exe var exeName "AbpDemo&…

【数学建模竞赛考点】近五年数维杯数学建模题型及算法模型总结

20204年第九届数维杯数学建模竞赛在5月10号开赛&#xff0c;为了帮助小伙伴们赛前充分准备&#xff0c;并且快速掌握历年的赛题类型&#xff0c;在这里给大家整理出了近五年的数维杯数学建模竞赛题目及考点方向&#xff0c;便于小伙伴们更好的巩固学习。 2019年 A题&#xff…

当项目经理的一定要考PMP嘛?

PMP资格认证并不是强制性要求&#xff0c;但强烈建议考虑获取该资格&#xff01;首先让我们来了解一下PMP是什么&#xff0c;然后再谈谈为什么建议考取PMP资格的理由。 PMP&#xff08;Project Management Professional&#xff09;是项目管理专业人员的资格认证。该认证由全球…

落雪音乐换源失败播放不了音乐——保姆级解决方法

不想看原因可以直接跳转到下面的解决方法 一、换源失败的原因二、解决方法注意&#xff01;2.1电脑版解决方法2.2 手机版解决方法前提&#xff08;必看&#xff01;&#xff09;解决方法 一、换源失败的原因 落雪开发者原话&#xff1a;虽然我们之前做了一些努力&#xff08;如…

《剑指Offer》笔记题解思路技巧优化_Part_7

《剑指Offer》笔记&题解&思路&技巧&优化_Part_7 &#x1f60d;&#x1f60d;&#x1f60d; 相知&#x1f64c;&#x1f64c;&#x1f64c; 相识&#x1f622;&#x1f622;&#x1f622; 开始刷题&#x1f7e2;1. LCR 179. 查找总价格为目标值的两个商品——和…

ocr识别tesseract.js本地复现

来源&#xff1a; https://github.com/naptha/tesseract.js chatgpt今天帮倒忙&#xff0c;一直给一些旧的东西&#xff0c;代码就老报错&#xff0c;最后还是我出面看看log和err调了一下&#xff0c;还的是我啊 复现效果 这个挺好复现的&#xff0c;用的英文模式比中文识别…

Matlab/simulink光伏发电的扰动观察法MPPT仿真(持续更新)

1.光伏发电的电导增量法MPPT仿真 2.光伏发电的恒定电压法MPPT仿真 3.光伏发电的扰动观察法MPPT仿真 4.光伏发电的占空比法MPPT仿真 5.基于神经网络的MPPT光伏发电仿真 6. 基于模糊控制的MPPT光伏发电仿真 7. 基于粒子群算法&#xff08;PSO&#xff09;的500w光伏系统MPPT控…

如何使用Douglas-042为威胁搜索和事件应急响应提速

关于Douglas-042 Douglas-042是一款功能强大的PowerShell脚本&#xff0c;该脚本可以提升数据分类的速度&#xff0c;并辅助广大研究人员迅速从取证数据中筛选和提取出关键数据。 该工具能够搜索和识别Windows生态系统中潜在的安全漏洞&#xff0c;Douglas-042会将注意力放在…

小程序商城 免 费 搭 建之java商城 电子商务Spring Cloud+Spring Boot+二次开发+mybatis+MQ+VR全景+b2b2c

java SpringCloud版本b2b2c鸿鹄云商平台全套解决方案 使用技术&#xff1a; Spring CloudSpring BootMybatis微服务服务监控可视化运营 B2B2C平台&#xff1a; 平台管理端(包含自营) 商家平台端(多商户入驻) PC买家端、手机wap/公众号买家端 微服务&#xff08;30个通用…

ELF文件内容详解——各节内容分析

文章目录 写在前面准备.text节.data节.strtab.symtab.shstrtab.shstrtab之后 写在前面 只看readelf这个工具说实话我感觉还是有点云里雾里&#xff0c;这里就逐字节分析一下ELF文件中text节&#xff08;代码段&#xff09;的内容 本文分析使用的汇编程序ELF文件内容详解这篇文…

苍穹外卖Day02——总结2

前期文章 文章标题地址苍穹外卖Day01——总结1https://blog.csdn.net/qq_43751200/article/details/135466359?spm1001.2014.3001.5501苍穹外卖Day01——解决总结1中存在的问题https://lushimeng.blog.csdn.net/article/details/135473412 总结2 前期文章1. 新增员工模块1.1 …