LeetCode 3265. Count Almost Equal Pairs I
weekly contest 412。
題目
輸入正整數陣列 nums。
若兩個整數 x, y 在執行以下操作最多一次後,能夠變得相等,則稱為幾乎相等:
- 選擇 x 或 y,並將選擇整數中的兩個數位交換。
求有多少滿足 i < j 的數對 (i, j) 且 nums[i] 和 nums[j] 幾乎相等。
注意:操作後的整數可以有前導零。
解法
前導零還挺麻煩的,例如 3 無法操作出其他結果,但是 30 可以操作成 03。
乾脆把整數轉成字串並補上前導零 (本題至多 7 位數字),這樣比較方便處理。
只有在兩字串的字元出現次數完全相等,且只有 0 或 2 個位置的字元不同時,才有可能相等。
時間複雜度 O(N^2 * log MX),其中 MX = max(nums)。
空間複雜度 O(log MX)。
class Solution:
def countPairs(self, nums: List[int]) -> int:
ans = 0
for i, x in enumerate(nums):
s = str(x).zfill(7)
for y in nums[:i]:
t = str(y).zfill(7)
diff = sum(c1 != c2 for c1, c2 in zip(s, t))
if Counter(s) == Counter(t) and diff <= 2:
ans += 1
return ans
上面方法會對同一個 nums[i] 重複處理好幾次,不太有效率。
每個元素是否能只處理一次?
試著從左到右枚舉 nums[j],暴力生成所有交換方式,並檢查是否存在於先前處理過的 nums[i] 之中。
注意先前提過的前導零問題,因此必需先排序,以利較小的元素優先處理。
時間複雜度 O(N log N + N (log MX)^3),其中 MX = max(nums)。
空間複雜度 O(N + (log MX)^2)。
class Solution:
def countPairs(self, nums: List[int]) -> int:
nums.sort()
ans = 0
d = Counter()
for x in nums:
for pat in all_pattern(x):
ans += d[pat]
d[x] += 1
return ans
def all_pattern(x):
a = list(str(x))
sz = len(a)
res = {x} # no swap
def swap(i, j):
a[i], a[j] = a[j], a[i]
def build():
res.add(int("".join(a)))
# 1 swap
for i in range(sz):
for j in range(i + 1, sz):
swap(i, j)
build()
swap(i, j)
return res