【LeetCode】1814. 统计一个数组中好对子的数目

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

题目描述

给你一个数组 nums ,数组中只包含非负整数。定义 rev(x) 的值为将整数 x 各个数字位反转得到的结果。比方说 rev(123) = 321 , rev(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

算法一:哈希表 + 数字转换1

思路

  • 通过题目给出的式子,我们可以设 f(i) = nums[i] - rev(nums[i]) ,因此如果满足 f(i) = f(j) ,则该下标对就称为 「好下标对」。

  • 从左到右遍历数组 nums ,并在遍历的过程中用 哈希表 统计每一个位置 i 的 f(i) 个数,则对于位置 j ,以 j 结尾的 「好下标对」的个数为此时哈希表中 f(j) 的数目。

    因此我们只需要遍历的时候同时统计以每一个位置为结尾的「好下标对」的数目。

  • 数字转换:字符串函数

    首先使用 to_string 将数字转换为字符串,然后将字符串反向读入,最后再使用函数 stoi 将反向字符串转化为数字。

收获

  • 刚好复习了之前学的 string 相关函数,将数字反转。

  • 我有想到哈希表,我一开始用的是 vector h;i - rev(i) 的值保存为下标,出现次数为值,但是当 i - rev(i) < 0 的时候,就会出错。

    题解用的哈希表是 unordered_map h; ,第一个值保存 i - rev(i) ,第二个值保存出现次数,解决了我上面出现的问题。

  • 统计出现次数:我一开始的想法是遍历哈希表,计算出每个 f(i) 的出现次数 n,再计算 n * (n - 1) / 2 ,就能得出,但这种方法需要等所有数字的 f(i) 遍历结束才能进行遍历。其实 n * (n-1) / 2 = (n-1) + (n-2) + ... + 1 ,因此当我们遍历到位置 j 的 f(j) 时,加上当前的出现次数,也就完成了出现次数的累加。

算法情况

  • 时间复杂度:O(n × M),其中 n 和 M 分别是数组 nums 的长度和数组 nums 中的最大值 。
  • 空间复杂度:O(n)

代码

class Solution {
public:
    int rev(int num){
        string s, res;
        // 将num转化为字符串
        s = to_string(num); 
        // 将字符串反向读入
        for(int i=s.size()-1; i>=0; i--){
            res.push_back(s[i]);
        }
        return stoi(res); 
    }
    int countNicePairs(vector<int>& nums) {
        unordered_map<int, int> h; 
        const int MOD = 1e9 + 7;
        int cnt=0;
        for(int num : nums){
            cnt = (cnt + h[num - rev(num)]) % MOD;
            h[num - rev(num)] ++;
        }
        return cnt;
    }
};

算法二:哈希表 + 数字转换 2

思路

  • 大体和算法一相同,算法二使用了另外一种数字转换的方法。

    while(i > 0){
      	j = j * 10 + i % 10;
        i /= 10;  
    }
    

收获

  • 学习了直接将数字进行反转,而不使用字符串函数。

算法情况

  • 时间复杂度:O(n × logM),其中 n 和 M 分别是数组 nums 的长度和数组 nums 中的最大值 。
  • 空间复杂度:O(n)

代码

class Solution {
public:
    int countNicePairs(vector<int>& nums) {
        unordered_map<int, int> h; 
        const int MOD = 1e9 + 7;
        int cnt=0;
        for(int num : nums){
            int i = num, j = 0;
            while(i > 0){
                j = j * 10 + i % 10;
                i /= 10;  
            }
            cnt = (cnt + h[num - j]) % MOD;
            h[num - j] ++;
        }
        return cnt;
    }
};

你可能感兴趣的:(LeetCode刷题,leetcode,算法,哈希算法)