力扣刷题(31-40)
31.下一个排列①题目题目目的使用原来的这些数字找到一个刚好比当前排列大的排列。题目要求②答案class Solution(object): def nextPermutation(self, nums): :type nums: List[int] :rtype: None Do not return anything, modify nums in-place instead. n len(nums) # 第一步从右向左寻找第一个 nums[i] nums[i 1] 的位置 i n - 2 #让 i 从倒数第二个元素开始 while i 0 and nums[i] nums[i 1]: i - 1 #让 i 向左移动一个位置 # 如果找到了可以变大的位置 if i 0: # 第二步从右向左寻找第一个大于 nums[i] 的数字 j n - 1 while nums[j] nums[i]: j - 1 # 第三步交换 nums[i] 和 nums[j] nums[i], nums[j] nums[j], nums[i] # 第四步反转 i 后面的部分 left i 1 right n - 1 while left right: nums[left], nums[right] nums[right], nums[left] left 1 right - 1③考点字典序字典序就是像查字典一样从左到右逐个比较。比较两个序列时先比较第一个元素如果相同再比较第二个一直比较到出现第一个不同的元素在这个位置元素更小的序列字典序更小。代码核心思路核心目标是在所有比当前数组大的排列中找到最小的那个排列。也就是让数组“刚好变大一点”而不是变大很多。代码思路可以概括为四步从右找转折点 → 从右找替换值 → 交换 → 反转后半部分第一步从右向左寻找第一个可以变大的位置第二步从右向左找一个刚好比nums[i]大的数字第三步交换nums[i]和nums[j]第四步反转i后面的部分32.困难最长的有效括号33.搜索螺旋排序数组①题目②答案class Solution(object): def search(self, nums, target): :type nums: List[int] :type target: int :rtype: int left 0 right len(nums) - 1 while left right: mid (left right) // 2 # 找到目标值 if nums[mid] target: return mid # 左半部分有序 if nums[left] nums[mid]: # target 在左半部分的有序区间中 if nums[left] target nums[mid]: right mid - 1 else: left mid 1 # 否则右半部分有序 else: # target 在右半部分的有序区间中 if nums[mid] target nums[right]: left mid 1 else: right mid - 1 return -1③考点为什么不能直接遍历最简单的方法是for i in range(len(nums)): if nums[i] target: return i但是这种方法的时间复杂度是O(n)题目明确要求O(log n)因此必须使用二分查找。34.在排序数组中查找元素的第一个和最后一个位置①题目②答案class Solution(object): def searchRange(self, nums, target): :type nums: List[int] :type target: int :rtype: List[int] # 查找 target 第一次出现的位置 def findLeft(): left 0 right len(nums) - 1 result -1 while left right: mid (left right) // 2 if nums[mid] target: result mid # 找到了以后继续向左寻找 right mid - 1 elif nums[mid] target: left mid 1 else: right mid - 1 return result # 查找 target 最后一次出现的位置 def findRight(): left 0 right len(nums) - 1 result -1 while left right: mid (left right) // 2 if nums[mid] target: result mid # 找到了以后继续向右寻找 left mid 1 elif nums[mid] target: left mid 1 else: right mid - 1 return result # 必须和 findLeft、findRight 函数定义保持同一级缩进 return [findLeft(), findRight()]③考点题目要求时间复杂度必须是O(log n)因此不能从头到尾遍历数组而要使用二分查找。普通二分查找不够普通二分查找只能保证找到某一个target但不一定找到第一个或最后一个。例如nums [5, 7, 7, 8, 8, 10]普通二分查找可能找到下标3也可能找到下标4。所以我们需要进行两次二分查找第一次寻找target的最左位置。第二次寻找target的最右位置35.搜索插入位置①题目②答案class Solution(object): def searchInsert(self, nums, target): :type nums: List[int] :type target: int :rtype: int left 0 right len(nums) - 1 while left right: mid (left right) // 2 if nums[mid] target: return mid elif nums[mid] target: left mid 1 else: right mid - 1 return left③考点二分查找为什么最后返回left这是这道题最重要的地方。当循环结束时一定有left right此时right指向最后一个小于target的位置left指向第一个大于target的位置因此left正是target应该插入的位置。也可以理解为小于 target 的元素 | target 应插入的位置 | 大于 target 的元素 ↑ left36.有效的数独①题目②答案class Solution(object): def isValidSudoku(self, board): :type board: List[List[str]] :rtype: bool # rows[i] 记录第 i 行出现过的数字 rows [set() for _ in range(9)] # cols[j] 记录第 j 列出现过的数字 cols [set() for _ in range(9)] # boxes[k] 记录第 k 个 3×3 宫格出现过的数字 boxes [set() for _ in range(9)] # 遍历 9 行 for i in range(9): # 遍历每一行的 9 列 for j in range(9): num board[i][j] # 空格不需要检查 if num .: continue # 计算当前位置属于哪个 3×3 宫格 box_index (i // 3) * 3 j // 3 # 只要行、列、宫格中有一个已经存在该数字就无效 if (num in rows[i] or num in cols[j] or num in boxes[box_index]): #if 条件换行时Python 编译器不知道条件是否结束,所以需要在整个 if 条件的外面包裹一层小括号 ()。 return False # 当前数字没有重复将它记录下来 rows[i].add(num) cols[j].add(num) boxes[box_index].add(num) # 所有位置都检查完没有发现重复 return True③考点set()set天生就是为“快速判断元素是否存在”设计的所以比用列表更符合题意。continue跳过当前这一轮循环直接进入下一轮循环break彻底终止整个循环。一旦遇到break整个循环直接结束后面的所有轮次都不执行37.困难解数独38.外观数列①题目②答案class Solution(object): def countAndSay(self, n): :type n: int :rtype: str # 第一项固定是 1 s 1 # 已经有了第 1 项因此只需要再生成 n - 1 次 for _ in range(n - 1): next_s [] count 1 # 从第二个字符开始与前一个字符比较 for i in range(1, len(s)): if s[i] s[i - 1]: # 和前一个字符相同连续数量加一 count 1 else: # 和前一个字符不同说明上一组连续字符结束 next_s.append(str(count)) next_s.append(s[i - 1]) # 开始统计新的一组字符 count 1 # 循环结束后最后一组字符还没有加入结果 next_s.append(str(count)) next_s.append(s[-1]) # 列表拼接成字符串作为下一轮的输入 s .join(next_s) return s③考点1.在代码中需要维护count当前字符连续出现了多少次next_s用来保存生成的下一项2.当s 1时字符串的长度len(s)等于 1。因此循环语句for i in range(1, len(s)):实际上变成了for i in range(1, 1):。在 Python 中range(1, 1)是一个空序列所以i不会取到任何值整个for循环体被完全跳过。3.s[-1]就是字符串1的最后一个字符也就是1本身4.append是“打包塞进去”extend是“拆开铺进去”。39.组合总和①题目②答案class Solution(object): def combinationSum(self, candidates, target): :type candidates: List[int] :type target: int :rtype: List[List[int]] result [] #保存所有符合要求的组合 path [] #表示当前正在尝试的组合 # 排序后可以进行剪枝 candidates.sort() #start 表示这次可以从 candidates 的哪个位置开始选择 #remain 表示距离目标值还差多少 def backtrack(start, remain): # 剩余值恰好为 0说明当前组合满足要求 if remain 0: result.append(path[:]) #path[:] 会复制一份当前列表将独立的列表保存到 result 中。 return for i in range(start, len(candidates)): num candidates[i] # 因为已经排序当前数字大于 remain # 后面的数字只会更大可以直接结束循环 if num remain: break # 选择当前数字 path.append(num) # i 不加 1表示当前数字还可以继续重复使用 backtrack(i, remain - num) # 撤销选择尝试下一个数字 path.pop() backtrack(0, target) return result③考点回溯法“剪枝”Pruning是计算机科学特别是算法和人工智能中的一个核心优化策略。它的核心思想非常直白在搜索或遍历的过程中通过某些规则提前判断出某些分支不可能产生最优解或有效解从而直接放弃“剪掉”这些分支不再继续往下搜索。1. 为什么不能直接result.append(path)在 Python 中当你执行result.append(path)时你并没有把path里的数据复制一份放进result你只是把path这个变量的内存地址引用放进了result中。回溯算法的核心在于“状态重置”。当我们在一条分支上找到答案后会通过path.pop()撤销刚才的选择退回到上一步继续寻找下一个答案。如果你直接append(path)由于result和path指向的是内存中的同一个列表后续所有的pop()操作都会把result里刚刚存进去的数据给“掏空”。最终你的result里会装满空列表[]。2.path[:]做了什么path[:]是 Python 中的切片操作它的完整写法相当于path[0:len(path)]。这个操作会在内存中创建一个全新的列表把path当前时刻的所有元素复制过去。当你执行result.append(path[:])时你存入result的是一个独立的快照副本。无论后续path怎么pop()、怎么变化这个已经存入result的副本都不会受到任何影响。path.append(num)的目的是“推进状态”在回溯的探索过程中我们需要不断地往当前路径中添加新的元素以便进入下一层递归。我们确实需要修改path这个列表本身。append正是用来修改原列表的方法。result.append(path[:])的目的是“保存快照”当我们找到一条完整的路径时我们需要把它存起来。此时我们绝对不能修改path而是需要把path当前的状态复制一份存进result。所以这里用path[:]来创建副本。break的作用是提前结束整个for循环不再尝试当前层级的后续数字。continue的作用是跳过当前这一轮的循环直接进入下一轮循环。40.组合总和Ⅱ①题目②答案class Solution(object): def combinationSum2(self, candidates, target): :type candidates: List[int] :type target: int :rtype: List[List[int]] # 先排序方便去重和剪枝 candidates.sort() res [] path [] def backtrack(start, remain): # remain 等于 0说明 path 中的数字之和正好等于 target if remain 0: res.append(path[:]) return # 从 start 开始选择数字 for i in range(start, len(candidates)): # 当前层中跳过重复数字 if i start and candidates[i] candidates[i - 1]: continue # 当前数字已经大于剩余目标值 # 后面的数字更大不需要继续尝试 if candidates[i] remain: break # 选择 candidates[i] path.append(candidates[i]) # i 1 表示当前元素不能再次使用 backtrack(i 1, remain - candidates[i]) # 撤销刚才的选择 path.pop() backtrack(0, target) return res③考点排序 回溯回溯的过程可以理解为依次尝试选择一个数字如果选择后还没有达到目标值就继续向后选择尝试完成后撤销这次选择再尝试其他数字。candidates.sort()默认是从小到大升序排列的如果想从大到小降序排列candidates.sort(reverseTrue)知识点复杂度

