简介
题目链接 Leetcode 1814. Count Nice Pairs in an Array
一旦看透题目的本质,这道题非常的简单。但是由于题目规定输入列表的尺寸在10的5次方这个范围,如下:
1 <= nums.length <= 10^5
0 <= nums[i] <= 10^9
会使解题者下意识的认为这题应该用堆栈(Heap),二分法,树之类的数据结构,但其实最终这题就是一个简单的O(N)
解法,非常意外。被误导的过程如下:
看到输入尺寸 -> 推断合理的时间复杂度 -> 利用时间复杂度找符合的解法和数据结构
。
所以,警惕输入尺寸带来先入为主的时间复杂度上的误导。尽管以上过程可以在多数时候帮助解题,但是不要被这样的模式限制自己的思维
注意:文章中一切注解皆为Python代码
理解题目
题目非常简单。给定一个列表,找出所有符合以下条件的对(Pairs),返回总共的对数,条件如下:
0 <= i < j < nums.length
nums[i] + rev(nums[j]) == nums[j] + rev(nums[i])
乍一看似乎只有O(N^2)
的解法,甚至想不出O(NlogN)
的解法,但其实简单的数学移项操作就能用O(N)
完成这个问题。
把原公式,通过移项变成如下公式:
nums[i] - rev(nums[i]) == nums[j] - rev(nums[j])
因此,实现O(N)
解法的步骤如下:
- 我们需要用
O(N)
做一个新的列表,把其中每一个数字都反过来 - 再对于每一个
nums[i] - rev(nums[i])
进行计数,这里可以用Python中的Counter
或者单纯的dict
- 接着对于每一个
nums[i] - rev(nums[i])
出现的频率,假定这个频率为freq
,那么可以形成的对数为freq * (freq-1)
- 最后返回对数总和即可
代码实现
class Solution:
def countNicePairs(self, nums: List[int]) -> int:
rev_nums = [int(str(num)[::-1]) for num in nums]
c = collections.Counter([i-j for i, j in zip(nums, rev_nums)])
return sum([freq * (freq-1) // 2 for _, freq in c.items() if freq > 1]) % int(1e9+7)
解题后的思考
经验固然重要,但不要被先入为主的经验限制了思考。