最少交换次数--(滑动窗口方案)

本文介绍了一种使用滑动窗口方法解决数组中将小于k的整数组合到一起所需的最小交换次数问题。主要思路是通过计算前缀和,找到满足条件的子数组,统计0的个数作为交换次数。并提供了相关题目和解题模板。

题目要求:

  1. 给出一个数组nums,你需要通过交换位置,将数组中 任何位置 上的 小于 k 的整数 组合到一起,并返回所有可能中所需最少的交换次数。
  2. 输出将数组A中小于k的整数组合到一起的最小交换次数。
  3. 组合在一起是指满足条件的数字相邻,不要求在数组中的位置相邻。

主要想法:

滑动窗口的思想
根据终点状态(交换后,1 都连在一起),逆推检查过程,所有 1 连在一起就意味着「原数组中 k 个 1」刚好可以让数组中长度为 k 的子数组的和为 k

  1. (使用前缀和可快速得到所有长度为 k 的区域中的数值之和 sum,k - sum 即为移动次数)
  2. 或者 :统计窗口中0的个数即为交换的次数

代码:

var minChange = function (nums, k) {
   
   
    // count表示符合条件的1的个数, index为存放符合条件位置的数组,times为最少交换次数
    let count = 0, index = [], times = Infinite;
    // 遍历nums得到index数组和count
    for(let i = 0; i < nums.length; i++) {
   
   
        if (nums[i] < k) {
   
   
            count++;
            index[i] = 1;
        }
    }
    // 当全都不符合或者全都符合条件,最少交换次数0
    if (!index.length || count === nums.length) return times;
    // 此处利用滑动窗口思想,拿到当前位置将数据组合在一起所需交换次数changeTime,
    // 将它和times作比较,取最小交换次数
    for(let i = 0; i < index.length - count; i++) {
   
   
        // 1. count - sum;
        let changeTime = count - index.slice(i, count).reduce((a, b) => a+b);
        // 或者 :统计窗口中0的个数即为交换的次数
        // let changeTime = 0;
        // for(let j of index.slice(i, count)) {
   
   
        //     !j ? changeTime++ : null;
        // }
        times = Math.min(changeTime, times);
    }
    return times;
}
console.log(minChange([1,3,1,4,0], 2))

### 华为OD模式 E卷 算法 最小交换次数 数据结构 #### 问题解析 华为OD模式下的E卷涉及的最小交换次数问题是典型的算法优化问题,通常与数组操作、排序以及特定条件下元素位置调整有关。该问题的核心在于如何通过最少的操作次数实现目标状态。具体到引用中的描述[^2],其核心逻辑是从给定范围内找到满足条件的最佳子区间。 此类问题一般可以通过滑动窗口技术解决,这是一种高效的线性时间复杂度方法,适用于处理连续子序列的相关约束问题。以下是针对这一问题的具体解决方案--- #### 解决方案设计 为了求解最小交换次数问题,可以采用如下策略: 1. **定义变量** 定义 `count` 表示需要保留的目标数量;`k` 是判断标准阈值;`minIdx` 和 `maxIdx` 则分别表示范围内的起始和结束索引。 2. **预处理输入数据** 遍历整个数组并统计大于 `k` 的元素总数作为初始交换成本。这一步骤有助于后续比较不同子区间的优劣。 3. **应用滑动窗口算法** 使用双指针维护一个固定大小为 `count` 的窗口,动态更新其中不符合条件的元素数目(即小于等于 `k` 的部分)。每次移动右边界扩展新区域的同时收缩左边界保持窗口尺寸不变。 4. **记录最优结果** 记录过程中遇到的最大符合条件的数量对应的最小不合法项数差额,从而得出全局意义上的最佳答案。 --- #### 示例代码实现 以下是基于Python语言的一种可能实现方式: ```python def min_swaps_to_cluster(arr, k, count): n = len(arr) # Step 1: Count the total number of elements greater than 'k' valid_count_total = sum(1 for num in arr if num > k) # If there are fewer valid numbers than required by 'count', it's impossible. if valid_count_total < count: return -1 # Step 2: Initialize sliding window variables current_valid_in_window = 0 max_valid_in_any_window = 0 # Sliding Window Technique for right in range(n): if arr[right] > k: current_valid_in_window += 1 # Ensure that our window size does not exceed 'count'. if right >= count: if arr[right - count] > k: current_valid_in_window -= 1 # Update maximum valid items found within any window so far. if right >= count - 1: max_valid_in_any_window = max(max_valid_in_any_window, current_valid_in_window) # The minimum swaps needed is simply how many more we need to reach 'count' from best case scenario. return count - max_valid_in_any_window # Example Usage if __name__ == "__main__": array_example = [2, 8, 5, 6, 9, 3] threshold_k = 4 target_count = 3 result = min_swaps_to_cluster(array_example, threshold_k, target_count) print(f"Minimum Swaps Required: {result}") ``` 上述程序实现了利用滑动窗口寻找指定长度内最大有效数值的方法,并据此推导出所需的最小交换次数[^2]。 --- #### 复杂度分析 - 时间复杂度:O(N),因为只需遍历一次数组完成所有必要计算。 - 空间复杂度:O(1),除了几个计数器外无需额外存储空间。 这种高效的方式非常适合大规模数据集上的快速评估需求。 --- #### 总结 综上所述,对于华为OD模式下关于E卷中提到的最小交换次数问题,借助滑动窗口技巧能够优雅而简洁地解决问题。这种方法不仅具备理论上的优越性能表现,而且易于理解和实际部署实施。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值