zoukankan      html  css  js  c++  java
  • 圆圈中最后剩下的数字

    题目描述:0,1,...,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。

    思路分析:(一)这个问题类似于从链表中删除,而且是循环链表,所以可以通过链表来描述,但由于问题中涉及到编号,故还是采用ArrayList来刻画比较好。具体分为以下几步:

    1.判断不合法情况,即m和n都小于1;

    2.创建一个大小为n的ArrayList,并给它们赋初值0--n-1来刻画编号;

    3.当链表的大小大于1执行如下操作:每隔m删除一个,并且对应的索引点发生变化。

    (二)分析被删除数字的规律,找出规律,编写代码,具体分析如下:

    假设从0-n-1中删除了第m个数字,则下一轮的数字排列为m,m+1,.....n-1,0,1,2,3...m-2,将该数字排列重新映射为0~n-2,则为

    m    0

    m+1    1  

    ....    ....

    n-1   n-1-m

    0    n-m

    1    n-m+1

    ...    ....

    m-2    n-2

    可以看出从右往左的映射关系为left=(right+m)%n,即0~n-1序列中最后剩下的数字等于(0~n-2序列中最后剩下的数字+m)%n,很明显当n=1时,只有一个数,那么剩下的数字就是0.

    问题转化为动态规划问题,关系表示为:

    f(n)=(f(n-1)+m)%n; 当n=1,f(1)=0;

    代码实现

    (1)链表描述

    import java.util.ArrayList;
    public class Solution {
        public int LastRemaining_Solution(int n, int m) {
           if(n==0||m<1)
           {
               return -1;
           }
            ArrayList<Integer> list = new ArrayList<Integer>();
            for(int i=0;i<n;i++)
            {
                list.add(i);
            }
           int  index = -1;
            while(list.size()>1)
            {
                index = (index+m)%list.size();
                list.remove(index);
                index--;
            }
            return list.get(0);
        }
    }

    (2)递归公式

    import java.util.ArrayList;
    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;
        }
    }
  • 相关阅读:
    2016Wireshark
    移动UI
    Javascript 严格模式详解
    [转]深入浅出JSONP解决ajax跨域问题
    savedev和save的区别
    jquery各版本区别
    Webpack学习笔记(一)
    Html5新特性
    chrome浏览器debug
    bootstrap笔记
  • 原文地址:https://www.cnblogs.com/Dream-chasingGirl/p/10295358.html
Copyright © 2011-2022 走看看