一、单词拆分
给你一个字符串 s
和一个字符串列表 wordDict
作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s
则返回 true
。
注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。
public class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
//1.将字典变成集合便于查找是否含有需要的字符串
Set<String> res = new HashSet(wordDict);
//2.确定i和dp的含义,i为长度,dp[i]为前i长的子串是否在字典中
boolean[] dp = new boolean[s.length() + 1];
//3.初始化dp数组
dp[0] = true;
//4.依次循环,从前向后遍历
for (int i = 1; i <= s.length(); i++) {
for (int j = 0; j < i; j++) {
//5.dp从j到i截取的部分存在子典中,就返回true,退出本次循环
if (dp[j] && res.contains(s.substring(j,i))) {
dp[i] = true;
break;
}
}
}
return dp[s.length()];
}
}
二、最长递增子序列
给你一个整数数组 nums
,找到其中最长严格递增子序列的长度。
子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7]
是数组 [0,3,1,6,2,2,7]
的
子序列。
class Solution {
public int lengthOfLIS(int[] nums) {
// 1.判断数组是否为空
if (nums.length == 0)
return 0;
// 2.确定i和dp的含义,i为数组中的第几个数字,dp[i]是截止这个数字的最长递增序列的个数
int[] dp = new int[nums.length];
// 3.初始化dp
Arrays.fill(dp, 1);
int max = 1;
// 4.从前向后遍历
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
max = Math.max(max, dp[i]);
}
// 5. 找到最大值作为结果返回
return max;
}
}
三、分割等和子集
给你一个 只包含正整数 的 非空 数组 nums
。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
class Solution {
public boolean canPartition(int[] nums) {
//1.首先判断数组是否可以均分为两份
int n = nums.length, sum = 0;
for (int i : nums) {
sum += i;
}
if (sum % 2 != 0) return false;
//2.若可以,以平均数为目标值
int target = sum / 2;
int[] dp = new int[target + 1];
for (int i = 0; i < n; i++) {
for (int j = target; j >= nums[i]; j--) {
dp[j] = Math.max (dp[j],dp[j-nums[i]] + nums[i]);
}
if (dp[target] == target) return true;
}
return dp[target] == target;
}
}