【PythonCode】力扣Leetcode16~20题Python版

news2024/12/23 19:07:14

【PythonCode】力扣Leetcode16~20题Python版

前言

力扣Leetcode是一个集学习、刷题、竞赛等功能于一体的编程学习平台,很多计算机相关专业的学生、编程自学者、IT从业者在上面学习和刷题。
在Leetcode上刷题,可以选择各种主流的编程语言,如C++、JAVA、Python、Go等。还可以在线编程,实时执行代码,如果代码通过了平台准备的测试用例,就可以通过题目。
本系列中的文章从Leetcode的第1题开始,记录我用Python语言提交的代码和思路,供Python学习参考。

16. 最接近的三数之和

给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。

返回这三个数的和。

假定每组输入只存在恰好一个解。

示例 1:
输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
示例 2:
输入:nums = [0,0,0], target = 1
输出:0
提示:
3 <= nums.length <= 1000
-1000 <= nums[i] <= 1000
-104 <= target <= 104

代码实现:

class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        nums.sort()
        n = len(nums)
        if n == 3 or target <= nums[0] + nums[1] + nums[2]:
            return nums[0] + nums[1] + nums[2]
        if target >= nums[n-1] + nums[n-2] + nums[n-3]:
            return nums[n-1] + nums[n-2] + nums[n-3]
        result = nums[0] + nums[1] + nums[2]
        for i in range(n - 2):
            if i > 0 and nums[i] == nums[i - 1]:
                continue
            j, k = i + 1, n - 1
            while j < k:
                if abs(nums[i] + nums[j] + nums[k] - target) < abs(result - target):
                    result = nums[i] + nums[j] + nums[k]
                if result == target:
                    return result
                if nums[i] + nums[j] + nums[k] > target:
                    k -= 1
                else:
                    j += 1
        return result

解题思路:本题是力扣15题《三数之和》的变化版,第15题是三个数之和为0,本题是三个数之和最接近目标值target,所以解题思路相似。

先将数组排序,首先分析特殊情况,如果数组只有三个数,那最接近目标值的三数之和必然就是三个数相加。因为将数组做了排序,如果目标值小于前三个数之和,那最接近目标值的三数之和就是前三个数之和,同理如果目标值大于最大的三个数之和,那最接近目标值的三数之和就是最后三个数之和。

对于一般的情况,首先先遍历获取第一个数,然后再用双指针的方式取第二个数和第三个数,将三数之和初始化为前三个数之和。使用双指针时,第二个数从第一个数的后一个开始取,第三个数从数组的最后一个数开始取,如果三数之和大于目标值,则第三个数的指针前移,如果三数之和小于目标值,则第二个数的指针后移,如果三数之和等于目标值直接返回。在遍历过程中不断更新三数之和,当找到与目标值相等或遍历完数组之后,程序结束。

17. 电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

在这里插入图片描述

示例 1:
输入:digits = “23”
输出:[“ad”,“ae”,“af”,“bd”,“be”,“bf”,“cd”,“ce”,“cf”]
示例 2:
输入:digits = “”
输出:[]
示例 3:
输入:digits = “2”
输出:[“a”,“b”,“c”]
提示:
0 <= digits.length <= 4
digits[i] 是范围 [‘2’, ‘9’] 的一个数字。

代码实现:

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        if digits == '':
            return []
        conversion = {'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl', '6': 'mno', '7': 'pqrs', '8': 'tuv', '9': 'wxyz'}
        def backtrack(index):
            if index == len(digits):
                result.append("".join(temp))
            else:
                digit = digits[index]
                for x in conversion[digit]:
                    temp.append(x)
                    backtrack(index + 1)
                    temp.pop()
        result = []
        temp = []
        backtrack(0)
        return result    

