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

96 阅读5分钟

题目解析

题目描述

小M参与的数组比赛游戏是一个基于比较的算法问题。游戏规则是每回合比较数组的前两个元素,较大的元素保留在数组首位,较小的元素移动到数组末尾。这个过程重复进行,直到某个元素连续赢得k次,该元素即为赢家。

输入输出

  • 输入:一个整数数组arr和一个整数k
  • 输出:赢得比赛的整数。

思路

  1. 初始化:我们需要一个变量来记录当前赢家(currentwinner),一个变量来记录赢家的连续胜利次数(wincount),以及一个变量来记录上一个赢家(lastwinner)。
  2. 比较和更新:在每一回合中,比较数组的前两个元素,较大的元素成为当前赢家,较小的元素移动到数组末尾。
  3. 检查连续胜利:如果当前赢家与上一个赢家相同,则连续胜利次数wincount加1;如果不同,则重置wincount为1,并更新lastwinner为当前赢家。
  4. 循环直至胜利:重复上述过程,直到某个元素连续赢得k次。

演示

  • 初始数组:[2, 1, 3, 5, 4, 6, 7, 9]k=2
  • 第一回合:比较2和1,2胜,数组变为[2, 3, 5, 4, 6, 7, 9, 1]
  • 第二回合:比较2和3,3胜,数组变为[3, 2, 5, 4, 6, 7, 9, 1]
  • 依此类推,直到某个元素连续赢得2次。

代码详解

public class Main {
    public static int solution(int[] arr, int k) {
        List<Integer> list = new ArrayList<>(); // 将数组转换为列表,便于操作
        for (Integer i : arr) list.add(i); // 将数组元素添加到列表中

        int wincount = 0; // 记录当前赢家的连续胜利次数
        int currentwinner = -1; // 当前赢家
        int lastwinner = -1; // 上一个赢家

        while (wincount < k) { // 循环直到某个元素连续赢得k次
            int a = list.get(0); // 第一个元素
            int b = list.get(1); // 第二个元素

            if (a > b) { // 如果a大于b
                list.add(b); // 将b移动到列表末尾
                list.remove(1); // 移除b
                currentwinner = a; // a成为当前赢家
            } else { // 如果b大于a
                list.add(a); // 将a移动到列表末尾
                list.remove(0); // 移除a
                currentwinner = b; // b成为当前赢家
            }

            if (currentwinner == lastwinner) // 如果当前赢家与上一个赢家相同
                wincount++; // 连续胜利次数加1
            else { // 如果不同
                wincount = 1; // 重置连续胜利次数为1
                lastwinner = currentwinner; // 更新上一个赢家
            }
        }
        return currentwinner; // 返回赢得比赛的整数
    }

    public static void main(String[] args) {
        int[] arr1 = {2, 1, 3, 5, 4, 6, 7, 9};
        System.out.println(solution(arr1, 2) == 5); // 测试样例1
        int[] arr2 = {3, 2, 1, 4};
        System.out.println(solution(arr2, 10) == 4); // 测试样例2
        int[] arr3 = {1, 9, 8, 7, 6, 5, 4, 3, 2, 11};
        System.out.println(solution(arr3, 7) == 9); // 测试样例3
    }
}

复杂度分析

时间复杂度

时间复杂度是指算法执行时间随输入数据规模增长的变化趋势。对于这个问题,我们的主要操作是循环和列表操作(添加和删除元素)。

  1. 循环:最坏情况下,我们需要进行k次循环,每次循环都会比较数组的前两个元素。
  2. 列表操作:每次比较后,较小的元素会被移动到数组的末尾,这涉及到一次添加和一次删除操作。在最坏情况下,这需要n-1次操作,其中n是数组的长度。

因此,时间复杂度可以表示为: [ O(k \times n) ] 其中k是连续胜利的次数,n是数组的长度。

空间复杂度

空间复杂度是指算法执行过程中临时占用存储空间的大小。

额外空间:我们使用了一个列表来存储数组元素,这需要额外的O(n)空间,其中n是数组的长度。

因此,空间复杂度可以表示为: [ O(n) ]

总结

  • 时间复杂度:( O(k \times n) ),其中k是连续胜利的次数,n是数组的长度。
  • 空间复杂度:( O(n) ),其中n是数组的长度。

这种分析假设每次比较和列表操作的时间复杂度为O(1),这在大多数情况下是合理的,因为列表的添加和删除操作通常可以在常数时间内完成。然而,在某些情况下,如果列表的实现涉及到复杂的数据结构(如平衡树),那么这些操作的时间复杂度可能会更高。

知识总结

知识点

  1. 数组和列表:了解数组和列表的区别,以及如何将数组转换为列表。
  2. 循环控制:掌握while循环的使用,以及如何控制循环的结束条件。
  3. 条件判断:熟悉if-else语句的使用,以及如何根据条件执行不同的操作。
  4. 算法逻辑:理解算法的逻辑流程,包括初始化、比较、更新和循环控制。

理解和建议

  • 理解:这个问题考察了基本的算法逻辑和数据结构操作。关键在于理解如何通过比较和更新操作来模拟游戏规则,并跟踪赢家的连续胜利次数。
  • 建议:对于初学者来说,可以先从简单的算法问题开始,逐步增加难度。在解决这类问题时,建议多画图,帮助理解算法的流程。同时,多写代码,实践是提高编程能力的最佳方式。在遇到问题时,不要急于求成,而是要耐心分析问题,逐步调试代码。