使用Java编程小红有一个长度为n的排列她可以选择两个位置然后交换两个位置的数。她想知道能否通过最多一次交换使得存在一个连续子段是长度为k的排列。排列是指一个长度为len的整数数组数组中包含1到len 的每个数且每个数只出现一次。输入描述一行两个整数nk表示排列长度和连续子段长度。一行n个整数a12an表示排列。1≤k≤n≤105输出描述如果能够通过最多一次交换存在一个连续子段是排列输出 YES并
思路:
- 首先判断原始排列是否已经是一个连续子段,如果是,则输出YES并且不需要交换位置;
- 如果不是连续子段,则遍历整个排列,找到第一个不在正确位置上的数,记为num;
- 从num开始向后找连续子段,直到找到长度为k的连续子段或者遍历完整个排列;
- 如果找到了长度为k的连续子段,输出YES,并输出交换的位置为num和子段的第一个数;
- 如果没有找到长度为k的连续子段,输出NO。
代码实现如下:
import java.util.Scanner;
public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int k = sc.nextInt(); int[] arr = new int[n]; for (int i = 0; i < n; i++) { arr[i] = sc.nextInt(); } sc.close();
// 判断是否已经是连续子段
boolean isConsecutive = true;
for (int i = 0; i < n; i++) {
if (arr[i] != i + 1) {
isConsecutive = false;
break;
}
}
if (isConsecutive) {
System.out.println("YES");
System.out.println("0");
} else {
// 找到第一个不在正确位置上的数
int num = 0;
for (int i = 0; i < n; i++) {
if (arr[i] != i + 1) {
num = arr[i];
break;
}
}
// 从num开始找连续子段
int start = 0;
int end = 0;
for (int i = 0; i < n; i++) {
if (arr[i] == num) {
start = i;
end = i + 1;
while (end < n && arr[end] == arr[end - 1] + 1) {
end++;
}
break;
}
}
// 判断是否找到了长度为k的连续子段
if (end - start == k) {
System.out.println("YES");
System.out.println("1");
System.out.println((start + 1) + " " + (end + 1));
} else {
System.out.println("NO");
}
}
}
}
原文地址: https://www.cveoy.top/t/topic/i6eb 著作权归作者所有。请勿转载和采集!