#P3054. 根据某条件聚类最少交换次数(100分)
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 173
            Accepted: 45
            Difficulty: 3
            
          
          
          
                       所属公司 : 
                              华为od
                                
            
                      
          
 
- 
                        算法标签>滑动窗口          
 
根据某条件聚类最少交换次数(100分)
题面描述
给定一个整数 K 和一个整数数组,请输出将所有小于 K 的数字组合到一起所需的最少交换次数。组合到一起的意思是这些数字在数组中连续排列,但不要求它们在原数组中的相对位置不变。
思路
记所有小于K的数的数量为count,那么我们用一个长度为current_count(初始为count)的滑动窗口扫描数组,每次移动时相当于窗口第一个数被弹出去,数组下一个数被加进来,那么我们记录max_count表示小于K的数最多时是多少,那么最少需要交换的次数就等于count-max_count
具体步骤
- 
读取输入:
- C++ 和 Java 通过标准输入读取数组和 K 值。
 - Python 使用 
sys.stdin读取输入,确保高效处理。 
 - 
统计小于 K 的元素数量:
- 通过遍历数组,统计满足条件的元素数量 
count。 
 - 通过遍历数组,统计满足条件的元素数量 
 - 
滑动窗口初始化:
- 计算第一个窗口(前 
count个元素)中满足条件的元素数量current_count。 
 - 计算第一个窗口(前 
 - 
滑动窗口遍历:
- 从窗口的下一个元素开始,逐步滑动窗口。
 - 每次滑动时,检查移出窗口的元素和新进入窗口的元素是否满足条件,更新 
current_count。 - 记录滑动过程中 
current_count的最大值max_count。 
 - 
计算最少交换次数:
- 最少交换次数为 
count - max_count,因为在最佳窗口中需要交换的元素最少。 
 - 最少交换次数为 
 - 
输出结果:
- 输出计算得到的最少交换次数。
 
 
cpp
#include <bits/stdc++.h>
using namespace std;
int main(){
    // 读取第一行输入的数组
    string line;
    getline(cin, line);
    vector<int> arr;
    int num;
    stringstream ss(line);
    while(ss >> num){
        arr.push_back(num);
    }
    // 读取第二行输入的K值
    int K;
    cin >> K;
    // 统计小于K的元素数量
    int count = 0;
    for(auto &x: arr){
        if(x < K) count++;
    }
    // 如果没有小于K的元素或全部小于K,交换次数为0
    if(count == 0 || count == arr.size()){
        cout << 0;
        return 0;
    }
    // 初始化滑动窗口
    int current_count = 0;
    for(int i=0;i<count;i++){
        if(arr[i] < K) current_count++;
    }
    int max_count = current_count;
    // 滑动窗口遍历
    for(int i=count;i<arr.size();i++){
        // 移出窗口的元素
        if(arr[i - count] < K) current_count--;
        // 新进入窗口的元素
        if(arr[i] < K) current_count++;
        // 更新最大值
        max_count = max(max_count, current_count);
    }
    // 计算最少交换次数
    int min_swaps = count - max_count;
    cout << min_swaps;
}
python
# 读取第一行输入的数组
import sys
def main():
    import sys
    arr = list(map(int, sys.stdin.readline().strip().split()))
    # 读取第二行输入的K值
    K = int(sys.stdin.readline())
    # 统计小于K的元素数量
    count = sum(1 for x in arr if x < K)
    # 如果没有小于K的元素或全部小于K,交换次数为0
    if count == 0 or count == len(arr):
        print(0)
        return
    # 初始化滑动窗口
    current_count = sum(1 for x in arr[:count] if x < K)
    max_count = current_count
    # 滑动窗口遍历
    for i in range(count, len(arr)):
        if arr[i - count] < K:
            current_count -=1
        if arr[i] < K:
            current_count +=1
        if current_count > max_count:
            max_count = current_count
    # 计算最少交换次数
    min_swaps = count - max_count
    print(min_swaps)
if __name__ == "__main__":
    main()
java
import java.util.*;
public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        // 读取第一行输入的数组
        String line = sc.nextLine();
        String[] parts = line.trim().split("\\s+");
        int[] arr = new int[parts.length];
        for(int i=0;i<parts.length;i++) {
            arr[i] = Integer.parseInt(parts[i]);
        }
        // 读取第二行输入的K值
        int K = sc.nextInt();
        // 统计小于K的元素数量
        int count = 0;
        for(int num : arr){
            if(num < K) count++;
        }
        // 如果没有小于K的元素或全部小于K,交换次数为0
        if(count ==0 || count == arr.length){
            System.out.println(0);
            return;
        }
        // 初始化滑动窗口
        int current_count = 0;
        for(int i=0;i<count;i++){
            if(arr[i] < K) current_count++;
        }
        int max_count = current_count;
        // 滑动窗口遍历
        for(int i=count;i<arr.length;i++){
            // 移出窗口的元素
            if(arr[i - count] < K) current_count--;
            // 新进入窗口的元素
            if(arr[i] < K) current_count++;
            // 更新最大值
            if(current_count > max_count){
                max_count = current_count;
            }
        }
        // 计算最少交换次数
        int min_swaps = count - max_count;
        System.out.println(min_swaps);
    }
}
        题目描述
给出数字 K ,请输出所有结果小于 K 的整数组合到一起的最少交换次数。
组合一起是指满足条件的数字相邻,不要求相邻后在数组中的位置。
数据范围:
−100<=K<=100
−100<= 数组中数值 <=100
输入描述
第一行输入数组:1 3 1 4 0
第二行输入 K 数值:2
输出描述
第一行输出最少交换次数:1
样例1
输入
1 3 1 4 0
2
输出
1
说明
小于 2 的表达式是 1 1 0, 共三种可能将所有符合要求数字组合一起,最少交换 1 次。