经典算法-动态规划
参考:
Leetcode(5)-最长回文子串(包含动态规划以及Manacher算法)
题目:word break
题目描述
给定一个字符串s和一组单词dict,判断s是否可以用空格分割成一个单词序列,使得单词序列中所有的单词都是dict中的单词(序列可以包含一个或多个单词)。
例如:
给定s=“leetcode”;
dict=["leet", "code"].
返回true,因为"leetcode"可以被分割成"leet code".
import java.util.Set;
public class Solution {
public boolean wordBreak(String s, Set<String> dict) {
boolean[] flags=new boolean[s.length()+1];
flags[0]=true;
for(int i=1;i<=s.length();i++){
for(int j=0;j<i;j++){
if(flags[j]&&dict.contains(s.substring(j,i))){
flags[i]=true;
break;
}
}
}
return flags[s.length()];
}
}
题解:flags[i]为true即表示字符串的0到i可以包含在字典中。状态转移方程为,0到j是否可以拆分为包含在字典中取决于,j前面的某个i为true并且i+1到j的字符在字典中包含。
题目:Candy
N个孩子站成一排,给每个人设定一个权重(已知)。按照如下的规则分配糖果: (1)每个孩子至少分得一颗糖果 (2)权重较高的孩子,会比他的邻居获得更多的糖果。
问:总共最少需要多少颗糖果?请分析算法思路,以及算法的时间,空间复杂度是多少。
public class Solution {
public int candy(int[] ratings) {
if(ratings==null||ratings.length==0){
return 0;
}
if(ratings.length==1){
return 1;
}
int[] tang=new int[ratings.length];
for(int i=0;i<tang.length;i++){
tang[i]=1;
}
for(int j=1;j<ratings.length;j++){
if(ratings[j]>ratings[j-1]){
tang[j]=tang[j-1]+1;
}
}
for(int k=ratings.length-2;k>=0;k--){
if(ratings[k]>ratings[k+1]&&tang[k]<=tang[k+1]){
tang[k]=tang[k+1]+1;
}
}
int sum=0;
for(int n=0;n<tang.length;n++){
sum=sum+tang[n];
}
return sum;
}
}
思路:
假设每个孩子分到的糖果数组为A[N],初始化为{1},因为每个人至少分到一颗糖。
方法一:
1、与前面的邻居比较,前向遍历权重数组ratings,如果ratings[i]>ratings[i-1],则A[i]=A[i-1]+1;
2、与后面的邻居比较,后向遍历权重数组ratings,如果ratings[i]>ratings[i+1]且A[i] <=A[i+1]+1,则更新A,A[i]=A[i+1]+1;
3、对A求和即为最少需要的糖果。
时间复杂度:O(n)
空间复杂度:O(n)


浙公网安备 33010602011771号