【日常系列】LeetCode《22·回溯1》

news2024/9/30 23:36:39

数据规模->时间复杂度

<=10^4 😮(n^2)
<=10^7:o(nlogn)
<=10^8:o(n)
10^8<=:o(logn),o(1)

内容

lc 112 和 113【剑指 34】 :路径总和
https://leetcode.cn/problems/path-sum/
https://leetcode.cn/problems/path-sum-ii/
提示1:
树中节点的数目在范围 [0, 5000] 内
-1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000
提示2:
树中节点总数在范围 [0, 5000] 内
-1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000

在这里插入图片描述
在这里插入图片描述

#lc 112 
#方案一:穷举所有路径+判断是否存在路径和(空间复杂度高)
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        self.res=list()
        path=list()
        self.dfs(root,path)
        #
        for onepath in self.res:
            if targetSum==sum(onepath):
                return True
        return False

    def dfs(self,node,path):
        if not node:return 
        path.append(node.val)
        if not node.left and not node.right: #叶子节点
            self.res.append(path[:]) #key:path[:],使res和path不能是同一个对象(‘回溯时清空’)
        #
        self.dfs(node.left,path)
        self.dfs(node.right,path)
        path.pop() #注:回溯时删当前节点

#方案二:计算每个节点的路径和(优化空间)
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        self.res=list()
        self.dfs(root,0)
        #
        for val in self.res:
            if targetSum==val:
                return True
        return False

    def dfs(self,node,onepathsum):
        if not node:return 
        onepathsum +=node.val
        if not node.left and not node.right: #叶子节点
            self.res.append(onepathsum)
        #
        self.dfs(node.left,onepathsum)
        self.dfs(node.right,onepathsum)

##方案三:计算每个节点的目标和(优化空间)
# Definition for a binary tree node.
# # class TreeNode:
# #     def __init__(self, val=0, left=None, right=None):
# #         self.val = val
# #         self.left = left
# #         self.right = right
# class Solution:
#     def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
#         self.res=list()
#         self.dfs(root,targetSum)
#         #
#         for val in self.res:
#             if val==0:
#                 return True
#         return False

#     def dfs(self,node,onepathtarget):
#         if not node:return 
#         onepathtarget -=node.val
#         if not node.left and not node.right: #叶子节点
#             self.res.append(onepathtarget) 
#         #
#         self.dfs(node.left,onepathtarget)
#         self.dfs(node.right,onepathtarget)

#方案四:提前返回(优化时间)
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        return self.dfs(root,targetSum)

    def dfs(self,node,onepathtarget): #bool
        if not node:return False #key:false
        onepathtarget -=node.val
        if not node.left and not node.right: #叶子节点
            return onepathtarget==0 
        #
        islefthasfind=self.dfs(node.left,onepathtarget)
        if islefthasfind:return True #提前退出
        return self.dfs(node.left,onepathtarget) or self.dfs(node.right,onepathtarget)

#lc 113
#方案一:拿到符合条件的路径及优化
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        self.res=list()
        path=list()
        self.dfs(root,path,targetSum)
        #
        return self.res
    
    def dfs(self,node,path,targetSum):
        if not node:return
        path.append(node.val)
        if not node.left and not node.right:
            if sum(path)==targetSum:
                self.res.append(path[:])
        #
        self.dfs(node.left,path,targetSum)
        self.dfs(node.right,path,targetSum)
        path.pop()

lc 46 和 47【剑指 083 和 084】【top100】 :全排列
https://leetcode.cn/problems/permutations/
https://leetcode.cn/problems/permutations-ii/
提示1:
1 <= nums.length <= 6
-10 <= nums[i] <= 10
nums 中的所有整数 互不相同
提示2:
1 <= nums.length <= 8
-10 <= nums[i] <= 10
nums 中的整数存在重复

#参考:https://www.bilibili.com/video/BV19v4y1S79W/?spm_id_from=333.337.search-card.all.click&vd_source=faf49b32c764ca86336e7f3fdff2c71f

#lc 46 
#时间:o(n!* n)
class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        self.res=list()
        path=list()
        used=[False]*len(nums)
        self.dfs(nums,path,used)
        return self.res
    
    #o(n)
    def dfs(self,nums,path,used):
        if len(path)==len(nums):#key:两层含义-终止;叶子节点
            self.res.append(path[:])
            return 
        #
        for i in range(len(nums)):
            #
            if used[i]:continue
            path.append(nums[i])
            used[i]=True
            #
            self.dfs(nums,path,used)
            #key:在回溯过程中,初始化(例如:1,2,3;1,3,2)
            path.pop()
            used[i]=False 
            
