列表

详情


3134. 找出唯一性数组的中位数

给你一个整数数组 nums 。数组 nums 唯一性数组 是一个按元素从小到大排序的数组,包含了 nums 的所有非空子数组中不同元素的个数。

换句话说,这是由所有 0 <= i <= j < nums.lengthdistinct(nums[i..j]) 组成的递增数组。

其中,distinct(nums[i..j]) 表示从下标 i 到下标 j 的子数组中不同元素的数量。

返回 nums 唯一性数组 中位数

注意,数组的 中位数 定义为有序数组的中间元素。如果有两个中间元素,则取值较小的那个。

 

示例 1:

输入:nums = [1,2,3]

输出:1

解释:

nums 的唯一性数组为 [distinct(nums[0..0]), distinct(nums[1..1]), distinct(nums[2..2]), distinct(nums[0..1]), distinct(nums[1..2]), distinct(nums[0..2])],即 [1, 1, 1, 2, 2, 3] 。唯一性数组的中位数为 1 ,因此答案是 1 。

示例 2:

输入:nums = [3,4,3,4,5]

输出:2

解释:

nums 的唯一性数组为 [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3] 。唯一性数组的中位数为 2 ,因此答案是 2 。

示例 3:

输入:nums = [4,3,5,4]

输出:2

解释:

nums 的唯一性数组为 [1, 1, 1, 1, 2, 2, 2, 3, 3, 3] 。唯一性数组的中位数为 2 ,因此答案是 2 。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: int medianOfUniquenessArray(vector<int>& nums) { } };

cpp 解法, 执行用时: 1646 ms, 内存消耗: 363.4 MB, 提交时间: 2024-05-01 11:00:49

class Solution {
public:
    int medianOfUniquenessArray(vector<int>& nums) {
        int n = nums.size();
        long long k = ((long long) n * (n + 1) / 2 + 1) / 2;

        auto check = [&](int upper) {
            long long cnt = 0;
            int l = 0;
            unordered_map<int, int> freq;
            for (int r = 0; r < n; r++) {
                freq[nums[r]]++;
                while (freq.size() > upper) {
                    int out = nums[l++];
                    if (--freq[out] == 0) {
                        freq.erase(out);
                    }
                }
                cnt += r - l + 1;
                if (cnt >= k) {
                    return true;
                }
            }
            return false;
        };

        int left = 0, right = n;
        while (left + 1 < right) {
            int mid = (left + right) / 2;
            (check(mid) ? right : left) = mid;
        }
        return right;
    }
};

java 解法, 执行用时: 497 ms, 内存消耗: 60.1 MB, 提交时间: 2024-05-01 11:00:32

class Solution {
    public int medianOfUniquenessArray(int[] nums) {
        int n = nums.length;
        long k = ((long) n * (n + 1) / 2 + 1) / 2;
        int left = 0;
        int right = n;
        while (left + 1 < right) {
            int mid = (left + right) / 2;
            if (check(nums, mid, k)) {
                right = mid;
            } else {
                left = mid;
            }
        }
        return right;
    }

    private boolean check(int[] nums, int upper, long k) {
        long cnt = 0;
        int l = 0;
        HashMap<Integer, Integer> freq = new HashMap<>();
        for (int r = 0; r < nums.length; r++) {
            freq.merge(nums[r], 1, Integer::sum);
            while (freq.size() > upper) {
                int out = nums[l++];
                if (freq.merge(out, -1, Integer::sum) == 0) {
                    freq.remove(out);
                }
            }
            cnt += r - l + 1;
            if (cnt >= k) {
                return true;
            }
        }
        return false;
    }
}

python3 解法, 执行用时: 3915 ms, 内存消耗: 33.9 MB, 提交时间: 2024-05-01 11:00:17

class Solution:
    def medianOfUniquenessArray(self, nums: List[int]) -> int:
        n = len(nums)
        k = (n * (n + 1) // 2 + 1) // 2

        def check(upper: int) -> bool:
            cnt = l = 0
            freq = Counter()
            for r, in_ in enumerate(nums):
                freq[in_] += 1
                while len(freq) > upper:
                    out = nums[l]
                    freq[out] -= 1
                    if freq[out] == 0:
                        del freq[out]
                    l += 1
                cnt += r - l + 1
                if cnt >= k:
                    return True
            return False

        return bisect_left(range(len(set(nums))), True, 1, key=check)

golang 解法, 执行用时: 678 ms, 内存消耗: 10 MB, 提交时间: 2024-05-01 11:00:02

func medianOfUniquenessArray(nums []int) int {
	n := len(nums)
	k := (n*(n+1)/2 + 1) / 2
	ans := 1 + sort.Search(n-1, func(upper int) bool {
		upper++
		cnt := 0
		l := 0
		freq := map[int]int{}
		for r, in := range nums {
			freq[in]++
			for len(freq) > upper {
				out := nums[l]
				freq[out]--
				if freq[out] == 0 {
					delete(freq, out)
				}
				l++
			}
			cnt += r - l + 1
			if cnt >= k {
				return true
			}
		}
		return false
	})
	return ans
}

上一题