解题思路:本题需要将字符串中每个数字对应的字母组合在一起,所以要遍历每一个数字对应的多个字母,然而数字的个数是0到4,不知道是几层遍历,不好求解。这里可以用回溯法,回溯法刚好可以穷举解空间的所有可能。参考:循序渐进,搞懂什么是回溯算法

按照回溯法的求解步骤,先定义回溯的解空间,本题是求数字对应的所有字母组合,所以结果是一个数组。回溯时,搜索树是一个高度最高为4的搜索树,深度优先遍历时在每一层取一个字母。在每次遍历到搜索树的叶结点时,会得到一种组合,将组合保存到求解的数组中,直到遍历完整个搜索树。

结合代码,首先定义好数字和字母的映射关系,初始化求解的结果数组result,回溯时的字母组合数组temp。然后定义回溯函数backtrack(),在回溯函数中,如果遍历到叶结点,就找到一种组合,所以当遍历的高度等于搜索树的高度时,要把当前的字母组合temp保存到result中,如果没有到叶结点,就在当前的结点取一个字母添加到temp中,往回回溯时,将上一个添加的字母从temp中移除,也就是将temp中的最后一个字母移除。最后调用回溯函数backtrack(),从高度0开始,从根结点开始遍历搜索树。

特殊情况,digits如果长度为0,此时不存在字母组合,直接返回空数组。

18. 四数之和

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。

示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:
输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]
提示:
1 <= nums.length <= 200
-109 <= nums[i] <= 109
-109 <= target <= 109

代码实现:

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        if len(nums) < 4:
            return []
        nums.sort()
        result = []
        for i in range(len(nums) - 3):
            if i > 0 and nums[i] == nums[i - 1]:
                continue
            for j in range(i + 1, len(nums) - 2):
                if j > i + 1 and nums[j] == nums[j - 1]:
                    continue
                x = j + 1
                y = len(nums) - 1
                while x < y:
                    if x < y and nums[i] + nums[j] + nums[x] + nums[y] < target:
                        x += 1
                        while nums[x] == nums[x-1] and x < y:
                            x += 1
                    if x < y and nums[i] + nums[j] + nums[x] + nums[y] > target:
                        y -= 1
                        while nums[y] == nums[y+1] and x < y:
                            y -= 1
                    if x < y and nums[i] + nums[j] + nums[x] + nums[y] == target:
                        result.append([nums[i], nums[j], nums[x], nums[y]])
                        x += 1
                        while nums[x] == nums[x-1] and x < y:
                            x += 1
        return result

解题思路:四数之和是三数之和的升级版,数字多了一个,但是整体解题思路不变,只是时间复杂度更大,情况也更复杂了。解题方法是嵌套遍历前两个数,后两个数用双指针。

先将数组排序,首先遍历取第一个数和第二个数,第一个数可以从数组第一个数遍历到数组的倒数第四个数,第二个数可以从第一个数的后一个数遍历到数组的倒数第三个数。然后用双指针取第三个数和第四个数,第三个数从第二个数的后一个数开始取,第四个数从数组最后一个数开始取。遍历第一个数和第二个数时,如果当前数值与前一个数值相等,则跳过(剪枝)。

取到四个数后,将四数之和与目标值比较,如果四数之和小于目标值,则第三个数的指针右移,如果四数之和大于目标值,则第四个数的指针左移,如果四数之和等于目标值,则找到一种组合,将当前组合保存到结果中。这里有两个注意点,一是找到一种组合后,不能跳过当前遍历,因为如果当前的四数之和等于0,第三个数变大,同时第四个数变小,可能还有其他组合的和也等于0,所以找到一种组合后,将第三个数的指针右移继续找。二是在移动第三个数或第四个数的指针时,如果当前的值等于上一个数的值,应继续移动指针,否则会将重复的组合添加到结果中,并且可能还有连续几个值相等的情况,所以代码是在while循环中移动指针。这里虽然多了一层循环,只有当数组中连续多个值相等才会跑到while循环的代码,对时间复杂度基本没有影响。

