单词拆分
原理思想:完全背包
1.确定dp数组以及下标的含义
**dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词**。
2. 确定递推公式
如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。
所以递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。
3.dp数组如何初始化
从递归公式中可以看出,dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]就是递归的根基,dp[0]一定要为true,否则递归下去后面都都是false了
public boolean wordBreak(String s, List<String> wordDict) {
boolean[] dp=new boolean[s.length()+1];
dp[0]=true;
for(int i=1; i<s.length()+1; i++)
for(int j=0; j<i; j++) {
if(dp[j]==true && wordDict.contains(s.substring(j, i))) {
dp[i]=true;
}
}
return dp[s.length()];
}
乘积最大
原理思想:
public int maxProduct(int[] nums) {
int[] dpMax=new int[nums.length]; //存储前i个数乘积的最大值
int[] dpMin=new int[nums.length]; //存储前i个数乘积的最小值
dpMax[0]=dpMin[0]=nums[0];
int max=nums[0]; //最终的最大值
for(int i=1; i<nums.length; i++) {
//更新最大和最小乘积值
dpMax[i]=Math.max(dpMin[i-1]*nums[i], Math.max(dpMax[i-1]*nums[i], nums[i]));
dpMin[i]=Math.min(dpMin[i-1]*nums[i], Math.min(dpMax[i-1]*nums[i], nums[i]));
//更新当前对大的连续子乘积
max=Math.max(dpMax[i], max);
}
return max;
}
其实可以不需要这个dp数组,只需要额外变量存储即可,因为更新 dp[i]
的时候,我们只用到 dp[i-1]
的信息,再之前的信息就用不到了。所以我们完全不需要一个数组,只需要一个变量去重复覆盖更新即可
public int maxProduct(int[] nums) {
int n = nums.length;
if (n == 0) {
return 0;
}
int dpMax = nums[0];
int dpMin = nums[0];
int max = nums[0];
for (int i = 1; i < n; i++) {
//更新 dpMin 的时候需要 dpMax 之前的信息,所以先保存起来
int preMax = dpMax;
dpMax = Math.max(dpMin * nums[i], Math.max(dpMax * nums[i], nums[i]));
dpMin = Math.min(dpMin * nums[i], Math.min(preMax * nums[i], nums[i]));
max = Math.max(max, dpMax);
}
return max;
作者:windliang
链接:https://leetcode.cn/problems/maximum-product-subarray/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by--36/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。