力扣 - 剑指 Offer 62. 圆圈中最后剩下的数字


题目

剑指 Offer 62. 圆圈中最后剩下的数字

思路1(模拟)

  • 使用链表模拟删除节点

代码

class Solution {
    public int lastRemaining(int n, int m) {
        int index = 0;

        // 初始化链表
        List list = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            list.add(i);
        }

        // 链表首尾相接模拟删除
        while (list.size() > 1) {
            // 这里需要减去1,因为我们使用的是上一个删除的索引下标,但是那个元素已经删除
            // 了,此时链表长度会小1,因此这里需要减去1,保证数组不会越界
            index = (index + m - 1) % list.size();
            list.remove(index);
        }

        // 返回链表的第一个元素,即最后一个元素
        return list.get(0);
    }
}

复杂度分析

  • 时间复杂度:\(O(MN)\)
  • 空间复杂度:\(O(N)\),N为链表的长度

思路2(动态规划)

  • 递推

代码

class Solution {
    public int lastRemaining(int n, int m) {
        // 如果只有一个元素,索引下标就是0
        int index = 0;

        // 最后一轮淘汰剩下两个人,所以从最后一轮开始递推
        for (int i = 2; i <= n; i++) {
            index = (index + m) % i;
        }

        return index;
    }
}

复杂度分析

  • 时间复杂度:\(O(N)\)
  • 空间复杂度:\(O(1)\)