• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
追梦女孩Y2
博客园    首页    新随笔    联系   管理    订阅  订阅
圆圈中最后剩下的数字

题目描述: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;
    }
}

 

posted on 2019-01-20 16:41  追梦女孩Y2  阅读(135)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3