一、题目描述
给出数字K,请输出所有结果小于K的整数组合到一起的最少交换次数。
组合一起是指满足条件的数字相邻,不要求相邻后在数组中的位置。
数据范围
-100 <=K <= 100
-100 <= 数组中数值 <= 100
二、输入描述
第一行输入数组:1 3 1 4 0
第二行输入K数值:2
三、输出描述
第一行输出最少较好次数:1
备注:
小于2的表达式是 1 1 0,共三种可能将所有符合要求数字组合在一起,最少交换1次
四、测试用例
测试用例1
1、输入
1 3 1 4 0
2
2、输出
1
3、说明
满足条件(< 2)的数字为:1, 1, 0,共 3 个。
滑动窗口情况:
窗口 [1,3,1]:满足 2 个
窗口 [3,1,4]:满足 1 个
窗口 [1,4,0]:满足 2 个
最大为 2,则交换次数 = 3 - 2 = 1
测试用例2
1、输入
5 1 3 2 4
4
2、输出
0
3、说明
满足条件(< 4)的数字为:1, 3, 2,共 3 个。
可选窗口:[1,3,2]已经连续,交换次数 = 3 - 3 = 0
五、解题思路
题目要求将数组中所有满足“数字 < K”的元素组合到一起(即在最终排列中相邻,原位置不要求连续),要求求出最少交换次数。核心思路是:
1、统计满足条件的元素个数(记为 targetCount)
这些元素最终要组合到一起,所以在数组中必然有一段连续区间长度为 targetCount。
2、滑动窗口求最大匹配数
用一个长度为 targetCount 的窗口,在数组上滑动,统计窗口内已有多少个满足“< K”的数字。
假设窗口内最多包含 maxCount 个满足条件的数字,那么只需要交换(targetCount – maxCount)个数字即可把窗口内“不满足”的数字换成满足条件的数字,从而将所有满足条件的数字组合在一起。
3、时间复杂度 O(n)
用数组、计数器与滑动窗口完成,不需要额外复杂数据结构。
4、具体解题步骤
- 确定滑动窗口大小,滑动窗口的大小取决于有多少个数小于k,假定总共有m个数小于k,这个数值即为滑动窗口的长度;
- 让滑动窗口从数组起始端向右滑动,每滑动一位,就计算出当前窗口内有多少个数小于k,将这些统计数字做比较,找出最大的,假定窗口内最多有n个数小于k;
- m与n的差值就是需要交换的次数。
六、Java算法源码
package com.guor.od;
import java.util.*;
public class OdTest02 {
/**
* 给出数字K,请输出所有结果小于K的整数组合到一起的最少交换次数
*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] arr = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
int K = sc.nextInt();
// 遍历数组,找出数组里面有多少个数字小于K,确定滑动窗口大小
int target = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] < K) {
target++;
}
}
// 滑动窗口左起点
int left = 0;
// 滑动窗口右终点
int right = target - 1;
// 记录当前窗口范围内有多少个数字小于K
int okSum = 0;
// 再遍历一次,确定初始窗口内有多少个数小于K
for (int i = 0; i <= right; i++) {
if (arr[i] < K) {
okSum++;
}
}
// max用来记录窗口内最多有多少个数小于K
int max = okSum;
// 窗口不停的向右滑动
while (right < arr.length - 1) {
// 左边滑出
if (arr[left++] < K) {
okSum--;
}
// 右边滑入
if (arr[++right] < K) {
okSum++;
}
if (okSum > max) {
max = okSum;
}
}
System.out.println(target - max);
}
}
七、效果展示
1、输入
1 2 3 4 2
3
2、输出
1
3、说明
(1)根据解题思路:
- 确定滑动窗口大小,滑动窗口的大小取决于有多少个数小于k,假定总共有m个数小于k,这个数值即为滑动窗口的长度;
- 让滑动窗口从数组起始端向右滑动,每滑动一位,就计算出当前窗口内有多少个数小于k,将这些统计数字做比较,找出最大的,假定窗口内最多有n个数小于k;
- m与n的差值就是需要交换的次数。
(2)具体解题思路:
- 滑动窗口的大小取决于有多少个数小于k --> m = 3;
- 滑动窗口大小为3,每三个一滑,计算当前窗口内有多少个数小于k;
- 1 2 3 --> 2个
- 2 3 4 --> 1个
- 3 4 2 --> 1个
- 将这些统计数字做比较,找出最大的n=2。
- m与n的差值就是需要交换的次数,即1。