#lc 47 
#结果去重剪枝
class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        nums.sort()#key1:去重基础
        self.res=list()
        path=list()
        used=[False]*len(nums)
        self.dfs(nums,path,used)
        return self.res
    

    def dfs(self,nums,path,used):
        #
        if len(nums)==len(path):
            self.res.append(path[:])
            return 
        #
        for i in range(len(nums)):
            #
            if used[i]:continue
            #这里的used[i-1]已经访问过,并回溯初始化了,为False
            #参考:https://gitee.com/douma_edu/douma_algo_training_camp/issues/I48M6Q
            if i>0 and nums[i]==nums[i-1] and not used[i-1]:continue #key2:树层去重
            path.append(nums[i])
            used[i]=True
            #
            self.dfs(nums,path,used)
            path.pop()
            used[i]=False

lc 77【剑指 080】:组合
https://leetcode.cn/problems/combinations/
提示:
1 <= n <= 20
1 <= k <= n

在这里插入图片描述

class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        if n<0 or k<0 or k>n:return []
        self.res=list()
        path=[]
        self.dfs(n,k,1,path)
        return self.res
    
    def dfs(self,n,k,start,path):
        if len(path)==k:
            self.res.append(path[:])
            return 
        #key:start,i+1
        for i in range(start,n+1):
            path.append(i)
            self.dfs(n,k,i+1,path)
            path.pop()

lc 39 和 40【剑指 081 和 082】【top100】:组合总和
https://leetcode.cn/problems/combination-sum/
https://leetcode.cn/problems/combination-sum-ii/
提示1:
1 <= candidates.length <= 30
2 <= candidates[i] <= 40
candidates 的所有元素 互不相同
1 <= target <= 40
candidates中的每个数字可重复使用
提示2:
1 <= candidates.length <= 100
1 <= candidates[i] <= 50
1 <= target <= 30
candidates中的每个数字只能使用一次

#lc 39 
class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        self.res=[]
        path=list()
        self.dfs(candidates,0,path,target)
        return self.res

    def dfs(self,nums,startindex,path,target):
        if target<0:return
        if target==0:
            self.res.append(path[:])
            return
        #
        for i in range(startindex,len(nums)):
            path.append(nums[i])
            #target-=nums[i]
            #key
            self.dfs(nums,i,path,target-nums[i])
            path.pop()
            #target+=nums[i]
#lc 40
class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        candidates.sort() #key1
        self.res=[]
        path=[]
        self.dfs(candidates,0,path,target)
        return self.res

    def dfs(self,nums,startindex,path,target):
        if target<0:return 
        if target==0:
            self.res.append(path[:])
            return
        #
        for i in range(startindex,len(nums)):
            #key2:去重关键(树层去重)
            if i>startindex and nums[i]==nums[i-1]:continue#key:i>startindex
            path.append(nums[i])
            self.dfs(nums,i+1,path,target-nums[i])#key:i+1,非重复选取索引(树枝去重)
            path.pop() 

lc 78 和 90【剑指 079】【top100】:子集
https://leetcode.cn/problems/subsets/
https://leetcode.cn/problems/subsets-ii/
提示:
1 <= nums.length <= 10
-10 <= nums[i] <= 10
第一种,#nums 中的所有元素 互不相同#
第二种,#nums 中的所有元素含重复元素#
在这里插入图片描述

# lc 78 
class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        self.res=[]
        path=list()
        self.dfs(nums,0,path)
        return self.res
    def dfs(self,nums,startindex,path):
        #key:‘子集’
        self.res.append(path[:])
        for i in range(startindex,len(nums)):
            path.append(nums[i])
            self.dfs(nums,i+1,path)
            path.pop()   
#lc 90
class Solution:
    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        #key1
        nums.sort()
        self.res=[]
        path=list()
        self.dfs(nums,0,path)
        return self.res

    def dfs(self,nums,startindex,path):
        #key:‘子集’
        self.res.append(path[:])
        for i in range(startindex,len(nums)):
            if i>startindex and nums[i]==nums[i-1]:continue #key2
            path.append(nums[i])
            self.dfs(nums,i+1,path)
            path.pop()