19. 删除链表的倒数第 N 个结点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

在这里插入图片描述

示例 1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
示例 3:
输入:head = [1,2], n = 1
输出:[1]
提示:
链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz

代码实现:

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        prev = ListNode(0, head)
        fast, slow = prev, prev
        for i in range(n):  
            fast = fast.next
        while fast.next:
            fast = fast.next  
            slow = slow.next
        slow.next = slow.next.next
        return prev.next

解题思路:要删除链表中的倒数第N个结点,首先要找到目标结点的前一个结点,也就是倒数第 n+1 个结点,修改前一个结点的 next 指针,让它指向目标结点的下一个结点,即倒数第 n-1 个结点。参考:Python实现单向链表

要找到链表的倒数第 n+1 个结点,可以先求出链表的长度 L ,第 L-n 个结点就是倒数 n+1 个结点。这样需要遍历两次链表,第一次求长度,第二次找倒数 n+1 个结点。还有一种更好的方法是使用双指针,这里的双指针和前面求三数之和时的用法有点差异,也叫快慢指针,两个指针的移动方向一样,一个在前一个在后。

在开始使用指针前,因为要找倒数第 n+1 个结点,假如 n 等于链表长度,也就是要删除链表的头结点,此时不存在倒数第 n+1 个结点,所以需要先对链表做一个特殊处理,在链表前加一个前置节点,使得双指针具有一般性。

在初始状态,让两个指针都指向链表的前置节点,然后让快的一个指针先向前移动 n 个结点,然后两个指针以相同的速度向后移动,直到快指针移动到链表的末尾,此时慢指针指向的节点就是倒数第 n+1 个结点。此时,将倒数第 n+1个结点的 next 指向倒数第 n-1 个结点,即可从链表中删除倒数第 n 个结点。

题目要求返回链表的头,因为在链表的前面加了一个前置节点,所以链表的头是前置节点的下一个节点,即 prev.next 。

20. 有效的括号

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。

示例 1:
输入:s = “()”
输出:true
示例 2:
输入:s = “()[]{}”
输出:true
示例 3:
输入:s = “(]”
输出:false
提示:
1 <= s.length <= 104
s 仅由括号 ‘()[]{}’ 组成

代码实现:

class Solution:
    def isValid(self, s: str) -> bool:
        dic = {'(': ')', '{': '}', '[': ']'}
        stack = []
        for c in s:
            if c in dic:
                stack.append(c)
            elif stack and dic[stack[-1]] == c:
                stack.pop()
            else:
                return False
        return not stack

解题思路:本题中,有效的字符串中括号是成对的,并且是按规则闭合的(可以嵌套),三种类型的括号都是先有左括号再有右括号,这种成对的判断刚好可以对应栈的入栈和出栈,所以可以用栈来实现本题。参考:Python实现栈

先初始化一个字典,维护左括号与右括号的关系,并初始化一个空栈(代码中这个栈用列表、字符串等都行)。遍历字符串s,如果当前的符号是关系字典中的key,则入栈,如果栈非空,并且当前的符号与栈顶的符号对应,能组成一组闭合的括号,则将栈顶的符号出栈。如果是其他情况(栈为空时遇到右括号、右括号与当前栈顶的左括号类型不一样不能闭合),则直接返回False。

遍历完字符串s,如果栈是空的,则表示字符串s有效,所有括号都能按规则闭合,如果栈非空,则表示字符串s无效,还剩余未闭合的括号。


相关阅读

【PythonCode】力扣Leetcode11~15题Python版

📢欢迎 点赞👍 收藏⭐ 评论📝 关注 如有错误敬请指正!

☟ 学Python,点击下方名片关注我。☟

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

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

相关文章

汇编语言(详解)

