代码随想录算法训练营第37天|LeetCode 518. 零钱兑换 II、377. 组合总和 Ⅳ、70. 爬楼梯 (进阶)

1. LeetCode 518. 零钱兑换 II

题目链接:https://leetcode.cn/problems/coin-change-ii/description/
文章链接:https://programmercarl.com/0518.零钱兑换II.html
视频链接:https://www.bilibili.com/video/BV1KM411k75j/

在这里插入图片描述

思路:
硬币无限,即,完全背包
物品:coins
背包:总金额amount
重量:硬币金额
价值:组合数量

本题关键:求方案个数,则递推公式如下:
dp[j] += dp[j - coins[i]];
求组合,遍历顺序是先物品再背包;
求排列,遍历顺序是先背包再物品。

解法:
class Solution {
    public int change(int amount, int[] coins) {
        //硬币无限。即完全背包
        //物品:coins
        //背包:总金额amount
        //重量:硬币金额
        //价值:组合数量
        // 1. 定义dp数组
        // dp[i]表示总金额是i的组合数量
        int[] dp = new int[amount+1];
        // 2. 递推公式
        // dp[j] += dp[j-coins[i]];
        // 3. 初始化
        dp[0]=1;
        // 4. 遍历顺序 先物品再背包
        for (int i=0;i<coins.length;i++) {
            for (int j=coins[i];j<=amount;j++) {
                dp[j] += dp[j-coins[i]];
            }
        }

        return dp[amount];

    }
}

2. LeetCode 377. 组合总和 Ⅳ

题目链接:https://leetcode.cn/problems/combination-sum-iv/description/
文章链接:https://programmercarl.com/0377.组合总和Ⅳ.html
视频链接:https://www.bilibili.com/video/BV1V14y1n7B6/

在这里插入图片描述

思路:
元素可以重复取 完全背包。又知,顺序不同的序列被视作不同的组合,即排列
物品:nums
背包:总和为target的背包
重量:物品的值
价值:组合个数
本题关键:是排列,而不是组合。

解法:
class Solution {
    public int combinationSum4(int[] nums, int target) {
        //元素可以重复取  完全背包
        //顺序不同的序列被视作不同的组合,即排列
        //物品:nums
        //背包:总和为target的背包
        //重量:物品的值
        //价值:排列个数
        //1. 定义dp数组 
        //dp[j] 总和是j的排列数
        int[] dp = new int[target+1];
        //2. 递推公式
        //dp[j] += dp[j-nums[i]];
        //3. 初始化
        dp[0]=1;
        //4. 遍历顺序 先背包再物品
        for (int j=0;j<=target;j++) {
            for (int i=0;i<nums.length;i++) {
                if (j>=nums[i]) {
                    dp[j]+=dp[j-nums[i]];
                }
            }
        }

        return dp[target];
    }
}

3. LeetCode 70. 爬楼梯 (进阶)

题目链接:https://kamacoder.com/problempage.php?pid=1067
文章链接:https://programmercarl.com/0070.爬楼梯完全背包版本.html

在这里插入图片描述

思路:
每次走多台阶数可以重复 即,完全背包
不同台阶的顺序不同,组合不同,即排列
物品:nums,每个物品的值为台阶数
背包:总台阶数是n的背包
重量:台阶数
价值:方法个数

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner src = new Scanner(System.in);
        String[] line = src.nextLine().split(" ");
        int n = Integer.parseInt(line[0]);// 总共台阶数
        int m = Integer.parseInt(line[1]);// 每次至多m个台阶
        int[] nums = new int[m];
        
        // 物品
        for (int i=0;i<m;i++) {
            nums[i] = i+1;
        }
        
        // 每次走多台阶数可以重复 即,完全背包
        // 不同多组合台阶是不同的,即排列
        // 物品:nums
        // 背包:总台阶数是n的背包
        // 重量:台阶数,每个物品的值为台阶数
        // 价值:方法个数
        // 1.定义dp数组 
        // dp[j] 表示总台阶数是j含有的所有方法个数
        int[] dp = new int[n+1];
        // 2.递推公式
        // dp[j] += dp[j-nums[i]]
        // 3.初始化
        dp[0] = 1;
        // 4.遍历顺序 先背包再物品
        for (int j=0;j<=n;j++) {
            for (int i=0;i<nums.length;i++) {
                if (j >= nums[i]) {
                    dp[j] += dp[j-nums[i]];
                }
            }
        }
        
        System.out.println(dp[n]);
    }
}
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第二十二算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,使得子数组的和大于等于给定的目标值。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口中的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二算法训练营的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值