返回
巧用二分:911. 在线选举,给定投票信息,求取绝对优势获胜者
后端
2023-11-25 12:31:23
- 在线选举
题目
这是 LeetCode 上的 911. 在线选举,难度为 中等。
Tag : 「二分」
给你两个整数数组 persons 和 times 。 在选举中,第 i 张票是在时刻为 times[i] 时投给候选人 persons[i] 的。
为了赢得选举,候选人需要获得多数选票。如果候选人获得的选票数大于或等于总选票数的一半,则该候选人获胜。
请你返回在选举中获胜的候选人,或者返回 “-1” 表示没有获胜者。
示例 1:
输入:persons = [0,1,1,0,0,1,0], times = [0,5,10,15,20,25,30]
输出:0
解释:
- 在时刻 0,候选人 0 获得一张选票。
- 在时刻 5,候选人 1 获得一张选票。
- 在时刻 10,候选人 1 获得一张选票。
- 在时刻 15,候选人 0 获得一张选票。
- 在时刻 20,候选人 0 获得一张选票。
- 在时刻 25,候选人 1 获得一张选票。
- 在时刻 30,候选人 0 获得一张选票。
候选人 0 总共获得 4 张选票,候选人 1 总共获得 3 张选票。所以候选人 0 在选举中获胜。
示例 2:
输入:persons = [0,0,0,0], times = [0,6,39,52]
输出:0
解释:
候选人 0 总共获得 4 张选票,候选人 1 没有获得选票。所以候选人 0 在选举中获胜。
示例 3:
输入:persons = [1,2,3], times = [0,0,6]
输出:-1
解释:
没有候选人获得多数选票,因此没有获胜者。
提示:
- $1 <= persons.length == times.length <= 5 * 10^4$
- $0 <= persons[i] < persons.length$
- $0 <= times[i] <= 10^9$
- times 按 非递减 顺序排列
解题思路
本题是一道「二分」题目,题目要求我们找出在选举中获胜的候选人,或者返回 “-1” 表示没有获胜者。我们可以使用二分查找的方法来解决这个问题。
首先,我们将 times 数组从小到大排序,然后使用二分查找的方法找到第 \frac{1}{2} 个元素对应的时刻。这个时刻将把选举过程划分为两个部分:在该时刻之前投出的选票和在该时刻之后投出的选票。
然后,我们可以分别计算在两个部分中每个候选人获得的选票数。如果在两个部分中都获得多数选票,则该候选人获胜。如果只有一个部分获得多数选票,则该候选人在该部分获胜。如果没有候选人在两个部分中都获得多数选票,则没有候选人获胜。
代码实现
def findWinner(persons, times):
# 将 times 数组从小到大排序
times.sort()
# 找到第 1/2 个元素对应的时刻
mid = len(times) // 2
# 计算在两个部分中每个候选人获得的选票数
votes1 = [0] * len(persons)
for i in range(mid):
votes1[persons[i]] += 1
votes2 = [0] * len(persons)
for i in range(mid, len(times)):
votes2[persons[i]] += 1
# 检查是否有候选人在两个部分中都获得多数选票
for i in range(len(persons)):
if votes1[i] > len(times) / 2 and votes2[i] > len(times) / 2:
return i
# 检查是否有候选人在一个部分中获得多数选票
for i in range(len(persons)):
if votes1[i] > len(times) / 2 or votes2[i] > len(times) / 2:
return i
# 没有候选人获胜
return -1
# 测试代码
persons = [0,1,1,0,0,1,0]
times = [0,5,10,15,20,25,30]
print(findWinner(persons, times)) # 0
persons = [0,0,0,0]
times = [0,6,39,52]
print(findWinner(persons, times)) # 0
persons = [1,2,3]
times = [0,0,6]
print(findWinner(persons, times)) # -1