剑指offer圆圈中最后剩下的数字 和 迭代器总结

迭代器只有++ ,--,==,!=四种运算方法,不能将iter = iteration+ 1,因为迭代器是指针类型,1是整数类型,不能直接相加赋值给一个指针。

题目描述

每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)

思路;每次结束后都必须从删除的下一个元素开始,记得审题要仔细。

解法1:使用环形链表模拟圆圈,使用环形链表,每次查找到最后一个元素时,都必须将迭代器返回到begin位置。

解法2:f(n,m)表示在n个数字中,删除第m 个数字最后剩下的数字。

f(n,m) =      0,n == 1;

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

//超时牛客不能通过
class Solution {
public:
    int LastRemaining_Solution(int n, int m){
        if(n == 1){
            return 0;
        }
        if(n == 0){
            return -1;
        }
        list<int> num;
        for(int i = 0;i < n;++i){//存储节点
            num.push_back(i);
        }
        list<int>::iterator iter = num.begin();
        while(num.size() > 1){
            for(int i = 1;i < m;++i){//找到指定节点
                ++iter;
                if(iter == num.end()){
                    iter = num.begin();
                }
            }
            ++iter;
            list<int>::iterator next = iter;//保存下一节点
            if(next == num.end()){
                next = num.begin();
            }
            num.erase(--iter);//删除找到的节点
            iter = next;
        }
        return *iter;
    }
};

解法2:

class Solution {
public:
    int LastRemaining_Solution(int n, int m){
        if(n < 1 ||m < 1){
            return -1;
        }

        int last = 0;
        for(int i = 1;i <= n;++i){
            last = (last + m) % i;
        }
        return last;
    }
};
时间: 2024-08-10 05:55:09

剑指offer圆圈中最后剩下的数字 和 迭代器总结的相关文章

剑指offer 数组中出现超过一半的数字

class Solution { public: int MoreThanHalfNum_Solution(vector<int> numbers) { if(numbers.empty()){ return 0; } if(numbers.size() == 1){ return numbers[0]; } int len = (int)numbers.size(); float target = len/2.0; map<int, int> m; for(int num: nu

剑指Offer对答如流系列 - 圆圈中最后剩下的数字

面试题62:圆圈中最后剩下的数字 题目描述 0, 1, -, n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字.求出这个圆圈里剩下的最后一个数字. 例如,从数字0开始每次删除第3个数字,则删除的前四个数字是2 0 4 1 因此最后剩下的数字是3 问题分析 思路一: 既然涉及到数据的频繁删除,可以考虑使用链表来存放数据,每次对长度取余数可以实现循环操作. 思路二: 这种问题规律性非常强,其实已经有对这一规律背后的数学模型的探究,即约瑟夫环 举一个具体的场景: 据说著名犹太历

剑指OFFER 整数中1出现的次数

剑指OFFER 整数中1出现的次数 class Solution { public: int hwo_many(int n) { int count=0; while(n!=0) { if(n%10==1)count++; n/=10; } return count; } int NumberOf1Between1AndN_Solution(int n) { int count = 0; for(int i=1;i<=n;i++){ count += hwo_many(i); } return

【剑指offer】旋转数组的最小数字

题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. 分析描述: 求一个数组中的最小值,最简单的办法就是逐个比较数组中各个元素的值,遍历完整个数组,即可得数组中最小元素.但这种方法存在的问题是时间复杂度为O(n). 利用题目中给出的条件:递增排序数组的旋转.利用递增排序的特点,可以用二分查找方法实现时间复杂度为O(logn)的查找.

【剑指offer】出现次数超过一半的数字

转载请注明出处:http://blog.csdn.net/ns_code/article/details/26957383 题目描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. 输入: 每个测试案例包括2行: 第一行输入一个整数n(1<=n<=100000),表示数组中元素的个数. 第二行输入n个整数,表示数组中的每个元素,这n个整数的范围是[1

剑指OFFER之旋转数组的最小数字(九度OJ1386)

题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. 输入: 输入可能包含多个测试样例,对于每个测试案例, 输入的第一行为一个整数n(1<= n<=1000000):代表旋转数组的元素个数. 输入的第二行包括n个整数,其中每个整数a的范围是(1<=a<=10000000). 输出: 对应每个测试案例, 输出旋转数组

编程算法 - 圆圈中最后剩下的数字(递推公式) 代码(C++)

圆圈中最后剩下的数字(递推公式) 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 0,1...,n-1这n个数字排成一个圆圈, 从数字0開始每次从这个圆圈里删除第m个数字. 求出这个圆圈里最后剩下的数字. 能够推导出约瑟夫环的递推公式, 使用循环进行求解,  时间复杂度O(n), 空间复杂度O(1). 代码: /* * main.cpp * * Created on: 2014.7.12 * Author: spike */ #incl

编程算法 - 圆圈中最后剩下的数字(循环链表) 代码(C++)

圆圈中最后剩下的数字(循环链表) 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 0,1...,n-1这n个数字排成一个圆圈, 从数字0开始每次从这个圆圈里删除第m个数字. 求出这个圆圈里最后剩下的数字. 使用循环链表, 依次遍历删除, 时间复杂度O(mn), 空间复杂度O(n). 代码: /* * main.cpp * * Created on: 2014.7.13 * Author: Spike */ #include <iostr

剑指Offer:旋转数组的最小数字【11】

剑指Offer:旋转数组的最小数字[11] 题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. NOTE:给出的所有元素都大于0,若数组大小为0,请返回0. 解题分析 我们用两个坐标,Left,Right分别表示左右两个递增序列的下标,刚开始L为0,R为4: 当Arr[Mid]>Arr[Left],可以说明,Mid及左边构