|
64 | 64 |
|
65 | 65 | <!-- 这里可写通用的实现逻辑 -->
|
66 | 66 |
|
| 67 | +**方法一:预处理 + 排序 + 二分查找** |
| 68 | + |
| 69 | +题目中回文数的范围是 $[1, 10^9]$,回文数由于对称性,我们可以在 $[1, 10^5]$ 的范围内枚举,然后将其翻转后拼接,得到所有的回文数,注意,如果是奇数长度的回文数,我们在翻转前要去掉最后一位。预处理得到的回文数数组记为 $ps$。我们对数组 $ps$ 进行排序。 |
| 70 | + |
| 71 | +接下来,我们对数组 $nums$ 进行排序,然后取 $nums$ 的中位数 $x$,我们只需要通过二分查找,在回文数组 $ps$ 中,找到一个与 $x$ 最接近的数,然后计算 $nums$ 变成这个数的代价,即可得到答案。 |
| 72 | + |
| 73 | +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(M)$。其中 $n$ 是数组 $nums$ 的长度,而 $M$ 是回文数组 $ps$ 的长度。 |
| 74 | + |
67 | 75 | <!-- tabs:start -->
|
68 | 76 |
|
69 | 77 | ### **Python3**
|
70 | 78 |
|
71 | 79 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
72 | 80 |
|
73 | 81 | ```python
|
74 |
| - |
| 82 | +ps = [] |
| 83 | +for i in range(1, 10**5 + 1): |
| 84 | + s = str(i) |
| 85 | + t1 = s[::-1] |
| 86 | + t2 = s[:-1][::-1] |
| 87 | + ps.append(int(s + t1)) |
| 88 | + ps.append(int(s + t2)) |
| 89 | +ps.sort() |
| 90 | + |
| 91 | + |
| 92 | +class Solution: |
| 93 | + def minimumCost(self, nums: List[int]) -> int: |
| 94 | + def f(x: int) -> int: |
| 95 | + return sum(abs(v - x) for v in nums) |
| 96 | + |
| 97 | + nums.sort() |
| 98 | + i = bisect_left(ps, nums[len(nums) // 2]) |
| 99 | + return min(f(ps[j]) for j in range(i - 1, i + 2) if 0 <= j < len(ps)) |
75 | 100 | ```
|
76 | 101 |
|
77 | 102 | ### **Java**
|
78 | 103 |
|
79 | 104 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
80 | 105 |
|
81 | 106 | ```java
|
82 |
| - |
| 107 | +public class Solution { |
| 108 | + private static long[] ps; |
| 109 | + private int[] nums; |
| 110 | + |
| 111 | + static { |
| 112 | + ps = new long[2 * (int) 1e5]; |
| 113 | + for (int i = 1; i <= 1e5; i++) { |
| 114 | + String s = Integer.toString(i); |
| 115 | + String t1 = new StringBuilder(s).reverse().toString(); |
| 116 | + String t2 = new StringBuilder(s.substring(0, s.length() - 1)).reverse().toString(); |
| 117 | + ps[2 * i - 2] = Long.parseLong(s + t1); |
| 118 | + ps[2 * i - 1] = Long.parseLong(s + t2); |
| 119 | + } |
| 120 | + Arrays.sort(ps); |
| 121 | + } |
| 122 | + |
| 123 | + public long minimumCost(int[] nums) { |
| 124 | + this.nums = nums; |
| 125 | + Arrays.sort(nums); |
| 126 | + int i = Arrays.binarySearch(ps, nums[nums.length / 2]); |
| 127 | + i = i < 0 ? -i - 1 : i; |
| 128 | + long ans = 1L << 60; |
| 129 | + for (int j = i - 1; j <= i + 1; j++) { |
| 130 | + if (0 <= j && j < ps.length) { |
| 131 | + ans = Math.min(ans, f(ps[j])); |
| 132 | + } |
| 133 | + } |
| 134 | + return ans; |
| 135 | + } |
| 136 | + |
| 137 | + private long f(long x) { |
| 138 | + long ans = 0; |
| 139 | + for (int v : nums) { |
| 140 | + ans += Math.abs(v - x); |
| 141 | + } |
| 142 | + return ans; |
| 143 | + } |
| 144 | +} |
83 | 145 | ```
|
84 | 146 |
|
85 | 147 | ### **C++**
|
86 | 148 |
|
87 | 149 | ```cpp
|
88 |
| - |
| 150 | +using ll = long long; |
| 151 | + |
| 152 | +ll ps[2 * 100000]; |
| 153 | + |
| 154 | +int init = [] { |
| 155 | + for (int i = 1; i <= 100000; i++) { |
| 156 | + string s = to_string(i); |
| 157 | + string t1 = s; |
| 158 | + reverse(t1.begin(), t1.end()); |
| 159 | + string t2 = s.substr(0, s.length() - 1); |
| 160 | + reverse(t2.begin(), t2.end()); |
| 161 | + ps[2 * i - 2] = stoll(s + t1); |
| 162 | + ps[2 * i - 1] = stoll(s + t2); |
| 163 | + } |
| 164 | + sort(ps, ps + 2 * 100000); |
| 165 | + return 0; |
| 166 | +}(); |
| 167 | + |
| 168 | +class Solution { |
| 169 | +public: |
| 170 | + long long minimumCost(vector<int>& nums) { |
| 171 | + sort(nums.begin(), nums.end()); |
| 172 | + int i = lower_bound(ps, ps + 2 * 100000, nums[nums.size() / 2]) - ps; |
| 173 | + auto f = [&](ll x) { |
| 174 | + ll ans = 0; |
| 175 | + for (int& v : nums) { |
| 176 | + ans += abs(v - x); |
| 177 | + } |
| 178 | + return ans; |
| 179 | + }; |
| 180 | + ll ans = LLONG_MAX; |
| 181 | + for (int j = i - 1; j <= i + 1; j++) { |
| 182 | + if (0 <= j && j < 2 * 100000) { |
| 183 | + ans = min(ans, f(ps[j])); |
| 184 | + } |
| 185 | + } |
| 186 | + return ans; |
| 187 | + } |
| 188 | +}; |
89 | 189 | ```
|
90 | 190 |
|
91 | 191 | ### **Go**
|
92 | 192 |
|
93 | 193 | ```go
|
| 194 | +var ps [2 * 100000]int64 |
| 195 | +
|
| 196 | +func init() { |
| 197 | + for i := 1; i <= 100000; i++ { |
| 198 | + s := strconv.Itoa(i) |
| 199 | + t1 := reverseString(s) |
| 200 | + t2 := reverseString(s[:len(s)-1]) |
| 201 | + ps[2*i-2], _ = strconv.ParseInt(s+t1, 10, 64) |
| 202 | + ps[2*i-1], _ = strconv.ParseInt(s+t2, 10, 64) |
| 203 | + } |
| 204 | + sort.Slice(ps[:], func(i, j int) bool { |
| 205 | + return ps[i] < ps[j] |
| 206 | + }) |
| 207 | +} |
| 208 | +
|
| 209 | +func reverseString(s string) string { |
| 210 | + cs := []rune(s) |
| 211 | + for i, j := 0, len(cs)-1; i < j; i, j = i+1, j-1 { |
| 212 | + cs[i], cs[j] = cs[j], cs[i] |
| 213 | + } |
| 214 | + return string(cs) |
| 215 | +} |
| 216 | +
|
| 217 | +func minimumCost(nums []int) int64 { |
| 218 | + sort.Ints(nums) |
| 219 | + i := sort.Search(len(ps), func(i int) bool { |
| 220 | + return ps[i] >= int64(nums[len(nums)/2]) |
| 221 | + }) |
| 222 | +
|
| 223 | + f := func(x int64) int64 { |
| 224 | + var ans int64 |
| 225 | + for _, v := range nums { |
| 226 | + ans += int64(abs(int(x - int64(v)))) |
| 227 | + } |
| 228 | + return ans |
| 229 | + } |
| 230 | +
|
| 231 | + ans := int64(math.MaxInt64) |
| 232 | + for j := i - 1; j <= i+1; j++ { |
| 233 | + if 0 <= j && j < len(ps) { |
| 234 | + ans = min(ans, f(ps[j])) |
| 235 | + } |
| 236 | + } |
| 237 | + return ans |
| 238 | +} |
| 239 | +
|
| 240 | +func abs(x int) int { |
| 241 | + if x < 0 { |
| 242 | + return -x |
| 243 | + } |
| 244 | + return x |
| 245 | +} |
| 246 | +``` |
94 | 247 |
|
| 248 | +### **TypeScript** |
| 249 | + |
| 250 | +```ts |
| 251 | +const ps = Array(2e5).fill(0); |
| 252 | + |
| 253 | +const init = (() => { |
| 254 | + for (let i = 1; i <= 1e5; ++i) { |
| 255 | + const s: string = i.toString(); |
| 256 | + const t1: string = s.split('').reverse().join(''); |
| 257 | + const t2: string = s.slice(0, -1).split('').reverse().join(''); |
| 258 | + ps[2 * i - 2] = parseInt(s + t1, 10); |
| 259 | + ps[2 * i - 1] = parseInt(s + t2, 10); |
| 260 | + } |
| 261 | + ps.sort((a, b) => a - b); |
| 262 | +})(); |
| 263 | + |
| 264 | +function minimumCost(nums: number[]): number { |
| 265 | + const search = (x: number): number => { |
| 266 | + let [l, r] = [0, ps.length]; |
| 267 | + while (l < r) { |
| 268 | + const mid = (l + r) >> 1; |
| 269 | + if (ps[mid] >= x) { |
| 270 | + r = mid; |
| 271 | + } else { |
| 272 | + l = mid + 1; |
| 273 | + } |
| 274 | + } |
| 275 | + return l; |
| 276 | + }; |
| 277 | + const f = (x: number): number => { |
| 278 | + return nums.reduce((acc, v) => acc + Math.abs(v - x), 0); |
| 279 | + }; |
| 280 | + |
| 281 | + nums.sort((a, b) => a - b); |
| 282 | + const i: number = search(nums[nums.length >> 1]); |
| 283 | + let ans: number = Number.MAX_SAFE_INTEGER; |
| 284 | + for (let j = i - 1; j <= i + 1; j++) { |
| 285 | + if (j >= 0 && j < ps.length) { |
| 286 | + ans = Math.min(ans, f(ps[j])); |
| 287 | + } |
| 288 | + } |
| 289 | + return ans; |
| 290 | +} |
95 | 291 | ```
|
96 | 292 |
|
97 | 293 | ### **...**
|
|
0 commit comments