汇编语言安装指南 第一步&#xff1a;在github上下载汇编语言的安装包 网址&#xff1a;GitHub - HaiPenglai/bilibili_assembly: B站-汇编语言-pdf、代码、环境等资料B站-汇编语言-pdf、代码、环境等资料. Contribute to HaiPenglai/bilibili_assembly development by creat…

一文让你彻底掌握操作符(超详细教程)

✅作者简介&#xff1a;大家好&#xff0c;我是小杨 &#x1f4c3;个人主页&#xff1a;「小杨」的csdn博客 &#x1f525;系列专栏&#xff1a;小杨带你玩转C语言【初阶】 &#x1f433;希望大家多多支持&#x1f970;一起进步呀&#xff01; 大家好呀&#xff01;我是小杨。小…

学习笔记-数据结构-线性表(2024-04-18)- 单向链表选择排序

试以单向链表为存储结构实现简单选择排序的算法。 实现递增排序&#xff0c;首先选择一个元素作为第一个比较值&#xff0c;遍历其他所有的元素&#xff0c;如果发现其他元素中有比它小的元素&#xff0c;则交换两个元素&#xff0c;这样每一趟都能找到符合要求的最小值 正经…

Turnitin查重时,论文里面的图片会不会被查到?

在撰写论文的时候&#xff0c;论文里面插入几张图片作为观点和数据的阐述在再正常不过了。但是&#xff0c;一旦涉及到论文查重&#xff0c;事情就变得有点复杂了。许多同学早使用Turnitin检测系统&#xff08;www.checktoo.com&#xff09;对论文查重时&#xff0c;就常问题到…

记录交叉编译环境配置--海思开发板的 嵌入式nginx和 php的移植

嵌入式 lnmp搭建的记录 一些交叉编译的配置环境思路分享&#xff1a;P&#xff1a;php编译PHP可能遇到的问题configure阶段&#xff1a;Makefile-make阶段&#xff1a;Makefile-make install阶段&#xff1a; N&#xff1a;Nginx 文章比较水&#xff0c;并没有没解决什么实际问…

现货白银保证金交易要先分析趋势

现货白银是保证金交易品种&#xff0c;买卖过程中可能会涉及数十倍的资金杠杆&#xff0c;所以它对投资者的分析水平和交易水平的要求都比较高&#xff0c;所以在进入这个市场之前&#xff0c;投资者需要先学习一些基本的分析方法&#xff0c;当中可以分为基本面和技术面两大流…

2024年外贸独立站建设首选:WordPress引领市场,助力企业出海

随着全球经济的不断融合与发展&#xff0c;越来越多的企业开始关注海外市场&#xff0c;希望通过建设外贸独立站来扩大品牌影响力和销售额。在众多的内容管理系统&#xff08;CMS&#xff09;中&#xff0c;WordPress以其强大的功能、丰富的插件资源和用户友好的操作界面&#…

医学临床预测模型发展新趋势-并联式

医学临床预测模型发展新姿势-并联式 现有的预测模型是对单个结局指标进行分类或者回归&#xff0c;得出最终的结论&#xff0c;而辅助医生进行临床决策。众所周知&#xff0c;临床决策过程中&#xff0c;医生通常会考虑多个结局指标来做出最终的决策&#xff1b;临床研究中也通…

多因子模型的因子分组-克隆巴赫α系数

优质博文&#xff1a;IT-BLOG-CN 在建立我们的Alpha模型之前&#xff0c;我们得先知道什么是Alpha&#xff1f;Alpha是一条或者一系列能够预测股票走势的信息资讯组合。而这每一条非随机的信息资讯&#xff0c;我们称之为多因子模型的因子。多因子模型因子的选择需要避免系统性…

苍穹外卖day1--开发环境搭建

整体结构 前端&#xff1a;管理端&#xff08;Web&#xff09; 用户端&#xff08;小程序&#xff09; 后端&#xff1a;后端服务&#xff08;Java&#xff09; 前端工程基于ngnix运行 启动nginx&#xff1a;双击nginx.exe即可启动nginx服务&#xff0c;访问端口号为80 后端…

