最小调整代价
描述
给一个整数数组,调整每个数的大小,使得相邻的两个数的差不大于一个给定的整数target,调整每个数的代价为调整前后的差的绝对值,求调整代价之和最小是多少。
样例
样例 1:
输入: [1,4,2,3], target=1
输出: 2
样例 2:
输入: [3,5,4,7], target=2
输出: 1
代码
public class Solution {
/*
* @param A: An integer array
* @param target: An integer
* @return: An integer
*/
public int MinAdjustmentCost(List<Integer> A, int target) {
if(A == null || A.size() == 0) return 0;
int n = A.size();
int[][] dp = new int[n + 1][101];
for(int i = 0; i <= n; i++){
for(int j = 0; j <= 100; j++){
dp[i][j] = Integer.MAX_VALUE;
}
}
for(int i = 0; i <= 100; i++){
dp[0][i] = 0;
}
for(int i = 1; i <= n; i++){
for(int j = 0; j <= 100; j++){
if(dp[i - 1][j] != Integer.MAX_VALUE){
for(int k = 0; k <= 100; k++){
if(Math.abs(j - k) <= target){
if(dp[i][k] > dp[i - 1][j] + Math.abs(A.get(i - 1) - k)){
dp[i][k] = dp[i - 1][j] + Math.abs(A.get(i - 1) - k);
}
}
}
}
}
}
int ans = Integer.MAX_VALUE;
for(int i = 0; i <= 100; i++){
if(ans > dp[n][i]){
ans = dp[n][i];
}
}
return ans;
}
}
背包问题
描述
在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i]
样例
Example 1:
Input: [3,4,8,5], backpack size=10
Output: 9
Example 2:
Input: [2,3,5,7], backpack size=12
Output: 12
代码
public class Solution {
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
public int backPack(int m, int[] A) {
int n = A.length;
boolean[][] dp = new boolean[n + 1][m + 1];
for(int i = 0; i <= n; i++){
for(int j = 0; j <= m; j++){
dp[i][j] = false;
}
}
dp[0][0] = true;
for(int i = 1; i <= n; i++){
for(int j = 0; j <= m; j++){
dp[i][j] = dp[i - 1][j];
if(j >= A[i - 1] && dp[i - 1][j - A[i - 1]]){
dp[i][j] = true;
}
}
}
for(int i = m; i >= 0; i--){
if(dp[n][i]){
return i;
}
}
return 0;
}
}
约翰的后花园
描述
约翰想在他家后面的空地上建一个后花园,现在有两种砖,一种3
dm的高度,7
dm的高度。约翰想围成x
dm的墙。如果约翰能做到,输出YES,否则输出NO。
样例
Example 1:
Input : x = 10
Output : "YES"
Explanation :
x = 3 + 7:That is, you need one batch of 3 dm height bricks and one batch of 7 dm height bricks.
Example 2:
Input : x = 5
Output : "NO"
Explanation:
John can not enclose a high 5 dm wall with 3 dm height bricks and 7 dm height bricks.
Example 3:
Input : x = 13
Output : "YES"
Explanation :
x = 2 * 3 + 7:That is, you need two batch of 3 dm height bricks and one batch of 7 dm height bricks.
代码
public class Solution {
/**
* @param x: the wall's height
* @return: YES or NO
*/
public String isBuild(int x) {
boolean[] dp = new boolean[x + 1];
for(int i = 3; i <= x; i++){
if(i == 3 || i == 7){
dp[i] = true;
continue;
}
if(i < 7){
dp[i] = dp[i - 3];
}
else{
dp[i] = dp[i - 3] || dp[i - 7];
}
}
if(dp[x]) return "YES";
else return "NO";
}
}
背包问题II
描述
有 n
个物品和一个大小为 m
的背包. 给定数组 A
表示每个物品的大小和数组 V
表示每个物品的价值.
问最多能装入背包的总价值是多大?
A[i], V[i], n, m
均为整数- 你不能将物品进行切分
- 你所挑选的要装入背包的物品的总大小不能超过
m
样例 1:
输入: m = 10, A = [2, 3, 5, 7], V = [1, 5, 2, 4]
输出: 9
解释: 装入 A[1] 和 A[3] 可以得到最大价值, V[1] + V[3] = 9
样例 2:
输入: m = 10, A = [2, 3, 8], V = [2, 5, 8]
输出: 10
解释: 装入 A[0] 和 A[2] 可以得到最大价值, V[0] + V[2] = 10
代码
public class Solution {
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @param V: Given n items with value V[i]
* @return: The maximum value
*/
public int backPackII(int m, int[] A, int[] V) {
int n = A.length;
int[][] dp = new int[n + 1][m + 1];
for(int i = 0; i <= n; i++){
for(int j = 0; j <= m; j++){
if(i == 0 || j == 0){
dp[i][j] = 0;
}
else if(A[i - 1] > j){
dp[i][j] = dp[i - 1][j];
}
else if(j >= A[i - 1]){
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - A[i - 1]] + V[i - 1]);
}
}
}
return dp[n][m];
}
}
换硬币
描述
给出不同面额的硬币以及一个总金额. 写一个方法来计算给出的总金额可以换取的最少的硬币数量. 如果已有硬币的任意组合均无法与总金额面额相等, 那么返回 -1
.
你可以假设每种硬币均有无数个
样例1
输入:
[1, 2, 5]
11
输出: 3
解释: 11 = 5 + 5 + 1
样例2
输入:
[2]
3
输出: -1
代码
这是一个典型的完全背包问题。
设dp[i][j]表示使用前i个硬币,总金额为j时需要的最少硬币数量。
dp[i][j]=max(dp[i-1][j],dp[i-1][j-k*coin[i]]+k) \quad (0\leq k*coin[i] \leq j)dp[i][j]=max(dp[i−1][j],dp[i−1][j−k∗coin[i]]+k)(0≤k∗coin[i]≤j)
public class Solution {
/**
* @param coins: a list of integer
* @param amount: a total amount of money amount
* @return: the fewest number of coins that you need to make up
*/
public int coinChange(int[] coins, int amount) {
int[] dp = new int[amount + 1];
dp[0] = 0;
for(int i = 1; i <= amount; i++){
dp[i] = -1;
for(int j = 0; j < coins.length; j++){
if(i >= coins[j] && dp[i - coins[j]] != -1){
if(dp[i] == -1 || dp[i] > dp[i - coins[j]] + 1){
dp[i] = dp[i - coins[j]] + 1;
}
}
}
}
return dp[amount];
}
}
背包问题III
描述
给定 n
种物品, 每种物品都有无限个. 第 i
个物品的体积为 A[i]
, 价值为 V[i]
.
再给定一个容量为 m
的背包. 问可以装入背包的最大价值是多少?
- 不能将一个物品分成小块.
- 放入背包的物品的总大小不能超过
m
.
样例
样例 1:
输入: A = [2, 3, 5, 7], V = [1, 5, 2, 4], m = 10
输出: 15
解释: 装入三个物品 1 (A[1] = 3, V[1] = 5), 总价值 15.
样例 2:
输入: A = [1, 2, 3], V = [1, 2, 3], m = 5
输出: 5
解释: 策略不唯一. 比如, 装入五个物品 0 (A[0] = 1, V[0] = 1).
代码
public class Solution {
/**
* @param A: an integer array
* @param V: an integer array
* @param m: An integer
* @return: an array
*/
public int backPackIII(int[] A, int[] V, int m) {
int n = A.length;
int[][] dp = new int[n + 1][m + 1];
for(int i = 1; i <= n; i++){
for(int j = 0; j <= m; j++){
dp[i][j] = dp[i - 1][j];
if(j >= A[i - 1]){
dp[i][j] = Math.max(dp[i][j - A[i - 1]] + V[i - 1], dp[i][j]);
}
}
}
return dp[n][m];
}
}
背包问题IV
描述
给出 n 个物品, 以及一个数组, nums[i]
代表第i个物品的大小, 保证大小均为正数并且没有重复, 正整数 target
表示背包的大小, 找到能填满背包的方案数。每一个物品可以使用无数次
您在真实的面试中是否遇到过这个题? 是
题目纠错
样例
样例1
输入: nums = [2,3,6,7] 和 target = 7
输出: 2
解释:
方案有:
[7]
[2, 2, 3]
样例2
输入: nums = [2,3,4,5] 和 target = 7
输出: 3
解释:
方案有:
[2, 5]
[3, 4]
[2, 2, 3]
代码
public class Solution {
/**
* @param nums: an integer array and all positive numbers, no duplicates
* @param target: An integer
* @return: An integer
*/
public int backPackIV(int[] nums, int target) {
int n = nums.length;
int[][] dp = new int[n + 1][target + 1];
dp[0][0] = 1;
for(int i = 1; i <= n; i++){
for(int j = 0; j <= target; j++){
int k = 0;
while(j >= k * nums[i - 1]){
dp[i][j] += dp[i - 1][j - k * nums[i - 1]];
k++;
}
}
}
return dp[n][target];
}
}
背包问题V
描述
给出 n 个物品, 以及一个数组, nums[i]
代表第i个物品的大小, 保证大小均为正数, 正整数 target
表示背包的大小, 找到能填满背包的方案数。每一个物品只能使用一次
样例
给出候选物品集合 [1,2,3,3,7]
以及 target 7
结果的集合为:
[7]
[1,3,3]
public class Solution {
/**
* @param nums: an integer array and all positive numbers
* @param target: An integer
* @return: An integer
*/
// dp[n][w] = dp[i - 1][w] + dp[i - 1][w - nums[i - 1]];
public int backPackV(int[] nums, int target) {
int n = nums.length;
int[][] dp = new int[n + 1][target + 1];
dp[0][0] = 1;
for(int i = 1; i <= target; i++){
dp[0][i] = 0;
}
for(int i = 1; i <= n; i++){
for(int j = 0; j <= target; j++){
dp[i][j] = dp[i - 1][j];
if(j >= nums[i - 1]){
dp[i][j] += dp[i - 1][j - nums[i - 1]];
}
}
}
return dp[n][target];
}
}