题目描述:
给出数字K,请输出所有结果小于K的整数组合到一起的最少交换次数组合一起是指满足条件的数字相邻,不要求相邻后在数组中的位置
数据范围
-100 <= K <= 100
-100 <= 数组中数值<= 100
输入描述:
第一行输入数组: 1 3 1 4 0
第二行输入K数值: 2
输出描述:
第一行输出最少较好次数: 1
补充说明:
小于2的表达式是1 1 0,共三种可能将所有符合要求数字组合一起,最少交换1次
示例:
示例1:
输入1 3 1 4 0
2
输出 1
示例2:
输入0 0 0 1 0
2
输出0
思路:
(仅个人解题思路,如有好的方法希望能够相互交流)
题目没有要求真的交换,我们只需要求它的最小交换次数就可以了。用数组0,1的翻转来代替交换。将小于k的值变为1,大于等于k的值变为0。
将问题转变为求一个长度等于数组中1的个数的滑窗,这个滑窗中0的个数最少
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class Test1{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] nums = sc.nextLine().split(" ");
int[] num = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
num[i] = Integer.parseInt(nums[i]);
}
int k = sc.nextInt();
int swapCount = minSwaps(num, k);
System.out.println(swapCount);
}
public static int minSwaps(int[] nums, int k) {
// 记录小于k的数并将其转换为0,1数组
int m=0;
for(int i=0;i<nums.length;i++){
if(nums[i]<k){
m++;
nums[i]=1;
}else{
nums[i]=0;
}
}
int left =0;
int right=0;
int minZeroCnt = Integer.MAX_VALUE;
int windowZeroCnt = 0;
while (right < nums.length) {
if (nums[right] == 0) windowZeroCnt++;//窗口新进来1个0,0的数量+1
if (right - left + 1 == m) {//如果滑窗等于k,更新最小0的值
minZeroCnt = Math.min(minZeroCnt, windowZeroCnt);
if (nums[left] == 0) windowZeroCnt--;//移动窗口
left++;
}
right++;
}
return minZeroCnt == Integer.MAX_VALUE ? 0 : minZeroCnt;
}
}