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; } };