一.单词拆分
问题概述:
给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true。


思路:
一个字符串可不可以拼接,可以将其拆分成两部分看,如果前部分是可以拆分的并且剩下一部分刚好在wordDict当中,那这个字符串就是可以拼接的。
代码:
javascript
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
Set<String> worldSet=new HashSet<>(wordDict);
int n=s.length()+1;
boolean[] dp=new boolean[n];
dp[0]=true;
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
if(dp[j]&&worldSet.contains(s.substring(j,i))){
dp[i]=true;
break;
}
}
}
return dp[n-1];
}
}
二.最长递增子序列
问题概述:


思路:
每个元素本身可以构成1个子序列,那dp[]初值都设为1。
那后面新加的nums[i]比前面nums[j]大就选nums[i]和nums[j]+1大的那个,
例如:nums=[10,1,2,5]
10 dp[0]=1
新加1 1<10 dp[1]=1
新加2 2<10 2>1 dp[2]=max(dp[1]+1,dp[2])
新加5 5<10 5>1 dp[3]=max(dp[1]+1,dp[3]) 5>2 dp[3]=max(dp[2]+1,dp[3])
代码:
java
class Solution {
public int lengthOfLIS(int[] nums) {
int n=nums.length;
int[] dp=new int[n];
int maxn=1;
for(int i=0;i<n;i++){
dp[i]=1;
}
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
if(nums[i]>nums[j]){
dp[i]=Math.max(dp[j]+1,dp[i]);
}
}
maxn=Math.max(maxn,dp[i]);
}
return maxn;
}
}
三.乘积最大子数组
问题概述:

思路:
新加一个nums[i],那此刻包含这个数的最大数要么就是正正 负负 本身得到的
代码:
java
class Solution {
public int maxProduct(int[] nums) {
int max=nums[0];
int min=nums[0];
int res=nums[0];
int n=nums.length;
for(int i=1;i<n;i++){
int tempmax=max;
int tempmin=min;
max=Math.max(nums[i],Math.max(tempmax*nums[i],tempmin*nums[i]));
min=Math.min(nums[i],Math.min(tempmax*nums[i],tempmin*nums[i]));
res=Math.max(res,max);
}
return res;
}
}
四.分割等和子集
问题概述:
给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

思路:
就是看能不能凑成总数的一半,如果总数和为奇数则可以直接返回false了,如果为偶数进一步判断,dp[11]是否为true,因为所给的nums本身不是有序的,所以需要每个遍历,
num=1
dp[11]=dp[11]||dp[11-1]
dp[10]=dp[10]||dp[10-1]
...
dp[1]=dp[1]||dp[1-1]=true
此时只有dp[0]、dp[1]为true
num=5
dp[11]=dp[11]||dp[11-5]
dp[10]=dp[10]||dp[10-5]
...
dp[5]=dp[5]||dp[0]
此时dp[0]、dp[1]、dp[5]为true
num=11
dp[11]=dp[11]||dp[11-11] 为true 现在已结束,dp[0]、dp[1]、dp[5]、dp[11]为true
代码:
java
class Solution {
public boolean canPartition(int[] nums) {
int sum=0;
for(int num : nums){
sum+=num;
}
if(sum%2==1){
return false;
}
int target=sum/2;
boolean[] dp=new boolean[target+1];
dp[0]=true;
for(int num:nums){
for(int j=target;j>=num;j--){
dp[j]=dp[j]||dp[j-num];
}
}
return dp[target];
}
}
五.最长有效括号
问题概述:
给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号 子串 的长度。
左右括号匹配,即每个左括号都有对应的右括号将其闭合的字符串是格式正确的,比如 "(()())"为6.

思路:
dp[i]表示以索引为i结尾的最长有效括号子串的长度。
①当结尾为'(',就是不合法的,就记0.
②当结尾为')', a.dp[i-1]为'(' :dp[i]=d[i-2]+2
b.dp[i-1]为')' : 需满足dp[i-dp[i-1]-1]=='('才能包起来,然后dp[i]=dp[i-1]+2+dp[i-dp[i-dp[i-1]-2]
注意:越界条件判断
代码:
java
class Solution {
public int longestValidParentheses(String s) {
int n=s.length();
if(n<2){
return 0;
}
int[] dp=new int[n];
int max=0;
for(int i=1;i<n;i++){
if(s.charAt(i)==')'){
if(s.charAt(i-1)=='('){
dp[i]=i-2>=0 ? dp[i-2]+2 : 2;
}else if(s.charAt(i-1)==')'){
if(i-dp[i-1]-1>=0&&s.charAt(i-dp[i-1]-1)=='('){
dp[i]=i-dp[i-1]-2>=0 ? dp[i-1]+2+dp[i-dp[i-1]-2] : dp[i-1]+2;
}
}
}
max=Math.max(max,dp[i]);
}
return max;
}
}