智慧浪潮下的产业园区:解读智慧化转型如何打造高效、绿色、安全的新产业高地

随着信息技术的飞速发展&#xff0c;智慧化转型已经成为产业园区发展的重要趋势。在智慧浪潮的推动下&#xff0c;产业园区通过集成应用物联网、大数据、云计算、人工智能等先进技术手段&#xff0c;实现园区的智慧化、高效化、绿色化和安全化&#xff0c;从而打造成为新产业高…

网络安全产品---数据库防火墙/审计

数据库防火墙 防火墙的类型繁多&#xff0c;即使下一代防火墙或者说AI防火墙集成功能再多&#xff0c;我觉得waf与数据库防火墙也有其无法被替代的理由&#xff0c;以此记录我对数据库防火墙的理解 what 数据库防火墙是基于数据库协议分析与访问行为控制的数据库安全防护产品…

ZStack教育云计算解决方案入选高质量数字化转型技术解决方案集

近日&#xff0c;中国信通院“铸基计划”《高质量数字化转型技术解决方案&#xff08;2023年度&#xff09;》&#xff08;以下简称“方案集”&#xff09;发布&#xff0c;云轴科技ZStack智慧教育云计算解决方案入选《高质量数字化转型技术解决方案集》。 为促进数字化转型相…

Kubernetes Pod OOMKilled诊断

Kubernetes Pod OOMKilled诊断 介绍 OOMKilled错误表示容器或pod已被终止&#xff0c;因为它使用的内存多于分配的内存。OOMKilled&#xff0c;通常称为Exit Code 137&#xff0c;是一种源自Linux的错误。OOM&#xff08;Out of Memory Manager&#xff09;是Linux系统上的一…

【Flutter】多语言方案二:GetX 版

介绍 多语言方案&#xff1a;GetX版&#xff0c;需要手动自定义字符串引用常量&#xff0c;优点不需要自己管理状态。 目录 介绍运行效果一、安装 GetX二、使用1.语言配置 在lib/core下创建一个language文件夹&#xff0c;文件夹下创建一个local.dart文件2.language文件夹下创…

网络行为分析与异常检测

构建防火墙和使用简单的安全解决方案不足以保护网络免受网络异常或攻击&#xff0c;因为DDoS攻击、未知恶意软件和其他安全威胁一直在上升&#xff0c;改变了网络安全格局。网络管理员必须积极主动地分析网络&#xff0c;获得对网络的完全控制&#xff0c;并全面了解网络流量活…

数据可视化(六):Pandas爬取NBA球队排名、爬取历年中国人口数据、爬取中国大学排名、爬取sina股票数据、绘制精美函数图像

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

Docker Compose 的安装和使用详解

Docker Compose 是 Docker 官方开源的容器编排(Orchestration)项目之一,用于快速部署分布式应用。本文将介绍 Docker Compose 的基本概念、安装流程及使用方法。 简介 Compose 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排。从功能上看,Docker C…

【AI自媒体制作】【AI工具】Midjourney中文站

Midjourney Midjourney中文站, MJ中文站 - 专业AI绘图网站 广场 绘画广场&#xff1a; 包含大量其他用户生成好的图片&#xff0c;可以自由保存。 视频广场&#xff1a; 普通用户目前只支持查看&#xff0c;无法下载 画夹广场&#xff1a; 有很多免费的画夹&#xff0c;比…

对接浦发银行支付(五)-- 主动查询支付结果

一、背景 上一篇我们介绍了支付回调接口的对接情况&#xff0c;当回调出现网络等异常情况&#xff0c;导致用户的支付订单未及时处理或处理失败的时候&#xff0c;商户则需要自己主动向浦发银行发起查询支付结果。 主动查询支付结果&#xff0c;发挥补偿重试的重要作用&#x…