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

news2024/12/23 23:29:47
  • 力扣面试经典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.coloradmin.cn/o/1467634.html

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

相关文章

【Activiti7】全新Activiti7工作流讲解

一、Activiti7概述 官网地址:https://www.activiti.org/ Activiti由Alfresco软件开发,目前最高版本Activiti 7。是BPMN的一个基于java的软件实现,不过 Activiti 不仅仅包括BPMN,还有DMN决策表和CMMN Case管理引擎,并且有自己的用户管理、微 服务API 等一系列功能,是一…

C#与VisionPro联合开发——INI存储和CSV存储

1、INI存储 INI 文件是一种简单的文本文件格式&#xff0c;通常用于在 Windows 环境中存储配置数据。INI 文件格式由一系列节&#xff08;section&#xff09;和键值对&#xff08;key-value pairs&#xff09;组成&#xff0c;用于表示应用程序的配置信息。一个典型的 INI 文…

Uipath 读取Word模板实现录用通知书PDF批量生成

本文主要讲解如何使用Uipath 读取Excel 面试人员信息表&#xff0c;读取Word模板&#xff0c;再批量生成录用通知书PDF文件&#xff0c;该自动化大大提高了HR 的工作效率。 注&#xff1a;本方案实现采用无代码模式&#xff0c;通过拖拉控件实现。 1. 数据准备 1.1 面试人员…

【力扣】Z 字形变换,模拟 + 直接构造

Z 字形变换原题地址 方法一&#xff1a;利用二维矩阵模拟 对于特殊情况&#xff0c;Z 字形变换后只有一行或只有一列&#xff0c;则变换后的字符串和原字符串相同。 对于一般情况&#xff0c;我们可以考虑按照题目要求&#xff0c;把字符串按照 Z 字形存储到二维数组中&…

高考志愿选择辅助系统

高考志愿选择辅助系统 获取源码——》公主号&#xff1a;计算机专业毕设大全

回归预测 | Matlab实现SSA-BiLSTM-Attention麻雀算法优化双向长短期记忆神经网络融合注意力机制多变量回归预测

回归预测 | Matlab实现SSA-BiLSTM-Attention麻雀算法优化双向长短期记忆神经网络融合注意力机制多变量回归预测 目录 回归预测 | Matlab实现SSA-BiLSTM-Attention麻雀算法优化双向长短期记忆神经网络融合注意力机制多变量回归预测预测效果基本描述程序设计参考资料 预测效果 基…

数据结构D4作业

1.实现单向循环链表的功能 loop.c #include "loop.h" loop_p create_loop() { loop_p H(loop_p)malloc(sizeof(loop)); if(HNULL) { printf("创建失败\n"); return NULL; } H->len0; H->nextH; ret…

0基础JAVA期末复习最终版

啊啊啊啊啊啊啊啊啊啊&#xff0c;根据网上各位大佬的复习资料&#xff0c;看了很多大多讲的是基础但对内容的整体把握上缺乏系统了解。但是很不幸最终挂科了&#xff0c;那个出题套路属实把我整神了&#xff0c;所以我决定痛改前非&#xff0c;酣畅淋漓的写下这篇文章。。。。…

做抖店想要快速起店怎么办?产品和流量是关键!新手可收藏!

大家好&#xff0c;我是电商小布。 在抖音小店开通完成后&#xff0c;大家考虑的第一件事情&#xff0c;一定是小店如何能够快速出单&#xff0c;成功起店。 店铺出单的重点&#xff0c;其实就在小店的运营上。 那么这么多的环节&#xff0c;关键点在哪呢&#xff1f; 答案…

unity屏幕受伤特效

//使用用途&#xff1a;同于屏幕掉血的后处理特效 //请结合和脚本&#xff1a;BloodScreen 挂载至摄像机使用本特效 //本特效设计之初未考虑兼容移动设备&#xff0c;请注意//使用说明&#xff1a; //掉血获取此脚本&#xff0c;将showBlood设置为true&#xff0c;如果您需要更…

