最少交换次数

一、题目描述

给出数字K,请输出所有结果小于K的整数组合到一起的最少交换次数。

组合一起是指满足条件的数字相邻,不要求相邻后在数组中的位置。

二、输入输出描述

1. 输入描述

  • 第一行输入一个整数数组(-100 <= 数组中数值 <= 100),元素以空格分隔;
  • 第二行输入一个目标整数 K(-100 <= K <= 100)。

2. 输出描述

输出一个整数,表示将所有结果小于K的整数组合在一起的最少交换次数。

三、示例

|----|-------------------------------------------|
| 输入 | 1 3 1 4 0 2 |
| 输出 | 1 |
| 说明 | 小于2的表达式是1 1 0, 共三种可能将所有符合要求数字组合一起,最少交换1次。 |

四、解题思路

1. 核心思想

将 "让所有小于 k 的元素集中" 的问题,转化为 "找到长度为count(小于 k 的元素总数)的子数组,其中包含的'大于等于 k 的元素个数最少'"------ 因为这个最少个数就是该子数组需要交换的次数(用窗口外的小于 k 的元素替换窗口内的大于等于 k 的元素)。

2. 问题本质分析

问题本质是子数组筛选优化

  • 所有小于 k 的元素必须形成连续子数组,该子数组的长度固定为count(小于 k 的元素总数),无法改变。
  • 交换次数的本质:窗口内 "非目标元素"(≥k)的个数(需要用窗口外的 "目标元素"(<k)替换它们,每替换 1 个就是 1 次交换)。
  • 因此,问题转化为:在所有长度为count的子数组中,找到 "非目标元素个数最少" 的子数组,其个数即为最小交换次数。
3. 核心逻辑
  • 固定窗口长度:窗口长度 = 小于 k 的元素总数count(只有这个长度的窗口能容纳所有目标元素)。
  • 初始窗口计数:计算第一个窗口(前count个元素)的非目标元素个数(初始交换次数)。
  • 滑动窗口优化:通过滑动窗口动态更新窗口内的非目标元素个数,避免重复遍历(时间复杂度从 O (n²) 优化到 O (n)),最终找到最小值。
4. 步骤拆解
  1. 输入解析与预处理

    • 读取数组nums和目标值k
    • 统计数组中小于 k 的元素总数count
    • 特殊情况:若count == 1,直接输出 0(无需交换)。
  2. 计算初始窗口的交换次数

    • 遍历数组前count个元素,统计其中≥k 的元素个数,作为初始交换次数minSwapCount(同时赋值给临时变量tmpSwapCount用于滑动更新)。
  3. 滑动窗口动态更新

    • 遍历数组从索引count到末尾(窗口右边界):
      • 确定当前窗口的左边界(j - countj为当前右边界)。
      • 对比左边界元素和右边界元素的类型(是否 < k),更新tmpSwapCount
      • tmpSwapCount更新minSwapCount(保留最小值)。
  4. 输出结果

    • 输出minSwapCount,即最少交换次数。

五、代码实现

java 复制代码
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        // 使用Scanner读取一行输入
        String numsStr = scanner.nextLine();
        // 按空格分割字符串并转换为整数数组
        String[] numParts = numsStr.split(" ");
        int[] nums = new int[numParts.length];
        for (int i = 0; i < numParts.length; i++) {
            nums[i] = Integer.parseInt(numParts[i]);
        }
        // 读取一个整数k
        int k = scanner.nextInt();
        // 计算数组中小于k的元素数量
        int count = 0;
        for (int num : nums) {
            if (num < k) {
                count++;
            }
        }
        // 如果小于k的元素数量为1,直接输出0
        if (count == 1) {
            System.out.println(0);
            return;
        }
        // 计算最少交换次数
        int minSwapCount = 0;
        for (int i = 0; i < count; i++) {
            if (nums[i] >= k) {
                minSwapCount++;
            }
        }
        int tmpSwapCount = minSwapCount;
        // 使用滑动窗口更新最小交换次数
        for (int j = count; j < nums.length; j++) {
            int preLeft = j - count;
            int curRight = j;
            if (nums[preLeft] >= k && nums[curRight] < k) {
                tmpSwapCount--;
            } else if (nums[preLeft] < k && nums[curRight] >= k) {
                tmpSwapCount++;
            }
            minSwapCount = Math.min(minSwapCount, tmpSwapCount);
        }
        // 输出最终的最小交换次数
        System.out.println(minSwapCount);
    }
}
相关推荐
深邃-17 小时前
【数据结构与算法】-二叉树(2):实现顺序结构二叉树(堆的实现),向上调整算法,向下调整算法,堆排序,TOP-K问题
数据结构·算法·二叉树·排序算法·堆排序··top-k
咸鱼2.017 小时前
【java入门到放弃】Dubbo
java·开发语言·dubbo
We་ct20 小时前
LeetCode 5. 最长回文子串:DP + 中心扩展
前端·javascript·算法·leetcode·typescript
JAVA面经实录9171 天前
Java企业级工程化·终极完整版背诵手册(无遗漏、全覆盖、面试+落地通用)
java·开发语言·面试
王老师青少年编程1 天前
csp信奥赛C++高频考点专项训练之贪心算法 --【哈夫曼贪心】:合并果子
c++·算法·贪心·csp·信奥赛·哈夫曼贪心·合并果子
叼烟扛炮1 天前
C++第二讲:类和对象(上)
数据结构·c++·算法·类和对象·struct·实例化
天疆说1 天前
【哈密顿力学】深入解读航天器交会最优控制中的Hamilton函数
人工智能·算法·机器学习
许彰午1 天前
CacheSQL(二):主从复制——OpLog 环形缓冲区与故障自动恢复
java·数据库·缓存
wuweijianlove1 天前
关于算法设计中的代价函数优化与约束求解的技术7
算法
小程故事多_801 天前
[大模型面试系列] 多轮对话 Agent 设计实战(含窗口优化 + 工具调用精髓)
人工智能·面试·职场和发展