代码随想录训练营day25 回溯

文章讲述了如何使用深度优先搜索(DFS)算法解决两个问题:组合总和III找出k个数之和等于n且每个数字最多使用一次的组合,以及电话号码的字母组合,将给定数字字符串转换为字母组合。通过递归实现的dfs函数展示了在这些场景下的解决方案。

 突然感觉把回溯当成是地下城迷宫的问题就一下子来感觉了,今天稍微能明白点道理了。哈哈哈。

第二题好绕。

216. 组合总和 III

找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:

  • 只使用数字1到9
  • 每个数字 最多使用一次 

返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

var (
    res[][]int
    path []int
)

func combinationSum3(k int,n int)[][]int{
    res,path = make([][]int,0),make([]int,0)

    dfs(k,n,1,0)
    return res
}


func dfs(k,n,start int,sum int){
    if len(path)==k{// 回溯一条边的停止条件,k个元素
        if sum ==n{//纳入结果的过滤条件 == n
            tmp :=make([]int,k)
            copy(tmp,path)
            res = append(res,tmp)
        }
        return 
    }

    for i:= start; i <= 9; i++{ 
        if sum + i > n || 9-i +1 < k-len(path){ break}
        path = append(path ,i)//记录本层地下城迷宫的内容路径
        dfs(k,n,i+1,sum+i)//从本层下潜到下一层地下城的通关密钥 i+1
        path = path[:len(path)-1]//path 作为全局变量,不保存本层的密钥,用于同层其他迷宫的路径保存
    }
}

17. 电话号码的字母组合

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

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

var(
    m []string
    path []byte
    res []string
)

func letterCombinations(digits string) []string {
    m = []string{"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"}
    path,res = make([]byte,0),make([]string,0)
    if digits == ""{ return res}
    dfs(digits,0)
    return res
}
func dfs(digits string,start int){
    if len(path)==len(digits){
        tmp:=string(path)
        res= append(res,tmp)
        return 
    }

    digit :=int(digits[start]-'0')
    str:=m[digit-2]//因为1是拨号键!!! 所以要去除0,1 ,-2

    for j:=0;j<len(str);j++{
        path = append(path,str[j])
        dfs(digits,start+1)
        path = path[:len(path)-1]
    }
}

### 代码随想录算法训练营 Day20 学习内容与作业 #### 动态规划专题深入探讨 动态规划是一种通过把原问题分解为相对简单的子问题的方式来求解复杂问题的方法[^1]。 #### 主要学习内容 - **背包问题系列** - 背包问题是典型的动态规划应用场景之一。这类题目通常涉及给定容量的背包以及一系列具有不同价值和重量的物品,目标是在不超过总容量的情况下最大化所选物品的价值。 - **状态转移方程构建技巧** - 构建合适的状态转移方程对于解决动态规划问题是至关重要的。这涉及到定义好dp数组(或表格),并找到从前一个状态到下一个状态之间的关系表达式[^2]。 - **优化空间复杂度方法** - 对于某些特定类型的DP问题,可以采用滚动数组等方式来减少所需的空间开销,从而提高程序效率[^3]。 #### 实战练习题解析 ##### 题目:零钱兑换 (Coin Change) 描述:给定不同面额的硬币 coins 和一个总金额 amount。编写函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 `-1`。 解决方案: ```python def coinChange(coins, amount): dp = [float('inf')] * (amount + 1) dp[0] = 0 for i in range(1, amount + 1): for coin in coins: if i >= coin and dp[i - coin] != float('inf'): dp[i] = min(dp[i], dp[i - coin] + 1) return dp[-1] if dp[-1] != float('inf') else -1 ``` 此段代码实现了基于自底向上的迭代方式解决问题,其中 `dp[i]` 表示达到金额 `i` 所需最小数量的硬币数目[^4]。 ##### 题目:完全平方数 (Perfect Squares) 描述:给出正整数 n ,找出若干个不同的 完全平方数 (比如 1, 4, 9 ...)使得它们的和等于n 。问至少需要几个这样的完全平方数? 解答思路同上一题类似,只是这里的“硬币”变成了各个可能的完全平方数值。 ```python import math def numSquares(n): square_nums = set([i*i for i in range(int(math.sqrt(n))+1)]) dp = [float('inf')] *(n+1) dp[0] = 0 for i in range(1,n+1): for sq in square_nums: if i>=sq: dp[i]=min(dp[i],dp[i-sq]+1); return dp[n]; ``` 这段代码同样运用了动态规划的思想去寻找最优解路径,并利用集合存储所有小于等于输入值的最大平方根内的平方数作为候选集[^5]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七咔七咔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值