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)
这道题的思路如下:
- 首先要想到如何找到能够让数组变成最后满足条件的最小代价,抛开回文数的条件限制。在一个按序排序的数组中,显然位于最小数和最大数之间的数才能让代价最小,离最小数越小或者离最大数越大代价就越大,但如果只针对最小数和最大数,在这两个数之间的数的代价之和花费是相同的,所以可以不考虑这两个极数,缩小范围。最终,如果数组大小是奇数,离该数越近则代价越小;如果是偶数,则是两个数之间即可。也就是贪心,配合数学中位数。
- 其次,要预处理所有的回文数,然后用二分找到满足上述代价最小的数。
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);
}
}