LeetCode刷题记录(三十):找出游戏的获胜者

113 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

找出游戏的获胜者

题目太长,示例没有截全。

image.png

题目解析

题目素材解析

根据本题目的描述,还有题目给的代码模板。

一共提供了两个素材。

  1. 数字n。

  2. 数字k。

并且规定1 <= k <= n <= 500。

我的解读

本道题题目特别长,读起来很费劲。

简明扼要的说一下。

数字n代表着n个位置;k代表着每次跳跃或者说每次运动的位置点数。

假设一个人在n个位置中,经过多次的按顺序跳跃,每次跳跃都视为移动k个位置点。

这个人每一次跳跃后,所在的位置都要被消除掉;多次跳跃后,只保留最后一个位置点。

最后这个位置点就是我们的预期结果值。

解题思路

来说一下我的解题思路吧。

第一步,先来排除一个特殊情况就是位置n等于1的时候,我一次提交失败就是因为这个特殊情况没有处理。

第二步,声明集合变量set,用于存放已经消除的值;位置点位i。

第三步,开始一级循环,一级循环体内,通过二级循环来跳跃位置点得到需要消除的点位;判断是否只剩下一个值。

第四步,二级循环体内,通过判断下一个点位是否被消除来确定是不是再移动一个点位。

等待循环结束,就能得到预期结果了,虽然笨点,但是还是比较清晰的。

代码

class Solution {
    public int findTheWinner(int n, int k) {
        if(n == 1){
            return 1;
        }
        Set<Integer> set = new HashSet<>();
        int i = 0;
        while (true){
            for (int j = 0; j < k; j++) {
                if(n < ++i){
                    i = i - n;
                }
                if(set.contains(i)){
                    while(set.contains(i)){
                        if(n < ++i){
                            i = i - n;
                        }
                    }
                }
            }
            set.add(i);
            if(set.size() == n - 1){
                break;
            }
        }
        int result = 1;
        for (int j = 1; j <= n; j++) {
            if(!set.contains(j)){
                result = j;
            }
        }
        return result;
    }

}

执行结果

明显是不理解的方案,这次的题目完全就是笨方法,但凡用一点巧劲也不至于这么惨。

image.png

试了试官方提供的题解,速度上差了好多,但是排名靠前的题解排名都不怎么高。。。。

image.png

Java代码本地执行

Java本地可调试代码,请参考github/Ijiran,可通过索引看到相应代码。