1.最长递增子序列
题目解析
算法讲解
编写代码
class Solution {
public int lengthOfLIS(int[] nums) {
// 1. 创建 dp 表
// 2. 初始化
// 3. 填表
// 4. 返回值
int n = nums.length;
int[] dp = new int[n];
for (int i = 0; i < n; i++)
dp[i] = 1;
int ret = 1;
for (int i = 1; i < n; i++) {
for (int j = 0; j < i; j++)
if (nums[j] < nums[i])
dp[i] = Math.max(dp[j] + 1, dp[i]);
ret = Math.max(ret, dp[i]);
}
return ret;
}
}
2.摆动序列
题目解析
算法讲解
编写代码
class Solution {
public int wiggleMaxLength(int[] nums) {
// 1. 创建 dp 表
// 2. 初始化
// 3. 填表
// 4. 返回值
int n = nums.length;
int[] f = new int[n];
int[] g = new int[n];
for (int i = 0; i < n; i++)
g[i] = f[i] = 1;
int ret = 1;
for (int i = 1; i < n; i++) {
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i])
f[i] = Math.max(g[j] + 1, f[i]);
else if (nums[j] > nums[i])
g[i] = Math.max(f[j] + 1, g[i]);
}
ret = Math.max(ret, Math.max(f[i], g[i]));
}
return ret;
}
}
其实最优解是贪心思路
3.最长递增子序列的个数
题目解析
算法讲解
一次遍历的思路
运用上述思想
编写代码
class Solution {
public int findNumberOfLIS(int[] nums) {
// 1. 创建 dp 表
// 2. 初始化
// 3. 填表
// 4. 返回值
int n = nums.length;
int[] len = new int[n];
int[] count = new int[n];
for (int i = 0; i < n; i++)
len[i] = count[i] = 1;
int retlen = 1, retcount = 1;
for (int i = 1; i < n; i++) {
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i]) {
if (len[j] + 1 == len[i]) // 计数
count[i] += count[j];
else if (len[j] + 1 > len[i]) // 重新计数
{
len[i] = len[j] + 1;
count[i] = count[j];
}
}
}
if (retlen == len[i])
retcount += count[i];
else if (retlen < len[i]) // 重新计数
{
retlen = len[i];
retcount = count[i];
}
}
return retcount;
}
}
4.最长数对链
题目解析
算法讲解
编写代码
class Solution {
public int findLongestChain(int[][] pairs) {
// 预处理
Arrays.sort(pairs, (a, b) -> a[0] - b[0]);
int n = pairs.length;
int[] dp = new int[n]; // 建表
for (int i = 0; i < n; i++)
dp[i] = 1; // 初始化
int ret = 1;
for (int i = 1; i < n; i++) {
for (int j = 0; j < i; j++)
if (pairs[j][1] < pairs[i][0])
dp[i] = Math.max(dp[j] + 1, dp[i]);
ret = Math.max(ret, dp[i]);
}
return ret;
}
}
5.最长定差子序列
题目解析
算法讲解
编写代码
class Solution {
public int longestSubsequence(int[] arr, int difference) {
// 创建⼀个哈希表,在哈希表中做 dp
Map<Integer, Integer> hash = new HashMap<Integer, Integer>();
// arr[i], dp[i]
int ret = 1;
for (int a : arr) {
hash.put(a, hash.getOrDefault(a - difference, 0) + 1);
ret = Math.max(ret, hash.get(a));
}
return ret;
}
}
6.最长的斐波那契子序列的长度(重点)
873. 最长的斐波那契子序列的长度 - 力扣(LeetCode)
题目解析
算法讲解
编写代码
class Solution {
public int lenLongestFibSubseq(int[] arr) {
// 优化:将 数组中的元素 + 下标 绑定在⼀起,扔到哈希表中
Map<Integer, Integer> hash = new HashMap<Integer, Integer>();
int n = arr.length;
for (int i = 0; i < n; i++)
hash.put(arr[i], i);
int[][] dp = new int[n][n];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
dp[i][j] = 2;
int ret = 2;
for (int j = 2; j < n; j++) // 固定最后⼀个数
for (int i = 1; i < j; i++) // 枚举倒数第⼆个数
{
int a = arr[j] - arr[i];
if (a < arr[i] && hash.containsKey(a))
dp[i][j] = dp[hash.get(a)][i] + 1;
ret = Math.max(ret, dp[i][j]);
}
return ret < 3 ? 0 : ret;
}
}
7.最长等差数列(困难)
题目解析
算法讲解
编写代码
class Solution {
public int longestArithSeqLength(int[] nums) {
// 优化
Map<Integer, Integer> hash = new HashMap<Integer, Integer>();
hash.put(nums[0], 0);
// 建表
int n = nums.length;
int[][] dp = new int[n][n];
for (int i = 0; i < n; i++) // 初始化
Arrays.fill(dp[i], 2);
int ret = 2;
for (int i = 1; i < n; i++) // 固定倒数第⼆个数
{
for (int j = i + 1; j < n; j++) // 枚举倒数第⼀个数
{
int a = 2 * nums[i] - nums[j];
if (hash.containsKey(a)) {
dp[i][j] = dp[hash.get(a)][i] + 1;
ret = Math.max(ret, dp[i][j]);
}
}
hash.put(nums[i], i);
}
return ret;
}
}
8.等差数列划分II - 子序列
题目解析
算法讲解
编写代码
class Solution {
public int numberOfArithmeticSlices(int[] nums) {
// 优化
Map<Long, List<Integer>> hash = new HashMap<>();
int n = nums.length;
for (int i = 0; i < n; i++) {
long tmp = (long) nums[i];
if (!hash.containsKey(tmp))
hash.put(tmp, new ArrayList<Integer>());
hash.get(tmp).add(i);
}
int[][] dp = new int[n][n];
int sum = 0;
for (int j = 2; j < n; j++) // 固定倒数第⼀个数
for (int i = 1; i < j; i++) // 枚举倒数第⼆个数
{
long a = 2L * nums[i] - nums[j];
if (hash.containsKey(a)) {
for (int k : hash.get(a))
if (k < i)
dp[i][j] += dp[k][i] + 1;
else
break; // ⼩优化
}
sum += dp[i][j];
}
return sum;
}
}