相关新闻

RTX5060显卡架构与性能深度解析

RTX5060显卡架构与性能深度解析

1. RTX5060显卡架构概览 2026年发布的RTX5060系列延续了NVIDIA经典的"60"系甜品卡定位,首次采用双版本同步发布策略。桌面版采用PG190 PCB设计,核心代号GN20-X6;移动版则使用GN20-X6M芯片,两者均基于Ada Lovelace Next架…

2026/7/21 6:10:24 阅读更多 →
OpenClaw:AI代码生成与审核重构开发流程

OpenClaw:AI代码生成与审核重构开发流程

1. 从代码编写到AI审核:OpenClaw如何重构开发流程 凌晨三点,我盯着屏幕上闪烁的光标,第17次重构那段该死的业务逻辑。突然意识到——我们正处在编程范式变革的前夜。OpenClaw的出现,让"程序员亲自敲代码"逐渐变成一种可…

2026/7/21 6:10:24 阅读更多 →
ROS中为PR2添加场景物体:MoveIt!空间建模实战指南

ROS中为PR2添加场景物体:MoveIt!空间建模实战指南

1. 项目概述:这不是“加个模型”那么简单,而是理解ROS机器人空间认知的第一课如果你刚接触ROS(Robot Operating System),看到“在rviz中为PR2增加场景物体”这个标题,第一反应可能是:“不就是拖…

