找出数组游戏的赢家

标签: 数组 模拟

难度: Medium

给你一个由 不同 整数组成的整数数组 arr 和一个整数 k

每回合游戏都在数组的前两个元素(即 arr[0]arr[1] )之间进行。比较 arr[0]arr[1] 的大小,较大的整数将会取得这一回合的胜利并保留在位置 0 ,较小的整数移至数组的末尾。当一个整数赢得 k 个连续回合时,游戏结束,该整数就是比赛的 赢家

返回赢得比赛的整数。

题目数据 保证 游戏存在赢家。

示例 1:

输入:arr = [2,1,3,5,4,6,7], k = 2
输出:5
解释:一起看一下本场游戏每回合的情况:

因此将进行 4 回合比赛,其中 5 是赢家,因为它连胜 2 回合。

示例 2:

输入:arr = [3,2,1], k = 10
输出:3
解释:3 将会在前 10 个回合中连续获胜。

示例 3:

输入:arr = [1,9,8,2,3,7,6,4,5], k = 7
输出:9

示例 4:

输入:arr = [1,11,22,33,44,55,66,77,88,99], k = 1000000000
输出:99

提示:

  • 2 <= arr.length <= 10^5
  • 1 <= arr[i] <= 10^6
  • arr 所含的整数 各不相同
  • 1 <= k <= 10^9

Submission

运行时间: 44 ms

内存: 26.6 MB

class Solution:
    def getWinner(self, arr: List[int], k: int) -> int:
        if k >= len(arr)-1: return max(arr)
        cur, tmp = arr[0], k
        for i in range(1, len(arr)):
            if cur > arr[i]:
                tmp -=1
            else:
                cur = arr[i]
                tmp = k-1
            if tmp == 0:
                return cur
        return cur

Explain

此题解采用模拟比赛的方式进行。首先,检查k是否大于等于数组长度减一,如果是,直接返回数组中的最大值,因为最大的元素一定能够在足够多的回合中连续获胜。否则,使用变量cur来记录当前连胜的数字,tmp来记录当前数字还需要赢得多少回合才能成为赢家。遍历数组中的元素,如果cur大于当前元素,则cur的连胜次数(tmp)减一;如果小于,更新cur为当前元素,并重置tmp为k-1。如果tmp降到0,则当前cur为赢家,直接返回。如果遍历结束后没有找到赢家,则返回最后的cur,因为它已经是剩下的最大值。

时间复杂度: O(n)

空间复杂度: O(1)

class Solution:
    def getWinner(self, arr: List[int], k: int) -> int:
        # 如果k大于等于数组长度减一,返回数组中的最大值
        if k >= len(arr)-1: return max(arr)
        # 初始化当前连胜的数字为数组第一个元素
        cur, tmp = arr[0], k
        # 遍历数组的其他元素
        for i in range(1, len(arr)):
            # 如果当前连胜的数字大于遍历到的元素
            if cur > arr[i]:
                tmp -= 1
            else:
                # 更新当前连胜的数字为新的元素
                cur = arr[i]
                tmp = k-1
            # 如果连胜次数为0,返回当前元素
            if tmp == 0:
                return cur
        # 如果没有元素达到连胜k次,返回最后的cur
        return cur

Explore

当k大于等于数组长度减一时,任何数字都至少有机会与数组中的其他所有数字比较一次。在这种情况下,数组中的最大值在遍历过程中总能持续获胜,因为它总是大于与之比较的任何其他数字。因此,最大值将可以连续获胜,直到它超过k次获胜,确保它是游戏的最终赢家。这就是为什么直接返回数组中的最大值是最优解的原因。

使用变量cur和tmp的方法简单且直接。变量cur用来追踪当前可能的赢家,而tmp用来记录该赢家还需要赢得多少次比赛才能确保胜利。这种方法的优点是空间复杂度低(O(1)),并且能够快速更新赢家和胜利次数。使用其他复杂数据结构,如队列或堆,可能增加实现复杂度,而且在这种特定场景下,并不会提供额外的性能优势,因为我们需要跟踪的只是当前的领先者和它还需赢得的比赛次数。

是的,根据题目的游戏规则,每次比较都代表一局比赛。当cur大于下一个元素时,这意味着cur赢得了这一局比赛,因此tmp(记录cur还需要赢得的比赛次数)需要减1。这样的设计确保了每次cur赢得比赛时,我们都逐步逼近它成为最终的赢家。

这种做法确实没有将cur之前的胜利纳入新的计算中,因为一旦出现一个更大的元素,这个元素就成为新的‘赢家候选’,并且需要重新计算其胜利的场次。这是因为游戏规则是连续获胜,一旦有新的更大元素出现,之前的赢家的连胜记录就被打断,新的赢家需要开始新的连胜记录。