P5682 [CSP-J2019 江西] 次大值
P5682 [CSP-J2019 江西] 次大值
https://www.luogu.com.cn/problem/P5682
[CSP-J2019 江西] 次大值
题目描述
Alice 有 nnn 个正整数,数字从 1∼n1 \sim n1∼n 编号,分别为 a1,a2,…,ana_1,a_2, \dots , a_na1,a2,…,an。
Bob 刚学习取模运算,于是便拿这 nnn 个数进行练习,他写下了所有
ai mod aj(1≤i,j≤n∧i≠j)a_i \bmod a_j (1 \le i,j \le n \wedge i \neq j)aimodaj(1≤i,j≤n∧i=j)
的值,其中 mod \bmodmod 表示取模运算。
Alice 想知道所有的结果中,严格次大值是多少。将取模后得到的所有值进行去重,即相同的结果数值只保留一个,剩余数中第二大的值就称为严格次大值。
输入格式
第一行一个正整数 nnn,表示数字个数。
第二行 nnn 个正整数表示 aia_iai。
输出格式
仅一行一个整数表示答案。
若取模结果去重后剩余数字不足两个,则输出 −1-1−1。
样例 #1
样例输入 #1
4
4 5 5 6
样例输出 #1
4
样例 #2
样例输入 #2
4
1 1 1 1
样例输出 #2
-1
样例 #3
样例输入 #3
7
12 3 8 5 7 20 15
样例输出 #3
12
提示
【数据范围】
对于 40%40\%40% 的数据,1≤n,ai≤1001\le n,a_i \le 1001≤n,ai≤100;
对于 70%70\%70% 的数据,1≤n≤30001\le n \le 30001≤n≤3000,1≤ai≤1051\le a_i \le 10^51≤ai≤105;
对于 100%100\%100% 的数据,3≤n≤2×1053 \le n \le 2\times 10^53≤n≤2×105,1≤ai≤1091\le a_i \le 10^91≤ai≤109。
【样例 111 解释】
所有取模的结果为 {4,4,4,1,0,5,1,0,5,2,1,1}\{4,4,4,1,0,5,1,0,5,2,1,1\}{4,4,4,1,0,5,1,0,5,2,1,1}。
去重后有:{0,1,2,4,5}\{0,1,2,4,5 \}{0,1,2,4,5},结果为 444。
昨天傻逼了,正确题解
package 信息学奥林匹克竞赛.CSP_J.Year2019;
import java.util.Arrays;
import java.util.Scanner;
public class 次大值_luogu {
/**
*
* @param args
*/
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt(); // 读取数组大小
int[] array = new int[n]; // 创建数组
for (int i = 0; i < n; i++) {
array[i] = scanner.nextInt(); // 读取数组元素
}
// 排序数组,按降序排列
Arrays.sort(array);
for (int i = 0; i < n / 2; i++) {
int temp = array[i];
array[i] = array[n - i - 1];
array[n - i - 1] = temp;
}
int k = 1;
while (k < n && array[k] == array[k - 1]) { // k坐标指向第二大的数
k++;
}
int l = k + 1;
while (l < n && array[l] == array[l - 1]) { // l坐标指向第三大的数
l++;
}
if (k >= n) {
System.out.println(-1);
} else if (l >= n) {
System.out.println(array[0] % array[k]);
} else {
// 哎呀,还是自己傻逼了,找前三大的数是没错,但不一定就是第三个数是,还的看具体取模,例如: 2,3,5 取模: 2,2,1,2,1,2 答案:1
System.out.println(Math.max(array[l], array[0] % array[k]));
}
scanner.close();
}
}
详细解析:
一、整体功能概述
这段代码的目的是读取一个整数数组,找到该数组中的次大值(第二大的数)和第三大的数,并在特定情况下输出数组中最大值对次大值取模的结果或者第三大的数与取模结果中的较大值。该程序主要用于解决与数组中特定数值关系相关的问题,可能是信息学竞赛中的一道题目要求。
二、代码详细解析
main
方法部分:Scanner scanner = new Scanner(System.in);
:创建一个用于从标准输入读取数据的Scanner
对象。int n = scanner.nextInt();
:读取输入的第一个整数,表示数组的大小。int[] array = new int[n];
:创建一个大小为n
的整数数组。for (int i = 0; i < n; i++) { array[i] = scanner.nextInt(); }
:循环读取n
个整数,填充到刚刚创建的数组中。Arrays.sort(array);
:使用Arrays
类的sort
方法对数组进行排序,默认是升序排列。for (int i = 0; i < n / 2; i++) {... }
:这个循环将排序后的数组反转,变为降序排列。通过交换数组的首尾元素,实现数组的逆序。int k = 1; while (k < n && array[k] == array[k - 1]) { k++; }
:这个循环用于找到次大值在数组中的位置。初始时k
为 1,循环条件是k
小于数组大小并且当前位置的元素与前一个位置的元素相等。如果相等,说明还没有找到次大值,继续向后遍历,直到找到一个与前一个元素不同的位置,此时k
指向次大值。int l = k + 1; while (l < n && array[l] == array[l - 1]) { l++; }
:类似地,这个循环用于找到第三大的值在数组中的位置。初始时l
为k + 1
,循环条件是l
小于数组大小并且当前位置的元素与前一个位置的元素相等。如果相等,说明还没有找到第三大值,继续向后遍历,直到找到一个与前一个元素不同的位置,此时l
指向第三大值。if (k >= n) {... } else if (l >= n) {... } else {... }
:这是一系列条件判断。- 如果
k
大于等于数组大小,说明数组中没有次大值,输出 -1。 - 如果
l
大于等于数组大小,说明数组中没有第三大的值,输出数组中最大值(即array[0]
)对次大值(即array[k]
)取模的结果。 - 如果既存在次大值又存在第三大的值,输出第三大的值(即
array[l]
)与最大值对次大值取模结果(即array[0] % array[k]
)中的较大值。
- 如果
scanner.close();
:关闭Scanner
对象,释放资源。
三、总结
这段代码通过对输入的整数数组进行排序和遍历,找到次大值和第三大值的位置,并根据不同情况进行输出。它充分利用了循环和条件判断来处理数组中的数据关系,展示了 Java 中数组操作、输入输出处理和逻辑判断的能力。这种类型的代码在信息学竞赛中可能用于解决涉及数组中数值关系的问题,要求选手能够熟练运用 Java 的基本语法和算法思想来解决具体的问题。