线性DP
LeetCode 300. 最长递增子序列
LeetCode674. 最长连续递增序列
题解:最长上升子串模板题
定义fi表示以i结尾的最长上升子串
nums[i-1] < nums[i],则有f[i] = f[i-1] + 1
nums[i-1] > nums[i],则有f[i] = 1
public class Solution {
public int findLengthOfLCIS(int[] nums) {
int n = nums.length;
int[] f = new int[n];
Arrays.fill(f, 1);
int res = 1;
for(int i = 0; i < n; i++) {
if(i > 0 && nums[i] > nums[i-1]) f[i] = f[i-1] + 1;
res = Math.max(res, f[i]);
}
return res;
}
}
携程2023030701
题目内容
定义一个数组为“稳定的”,当且仅当数组中相邻的两个元素之差的绝对值不超过1。
例如:
- 数组
[2, 3, 2, 2, 1]
是稳定的,因为相邻元素之差不超过1。 - 数组
[1, 3, 2]
不是稳定的,因为1和3之间的差的绝对值超过了1。
给定一个由 n
个整数组成的数组 a
,求该数组的最长的稳定的连续子数组的长度。
输入描述
第一行输入一个正整数 n
,代表数组的大小。
第二行输入 n
个正整数 ai,代表数组的元素。
1 ≤ n ≤ 100000,1 ≤ ai ≤ 10^9
输出描述
一个正整数,代表最长连续稳定子数组的长度。
样例
输入
6
2 3 5 4 5 6
输出
4
思路
和likou674. 最长连续递增序列差不多。
f[i]
为以 i
结尾的稳定子数组的长度。
f[i]
初始值为 1,如果它与它左侧的元素 nums[i-1]
的差值 diff = abs(nums[i] - nums[i-1])
满足 diff ≤ 1
,则有 f[i] = f[i-1] + 1
`import java.util.*;
public class Main {
static final int N = 100010;
static int n, a[] = new int[N], f[] = new int[N];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
int res = 1;
f[0] = 1;
for (int i = 1; i < n; i++) {
if (Math.abs(a[i] - a[i - 1]) <= 1) {
f[i] = f[i - 1] + 1;
} else {
f[i] = 1;
}
res = Math.max(res, f[i]);
}
System.out.println(res);
}
}`
科大讯飞2022101001
输入:
第一行字符串表示赛道X的奖金编号。
第二行字符串表示赛道Y的奖金编号。
编号范围为a-z和0-9,赛道关卡数为1-100。
输出:
两兄弟最多可获得的奖金数。
示例:
输入:
1323467
1378694
输出:
4
说明:
如赛道X和Y中获得奖金1和6,不连续,获得2份奖金;
如获得奖金1和3,连续,获得4份奖金。
思路:
这道题和力扣718.最长连续子数组一模一样
定义 f[i][j] 为以 nums1[i] 结尾和以 nums2[j] 结尾的最长公共子串
- nums1[i] 不等于 nums2[j],则有 f[i][j] = 0
- nums1[i] 等于 nums2[j],则有 f[i][j] = f[i-1][j-1] + 1
package com.coedes.dp.kedaxunfei20221010;
import java.util.Scanner;
/**
* @author 17259
* @create 2024-06-15 17:51
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String X = sc.nextLine();
String Y = sc.nextLine();
System.out.println(solve(X, Y));
}
private static int solve(String X, String Y) {
int lenX = X.length();
int lenY = Y.length();
int[][] dp = new int[lenX + 1][lenY + 1];
int res = 0;
for (int i = 1; i <= lenX; i++) {
for (int j = 1; j <= lenY; j++) {
if (X.charAt(i - 1) == Y.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1] + 1;
}
res = Math.max(dp[i][j],res);
}
}
return res*2;
}
}
20221013荣耀
在某个遥远国度里有一种传统的游戏叫做“跳跳棋”。游戏棋盘呈直线状,共有N格,起始位置和结束位置在棋盘之外。每格有不同的积分值,玩家每次跳跃必须跳过一个或多个格子,不允许跳到相邻格子或回跳。目标是通过跳跃获取最高积分。
输入描述:
- 第一行是整数N,表示跳棋格数(1 ≤ N ≤ 100,000)
- 第二行是N个整数,每个整数表示对应格子的积分值(1 ≤ M ≤ 1,000)
输出描述:
- 能获得的最高积分
示例:
输入
3
1 5 2
输出
5
思路:
这和力扣198.打家劫舍 思路一样,
起始位置和结束位置在棋盘之外 且 (1 ≤ N ≤ 100,000) ,定义长度为 N+1 数组 ,起点为0
package com.coedes.dp.rongyao20221013;
import java.util.Scanner;
/**
* @author 17259
* @create 2024-06-16 10:44
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int[] M = new int[N+1];
for (int i = 1; i <= N; i++) {
M[i] = sc.nextInt();
}
System.out.println(solve(M));
}
private static long solve(int[] m) {
int length = m.length;
long[] dp = new long[length];
dp[1] = m[1];
for (int i = 2; i < length; i++) {
dp[i] = Math.max(dp[i-1],dp[i-2]+m[i]);
}
return dp[length-1];
}
}
2023081101 快手
一个整数数组中选出一些数,使得这些数的和尽可能大,但不允许选择相邻的元素。要求设计一个算法,在O(n)的时间复杂度内计算出答案。
输入描述:
- 一行输入包含n个正整数,以EOF结尾。
输出描述:
- 第一行输出选中的数在整数数组中的索引,空格隔开,以空格结束。
- 第二行输出选中的数的和。
示例:
输入
1 6 2 7 3 8 4 9 5 10
输出
1 3 5 7 9
40
思路:
打家劫舍 + 标记数组
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
/**
* @author 17259
* @create 2024-06-16 12:51
*/
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String[] split = reader.readLine().split(" ");
int n = split.length;
long[] a = new long[n + 1];
for (int i = 1; i <= n; i++) {
a[i] = Long.parseLong(split[i - 1]);
}
solve(a, n);
}
private static void solve(long[] a, int n) {
long[] dp = new long[n + 1];
boolean[] flag = new boolean[n + 1];
dp[0] = 0;
dp[1] = a[1];
flag[1] = true;
for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 1];
long val = dp[i - 2] + a[i];
if (val > dp[i]) {
dp[i] = val;
flag[i] = true;
}
}
List<Integer> ans = new ArrayList<>();
int cur = n;
while (cur > 0) {
if (flag[cur]) {
ans.add(cur - 1);
cur -= 2;
} else {
cur -= 1;
}
}
for (int i = ans.size() - 1; i >= 0; --i) {
System.out.print(ans.get(i) + " ");
}
System.out.println();
System.out.println(dp[n]);
}
}