基础光学系列:(一)光学在机器视觉中的角色:原理、应用与学习途径

光学是一门研究光的产生、传播以及与物质相互作用的科学&#xff0c;对于机器视觉技术的发展至关重要。机器视觉利用计算机和相机系统模拟人类视觉&#xff0c;解释和理解图像&#xff0c;广泛应用于制造业、医疗、安全监控等领域。本文旨在探讨光的传播原理及其在机器视觉中的…

【Python-语法】

Python-语法 ■ Python基础■ 数据类型■ 注释 单行注释&#xff0c;多行注释■ 编码方式 ■■■■■ ■ Python基础 ■ 数据类型 ■ 注释 单行注释&#xff0c;多行注释 ■ 编码方式 ■ ■ ■ ■ ■

花生壳内网穿透教程(图文并茂)

目录 前言&#xff1a; 使用教程&#xff1a; 1.注册账号 2.软件下载及安装&#xff1a; 3.账号绑定及花生壳的使用 4.内网穿透的配置&#xff08;重点&#xff09; 4.2 新增映射页面&#xff1a; 4.3 上面几种映射的区别&#xff1a; 4.4 上面TCP类型的区别&#xff1a;…

【Android 性能优化:内存篇】——ExoPlayer 释放后内存没有恢复问题探索

背景 最近笔者承接项目的内存优化指标&#xff0c;在内存调研的过程中发现项目中视频播放结束后&#xff0c;内存没有恢复到播放前到水平。项目中用的 EXO 版本为2.19.1&#xff0c;并且笔者自己也写了个简单的 Demo&#xff0c;发现也是如此。虽然有一些偏门方法可以优化&…

第九届大数据与计算国际会议 (ICBDC 2024) 即将召开!

2024年第九届大数据与计算国际会议&#xff08;ICBDC 2024&#xff09;将于2024年5月24至26日在泰国曼谷举行。本次会议由朱拉隆功大学工程学院工业工程系主办。ICBDC 2024的宗旨是展示大数据和计算主题相关科学家的最新研究和成果&#xff0c;为来自不同地区的专家代表们提供一…

基于PID-bang-bang控制算法的卫星姿态控制matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于PID-bang-bang控制算法的卫星姿态控制。仿真输出控制器的控制收敛曲线&#xff0c;卫星姿态调整过程的动画。 2.系统仿真结果 3.核心程序与模型 版本&#xff1a;MATLAB…

CSRF攻击和防御

CSRF:Cross Site Request Forgery 跨站请求伪造 攻击&#xff1a; 攻击者盗用你的身份&#xff0c;以你的名义发送恶意请求&#xff08;邮件&#xff0c;消息&#xff0c;盗取账号&#xff0c;购买物品&#xff09; GET请求的伪造方式 POST请求的伪造方式 防御&#xff1a…

SpringBoot -【SmartInitializingSingleton】基础使用及应用场景

SmartInitializingSingleton 在继续深入探讨 SmartInitializingSingleton接口之前&#xff0c;让我们先了解一下 Spring Framework 的基本概念和背景。Spring Framework 是一个开源的 JavaEE&#xff08;Java Enterprise Edition&#xff09;全栈&#xff08;full-stack&#x…

javaEE图书馆自习室订座系统信用springmvc+springboot+mybatis

研究的内容是设计和实现图书馆自习室系统&#xff0c;便捷广大师生对自习室的使用&#xff0c;协助图书馆自习室管理。在设计过程中&#xff0c;系统的用户角色和权限分配如下&#xff1a; &#xff08;1&#xff09;馆长 用户管理&#xff1a;拥有自习室管理员、普通用户的所有…

29. 【Linux教程】Linux 用户介绍

本小节介绍 Linux 用户的基础知识&#xff0c;了解 Linux 系统中有哪些用户&#xff0c;如何查看当前 Linux 系统中有哪些用户&#xff0c;每一个 Linux 用户的权限取决于这些账号登录时获取到的权限。 1. Linux 用户类型 Linux 系统是一个多用户多任务的操作系统&#xff0c;…