最少硬币数问题
问题描述
给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。你可以认为每种硬币的数量是无限的。详见leetcode322
问题分析
设f(n)为amount=n时使用的最少金币数。遍历coins数组,选择f(n-coins[i])(i=0,1,coins.length-1)的最小值,即为需要的最少硬币数,递归继续寻找f(n-coins[i])的最小值,初始时f(0)=0,如果一些总金额无法凑成时,可以使用amount+1填充数组。
代码实现
java
public int coinChange(int[] coins, int amount) {
int[] res = new int[amount+1];
int max = amount+1;
Arrays.fill(res,max);
res[0] = 0;
int[] temp = new int[coins.length];
for(int i=1;i<amount+1;i++){
for(int j=0;j<coins.length;j++){
int leftAmount = i - coins[j];
temp[j] = leftAmount>=0?res[leftAmount]+1:max;
}
int min = max;
for(int j=0;j<coins.length;j++){
min = Math.min(temp[j],min);
}
res[i]= min;
}
if(res[amount]==max){
return -1;
}
return res[amount];
}
最长连续递增子序列
问题描述
给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。连续递增的子序列 可以由两个下标 l 和 r(l < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列。详见leetcode674
问题分析
这道题,我们之前使用滑动窗口的方式也可以解决,使用动态规划解题时,对于连续递增子序列的最后一个元素nums[k],存在两种情况,第一种是最长连续递增子序列长度为1,连续递增子序列只包含一个元素nums[k],第二种是存在k-1,使得nums[k-1]<num[k],设f[k]为到下标k处的连续递增子序列长度,则,如果nums[k-1]>=nums[k],f[k]=1,否则f[k]=f[k-1]+1,初始值f[0]=1,
代码实现
滑动窗口实现
java
public int findLengthOfLCIS(int[] nums) {
if(nums.length==0||nums.length==1){
return nums.length;
}
int res = 1;
int count =1;
for(int i=1;i<nums.length;i++){
if(nums[i-1]>=nums[i]){
count =1;
}else{
count++;
}
if(count>res){
res = count;
}
}
return res;
}
动态规划实现
java
public int findLengthOfLCIS(int[] nums) {
int[] dp = new int[nums.length];
Arrays.fill(dp,1);
int max = 1;
for(int i=1;i<nums.length;i++){
if(nums[i]>nums[i-1]){
dp[i] = dp[i-1]+1;
max = Math.max(dp[i],max);
}
}
return max;
}
最长递增子序列
问题描述
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。详见leetcode300
问题分析
这道题与上一题相似,只是不需要连续递增。对于最长递增子序列的最后一个元素nums[k],存在两种情况,第一种是最长连续递增子序列长度为1,连续递增子序列只包含一个元素nums[k],第二种是存在i,使得i<k,nums[i]<num[k],设f[k]为到下标k处的连续递增子序列长度,则f[k] = max{f[i]+1}(i是所有nums[i]<nums[k]的集合)
代码实现
java
public int lengthOfLIS(int[] nums) {
int[] dp = new int[nums.length];
Arrays.fill(dp,1);
for(int i=1;i<nums.length;i++){
for(int j=i-1;j>=0;j--){
if(nums[j]<nums[i]&&dp[j]+1>dp[i]){
dp[i] = dp[j]+1;
}
}
}
int max = 1;
for(int i=0;i<nums.length;i++){
max = Math.max(max,dp[i]);
}
return max;
}
最少完全平方数
问题描述
给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。详见leetcode279
问题分析
设f(n)表示和为 n 的完全平方数的最少数量 。则f(n)=min{f(n-jj)+1}(j是满足所有jj<=n的j的集合).初始时f(0) = 0.
代码实现
java
public int numSquares(int n) {
int[] f = new int[n+1];
Arrays.fill(f,Integer.MAX_VALUE);
f[0] = 0;
for(int i=1;i<n+1;i++){
for(int j=1;j*j<=i;j++){
if(f[i-j*j]+1<f[i]){
f[i] = f[i-j*j]+1;
}
}
}
return f[n];
}
跳跃游戏
问题描述
给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。详见leetcode55
问题分析
设f(n)是一个boolean数组,为true表示可以跳到数组下标n处,为false表示无法跳到数组下标n处。f(n)为true的条件是f(i)为true,n-1-i<nums[i],初始时f(0)=true
java
public boolean canJump(int[] nums) {
boolean[] f = new boolean[nums.length];
Arrays.fill(f,false);
f[0] = true;
for(int i=1;i<nums.length;i++){
for(int j=0;j<i;j++){
if(f[j]&&j+nums[j]>=i){
f[i] = true;
break;
}
}
}
return f[nums.length-1];
}