【Py/Java/C++三种语言详解】LeetCode每日一题240131【哈希表】LeetCode2670、找出不同元素数目差数组

有华为OD考试扣扣交流群可加 948025485
可上全网独家的 欧弟OJ系统 练习华子OD、大厂真题
绿色聊天软件戳 od1336了解算法冲刺训练

文章目录

  • 题目链接
  • 题目描述
  • 解题思路
    • 前缀包含的不同元素个数
    • 后缀包含的不同元素个数
  • 代码
    • Python
    • Java
    • C++
    • 时空复杂度
  • 华为OD算法/大厂面试高频题算法练习冲刺训练

题目链接

LeetCode2670、找出不同元素数目差数组

题目描述

给你一个下标从 0 开始的数组 nums ,数组长度为 n

nums不同元素数目差 数组可以用一个长度为 n 的数组 diff 表示,其中 diff[i] 等于前缀 nums[0, ..., i] 中不同元素的数目 减去 后缀 nums[i + 1, ..., n - 1] 中不同元素的数目。

返回 nums不同元素数目差 数组。

注意 nums[i, ..., j] 表示 nums 的一个从下标 i 开始到下标 j 结束的子数组(包含下标 ij 对应元素)。特别需要说明的是,如果 i > j ,则 nums[i, ..., j] 表示一个空子数组。

示例 1

输入:nums = [1,2,3,4,5]
输出:[-3,-1,1,3,5]
解释: 对于 i = 0,前缀中有 1 个不同的元素,而在后缀中有 4 个不同的元素。因此,diff[0] = 1 - 4 = -3 。 对于 i = 1,前缀中有 2 个不同的元素,而在后缀中有 3 个不同的元素。因此,diff[1] = 2 - 3 = -1 。 对于 i = 2,前缀中有 3 个不同的元素,而在后缀中有 2 个不同的元素。因此,diff[2] = 3 - 2 = 1 。 对于 i = 3,前缀中有 4 个不同的元素,而在后缀中有 1 个不同的元素。因此,diff[3] = 4 - 1 = 3 。 对于 i = 4,前缀中有 5 个不同的元素,而在后缀中有 0 个不同的元素。因此,diff[4] = 5 - 0 = 5 。

示例 2

输入:nums = [3,2,3,4,2]
输出:[-2,-1,0,2,3]
解释: 对于 i = 0,前缀中有 1 个不同的元素,而在后缀中有 3 个不同的元素。因此,diff[0] = 1 - 3 = -2 。 对于 i = 1,前缀中有 2 个不同的元素,而在后缀中有 3 个不同的元素。因此,diff[1] = 2 - 3 = -1 。 对于 i = 2,前缀中有 2 个不同的元素,而在后缀中有 2 个不同的元素。因此,diff[2] = 2 - 2 = 0 。 对于 i = 3,前缀中有 3 个不同的元素,而在后缀中有 1 个不同的元素。因此,diff[3] = 3 - 1 = 2 。 对于 i = 4,前缀中有 3 个不同的元素,而在后缀中有 0 个不同的元素。因此,diff[4] = 3 - 0 = 3 。

提示

  • 1 <= n == nums.length <= 50
  • 1 <= nums[i] <= 50

解题思路

本题的数据量很低,O(N^2)的暴力解肯定能过。略去不表。

接下来主要讨论O(N)复杂度的解法。

对于特定位置i,前缀和后缀所包含的不同元素的个数是分开计算的。故分别讨论如何计算前缀和后缀的情况。

考虑从左往右遍历下标i

前缀包含的不同元素个数

这个比较容易想到,直接用自带去重功能的哈希集合来完成。

遍历i的过程中,将元素nums[i]加入哈希集合set_left,此时前缀包含的不同元素的个数即为len(set_left)

后缀包含的不同元素个数

后缀就没办法用哈希集合来完成了,因为在遍历到i的时候,我们无法得知在i的右边是否还存在和nums[i]相同的元素。

但是我们可以知道,如果i的右边不存在nums[i]相同的元素,那么i就是元素nums[i]出现在数组nums中的最后一个下标。

因此我们可以在遍历i之前,预处理一个哈希表dic_last_idx,用于储存每一个元素numnums中最后出现的下标。另外初始化一个变量right,用于表示后缀中不重复的元素个数。

在遍历过程中,一旦发现i == dic_last_idx[nums[i]],说明此时i的右边已经没有其他重复的同一元素,这意味着在下标i的后缀中,所包含的不同元素的个数减少1,即right -= 1

前缀和后缀的情况都讨论完毕之后,存在ans[i] = len(set_left) - right成立

代码

Python

class Solution:
    def distinctDifferenceArray(self, nums: List[int]) -> List[int]:
        n = len(nums)
        ans = [0] * n
        set_left = set()
        dic_last_idx = dict()
        for i, num in enumerate(nums):
            dic_last_idx[num] = i
        right = len(dic_last_idx)
        for i, num in enumerate(nums):
            set_left.add(num)
            if dic_last_idx[num] == i:
               right -= 1
            ans[i] = len(set_left) - right
        return ans

Java

class Solution {
    public int[] distinctDifferenceArray(int[] nums) {
        int n = nums.length;
        int[] ans = new int[n];
        Set<Integer> setLeft = new HashSet<>();
        Map<Integer, Integer> dicLastIdx = new HashMap<>();
        int right = 0;

        for (int i = 0; i < n; i++) {
            dicLastIdx.put(nums[i], i);
        }

        right = dicLastIdx.size();

        for (int i = 0; i < n; i++) {
            setLeft.add(nums[i]);

            if (dicLastIdx.get(nums[i]) == i) {
                right -= 1;
            }

            ans[i] = setLeft.size() - right;
        }

        return ans;
    }
}

C++

class Solution {
public:
    vector<int> distinctDifferenceArray(vector<int>& nums) {
        int n = nums.size();
        vector<int> ans(n, 0);
        unordered_set<int> setLeft;
        unordered_map<int, int> dicLastIdx;
        int right = 0;

        for (int i = 0; i < n; i++) {
            dicLastIdx[nums[i]] = i;
        }

        right = dicLastIdx.size();

        for (int i = 0; i < n; i++) {
            setLeft.insert(nums[i]);

            if (dicLastIdx[nums[i]] == i) {
                right -= 1;
            }

            ans[i] = setLeft.size() - right;
        }

        return ans;
    }
};

时空复杂度

时间复杂度:O(N)。仅需一次遍历数组

空间复杂度:O(N)。哈希表、哈希集合所占空间


华为OD算法/大厂面试高频题算法练习冲刺训练

  • 华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!

  • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

  • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

  • 60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁

  • 可上全网独家的欧弟OJ系统练习华子OD、大厂真题

  • 可查看链接 大厂真题汇总 & OD真题汇总(持续更新)

  • 绿色聊天软件戳 od1336了解更多

你可能感兴趣的:(LeetCode,#,哈希表,java,c++,leetcode,python,散列表,算法)