1814-统计一个数组中好对子的数目

Raphael Liu Lv10

给你一个数组 nums ,数组中只包含非负整数。定义 rev(x) 的值为将整数 x 各个数字位反转得到的结果。比方说 rev(123) = 321rev(120) = 21 。我们称满足下面条件的下标对 (i, j)好的

  • 0 <= i < j < nums.length
  • nums[i] + rev(nums[j]) == nums[j] + rev(nums[i])

请你返回好下标对的数目。由于结果可能会很大,请将结果对 109 + 7 取余 后返回。

示例 1:

**输入:** nums = [42,11,1,97]
**输出:** 2
**解释:** 两个坐标对为:
 - (0,3):42 + rev(97) = 42 + 79 = 121, 97 + rev(42) = 97 + 24 = 121 。
 - (1,2):11 + rev(1) = 11 + 1 = 12, 1 + rev(11) = 1 + 11 = 12 。

示例 2:

**输入:** nums = [13,10,35,24,76]
**输出:** 4

提示:

  • 1 <= nums.length <= 105
  • 0 <= nums[i] <= 109

方法一:哈希表

思路与算法

首先题目给出一个下标从 0 开始长度为 n 的非负整数数组 nums,并给出「好下标对」的定义——对于某一个下标对 (i, j),0 \le i < j < n,若满足:

nums}[i] + \textit{rev}(\textit{nums}[j]) = \textit{nums}[j] + \textit{rev}(\textit{nums}[i]) \tag{1

则该下标对为「好下标对」。现在我们设:f(i) = \textit{nums}[i] - \textit{rev}(\textit{nums}[i]),则表达式 (1) 可以等价于:

f(i) = f(j) \tag{2

那么我们从左到右遍历数组 nums,并在遍历的过程用「哈希表」统计每一个位置 i,0 \le i < n 的 f(i) 的个数,则对于位置 j,0 \le j < n,以 j 结尾的「好下标对」的个数为此时「哈希表」中 f(j) 的数目。那么我们只需要在遍历时同时统计以每一个位置为结尾的「好下标对」数目即可。

代码

[sol1-Python3]
1
2
3
4
5
6
7
8
9
class Solution:
def countNicePairs(self, nums: List[int]) -> int:
res = 0
cnt = Counter()
for i in nums:
j = int(str(i)[::-1])
res += cnt[i - j]
cnt[i - j] += 1
return res % (10 ** 9 + 7)
[sol1-Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public int countNicePairs(int[] nums) {
final int MOD = 1000000007;
int res = 0;
Map<Integer, Integer> h = new HashMap<Integer, Integer>();
for (int i : nums) {
int temp = i, j = 0;
while (temp > 0) {
j = j * 10 + temp % 10;
temp /= 10;
}
res = (res + h.getOrDefault(i - j, 0)) % MOD;
h.put(i - j, h.getOrDefault(i - j, 0) + 1);
}
return res;
}
}
[sol1-C#]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Solution {
public int CountNicePairs(int[] nums) {
const int MOD = 1000000007;
int res = 0;
IDictionary<int, int> h = new Dictionary<int, int>();
foreach (int i in nums) {
int temp = i, j = 0;
while (temp > 0) {
j = j * 10 + temp % 10;
temp /= 10;
}
h.TryAdd(i - j, 0);
res = (res + h[i - j]) % MOD;
h[i - j]++;
}
return res;
}
}
[sol1-C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public:
int countNicePairs(vector<int>& nums) {
const int MOD = 1000000007;
int res = 0;
unordered_map<int, int> h;
for (int i : nums) {
int temp = i, j = 0;
while (temp > 0) {
j = j * 10 + temp % 10;
temp /= 10;
}
res = (res + h[i - j]) % MOD;
h[i - j]++;
}
return res;
}
};
[sol1-C]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
typedef struct {
int key;
int val;
UT_hash_handle hh;
} HashItem;

HashItem *hashFindItem(HashItem **obj, int key) {
HashItem *pEntry = NULL;
HASH_FIND_INT(*obj, &key, pEntry);
return pEntry;
}

bool hashAddItem(HashItem **obj, int key, int val) {
if (hashFindItem(obj, key)) {
return false;
}
HashItem *pEntry = (HashItem *)malloc(sizeof(HashItem));
pEntry->key = key;
pEntry->val = val;
HASH_ADD_INT(*obj, key, pEntry);
return true;
}

bool hashSetItem(HashItem **obj, int key, int val) {
HashItem *pEntry = hashFindItem(obj, key);
if (!pEntry) {
hashAddItem(obj, key, val);
} else {
pEntry->val = val;
}
return true;
}

int hashGetItem(HashItem **obj, int key, int defaultVal) {
HashItem *pEntry = hashFindItem(obj, key);
if (!pEntry) {
return defaultVal;
}
return pEntry->val;
}

void hashFree(HashItem **obj) {
HashItem *curr = NULL, *tmp = NULL;
HASH_ITER(hh, *obj, curr, tmp) {
HASH_DEL(*obj, curr);
free(curr);
}
}

int countNicePairs(int* nums, int numsSize) {
const int MOD = 1000000007;
int res = 0;
HashItem *h = NULL;
for (int i = 0; i < numsSize; i++) {
int temp = nums[i], j = 0;
while (temp > 0) {
j = j * 10 + temp % 10;
temp /= 10;
}
int val = hashGetItem(&h, nums[i] - j, 0);
res = (res + val) % MOD;
hashSetItem(&h, nums[i] - j, val + 1);
}
hashFree(&h);
return res;
}
[sol1-JavaScript]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var countNicePairs = function(nums) {
const MOD = 1000000007;
let res = 0;
const h = new Map();
for (const i of nums) {
let temp = i, j = 0;
while (temp > 0) {
j = j * 10 + temp % 10;
temp = Math.floor(temp / 10);
}
res = (res + (h.get(i - j) || 0)) % MOD;
h.set(i - j, (h.get(i - j) || 0) + 1);
}
return res;
};
[sol1-Golang]
1
2
3
4
5
6
7
8
9
10
11
12
func countNicePairs(nums []int) (ans int) {
cnt := map[int]int{}
for _, num := range nums {
rev := 0
for x := num; x > 0; x /= 10 {
rev = rev*10 + x%10
}
ans += cnt[num-rev]
cnt[num-rev]++
}
return ans % (1e9 + 7)
}

复杂度分析

  • 时间复杂度:O(n \times \log C),其中 n 为数组 nums 的长度,C 为数组 nums 中的数字范围。其中 O(\log C) 为反转数位的时间复杂度。
  • 空间复杂度:O(n),其中 n 为数组 nums 的长度,主要为哈希表的空间开销。
 Comments
On this page
1814-统计一个数组中好对子的数目