2026/7/21 6:10:23 阅读更多 →

最新新闻

EDMA3性能优化实战:从系统优先级到传输控制器的深度调优

EDMA3性能优化实战:从系统优先级到传输控制器的深度调优

1. 项目概述与核心价值 在嵌入式系统开发,尤其是涉及音视频处理、高速数据采集或实时通信的场景里,CPU常常被海量的数据搬运任务所拖累。想象一下,一个480P的视频流,每秒30帧,每帧数据量接近1MB,如果全靠CP…

2026/7/21 20:53:22 阅读更多 →
数学资源宝库:Awesome Math项目深度解析与实用指南

数学资源宝库:Awesome Math项目深度解析与实用指南

数学资源宝库:Awesome Math项目深度解析与实用指南 【免费下载链接】awesome-math A curated list of awesome mathematics resources 项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-math 在数学学习和研究的世界里,寻找优质资源往往…

2026/7/21 20:53:22 阅读更多 →
如何在Windows电脑上轻松安装ChromeOS:Brunch框架完整指南

如何在Windows电脑上轻松安装ChromeOS:Brunch框架完整指南

如何在Windows电脑上轻松安装ChromeOS:Brunch框架完整指南 【免费下载链接】brunch Boot ChromeOS on x86_64 PC - Supports Intel CPU/GPU from 8th gen or AMD Ryzen 项目地址: https://gitcode.com/gh_mirrors/bru/brunch 你是否厌倦了Windows系统的臃肿和…

