目录
相差不超过k的最多数(滑动窗⼝)
题目解析
1.题目链接:相差不超过k的最多数_牛客题霸_牛客网
2.题目描述
描述
给定一个数组,选择一些数,要求选择的数中任意两数差的绝对值不超过 kk 。问最多能选择多少个数?
输入描述:
第一行输入两个正整数 nn和kk。
第二行输入 nn 个正整数a_iai,用空格隔开,表示这个数组。输出描述:
一个正整数,代表能选的最多数量。
数据范围:
1\leq n \leq 2 \times 10^51≤n≤2×105
1\leq k, a_i \leq 10^91≤k,ai≤109示例1
输入:
5 3
2 1 5 3 2输出:
4
说明:
显然,1和5不能同时选。所以最多只能选4个数。
讲解算法原理
解法:
算法思路:
排序+滑动窗⼝
编写代码
c++算法代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 2e5 + 10;
int n, k;
int arr[N];
int main()
{
cin >> n >> k;
for(int i = 0; i < n; i++) cin >> arr[i]; sort(arr, arr + n);
int left = 0, right = 0, ret = 1; while(right < n)
{
while(arr[right] - arr[left] > k)
{
left++;
}
ret = max(ret, right - left + 1); right++;
}
cout << ret << endl;
return 0;
}
java算法代码:
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in); int n = in.nextInt(), k = in.nextInt(); int[] arr = new int[n]; for(int i = 0; i < n; i++)
{
arr[i] = in.nextInt();
}
Arrays.sort(arr); int left = 0, right = 0, ret = 0; while(right < n) { while(arr[right] - arr[left] > k) { left++; } ret = Math.max(ret, right - left + 1); right++;
}
System.out.println(ret);
}
}
最⻓公共⼦序列(⼀)(动态规划-LCS)
题目解析
1.题目链接:最长公共子序列(一)_牛客题霸_牛客网
2.题目描述
描述
给定两个字符串 s1 和 s2,长度为 n 和 m 。求两个字符串最长公共子序列的长度。
所谓子序列,指一个字符串删掉部分字符(也可以不删)形成的字符串。例如:字符串 "arcaea" 的子序列有 "ara" 、 "rcaa" 等。但 "car" 、 "aaae" 则不是它的子序列。
所谓 s1 和 s2 的最长公共子序列,即一个最长的字符串,它既是 s1 的子序列,也是 s2 的子序列。
数据范围 : 1\leq m,n\leq 10001≤m,n≤1000 。保证字符串中的字符只有小写字母。
要求:空间复杂度 O(mn)O(mn),时间复杂度 O(mn)O(mn)
进阶:空间复杂度 O(min(m,n))O(min(m,n)),时间复杂度 O(mn)O(mn)
输入描述:
第一行输入一个整数 n 和 m ,表示字符串 s1 和 s2 的长度。
接下来第二行和第三行分别输入一个字符串 s1 和 s2。
输出描述:
输出两个字符串的最长公共子序列的长度
示例1
输入:
5 6
abcde
bdcaaa输出:
2
说明:
最长公共子序列为 "bc" 或 "bd" ,长度为2
示例2
输入:
3 3
abc
xyz输出:
0
讲解算法代码
解法:
算法思路:
经典两个字符串之间的dp问题。
1. 状态表⽰: dp[i][j] 表⽰:字符串s1中 [0, i] 区间与字符串s2中 [0, j] 区间内所有的⼦序列中,最⻓公共⼦序列的⻓度是多少。
2. 状态转移⽅程:根据最后⼀个位置的字符情况,划分问题:
a. s1[i] == s2[j]:dp[i][j] = dp[i - 1][j - 1] + 1;
b. s1[i] != s2[j]:dp[i][j] = max(dp[i - 1][j], do[i][j - 1])。
为了防⽌越界,我们把字符串的起始位置从1开始计算。
编写代码
c++算法代码:
#include <iostream>
using namespace std;
const int N = 1010;
int n, m;
char s1[N];
char s2[N];
int dp[N][N];
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> s1[i]; for(int i = 1; i <= m; i++) cin >> s2[i];
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
if(s1[i] == s2[j]) dp[i][j] = dp[i - 1][j - 1] + 1; else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); }
}
cout << dp[n][m] << endl;
return 0;
}
java算法代码:
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in); int n = in.nextInt(), m = in.nextInt(); char[] s1 = in.next().toCharArray(); char[] s2 = in.next().toCharArray(); int[][] dp = new int[n + 1][m + 1];
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
if(s1[i - 1] == s2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
else dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
System.out.println(dp[n][m]);
}
}