背包问题解题思路
背包问题的特征就是给定一个数组nums和一个target,数组元素可以是数字也可以是字符串,然后通过对数组元素的排列组合得到target。
LeetCode上这类题目有:
139. 单词拆分
377. 组合总和 Ⅳ
416. 分割等和子集
494. 目标和
518. 零钱兑换 II
一、背包问题的三种类型
1、0-1背包,数组中元素不可重复使用,解题关键为:nums放外循环,target放内循环,且内循环倒序。
2、完全背包,数组中元素可以重复使用,解题关键为:nums放外循环,target放内循环,且内循环正序。
3、需要考虑元素的顺序,如[1、2]和[2、1]算两个答案而不是一个时,解题关键为:target放放外循环,nums放内循环。
二、解题思路
基本思路是使用动态规划的方法完成解题。下面通过具体例题来详解:
1、组合总和问题
class Solution {
//题目描述
//给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。
//请你从 nums 中找出并返回总和为 target 的元素组合的个数。
//题目数据保证答案符合 32 位整数范围。
//示例 1:
//输入:nums = [1,2,3], target = 4
//输出:7
//解释:
//所有可能的组合为:
//(1, 1, 1, 1)
//(1, 1, 2)
//(1, 2, 1)
//(1, 3)
//(2, 1, 1)
//(2, 2)
//(3, 1)
//请注意,顺序不同的序列被视作不同的组合。
public int combinationSum4(int[] nums, int target) {
//典型的背包问题,题目描述说需要考虑顺序,并且元素可以复用
//套用第三种类型的思路
int[] dp = new int[target + 1];
//dp[i]记录的是组成和为i的组合的数量
//动态规划的边界条件确定:
//组成和为0的数,只要不选nums里的任何数,就可以组成和为0的数,因此有一种
dp[0] = 1;
//外层循环放target
for (int i = 1; i <= target; i++) {
//内层循环放nums
for