2026/7/21 20:53:22 阅读更多 →
从POC到EXP:绕过NX/PIE、vtable劫持与堆利用的实战解析

从POC到EXP:绕过NX/PIE、vtable劫持与堆利用的实战解析

1. 项目概述:从概念验证到武器化利用的鸿沟在漏洞研究的圈子里,拿到一个CVE编号,比如CVE-2025-0282,然后写出一个能稳定触发崩溃的POC(概念验证),这通常只是万里长征的第一步。真正的挑战&#…

2026/7/21 20:53:22 阅读更多 →
Powerlevel10k终极指南:5分钟打造专业级Zsh终端提示符

Powerlevel10k终极指南:5分钟打造专业级Zsh终端提示符

Powerlevel10k终极指南:5分钟打造专业级Zsh终端提示符 【免费下载链接】powerlevel10k A Zsh theme 项目地址: https://gitcode.com/GitHub_Trending/po/powerlevel10k 你是否厌倦了单调的终端界面?是否希望在命令行工作时能一目了然地获取关键信…

2026/7/21 20:53:22 阅读更多 →
UE5高分辨率渲染下阴影条纹问题的成因分析与系统解决方案

UE5高分辨率渲染下阴影条纹问题的成因分析与系统解决方案

1. 项目概述:高分辨率下的“条纹阴影”究竟是什么? 在UE5项目里,当你把渲染分辨率拉到4K、8K甚至更高,准备截一张惊艳的展示图或渲染一段高质量影片时,屏幕上那些本该平滑的阴影区域,却突然出现了令人抓狂的…

2026/7/21 20:52:21 阅读更多 →

日新闻

Octane Render与C4D汉化版安装与优化指南

Octane Render与C4D汉化版安装与优化指南

1. Octane Render与C4D的黄金组合:为什么选择这个方案?在三维创作领域,渲染器的选择往往决定了作品的最终呈现质量和工作效率。作为Cinema 4D(C4D)用户,Octane Render的GPU加速特性与实时预览功能&#xff…

2026/7/21 0:00:19 阅读更多 →
GPMC接口设计:异步/同步模式与多路复用配置实战

GPMC接口设计:异步/同步模式与多路复用配置实战

1. GPMC接口设计:从硬件连接到软件配置的全局视角在嵌入式系统开发中,尤其是基于TI Sitara系列如AM263x这类高性能微控制器的项目里,外部存储器的扩展几乎是绕不开的一环。无论是存放大量非易失性代码的NOR Flash,还是作为高速数据…

2026/7/21 0:00:19 阅读更多 →
UE5 GAS框架下RPG被动技能系统:从核心原理到实战实现

UE5 GAS框架下RPG被动技能系统:从核心原理到实战实现

1. 项目概述:UE5 GAS RPG被动技能的核心价值在UE5里用GAS(Gameplay Ability System)做RPG游戏,主动技能像是你手里的武器,按一下打一下,逻辑直接,反馈也快。但被动技能,它更像是你身…

2026/7/21 0:00:19 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/21 8:48:31 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/21 5:34:47 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/21 8:25:39 阅读更多 →

月新闻