Woodyiiiiiii / LeetCode

My private record of Leetcode solution

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Leetcode 2967. Minimum Cost to Make Array Equalindromic

Woodyiiiiiii opened this issue · comments

2967. Minimum Cost to Make Array Equalindromic

2967. Minimum Cost to Make Array Equalindromic
预处理回文数+中位数贪心(Python/Java/C++/Go)

这道题的思路如下:

  1. 首先要想到如何找到能够让数组变成最后满足条件的最小代价,抛开回文数的条件限制。在一个按序排序的数组中,显然位于最小数和最大数之间的数才能让代价最小,离最小数越小或者离最大数越大代价就越大,但如果只针对最小数和最大数,在这两个数之间的数的代价之和花费是相同的,所以可以不考虑这两个极数,缩小范围。最终,如果数组大小是奇数,离该数越近则代价越小;如果是偶数,则是两个数之间即可。也就是贪心,配合数学中位数
  2. 其次,要预处理所有的回文数,然后用二分找到满足上述代价最小的数。
class Solution {
    
    static List<Integer> palindromes = new ArrayList<>();
    static int N;

    static {
        for (int i = 1; i <= 9; i++) {
            palindromes.add(i);
        }
        for (int i = 2; i <= 9; i++) {
            for (int j = (int) Math.pow(10, i / 2 - 1); j < Math.pow(10, i / 2); j++) {
                String s = String.valueOf(j);
                StringBuilder sb = new StringBuilder(s);
                StringBuilder rv = new StringBuilder(sb);
                rv.reverse();
                if (i % 2 == 0) {
                    palindromes.add(Integer.parseInt(sb + rv.toString()));
                } else {
                    for (int k = 0; k <= 9; k++) {
                        palindromes.add(Integer.parseInt(sb.toString() + k + rv));
                    }
                }
            }
        }
        N = palindromes.size();
    }

    public long minimumCost(int[] nums) {
        int n = nums.length;
        Arrays.sort(nums);

        if (n % 2 != 0) {
            int mid = nums[n / 2];
            int low = low(mid), high = high(mid);
            return Math.min(cost(nums, low), cost(nums, high));
        } else {
            int mid1 = nums[n / 2], mid2 = nums[n / 2 - 1];
            int high1 = high(mid2);
            int low2 = low(mid1);
            return Math.min(cost(nums, low2), cost(nums, high1));
        }
    }

    private long cost(int[] nums, long x) {
        long res = 0;
        for (int num : nums) {
            res += Math.abs(x - num);
        }
        return res;
    }

    private int low(int x) {
        int l = 0, r = N;
        while (l < r) {
            int m = (l + r) >> 1;
            if (palindromes.get(m) > x) {
                r = m;
            } else {
                l = m + 1;
            }
        }
        return palindromes.get(l - 1);
    }

    private int high(int x) {
        int l = 0, r = N;
        while (l < r) {
            int m = (l + r) >> 1;
            if (palindromes.get(m) < x) {
                l = m + 1;
            } else {
                r = m;
            }
        }
        return l < N ? palindromes.get(l) : palindromes.get(l - 1);
    }
    
}