一、计算绝对值
题目描述:
给出n个正整数,要求找出相邻两个数字中差的绝对值最小的一对数字,如果有差的绝对值相同的,则输出最前面的一对数。2<n<=100,正整数都在10^16范围内。
输入:
输入包含2行,第一行为n,第二行是n个用空格分隔的正整数。
输出:
输出包含一行两个正整数,要求按照原来的顺序输出。
样例输入:
9
1 3 4 7 2 6 5 12 32
样例输出:
3 4
程序如下:(AC18%)
package test;
import java.util.Scanner;
public class Test4 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String one = sc.nextLine();
String two = sc.nextLine();
String[] t = two.split(" ");
int n = Integer.parseInt(one);
int[] a = new int[n];
for(int i=0;i<n;i++) {
a[i] = Integer.parseInt(t[i]);
}
int[] b = new int[n-1];
for(int i=0;i<n-1;i++) {
b[i] = Math.abs(a[i]-a[i+1]);
}
int count = Integer.MAX_VALUE;
int flag = 0;
for(int i=0;i<n-1;i++) {
if(b[i]<count) {
count = b[i];
flag = i;
}
}
System.out.println(a[flag]+" "+a[flag+1]);
}
}
看了牛客讨论区后,发现问题出在数据类型选择上,题目要求最大在10^16范围,应选用Long Long(C语言)、BigInteger(Java语言)。
二、月光宝盒的密码
题目描述:
小希偶然得到了传说中的月光宝盒,然而打开月光宝盒需要一串密码。虽然小希并不知道密码具体是什么。但是月光宝盒说明书上有着一个长度为n(2<=N<=50000)的序列a(-10 ^9 <= a[i] <= 10 ^9)的范围内。下面写着一句话,密码是这个序列的最长的严格上升子序列的长度(严格上升子序列是指,子序列的元素是严格递增的,例如:[5,1,6,2,4]的最长严格上升子序列为[1,2,4]),请你帮小希找打这个密码。
输入:
第1行:1个数N,N为序列的长度(2<=N<=50000)
第2到N+1行:每行1个数,对应序列的元素(-10 ^9 <= a[i] <= 10 ^9)
输出:
一个正整数表示严格最长上升子序列的长度
样例输入:
8
5
1
6
8
2
4
5
10
样例输出:
5
程序如下:(AC82%)
package test;
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] a = new int[n];
int count = 0;
while(sc.hasNext()) {
int num = sc.nextInt();
a[count] = num;
count++;
if(count >= n) {
break;
}
}
//记录上升序列的长度,dp[i]表示以a[i]结尾的子序列的最大长度
int[] dp = new int[n];
//记录dp数组中的最大值
int result = 0;
//按顺序计算dp值
for(int i=0;i<n;i++) {
dp[i] = 1;
for(int j=0;j<i;j++) {
if(a[i]>a[j] && dp[j]+1 > dp[i]) {
dp[i] = dp[j] + 1;
}
}
result = Math.max(result, dp[i]);
}
System.out.println(result);
sc.close();
}
}
思路:利用动态规划来降低复杂度。
令dp[i]表示以a[i]结尾的最长上升子序列的长度,对a[i]来说有两种可能:
1)如果在i之前存在比a[i]小的数a[j](j<i),并且dp[j]+1>dp[i](即把a[i]放到以a[j]结尾的子序列之后其长度大于当前以a[i]结尾的子序列的长度),那么就把a[i]放到之前以a[j]结尾的子序列之后,并令其长度+1(即dp[i] = dp[j]+1)。
2)如果a[i]之前的所有数都比它大,那么只能a[i]自身成一个子序列,其长度为1。
三、检查卫生
题目描述:
一条直线上有n个教室,每个教室有一个当前的整洁度,第i个教室的整洁度为ai。有m个老师会来检查这n个教室的卫生情况,第i个老师抽查区间[Li,Ri]中的所有教室即第Li个教室,第Li+1个教室,一直到第Ri个教室,他们打分就是这个区间中所有教室的整洁度之和。而本次检查的最终总分就是这m个老师打分之和。检查马上就要开始了,你现在还可以打扫一间教室,打扫可以使得这间教室的整洁度再加1,请你选一间教室,使得最终检查的总得分最高!
输入:
第一行两个整数n,m(1<=n<=100000)
接下来一行n个整数a1,a2,…,an(0<=ai<=100)
最后输入m行,每行两个整数Li,Ri,表示每个老师抽查的区间(1<=Li<=Ri<=n)
输出:
输出一个数,最高得分。
样例输入:
4 3
1 2 3 4
1 4
2 4
3 4
样例输出:
29
提示:
测试样例中,打扫最后一个教室即可得到答案。
程序如下:
(未做,后续完善)
四、特殊的测试
题目描述:
小C在做一种特殊的服务器负载测试,对于一个请求队列中的请求,每一个请求都有一个负载值,为了保证服务器稳定,请求队列中的请求符合必须按照先递增后递减的规律(仅递增,仅递减也可以),比如[1,2,8,4,3],[1,3,5]和[10]这些是满足规律的,还有一些不满足的,比如[1,2,2,1],[2,1,2]和[10,10],现在给你一个请求队列,你可以对请求的负荷值进行增加,要求你调整队列中请求的负荷值,使数组满足条件。最后输出使队列满足条件最小的增加总和。
输入:
输入有两行,第一行是N(1<=n<=5000),代表请求队列的请求数量。
第二行有N个数字a1,a2,…,an(1<=ai<=10^9)。Ai是第i个请求的负荷值。
输出:
输出这个最小增加总和
样例输入:
5
1 4 3 2 5
输出:
6
提示:
样例解释:此时合法队列为[1,4,3,2,5],最小增加和为6。
程序如下:(AC64%)
package test;
import java.util.Scanner;
public class Test2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String first = sc.nextLine();
String second = sc.nextLine();
String[] sec = second.split(" ");
int n = Integer.parseInt(first);
int[] a = new int[n];
for(int i=0;i<n;i++) {
a[i] = Integer.parseInt(sec[i]);
}
int start = 0;
int end = n-1;
int min = 0;
while(start < end && start+1 <= end && end-1 >= 0) {
if(a[start]<a[start+1]) {
start++;
}
if(a[end]<a[end-1]) {
end--;
}
//找出需要处理的数据
if(a[start]>a[end]) {
for(int i=end-1;i>start;i--) {
min += a[i+1]-a[i]+1;
a[i] = a[i+1] + 1;
}
}else {
for(int i=start+1;i<end;i++) {
min += a[i-1]-a[i]+1;
a[i] = a[i-1]+1;
}
}
}
System.out.println(min);
}
}
本文精选了四个编程挑战题目,包括寻找最小绝对值差的数字对、求解最长严格上升子序列、提高卫生检查分数及调整请求队列负荷。通过详细解析,展示了解决算法问题的技巧和策略。
1050

被折叠的 条评论
为什么被折叠?



