1.队列的最大值
滑动窗口的最大值:给定一个数组和滑动窗口的大小,找出所有滑动窗口的最大值。
思路:建立一个两段开口的队列index,用来保存有可能是滑动窗口最大值得数字的下标。在存入一个数字的下标之前,首先要判断队列里已有数字是否小于待存入的数字。如果已有的数字小于待存入的数字,那么这些数字不可能是滑动窗口的最大值,因此将他们一次pop_back。同时,如果队列头部的数字已经从窗口滑出,那么滑出的数字也需要从队列的头部删除(pop_front)。

class Solution {
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size)
    {
        vector<int> maxInWindows;
        if(num.size()>=size&&size>=1)
        {
            deque<int> index;
            for(unsigned int i=0;i<size;i++)//放入一个滑动窗口,令队头是窗口的最大值
            {
                while(!index.empty()&&num[i]>=num[index.back()])
                {
                    index.pop_back();//要放入的数大于队尾,就把队尾弹出
                }
                index.push_back(i);//放入新数字
            }
            for(unsigned int i=size;i<num.size();i++)
            {
                maxInWindows.push_back(num[index.front()]);//存一个最大值
                while(!index.empty()&&num[i]>=num[index.back()])
                    index.pop_back();//要放入的数大于队尾,就把队尾弹出
                if(!index.empty()&&index.front()<=(int)(i-size))
                    index.pop_front();//队头大于滑动窗口范围,就弹出
                index.push_back(i);//放入新数字
            }
            maxInWindows.push_back(num[index.front()]);
        }
        return maxInWindows;
    }
};

2.n个骰子的点数
n个骰子扔在地上,所有骰子朝上一面的点数之和为s,输入n,打印出s的所有可能值出现的概率。
思路:基于循环求骰子点数:考虑两个数组来存储骰子点数的每个总数出现的次数。在一轮循环中,第一个数组中的第n个数字表示骰子和为n出现的次数。在下一轮循环中,加上一个新的骰子,此时和为n的骰子出现的次数应该等于上一轮循环中骰子点数和为n-1,n-2,n-3,n-4,n-5,n-6的次数的总和,所以我们把另一个数组的第n个数字设为前一个数组对应的第n-1,n-2,n-3,n-4,n-5,n-6个数字之和

    void PrintProbability(int number)//n
    {
        if(number<1) return;
        int* pProbabilities[2];
        pProbabilities[0]=new int[g_maxValue*number+1];//6*n+1
        pProbabilities[1]=new int[g_maxValue*number+1];
        for(int i=0;i<g_maxValue*number+1;i++)
        {
            pProbabilities[0][i]=0;
            pProbabilities[1][i]=0;
        }
        int flag=0;
        for(int i=1;i<=g_maxValue;i++)
        {
            pProbabilities[flag][i]=1;
        }//只有一个骰子
        for(int k=2;k<=number;k++)
        {
            for(int i=0;i<k;i++)
            {
                pProbabilities[1-flag][i]=0;
            }
            for(int i=k;i<=g_maxValue*k;i++)
            {
                pProbabilities[1-flag][i]=0;
                for(int j=1;j<=i&&j<=g_maxValue;j++)
                {
                    pProbabilities[1-flag][i]+=pProbabilities[flag][i-j];//f(n)=f(n-1)+...+f(n-6)
                }
            }
            flag=1-flag;//交换两个数组
        }
        double total=pow((double)g_maxValue,number);
        for(int i=number;i<=g_maxValue*number;i++)
        {
            double ratio=(double)pProbabilities[flag][i]/total;
            printf("%d: %e\n",i,ratio);
        }
        delete[] pProbabilities[0];
        delete[] pProbabilities[1];
    }

3.扑克牌中的顺子
从扑克牌中随机抽取5张牌,判断是不是一个顺子。A代表1,J-K 11-13,大小王看作任意数字。
思路:首先把数组排序;其次统计0的个数;最后统计排序之后的数组中相邻数字之间的空缺总数。如果空缺的总数小于或等于0的个数,那么此数组连续;否则不连续。另外要注意不能有对子出现。

class Solution {
public:
    bool IsContinuous( vector<int> numbers ) {
        int len=numbers.size();
        if(len!=5) return false;
        sort(numbers.begin(),numbers.end());
        int num=0;
        for(int i=0;i<len&&numbers[i]==0;i++)
        {
            num++;//统计0的数目
        }
        int small=num;
        int big=small+1;
        int sumOfGap=0;
        while(big<len)
        {
            if(numbers[small]==numbers[big])
                return false;//出现了对子
            sumOfGap+=numbers[big]-numbers[small]-1;//记录二者间的距离
            if(sumOfGap>num)//一旦此距离不能用0填,就返回false
                return false;
            small++;
            big++;
        }
        return true;
    }
};