滑动窗口内唯一元素数量和

Lintcode 692

已知:

给一个数组和一个滑动窗口的大小, 求每一个窗口内唯一元素的个数和

示例:

给一个数组 nums = [1, 2, 1, 3, 3] 和 k = 3
第一个窗口为 [1, 2, 1], 只有 2 是唯一的, 计数为 1.
第二个窗口为 [2, 1, 3], 所有的元素都是唯一的, 计数为 3.
第三个窗口为 [1, 3, 3], 只有 1 是唯一的, 计数为 1.
总数为 1 + 3 + 1 = 5
返回 5

思路:
最朴素的思路莫过于给定每个窗口时都重新进行一次计算,得到结果,当然我没那么写,因为题目本身有很明显的递推的关系,只是如何将滑动前一次的数据用到下一次来而已。

在这里,我才用的方法是: 建立一个数组,数组的下标是窗口内元素的值,也就是以示例为例子的话,a[0] = 0, a[1] = 2, a[2] = 1, a[3] = 2
每次窗口滑动时,滑动前第一位数作下标的数组的值-1,滑动后最后一位作下标的数组的值+1.

public class Solution {
    public int slidingWindowUniqueElementsSum(int[] nums, int k) {
        int max = max(nums);
        int[] count = new int[max + 1];
        for (int i = 0; i < k && i < nums.length; i++) {
            count[nums[i]]++;
        }

        //会出现nums.length <= k 的情况,也就是窗口比数组大的情况
        int ret = calculate(count);
        if (nums.length <= k) {
            return ret;
        }

        //滑动
        //下标为 滑动后的第一个数-1 的值--
        //下标为 滑动后的最后一个数 的值++
        for (int i = 1; i <= nums.length - k; i++) {
            count[nums[i - 1]]--;
            count[nums[i + k - 1]]++;
            ret += calculate(count);
        }

        return ret;
    }

    private int calculate(int[] count) {
        int ret = 0;
        for (int i = 0; i < count.length; i++) {
            if (count[i] == 1) {
                ret++;
            }
        }
        return ret;
    }

    private int max(int[] nums) {
        if (nums.length == 0)
            return -1;
        int ret = nums[0];
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] > ret) {
                ret = nums[i];
            }
        }
        return ret;
    }
};

其实请读者思考一下,因为以上代码还有可以优化的地方,也就是说,如果数组为{1,2,3,1000,1000}这样的情况,有没有方法减少calculate函数的工作量呢?

谢谢您的阅读,希望对您有所帮助( • ̀ω•́ )✧

猜你喜欢

转载自blog.csdn.net/mio_bass/article/details/78853897
今日推荐