比赛的赢家 | 豆包MarsCode AI刷题

123 阅读4分钟

学习方法与心得

这道题目结合了数组的遍历与逻辑判断,核心在于动态跟踪当前胜者及其连胜次数。通过简单的遍历和条件判断可以快速解决问题。这一类问题锻炼了数组操作的逻辑处理能力,以及对边界条件的把握。

以下是我的心得:

  1. 理解规则并手动模拟几次比赛过程是解题的起点。
  2. 在实现时,注重变量的含义和更新方式(如胜者的追踪与重置)。
  3. 通过充分利用题目条件(如比赛一定会有赢家),可以简化代码逻辑。

1. 题目解析

题目规则

  1. 每轮比赛由 arr[0]arr[1] 比较,较大的元素成为新胜者。
  2. 胜者会继续比赛,失败者移到队尾。
  3. 如果某个元素连续赢得 k 次,则游戏结束并返回该元素。
  4. 如果遍历数组后仍无连续胜者,胜者为最后剩下的元素。

特殊情况

  1. 如果 k == 1,只需比较数组的前两个元素即可返回结果。
  2. 如果数组长度为 1,直接返回唯一元素。

2. 思路分析

  1. 手动模拟比赛规则: 从数组的第一个元素开始,逐个比较相邻的元素并更新当前胜者,统计连胜次数。

  2. 优化胜者更新: 通过变量 winner 记录当前胜者,变量 count 记录其连胜次数。

    • 如果当前胜者继续赢,则 count++
    • 如果当前胜者被击败,则更新 winner 并将 count 重置为 1。
  3. 提前终止条件

    • 若某元素的连胜次数达到 k,直接返回该元素。
    • 如果遍历完整个数组,最后的胜者为当前 winner
  4. 时间复杂度: 每个元素最多比较一次,因此时间复杂度为 O(n)O(n)O(n)。


3. 代码详解

public class Main {
    public static int solution(int[] arr, int k) {
        int n = arr.length;
​
        // 特殊情况1:k == 1,直接比较前两个元素
        if (k == 1) {
            return Math.max(arr[0], arr[1]);
        }
        // 特殊情况2:数组长度为1
        if (n == 1) {
            return arr[0];
        }
​
        // 初始化胜者为第一个元素,连胜次数为0
        int winner = arr[0];
        int count = 0;
​
        // 遍历数组,模拟比赛过程
        for (int i = 1; i < n; i++) {
            if (winner > arr[i]) {
                // 当前胜者继续胜利
                count++;
            } else {
                // 更新胜者
                winner = arr[i];
                count = 1;
            }
​
            // 胜者达到k连胜时返回
            if (count == k) {
                return winner;
            }
        }
​
        // 返回最终胜者
        return winner;
    }
​
    public static void main(String[] args) {
        int[] arr1 = { 2, 1, 3, 5, 4, 6, 7, 9 };
        System.out.println(solution(arr1, 2) == 5); // 输出:5
​
        int[] arr2 = { 3, 2, 1, 4 };
        System.out.println(solution(arr2, 10) == 4); // 输出:4
​
        int[] arr3 = { 1, 9, 8, 7, 6, 5, 4, 3, 2, 11 };
        System.out.println(solution(arr3, 7) == 9); // 输出:9
    }
}
​

代码分析

  1. 特殊情况处理

    • k == 1 时,直接返回前两元素中的较大值,避免不必要的逻辑处理。
    • 数组长度为 1 时,直接返回元素本身。
  2. 比赛逻辑

    • 遍历数组,比较当前 winnerarr[i] 的大小。
    • winner 连胜,则增加连胜次数;否则更新 winner 并重置连胜次数。
  3. 提前终止

    • 若某个元素的连胜次数达到 k,立即返回该元素,避免多余计算。

4. 学习总结与经验

  1. 模拟比赛思路: 手动模拟题目中的比赛过程,并将过程抽象为程序逻辑。

    • 通过两个变量(winnercount)完成整个比赛流程的记录与判断。
  2. 提前终止条件的利用: 在满足特定条件(如连胜次数达到 k)时立即返回结果,可以提高程序效率。

  3. 边界条件的处理

    • k == 1 和数组长度为 1 等特殊情况,单独处理,避免复杂逻辑引入冗余。
  4. 优化代码结构

    • 将条件判断与变量更新分开,保持逻辑清晰,易于调试。

5. 学习方法与建议

  1. 分析问题规则: 仔细阅读题目,结合示例手动模拟过程,有助于理清解题思路。
  2. 变量的选择与定义: 定义合理的变量(如 winnercount),简化代码逻辑,避免复杂状态的管理。
  3. 代码结构清晰: 将特殊情况单独处理,主体逻辑集中在循环中,保持代码的条理性和可读性。
  4. 多练习类似问题: 通过练习队列、数组模拟等问题,掌握类似规则题目的通用解法。