【c++笔试强训】(第四十四篇)

目录

相差不超过k的最多数(滑动窗⼝)

题目解析

讲解算法原理

编写代码

最⻓公共⼦序列(⼀)(动态规划-LCS)

题目解析

讲解算法代码

编写代码


相差不超过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]);
 }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值