zoukankan      html  css  js  c++  java
  • 剑指offer(62):孩子们的游戏(圆圈中最后剩下的数)约瑟夫环问题

    题目描述

    每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
     
    如果没有小朋友,请返回-1
     
    链表C++实现
    /*struct ListNode {
        int val;
        struct ListNode *next;
        ListNode(int x) :
                val(x), next(NULL) {
        }
    };*/
    class Solution {
    public:
        
        int LastRemaining_Solution(int n, int m)
        {
            if(n==0) return -1;
            ListNode *p = NULL;
            ListNode *head = NULL;
            //建立初始链表
            for(int i=0;i<n;i++){
                ListNode *s = new ListNode(i);
                if(p == NULL){//头结点单独处理并保存
                    p = s;
                    head = p;
                }
                else{
                    p->next = s;
                    p = s;
                }
            }
            p->next = head;//环形链表
            //退圈过程
            int count = 0;//从0开始计数
            ListNode *q = NULL;//暂存要释放的结点
            while(!(p->next == p)){//当链表中结点数目大于1时执行
                while(count<m-1){
                    count++;
                    p = p->next;
                }
                q = p->next;//暂存要释放的结点,注意顺序
                p->next = p->next->next;
                count = 0;//重新开始计数
                free(q);
            }
            return p->val;
        }
    };

    java数组实现:

    public class Solution {
        public int LastRemaining_Solution(int n, int m) {
            if(n == 0) return -1;
            int[] children = new int[n];
            int indexN = 0;//记录下标,
            int count = 0;//计数
            int arrayNum = n;//记录还有几个孩子没有出圈
            while(arrayNum > 0){ //当存在未出圈的孩子时
                while(count<m-1){  //计数
                    //只有当children[indexN]==0才代表未出圈,==-1代表已出圈
                    if(children[indexN] != -1){  
                        count++;
                    }
                    indexN = (indexN + 1) % n; //注意取模
                }
                /*
                这里是采坑的地方,一定要注意,
                当count=m-1时,children[indexN]可能已出圈,要循环找到未出圈的那个下标*/
                while (children[indexN] != 0){  
                    indexN = (indexN + 1) % n;
                }
                children[indexN] = -1;//找到后出圈
                
                /*开始下一轮的计数*/
                count = 0;
                indexN = (indexN + 1) % n;
                arrayNum--; //圈内人数-1
            }
            if(indexN == 0)
                return n-1;
            else
                return indexN-1;
        }
    }
  • 相关阅读:
    数据结构之二叉树解析
    并发出体验 -- 解决小规模并发下单的问题
    JDBC事务控制
    数据库中悲观锁与乐观锁的总结实践
    浅析实际项目中对数据库设计的一些思考
    Java中实现多线程的四种方式
    将本地文件上传至github
    git/github 生成密钥
    git常用命令
    解决git每次提交推送都要输入密码
  • 原文地址:https://www.cnblogs.com/ttzz/p/13881481.html
Copyright © 2011-2022 走看看