lc 17【top100】:电话号码的字母组合
https://leetcode.cn/problems/letter-combinations-of-a-phone-number/
提示:
0 <= digits.length <= 4
digits[i] 是范围 [‘2’, ‘9’] 的一个数字。
在这里插入图片描述

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        if not digits:return []
        
        self.phone = {
            "2": "abc",
            "3": "def",
            "4": "ghi",
            "5": "jkl",
            "6": "mno",
            "7": "pqrs",
            "8": "tuv",
            "9": "wxyz",
        }

        self.res=[]
        path=''
        self.dfs(digits,0,path)
        return self.res

    def dfs(self,digits,index,path):
        if index==len(digits):
            self.res.append(path[:])
            return
        #key
        for c in self.phone[digits[index]]:
            self.dfs(digits,index+1,path+c)

lc 93【剑指 087】:复原 IP 地址
https://leetcode.cn/problems/restore-ip-addresses/
提示:
1 <= s.length <= 20
s 仅由数字组成
在这里插入图片描述

class Solution:
    def restoreIpAddresses(self, s: str) -> List[str]:
        self.res=[]
        path=''
        self.dfs(s,0,path,0)
        return self.res
    

    def is_valid_seg(self,seg):
        if len(seg)>3:return False
        return len(seg)==1 if seg[0]== '0' else int(seg)<=255


    def dfs(self,s,startindex,path,seg_cnts):
        if seg_cnts>4:return
        if seg_cnts==4 and startindex==len(s):
            self.res.append(path) #[:]
            return

        #key
        for i in range(1,4):
            if startindex+i>len(s):break
            #
            seg=s[startindex:startindex+i] #取不到startindex+i
            if not self.is_valid_seg(seg):continue
            suffix='' if seg_cnts==3 else '.' #seg_cnts+1=4
            self.dfs(s,startindex+i,path+seg+suffix,seg_cnts+1)

lc 22【剑指 085】【top100】:括号生成
https://leetcode.cn/problems/generate-parentheses/
提示:
1 <= n <= 8

在这里插入图片描述

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        self.res=[]
        self.dfs(n,'',0,0)
        return self.res

    def dfs(self,n,path,open,close):
        if open>n or close>open:return
        if len(path)==2*n:
            self.res.append(path)
            return
        #
        self.dfs(n,path+'(',open+1,close)
        self.dfs(n,path+')',open,close+1)

lc 51 :N 皇后
https://leetcode.cn/problems/n-queens/
提示:
1 <= n <= 9
在这里插入图片描述

class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        self.res=[]
        #
        self.rows=[0]*n #标-行攻位
        self.cols=[0]*n #列攻位
        self.mains=[0]*(2*n-1) #主对角
        self.secondary=[0]*(2*n-1) #副对角
        #
        self.dfs(0,n)
        return self.res
    
    def dfs(self,row,n):
        if row>=n:return
        #
        for col in range(n):
            if self.is_valid_pos(row,col,n):
                self.placeQ(row,col,n)
                if row==n-1:self.addsolution(n)
                #下一行放置
                self.dfs(row+1,n)
                self.removeQ(row,col,n)#撤销,回溯
    
    def is_valid_pos(self,row,col,n):
        #+self.rows[row],可省略,因为是一行一行放的,判断时候行中是肯定无的
        return self.cols[col]+self.mains[row-col+(n-1)]+self.secondary[row+col]==0 
        

    def placeQ(self,row,col,n):
        self.rows[row]=col
        self.cols[col]=1
        self.mains[row-col+(n-1)]=1
        self.secondary[row+col]=1
    
    def addsolution(self,n):
        sol=[]
        for i in range(n):
            #每一行结果
            col=self.rows[i]
            sb=''
            for j in range(col):sb+='.' 
            sb+='Q'
            for j in range((n-col)-1):sb+='.' #例如:col=1,(,Q,,)n=4
            #
            sol.append(sb)
        self.res.append(sol)

    
    def removeQ(self,row,col,n):
        self.rows[row]=0
        self.cols[col]=0
        self.mains[row-col+(n-1)]=0
        self.secondary[row+col]=

lc 37 :数独问题
https://leetcode.cn/problems/sudoku-solver/
提示:
board.length == 9
board[i].length == 9
board[i][j] 是一位数字或者 ‘.’
题目数据 保证 输入数独仅有一个解

在这里插入图片描述

