剑指offer—62.孩子们的游戏(圆圈中最后剩下的数)—分析及代码(Java)

@toc

一、题目

每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数 m,让编号为 0 的小朋友开始报数。每次喊到 m-1 的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续 0 … m-1 报数 … 这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从 0 到 n-1 )

如果没有小朋友,请返回 -1。

二、分析及代码

1. 环形链表模拟

(1)思路

最直接的方法是,基于环形链表模拟题中的圆圈,此时时间复杂度为 O(mn),空间复杂度为 O(n)。

(2)代码

public class Solution {
    
    
    public int LastRemaining_Solution(int n, int m) {
    
    
        if (n < 1)
            return -1;
        if (n == 1)
            return 0;
        
        ListNode head = new ListNode(0);
        ListNode pre = head;
        ListNode node = null;
        for (int i = 1; i < n; i++) {
    
    
            node = new ListNode(i);
            pre.next = node;
            pre = node;
        }
        node.next = head;
        
        while (node.next != node) {
    
    
            for (int i = 0; i < m - 1; i++)
                node = node.next;
            node.next = node.next.next;
        }
        
        return node.val;
    }
}

class ListNode {
    
    
    int val;
    ListNode next = null;

    ListNode(int val) {
    
    
        this.val = val;
    }
}

(3)结果

运行时间:28ms,占用内存:9420k。

2. 递推公式

先数学归纳得到剩下数字的递推公式,具体过程可参照《剑指offer》书本,得到的公式为:

f(n,m)=0, n=1  
f(n,m)=[f(n-1,m)+m]%n, n>1  

结合递推公式,可通过递归或循环快速计算得到结果。

(2)代码

public class Solution {
    
    
    public int LastRemaining_Solution(int n, int m) {
    
    
        if (n < 1)
            return -1;
        int num = 0;
        for (int i = 2; i <= n; i++)
            num = (num + m) % i;
        return num;
    }
}

(3)结果

运行时间:18ms,占用内存:9204k。

三、其他

暂无。

猜你喜欢

转载自blog.csdn.net/zml66666/article/details/112155771