45、圆圈中最后剩下的数字

思路1:环形链表,每次只删除一个数,都从第0个开始。每次都从链表重复遍历,每删除一个,走m步,共n遍

时间O(nm),空间o(n)

import java.util.*;
public class Solution {
    public int LastRemaining_Solution(int n, int m) {
        if(n < 1 || m < 1) {
            return -1;
        }
        List<Integer> list =  new LinkedList<>();
        for (int i = 0; i < n; i++) {
            list.add(i);
        }
        int idx = 0;
        while(list.size() > 1) {
            // 只要移动m-1次就可以移动到下一个要删除的元素上
            for (int i = 1; i < m; i++) {
                idx = (idx + 1) % list.size();//保证删除后,当数组数量小于m时,仍能正确的去删除
            }
            list.remove(idx);
        }
        
        return  list.get(0);
    }
    
}
View Code

思路2:时间O(n),空间o(1),

f(n,m) = f '(n - 1, m) {删除一个数后,再每次去删除第m个,最后剩下的数  ,一定等于, 上一次操作中,再每次去删除第m个,最后剩下的数}

即,不管处于第几次删除第m个数的循环里,最后剩下的数是一样的。

f(n,m) = {0,n=1(f(n,m)表示在n个数中,每次删除第m个后,最后剩下的一个数)

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

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

 测试:输入m小于n,输入的m大于n,特殊输入;圆圈有0个数;性能从4000个数删除997

原文地址:https://www.cnblogs.com/lingli-meng/p/7102691.html