class Solution:
    def solveSudoku(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        #初始化
        self.row_used=[[False]*10 for _ in range(9)] #[9][10]
        self.col_used=[[False]*10 for _ in range(9)] #[9][10]
        self.box_used=[[[False]*10 for _ in range(3)] for _ in range(3)] #[3][3][10]
        for i in range(len(board)):
            for j in range(len(board[0])):
                num=ord(board[i][j])-ord('0')
                if 1<=num<=9:
                    self.row_used[i][num]=self.col_used[j][num]=self.box_used[i//3][j//3][num]=True
        
        #
        self.dfs(board,0,0)
        
    
    def dfs(self,board,row,col):
        if col==len(board[0]):
            row+=1
            col=0
            if row==len(board):
                return True
        
        if board[row][col]=='.': #填充条件
            for num in range(1,10):
                can_place= self.row_used[row][num]==self.col_used[col][num]==self.box_used[row//3][col//3][num]==False #key
                if can_place:
                    self.row_used[row][num]=self.col_used[col][num]=self.box_used[row//3][col//3][num]=True
                    board[row][col]=str(num)
                    ##填充成功,返回true
                    if self.dfs(board,row,col+1):return True
                    ##填充失败,回溯,撤销
                    self.row_used[row][num]=self.col_used[col][num]=self.box_used[row//3][col//3][num]=False
                    board[row][col]='.'
        else: #跳格
            return self.dfs(board,row,col+1)
        
        return False

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

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

相关文章

一文分析Linux虚拟化KVM-Qemu(概念篇)

说明&#xff1a; KVM版本&#xff1a;5.9.1 QEMU版本&#xff1a;5.0.0 工具&#xff1a;Source Insight 3.5&#xff0c; Visio 1. 概述 从这篇文章开始&#xff0c;将开始虚拟化的系列研究了&#xff0c;大概会涉及到ARM64虚拟化支持、KVM、QEMU等分析&#xff1b; 虚拟…

小米裁员,我有话说

大家好&#xff0c;我是梦想家Alex 。好久没有为大家分享有关职场人生相关的文章了&#xff0c;最近阳康之后&#xff0c;灵感爆棚&#xff0c;想跟大家好好聊一聊。 如果你问我&#xff0c;近期互联网圈热度最高的事情&#xff0c;我想一定少不了小米和腾讯这两家科技巨头的身…

html实现ip输入框功能代码

伪代码&#xff1a; <style> .login-user {display: flex;color: #000;line-height: 30px; } .login-user input{height: 46px;border-radius: 4px;margin: 0px 4px; } </style><div class"layui-form-item login-user"><inp…

数据可视化②:bi解决方案之大学生就业分析

大学生就业是和我们息息相关的话题&#xff0c;每一位大学生都关注着&#xff0c;我们常常在网络上看到有关大学生就业的话题&#xff0c;比如毕业季的一些讨论。在大一的创新创业课中&#xff0c;我们也了解到自己所学的专业和以后如何就业&#xff0c;往哪方面就业。但我们了…

进程与线程的区别和联系是什么?

进程概念的引入 在多道程序的环境下&#xff0c;程序的并发执行代替了程序的顺序执行。它破坏了程序的封闭性和可再现性&#xff0c;使得程序和计算不再一一对应&#xff0c;而且由于资源共享和程序的并发执行导致在各个程序活动之间可能存在相互制约关系。总之&#xff0c;程…

MobTech秒验 I 寒冬加时,金融行业如何走出阴霾?

互联网流量红利将逝&#xff0c;企业运营重点已从“以产品为重心”转移至“以用户为导向”&#xff0c;而用户时间的碎片化及不聚焦&#xff0c;往往造成了线上运营推广投放后的石沉大海。 当下&#xff0c;迫切需要去做的是对存量数据的精细化管理&#xff0c;企业应打破数据…

Kafka的终极UI工具丨Offset Explorer功能简介

Offset Explorer&#xff08;以前称为Kafka Tool&#xff09;是一个用于管理和使Apache Kafka 集群的GUI应用程序。它提供了一个直观的UI&#xff0c;允许人们快速查看Kafka集群中的对象以及存储在集群主题中的消息。它包含面向开发人员和管理员的功能。 一些关键功能包括&…

Java 中的浅拷贝和深拷贝

开发过程中&#xff0c;有时会遇到把现有的一个对象的所有成员属性拷贝给另一个对象的需求。这个时候就会用到拷贝这个概念。把原对象定义成 A&#xff0c;拷贝后的对象定义成 B&#xff0c;如果只是单纯使用 clone 方法进行拷贝&#xff0c;你会发现&#xff1a; 对于八个基本…

基于unity物体定点移动与模拟刹车的细节 GIF 图文详解——线性差值函数以及平滑阻尼的运用和实践(Lerp AND SmoothDamp)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 收录于专栏 [unity常用API] ⭐相关文章&#xff1a;基础不牢&#xff0c;地动山摇系列 ------ 软硬通吃 unity常用API ⭐…

Arduino与Proteus仿真实例-TFT LCD绘制酷炫曲线图表

TFT LCD绘制酷炫曲线图表 本文将介绍如何在ILI9341 TFT LCD中绘制酷炫曲线图表仿真。 在前面的文章中,对ILI9341的驱动仿真作了详细的介绍,请参考: Arduino与Proteus仿真实例-TFT显示屏(ILI9341驱动器)SPI驱动仿真1、仿真电路原理图 2、仿真代码实现 本次实例使用到如下开…

23种设计模式(一)——单例模式【对象性能】

文章目录意图什么时候使用单例单例模式的实现1、有缺陷的懒汉式2、线程安全、内存安全的懒汉式单例 &#xff08;智能指针&#xff0c;锁&#xff09;3、最推荐的懒汉式单例([magic](https://so.csdn.net/so/search?qmagic&spm1001.2101.3001.7020) static )——局部静态变…

Wondershare 有哪些不错的办公软件呢

第一款 Wondershare UniConverter14 Wondershare UniConverter中文学习版(万兴优转)是一款国产全能视频格式转换软件.万兴格式转换器最新版具有音视频格式转换,合并视频,视频压缩,视频编辑,视频录制,视频下载,视频元数据修复,VR视频转换,字幕编辑器,GIF制作,DVD刻录等一站式视…

天线参数介绍

1.天线辐射元件种类图1-1 天线辐射元件种类如图1-1所示&#xff0c;天线辐射元件种类有&#xff1a;电镀偶极子、印刷电路偶极子、裂缝波导、凹口辐射器、矩形贴片辐射器、开口波导等。2、天线参数2.1 天线方向图天线方向图又叫辐射方向图&#xff08;radiation pattern&#x…

【MySQL基础教程】多表查询

前言 本文为 【MySQL基础教程】多表查询 相关知识&#xff0c;下边将对多表关系&#xff0c;多表查询概述&#xff0c;内连接&#xff0c;外连接&#xff0c;自连接&#xff0c;子查询&#xff0c;多表查询案例等进行详尽介绍~ &#x1f4cc;博主主页&#xff1a;小新要变强 的…

分布式理论协议与算法 第一弹 CAP理论

CAP 理论&#xff0c;也被称为 CAP 协议&#xff0c;指的是在一个分布式系统中&#xff0c;最多只能同时满足「一致性&#xff08;Consistency&#xff09;」、「可用性&#xff08;Availability&#xff09;」和「分区容错性&#xff08;Partition tolerance&#xff09;」这三…

Vue3 中组合式下的侦听器

目录前言&#xff1a;前置代码&#xff1a;创建侦听器停止侦听器watch侦听&#xff1a;对象中的某一个属性变化(需要提供getter函数才行)watch侦听&#xff1a;整个对象watch侦听&#xff1a;如果嵌套属性发生改变&#xff0c;默认是无法执行回调函数的?watch侦听&#xff1a;…

【实战与杂谈】如何复活一个开源网站-游戏王卡片生成器

1. 杂谈 作为一名十多年游戏王玩家&#xff0c;学生时代玩的是PSP和PS2上的游戏&#xff0c;到毕业后使用YGOPRO同步新卡片进行联网对战&#xff0c;再到现在约到线下进行实体卡片游戏。有些卡片价格太贵&#xff0c;因此我们对于这些卡在未购买之前都会自己打印出来暂时游玩…

sec5-属性

1 属性 GObject系统提供属性。属性是由实例保存的值&#xff0c;实例是GObject的后代&#xff0c;它们对其他实例开放。可以通过他们的名字访问他们。 例如&#xff0c;GtkWindow具有"title"、“default-width”、"default-height"等属性。字符串"t…

正经科普:DDos高防ip详解

白衬衫容易发黄&#xff0c; 一般洗衣液很难洗掉&#xff0c; 不少人为此感到头疼&#xff0c; 不妨在洗的时候吃点头痛药。 这边我也不多废话,大家直接看图,高防ip原理如下清洗能力 DDoS高防IP采用BGP链路对接全国各地30家运营商&#xff0c;总防御能力超4T。采用电信云堤近源…

智能优化算法:人工兔优化算法-附代码

智能优化算法&#xff1a;人工兔优化算法 摘要&#xff1a;人工兔优化算法( [Artificial rabbits optimization&#xff0c;RSO)是 Liying Wang等 于 2022 年提出的一种新型元启发式优化算法 。 该算法受来源于自然界中兔子的生存策略的启发&#xff0c;具有寻优能力强&#x…