LC 2967. 使数组成为等数数组的最小代价

https://leetcode.cn/problems/minimum-cost-to-make-array-equalindromic/

大概可以分解成为3个部分:

题目还有两个优化:

  1. 回文数不用每次都计算。这个计算好像放在class init里面不行,还必须写在全局代码初始化里面。
  2. 可以根据 `nums` 最大最小值选择回文数,这个过程可以将许多回文数删除掉。

代码稍微有点乱,在 `cap_options` 里面还用了二分,不用二分时间会上来许多。

#!/usr/bin/env python
# coding:utf-8
# Copyright (C) dirlt
from typing import List


def gen_options(N):
    def reverse(x):
        ans = 0
        while x:
            ans = ans * 10 + x % 10
            x = x // 10
        return ans

    for x in range(10):
        yield x

    for sz in range(2, N):
        mid = sz // 2
        lower, upper = 10 ** (mid - 1), 10 ** mid
        if sz % 2 == 1:
            for head in range(lower, upper):
                tail = reverse(head)
                for x in range(10):
                    yield (head * 10 + x) * upper + tail
        else:
            for head in range(lower, upper):
                tail = reverse(head)
                yield head * upper + tail


OPTIONS = list(gen_options(10))


class Solution:
    def minimumCost(self, nums: List[int]) -> int:
        nums.sort()
        options = OPTIONS

        def cap_options():
            s, e = 0, len(options) - 1
            while s <= e:
                m = (s + e) // 2
                if options[m] > nums[0]:
                    e = m - 1
                else:
                    s = m + 1
            lower = e

            s, e = 0, len(options) - 1
            while s <= e:
                m = (s + e) // 2
                if options[m] < nums[-1]:
                    s = m + 1
                else:
                    e = m - 1
            upper = s
            return options[lower: upper + 1]

        capped_options = cap_options()
        acc = ans = sum(nums)

        left, last = 0, 0
        i = 0
        for x in capped_options:
            a, b = 0, 0
            acc += left * (x - last)
            while i < len(nums) and nums[i] <= x:
                left += 1
                a += abs(nums[i] - last)
                b += abs(nums[i] - x)
                i += 1
            acc -= a
            acc += b
            right = len(nums) - left
            acc -= right * (x - last)
            last = x

            ans = min(ans, acc)
            # print(x, acc)
        return ans