diff --git a/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/README.md b/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/README.md index d72a88ca8090e..2c4c5cf39502c 100644 --- a/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/README.md +++ b/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/README.md @@ -64,6 +64,14 @@ +**方法一:预处理 + 排序 + 二分查找** + +题目中回文数的范围是 $[1, 10^9]$,回文数由于对称性,我们可以在 $[1, 10^5]$ 的范围内枚举,然后将其翻转后拼接,得到所有的回文数,注意,如果是奇数长度的回文数,我们在翻转前要去掉最后一位。预处理得到的回文数数组记为 $ps$。我们对数组 $ps$ 进行排序。 + +接下来,我们对数组 $nums$ 进行排序,然后取 $nums$ 的中位数 $x$,我们只需要通过二分查找,在回文数组 $ps$ 中,找到一个与 $x$ 最接近的数,然后计算 $nums$ 变成这个数的代价,即可得到答案。 + +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(M)$。其中 $n$ 是数组 $nums$ 的长度,而 $M$ 是回文数组 $ps$ 的长度。 + ### **Python3** @@ -71,7 +79,24 @@ ```python - +ps = [] +for i in range(1, 10**5 + 1): + s = str(i) + t1 = s[::-1] + t2 = s[:-1][::-1] + ps.append(int(s + t1)) + ps.append(int(s + t2)) +ps.sort() + + +class Solution: + def minimumCost(self, nums: List[int]) -> int: + def f(x: int) -> int: + return sum(abs(v - x) for v in nums) + + nums.sort() + i = bisect_left(ps, nums[len(nums) // 2]) + return min(f(ps[j]) for j in range(i - 1, i + 2) if 0 <= j < len(ps)) ``` ### **Java** @@ -79,19 +104,190 @@ ```java - +public class Solution { + private static long[] ps; + private int[] nums; + + static { + ps = new long[2 * (int) 1e5]; + for (int i = 1; i <= 1e5; i++) { + String s = Integer.toString(i); + String t1 = new StringBuilder(s).reverse().toString(); + String t2 = new StringBuilder(s.substring(0, s.length() - 1)).reverse().toString(); + ps[2 * i - 2] = Long.parseLong(s + t1); + ps[2 * i - 1] = Long.parseLong(s + t2); + } + Arrays.sort(ps); + } + + public long minimumCost(int[] nums) { + this.nums = nums; + Arrays.sort(nums); + int i = Arrays.binarySearch(ps, nums[nums.length / 2]); + i = i < 0 ? -i - 1 : i; + long ans = 1L << 60; + for (int j = i - 1; j <= i + 1; j++) { + if (0 <= j && j < ps.length) { + ans = Math.min(ans, f(ps[j])); + } + } + return ans; + } + + private long f(long x) { + long ans = 0; + for (int v : nums) { + ans += Math.abs(v - x); + } + return ans; + } +} ``` ### **C++** ```cpp - +using ll = long long; + +ll ps[2 * 100000]; + +int init = [] { + for (int i = 1; i <= 100000; i++) { + string s = to_string(i); + string t1 = s; + reverse(t1.begin(), t1.end()); + string t2 = s.substr(0, s.length() - 1); + reverse(t2.begin(), t2.end()); + ps[2 * i - 2] = stoll(s + t1); + ps[2 * i - 1] = stoll(s + t2); + } + sort(ps, ps + 2 * 100000); + return 0; +}(); + +class Solution { +public: + long long minimumCost(vector& nums) { + sort(nums.begin(), nums.end()); + int i = lower_bound(ps, ps + 2 * 100000, nums[nums.size() / 2]) - ps; + auto f = [&](ll x) { + ll ans = 0; + for (int& v : nums) { + ans += abs(v - x); + } + return ans; + }; + ll ans = LLONG_MAX; + for (int j = i - 1; j <= i + 1; j++) { + if (0 <= j && j < 2 * 100000) { + ans = min(ans, f(ps[j])); + } + } + return ans; + } +}; ``` ### **Go** ```go +var ps [2 * 100000]int64 + +func init() { + for i := 1; i <= 100000; i++ { + s := strconv.Itoa(i) + t1 := reverseString(s) + t2 := reverseString(s[:len(s)-1]) + ps[2*i-2], _ = strconv.ParseInt(s+t1, 10, 64) + ps[2*i-1], _ = strconv.ParseInt(s+t2, 10, 64) + } + sort.Slice(ps[:], func(i, j int) bool { + return ps[i] < ps[j] + }) +} + +func reverseString(s string) string { + cs := []rune(s) + for i, j := 0, len(cs)-1; i < j; i, j = i+1, j-1 { + cs[i], cs[j] = cs[j], cs[i] + } + return string(cs) +} + +func minimumCost(nums []int) int64 { + sort.Ints(nums) + i := sort.Search(len(ps), func(i int) bool { + return ps[i] >= int64(nums[len(nums)/2]) + }) + + f := func(x int64) int64 { + var ans int64 + for _, v := range nums { + ans += int64(abs(int(x - int64(v)))) + } + return ans + } + + ans := int64(math.MaxInt64) + for j := i - 1; j <= i+1; j++ { + if 0 <= j && j < len(ps) { + ans = min(ans, f(ps[j])) + } + } + return ans +} + +func abs(x int) int { + if x < 0 { + return -x + } + return x +} +``` +### **TypeScript** + +```ts +const ps = Array(2e5).fill(0); + +const init = (() => { + for (let i = 1; i <= 1e5; ++i) { + const s: string = i.toString(); + const t1: string = s.split('').reverse().join(''); + const t2: string = s.slice(0, -1).split('').reverse().join(''); + ps[2 * i - 2] = parseInt(s + t1, 10); + ps[2 * i - 1] = parseInt(s + t2, 10); + } + ps.sort((a, b) => a - b); +})(); + +function minimumCost(nums: number[]): number { + const search = (x: number): number => { + let [l, r] = [0, ps.length]; + while (l < r) { + const mid = (l + r) >> 1; + if (ps[mid] >= x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + }; + const f = (x: number): number => { + return nums.reduce((acc, v) => acc + Math.abs(v - x), 0); + }; + + nums.sort((a, b) => a - b); + const i: number = search(nums[nums.length >> 1]); + let ans: number = Number.MAX_SAFE_INTEGER; + for (let j = i - 1; j <= i + 1; j++) { + if (j >= 0 && j < ps.length) { + ans = Math.min(ans, f(ps[j])); + } + } + return ans; +} ``` ### **...** diff --git a/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/README_EN.md b/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/README_EN.md index 2e9b90c469847..7d70b0530e373 100644 --- a/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/README_EN.md +++ b/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/README_EN.md @@ -58,30 +58,226 @@ It can be shown that changing all elements to any palindromic number other than ## Solutions +**Solution 1: Preprocessing + Sorting + Binary Search** + +The range of palindrome numbers in the problem is $[1, 10^9]$. Due to the symmetry of palindrome numbers, we can enumerate in the range of $[1, 10^5]$, then reverse and concatenate them to get all palindrome numbers. Note that if it is an odd-length palindrome number, we need to remove the last digit before reversing. The array of palindrome numbers obtained by preprocessing is denoted as $ps$. We sort the array $ps$. + +Next, we sort the array $nums$ and take the median $x$ of $nums$. We only need to find a number in the palindrome array $ps$ that is closest to $x$ through binary search, and then calculate the cost of $nums$ becoming this number to get the answer. + +The time complexity is $O(n \times \log n)$, and the space complexity is $O(M)$. Here, $n$ is the length of the array $nums$, and $M$ is the length of the palindrome array $ps$. + ### **Python3** ```python - +ps = [] +for i in range(1, 10**5 + 1): + s = str(i) + t1 = s[::-1] + t2 = s[:-1][::-1] + ps.append(int(s + t1)) + ps.append(int(s + t2)) +ps.sort() + + +class Solution: + def minimumCost(self, nums: List[int]) -> int: + def f(x: int) -> int: + return sum(abs(v - x) for v in nums) + + nums.sort() + i = bisect_left(ps, nums[len(nums) // 2]) + return min(f(ps[j]) for j in range(i - 1, i + 2) if 0 <= j < len(ps)) ``` ### **Java** ```java - +public class Solution { + private static long[] ps; + private int[] nums; + + static { + ps = new long[2 * (int) 1e5]; + for (int i = 1; i <= 1e5; i++) { + String s = Integer.toString(i); + String t1 = new StringBuilder(s).reverse().toString(); + String t2 = new StringBuilder(s.substring(0, s.length() - 1)).reverse().toString(); + ps[2 * i - 2] = Long.parseLong(s + t1); + ps[2 * i - 1] = Long.parseLong(s + t2); + } + Arrays.sort(ps); + } + + public long minimumCost(int[] nums) { + this.nums = nums; + Arrays.sort(nums); + int i = Arrays.binarySearch(ps, nums[nums.length / 2]); + i = i < 0 ? -i - 1 : i; + long ans = 1L << 60; + for (int j = i - 1; j <= i + 1; j++) { + if (0 <= j && j < ps.length) { + ans = Math.min(ans, f(ps[j])); + } + } + return ans; + } + + private long f(long x) { + long ans = 0; + for (int v : nums) { + ans += Math.abs(v - x); + } + return ans; + } +} ``` ### **C++** ```cpp - +using ll = long long; + +ll ps[2 * 100000]; + +int init = [] { + for (int i = 1; i <= 100000; i++) { + string s = to_string(i); + string t1 = s; + reverse(t1.begin(), t1.end()); + string t2 = s.substr(0, s.length() - 1); + reverse(t2.begin(), t2.end()); + ps[2 * i - 2] = stoll(s + t1); + ps[2 * i - 1] = stoll(s + t2); + } + sort(ps, ps + 2 * 100000); + return 0; +}(); + +class Solution { +public: + long long minimumCost(vector& nums) { + sort(nums.begin(), nums.end()); + int i = lower_bound(ps, ps + 2 * 100000, nums[nums.size() / 2]) - ps; + auto f = [&](ll x) { + ll ans = 0; + for (int& v : nums) { + ans += abs(v - x); + } + return ans; + }; + ll ans = LLONG_MAX; + for (int j = i - 1; j <= i + 1; j++) { + if (0 <= j && j < 2 * 100000) { + ans = min(ans, f(ps[j])); + } + } + return ans; + } +}; ``` ### **Go** ```go +var ps [2 * 100000]int64 + +func init() { + for i := 1; i <= 100000; i++ { + s := strconv.Itoa(i) + t1 := reverseString(s) + t2 := reverseString(s[:len(s)-1]) + ps[2*i-2], _ = strconv.ParseInt(s+t1, 10, 64) + ps[2*i-1], _ = strconv.ParseInt(s+t2, 10, 64) + } + sort.Slice(ps[:], func(i, j int) bool { + return ps[i] < ps[j] + }) +} + +func reverseString(s string) string { + cs := []rune(s) + for i, j := 0, len(cs)-1; i < j; i, j = i+1, j-1 { + cs[i], cs[j] = cs[j], cs[i] + } + return string(cs) +} + +func minimumCost(nums []int) int64 { + sort.Ints(nums) + i := sort.Search(len(ps), func(i int) bool { + return ps[i] >= int64(nums[len(nums)/2]) + }) + + f := func(x int64) int64 { + var ans int64 + for _, v := range nums { + ans += int64(abs(int(x - int64(v)))) + } + return ans + } + + ans := int64(math.MaxInt64) + for j := i - 1; j <= i+1; j++ { + if 0 <= j && j < len(ps) { + ans = min(ans, f(ps[j])) + } + } + return ans +} + +func abs(x int) int { + if x < 0 { + return -x + } + return x +} +``` +### **TypeScript** + +```ts +const ps = Array(2e5).fill(0); + +const init = (() => { + for (let i = 1; i <= 1e5; ++i) { + const s: string = i.toString(); + const t1: string = s.split('').reverse().join(''); + const t2: string = s.slice(0, -1).split('').reverse().join(''); + ps[2 * i - 2] = parseInt(s + t1, 10); + ps[2 * i - 1] = parseInt(s + t2, 10); + } + ps.sort((a, b) => a - b); +})(); + +function minimumCost(nums: number[]): number { + const search = (x: number): number => { + let [l, r] = [0, ps.length]; + while (l < r) { + const mid = (l + r) >> 1; + if (ps[mid] >= x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + }; + const f = (x: number): number => { + return nums.reduce((acc, v) => acc + Math.abs(v - x), 0); + }; + + nums.sort((a, b) => a - b); + const i: number = search(nums[nums.length >> 1]); + let ans: number = Number.MAX_SAFE_INTEGER; + for (let j = i - 1; j <= i + 1; j++) { + if (j >= 0 && j < ps.length) { + ans = Math.min(ans, f(ps[j])); + } + } + return ans; +} ``` ### **...** diff --git a/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/Solution.cpp b/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/Solution.cpp new file mode 100644 index 0000000000000..923c31f196570 --- /dev/null +++ b/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/Solution.cpp @@ -0,0 +1,39 @@ +using ll = long long; + +ll ps[2 * 100000]; + +int init = [] { + for (int i = 1; i <= 100000; i++) { + string s = to_string(i); + string t1 = s; + reverse(t1.begin(), t1.end()); + string t2 = s.substr(0, s.length() - 1); + reverse(t2.begin(), t2.end()); + ps[2 * i - 2] = stoll(s + t1); + ps[2 * i - 1] = stoll(s + t2); + } + sort(ps, ps + 2 * 100000); + return 0; +}(); + +class Solution { +public: + long long minimumCost(vector& nums) { + sort(nums.begin(), nums.end()); + int i = lower_bound(ps, ps + 2 * 100000, nums[nums.size() / 2]) - ps; + auto f = [&](ll x) { + ll ans = 0; + for (int& v : nums) { + ans += abs(v - x); + } + return ans; + }; + ll ans = LLONG_MAX; + for (int j = i - 1; j <= i + 1; j++) { + if (0 <= j && j < 2 * 100000) { + ans = min(ans, f(ps[j])); + } + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/Solution.go b/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/Solution.go new file mode 100644 index 0000000000000..3f6b36621dcbd --- /dev/null +++ b/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/Solution.go @@ -0,0 +1,52 @@ +var ps [2 * 100000]int64 + +func init() { + for i := 1; i <= 100000; i++ { + s := strconv.Itoa(i) + t1 := reverseString(s) + t2 := reverseString(s[:len(s)-1]) + ps[2*i-2], _ = strconv.ParseInt(s+t1, 10, 64) + ps[2*i-1], _ = strconv.ParseInt(s+t2, 10, 64) + } + sort.Slice(ps[:], func(i, j int) bool { + return ps[i] < ps[j] + }) +} + +func reverseString(s string) string { + cs := []rune(s) + for i, j := 0, len(cs)-1; i < j; i, j = i+1, j-1 { + cs[i], cs[j] = cs[j], cs[i] + } + return string(cs) +} + +func minimumCost(nums []int) int64 { + sort.Ints(nums) + i := sort.Search(len(ps), func(i int) bool { + return ps[i] >= int64(nums[len(nums)/2]) + }) + + f := func(x int64) int64 { + var ans int64 + for _, v := range nums { + ans += int64(abs(int(x - int64(v)))) + } + return ans + } + + ans := int64(math.MaxInt64) + for j := i - 1; j <= i+1; j++ { + if 0 <= j && j < len(ps) { + ans = min(ans, f(ps[j])) + } + } + return ans +} + +func abs(x int) int { + if x < 0 { + return -x + } + return x +} \ No newline at end of file diff --git a/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/Solution.java b/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/Solution.java new file mode 100644 index 0000000000000..a5fcc83957b9c --- /dev/null +++ b/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/Solution.java @@ -0,0 +1,38 @@ +public class Solution { + private static long[] ps; + private int[] nums; + + static { + ps = new long[2 * (int) 1e5]; + for (int i = 1; i <= 1e5; i++) { + String s = Integer.toString(i); + String t1 = new StringBuilder(s).reverse().toString(); + String t2 = new StringBuilder(s.substring(0, s.length() - 1)).reverse().toString(); + ps[2 * i - 2] = Long.parseLong(s + t1); + ps[2 * i - 1] = Long.parseLong(s + t2); + } + Arrays.sort(ps); + } + + public long minimumCost(int[] nums) { + this.nums = nums; + Arrays.sort(nums); + int i = Arrays.binarySearch(ps, nums[nums.length / 2]); + i = i < 0 ? -i - 1 : i; + long ans = 1L << 60; + for (int j = i - 1; j <= i + 1; j++) { + if (0 <= j && j < ps.length) { + ans = Math.min(ans, f(ps[j])); + } + } + return ans; + } + + private long f(long x) { + long ans = 0; + for (int v : nums) { + ans += Math.abs(v - x); + } + return ans; + } +} \ No newline at end of file diff --git a/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/Solution.py b/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/Solution.py new file mode 100644 index 0000000000000..602f8df4810ee --- /dev/null +++ b/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/Solution.py @@ -0,0 +1,18 @@ +ps = [] +for i in range(1, 10**5 + 1): + s = str(i) + t1 = s[::-1] + t2 = s[:-1][::-1] + ps.append(int(s + t1)) + ps.append(int(s + t2)) +ps.sort() + + +class Solution: + def minimumCost(self, nums: List[int]) -> int: + def f(x: int) -> int: + return sum(abs(v - x) for v in nums) + + nums.sort() + i = bisect_left(ps, nums[len(nums) // 2]) + return min(f(ps[j]) for j in range(i - 1, i + 2) if 0 <= j < len(ps)) diff --git a/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/Solution.ts b/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/Solution.ts new file mode 100644 index 0000000000000..431112126f4db --- /dev/null +++ b/solution/2900-2999/2967.Minimum Cost to Make Array Equalindromic/Solution.ts @@ -0,0 +1,40 @@ +const ps = Array(2e5).fill(0); + +const init = (() => { + for (let i = 1; i <= 1e5; ++i) { + const s: string = i.toString(); + const t1: string = s.split('').reverse().join(''); + const t2: string = s.slice(0, -1).split('').reverse().join(''); + ps[2 * i - 2] = parseInt(s + t1, 10); + ps[2 * i - 1] = parseInt(s + t2, 10); + } + ps.sort((a, b) => a - b); +})(); + +function minimumCost(nums: number[]): number { + const search = (x: number): number => { + let [l, r] = [0, ps.length]; + while (l < r) { + const mid = (l + r) >> 1; + if (ps[mid] >= x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + }; + const f = (x: number): number => { + return nums.reduce((acc, v) => acc + Math.abs(v - x), 0); + }; + + nums.sort((a, b) => a - b); + const i: number = search(nums[nums.length >> 1]); + let ans: number = Number.MAX_SAFE_INTEGER; + for (let j = i - 1; j <= i + 1; j++) { + if (j >= 0 && j < ps.length) { + ans = Math.min(ans, f(ps[j])); + } + } + return ans; +}