小R的城市稳定性挑战| 豆包MarsCode AI刷题

12 阅读2分钟

问题描述

小R所在的国家有 𝑛n 个城市,每个城市的人口为 𝑎𝑖ai​。如果某个城市的人口不超过其他任何一个城市人口的两倍,那么这个城市就被认为是稳定的。国家可以对部分城市实施政策,从而改变它们的人口数量。你的任务是帮助小R找到最少需要对多少个城市进行人口修改,才能使所有城市都变得稳定。

例如:对于城市人口为 [1, 2, 3, 4] 的国家,最少需要对1个城市执行政策,才能使所有城市稳定。


测试样例

样例1:

输入:n = 4 ,a = [1, 2, 3, 4]
输出:1

样例2:

输入:n = 5 ,a = [1, 10, 20, 30, 40]
输出:2

样例3:

输入:n = 3 ,a = [100, 50, 200]
输出:1

思路分析

解题思路:

  1. 排序:首先,我们将城市的人口数组a进行排序。排序后,我们可以更容易地比较相邻城市的人口,从而判断是否满足稳定条件。
  2. 滑动窗口:使用滑动窗口的方法来找到最大的满足稳定条件的子数组长度。滑动窗口的左边界left和右边界right初始化为0。我们逐渐移动右边界right,对于每个新的right位置,我们检查当前窗口内的城市是否满足稳定条件。
  3. 调整左边界:如果当前窗口不满足稳定条件(即a[right] > 2 * a[left]),则我们需要移动左边界left,直到窗口内的城市再次满足稳定条件。
  4. 更新最大长度:每次移动右边界后,我们更新最大满足稳定条件的子数组长度maxValidLen
  5. 计算修改次数:最后,最小修改次数等于总城市数n减去最大满足稳定条件的子数组长度maxValidLen

感悟

  • 排序的妙用:排序是算法中常用的技巧,它可以简化很多问题的处理。在这个问题中,排序使得我们可以通过简单的相邻元素比较来检查条件,而无需复杂的嵌套循环或排序后的索引映射。
  • 双指针技巧:双指针是处理数组和链表问题时的一种高效技巧。通过两个指针的协同移动,可以在一次遍历中解决很多问题,如寻找最长子序列、子数组等。

代码实现

import java.util.Arrays;

public class Main {
    public static int solution(int n, int[] a) {
        Arrays.sort(a); 
        int left = 0; 
        int maxValidLen = 0; 
        for (int right = 0; right < n; right++) {
            while (left < n && a[right] > 2 * a[left]) {
                left++;
            }
            maxValidLen = Math.max(maxValidLen, right - left + 1);
        }
        return n - maxValidLen;
    }

    public static void main(String[] args) {
        System.out.println(solution(4, new int[]{1, 2, 3, 4}) == 1);
        System.out.println(solution(5, new int[]{1, 10, 20, 30, 40}) == 2);
        System.out.println(solution(3, new int[]{100, 50, 200}) == 1);
    }
}