跳转至

1150. 检查一个数是否在数组中占绝大多数 🔒

题目描述

给出一个按 非递减 顺序排列的数组 nums,和一个目标数值 target。假如数组 nums 中绝大多数元素的数值都等于 target,则返回 True,否则请返回 False

所谓占绝大多数,是指在长度为 N 的数组中出现必须 超过 N/2 

 

示例 1:

输入:nums = [2,4,5,5,5,5,5,6,6], target = 5
输出:true
解释:
数字 5 出现了 5 次,而数组的长度为 9。
所以,5 在数组中占绝大多数,因为 5 次 > 9/2。

示例 2:

输入:nums = [10,100,101,101], target = 101
输出:false
解释:
数字 101 出现了 2 次,而数组的长度是 4。
所以,101 不是 数组占绝大多数的元素,因为 2 次 = 4/2。

 

提示:

  • 1 <= nums.length <= 1000
  • 1 <= nums[i] <= 10^9
  • 1 <= target <= 10^9

解法

方法一:二分查找

我们注意到,数组 $nums$ 中的元素是非递减的,也就是说,数组 $nums$ 中的元素单调递增。因此,我们可以使用二分查找的方法,找到数组 $nums$ 中第一个大于等于 $target$ 的元素的下标 $left$,以及第一个大于 $target$ 的元素的下标 $right$。如果 $right - left > \frac{n}{2}$,则说明数组 $nums$ 中的元素 $target$ 出现的次数超过了数组长度的一半,因此返回 $true$,否则返回 $false$。

时间复杂度 $O(\log n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 $nums$ 的长度。

1
2
3
4
5
class Solution:
    def isMajorityElement(self, nums: List[int], target: int) -> bool:
        left = bisect_left(nums, target)
        right = bisect_right(nums, target)
        return right - left > len(nums) // 2
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
    public boolean isMajorityElement(int[] nums, int target) {
        int left = search(nums, target);
        int right = search(nums, target + 1);
        return right - left > nums.length / 2;
    }

    private int search(int[] nums, int x) {
        int left = 0, right = nums.length;
        while (left < right) {
            int mid = (left + right) >> 1;
            if (nums[mid] >= x) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }
}
1
2
3
4
5
6
7
8
class Solution {
public:
    bool isMajorityElement(vector<int>& nums, int target) {
        auto left = lower_bound(nums.begin(), nums.end(), target);
        auto right = upper_bound(nums.begin(), nums.end(), target);
        return right - left > nums.size() / 2;
    }
};
1
2
3
4
5
func isMajorityElement(nums []int, target int) bool {
    left := sort.SearchInts(nums, target)
    right := sort.SearchInts(nums, target+1)
    return right-left > len(nums)/2
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
function isMajorityElement(nums: number[], target: number): boolean {
    const search = (x: number) => {
        let left = 0;
        let right = nums.length;
        while (left < right) {
            const mid = (left + right) >> 1;
            if (nums[mid] >= x) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left;
    };
    const left = search(target);
    const right = search(target + 1);
    return right - left > nums.length >> 1;
}

方法二:二分查找(优化)

方法一中,我们使用了两次二分查找,分别找到数组 $nums$ 中第一个大于等于 $target$ 的元素的下标 $left$,以及第一个大于 $target$ 的元素的下标 $right$。但是,我们可以使用一次二分查找,找到数组 $nums$ 中第一个大于等于 $target$ 的元素的下标 $left$,然后判断 $nums[left + \frac{n}{2}]$ 是否等于 $target$,如果相等,说明数组 $nums$ 中的元素 $target$ 出现的次数超过了数组长度的一半,因此返回 $true$,否则返回 $false$。

时间复杂度 $O(\log n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 $nums$ 的长度。

1
2
3
4
5
class Solution:
    def isMajorityElement(self, nums: List[int], target: int) -> bool:
        left = bisect_left(nums, target)
        right = left + len(nums) // 2
        return right < len(nums) and nums[right] == target
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
    public boolean isMajorityElement(int[] nums, int target) {
        int n = nums.length;
        int left = search(nums, target);
        int right = left + n / 2;
        return right < n && nums[right] == target;
    }

    private int search(int[] nums, int x) {
        int left = 0, right = nums.length;
        while (left < right) {
            int mid = (left + right) >> 1;
            if (nums[mid] >= x) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }
}
1
2
3
4
5
6
7
8
9
class Solution {
public:
    bool isMajorityElement(vector<int>& nums, int target) {
        int n = nums.size();
        int left = lower_bound(nums.begin(), nums.end(), target) - nums.begin();
        int right = left + n / 2;
        return right < n && nums[right] == target;
    }
};
1
2
3
4
5
6
func isMajorityElement(nums []int, target int) bool {
    n := len(nums)
    left := sort.SearchInts(nums, target)
    right := left + n/2
    return right < n && nums[right] == target
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
function isMajorityElement(nums: number[], target: number): boolean {
    const search = (x: number) => {
        let left = 0;
        let right = n;
        while (left < right) {
            const mid = (left + right) >> 1;
            if (nums[mid] >= x) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left;
    };
    const n = nums.length;
    const left = search(target);
    const right = left + (n >> 1);
    return right < n && nums[right] === target;
}

评论