1.最大子数组和
题目解析
算法讲解
编写代码
class Solution {
public int maxSubArray(int[] nums) {
// 1. 创建 dp 表
// 2. 初始化
// 3. 填表
// 4. 返回结果
int n = nums.length;
int[] dp = new int[n + 1];
int ret = Integer.MIN_VALUE;
for (int i = 1; i <= n; i++) {
dp[i] = Math.max(nums[i - 1], dp[i - 1] + nums[i - 1]);
ret = Math.max(ret, dp[i]);
}
return ret;
}
}
2.环形子数组最大和
题目解析
算法讲解
正难则反
编写代码
class Solution {
public int maxSubarraySumCircular(int[] nums) {
// 1. 创建 dp 表
// 2. 初始化
// 3. 填表
// 4. 返回值
int n = nums.length;
int[] f = new int[n + 1];
int[] g = new int[n + 1];
int sum = 0, fmax = Integer.MIN_VALUE, gmin = Integer.MAX_VALUE;
for (int i = 1; i <= n; i++) {
int x = nums[i - 1];
f[i] = Math.max(x, x + f[i - 1]);
fmax = Math.max(fmax, f[i]);
g[i] = Math.min(x, x + g[i - 1]);
gmin = Math.min(gmin, g[i]);
sum += x;
}
return sum == gmin ? fmax : Math.max(fmax, sum - gmin);
}
}
3.乘积最大子数组
题目解析
算法讲解
编写代码
class Solution {
public int maxProduct(int[] nums) {
// 1. 创建 dp 表
// 2. 初始化
// 3. 填表
// 4. 返回值
int n = nums.length;
int[] f = new int[n + 1];
int[] g = new int[n + 1];
f[0] = g[0] = 1;
int ret = Integer.MIN_VALUE;
for (int i = 1; i <= n; i++) {
int x = nums[i - 1], y = f[i - 1] * nums[i - 1], z = g[i - 1] * nums[i - 1];
f[i] = Math.max(x, Math.max(y, z));
g[i] = Math.min(x, Math.min(y, z));
ret = Math.max(ret, f[i]);
}
return ret;
}
}
4.乘积为正数的最长子数组
题目解析
算法讲解
编写代码
class Solution {
public int getMaxLen(int[] nums) {
// 1. 创建 dp 表
// 2. 初始化
// 3. 填表
// 4. 返回值
int n = nums.length;
int[] f = new int[n + 1];
int[] g = new int[n + 1];
int ret = Integer.MIN_VALUE;
for (int i = 1; i <= n; i++) {
if (nums[i - 1] > 0) {
f[i] = f[i - 1] + 1;
g[i] = g[i - 1] == 0 ? 0 : g[i - 1] + 1;
} else if (nums[i - 1] < 0) {
f[i] = g[i - 1] == 0 ? 0 : g[i - 1] + 1;
g[i] = f[i - 1] + 1;
}
ret = Math.max(ret, f[i]);
}
return ret;
}
}
5.等差数列划分
题目解析
算法讲解
编写代码
class Solution {
public int numberOfArithmeticSlices(int[] nums) {
// 1. 创建 dp 表
// 2. 初始化
// 3. 填表
// 4. 返回值
int n = nums.length;
int[] dp = new int[n];
int sum = 0;
for (int i = 2; i < n; i++) {
dp[i] = nums[i] - nums[i - 1] == nums[i - 1] - nums[i - 2] ? dp[i - 1] + 1 : 0;
sum += dp[i];
}
return sum;
}
}
6.最长湍流子数组
题目解析
算法讲解
为1是单干的情况
此时画叉的情形不用考虑
编写代码
class Solution {
public int maxTurbulenceSize(int[] arr) {
// 1. 创建 dp 表
// 2. 初始化
// 3. 填表
// 4. 返回值
int n = arr.length;
int[] f = new int[n];
int[] g = new int[n];
for (int i = 0; i < n; i++)
f[i] = g[i] = 1;
int ret = 1;
for (int i = 1; i < n; i++) {
if (arr[i - 1] < arr[i])
f[i] = g[i - 1] + 1;
else if (arr[i - 1] > arr[i])
g[i] = f[i - 1] + 1;
ret = Math.max(ret, Math.max(f[i], g[i]));
}
return ret;
}
}
7.单词拆分
题目解析
算法讲解
编写代码
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
// 优化⼀:将字典⾥⾯的单词存在哈希表⾥⾯
Set<String> hash = new HashSet(wordDict);
int n = s.length();
boolean[] dp = new boolean[n + 1];
dp[0] = true; // 初始化,保证我们后续填表是正确的
s = " " + s; // 处理下标的映射关系
for (int i = 1; i <= n; i++) // 填 dp[i]
{
for (int j = i; j >= 1; j--) // 最后⼀个单词的起始位置
{
if (dp[j - 1] && hash.contains(s.substring(j, i + 1))) {
dp[i] = true;
break; // 优化⼆
}
}
}
return dp[n];
}
}
8.环绕字符串中唯一的子字符串
题目解析
算法讲解
升级版
编写代码
class Solution {
public int findSubstringInWraproundString(String ss) {
int n = ss.length();
char[] s = ss.toCharArray();
// 1. 利⽤ dp 得到每⼀个位置为结尾的最⻓连续数组的⻓度
int[] dp = new int[n];
for (int i = 0; i < n; i++)
dp[i] = 1;
for (int i = 1; i < n; i++)
if (s[i - 1] + 1 == s[i] || (s[i - 1] == 'z' && s[i] == 'a'))
dp[i] += dp[i - 1];
// 2. 去重
int[] hash = new int[26];
for (int i = 0; i < n; i++)
hash[s[i] - 'a'] = Math.max(hash[s[i] - 'a'], dp[i]);
// 3. 返回结果
int sum = 0;
for (int x : hash)
sum += x;
return sum;
}
}