组合问题
题目
- 描述
有 1 元,2 元,5 元,10 元纸币,输入一个数据 n,求这些纸币加起来等于 N 的组合数。
题目记不太清了,大概是这个意思:
w + 2x + 5y + 10z = n
求组合数
- 输入与输出
输入 37
输出 160
思路
- 暴力(当时就这么写的)
- 四个 for 循环
- 广度优先搜索 + 回溯
- 将 1,2,5,10 变为数组,方便后面取用
- 利用 bfs 进行搜索
- 剪枝
代码
暴力
public int method(int n) {
int res = 0;
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= n/2; j++) {
for (int k = 0; k <= n/5; k++) {
for (int l = 0; l <= n/10; l++) {
if ((i + 2*j + 5*k + 10*l) == n) {
res++;
}
}
}
}
}
return res;
}
bfs
public int method(int[] money, int n) {
if (money == null || money.length == 0) return res;
helper(money,n,0,0);
return res;
}
public void helper(int[] money,int n,int index,int sum) {
// 如果满足, 返回
if (sum == n) {
res++;
return;
}
for (int i = index; i < money.length; i++) {
// 如果已经大于 n, 那么后面的也不用取了
if (sum + money[i] > n) break;
// 因为园子可以取很多次, 所以 index == i
helper(money,n,i,sum+money[i]);
}
}
递增子序列
- 描述
一群人已经排成一排了,但是身高无序,例如
[178,180,171,162,190]
,其最长递增子序列为[178,180,190]
,长度为 3,返回递增子序列的最大长度。
- 输入
输入
[178,180,171,162,190]
输出 3
思路
- 暴力
- 定义 max 作为结果
- 双循环遍历数组,记录该次 i 循环的最大值 tmpMax
- 每次 i 循环结束与 max 比较
- max = Math.max(max,tmpMax)
这是我自己的思路,但是只 ac 了 30%
- dp 动态规划
代码
dp
public int lengthOfLIS(int[] nums) {
if (0 == nums.length) {
return 0;
}
if (1 == nums.length) {
return 1;
}
int[] dp = new int[nums.length];
// 记录最大值
int res = 0;
Arrays.fill(dp, 1);
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
res = Math.max(dp[i], res);
}
}
return res;
}