第二篇是后面的30题,不是那么容易做出来
1.统计一个数字在排序数组中出现的次数。
这个是两次binary search
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
int number=0;
int length=data.size();
if(data.empty()!=true&&length>0){
int first=getfirstk(data,length,k,0,length-1);
int last=getlastk(data,length,k,0,length-1);
if(first>-1&&last>-1){
number=last-first+1;
}
}
return number;
}
int getfirstk(vector<int>data,int length,int k,int start,int end){
if(start>end) return -1;
int middleIndex=(start+end)/2;
int middleData=data[middleIndex];
if(middleData==k){
if((middleIndex>0&&data[middleIndex-1]!=k)||middleIndex==0){
return middleIndex;
}
else
end=middleIndex-1;
}
else if(middleData>k)
end=middleIndex-1;
else
start=middleIndex+1;
return
getfirstk(data,length,k,start,end);
}
int getlastk(vector<int>data,int length,int k,int start,int end){
if(start>end)
return -1;
int middleIndex=(start+end)/2;
int middleData=data[middleIndex];
if(middleData==k){
if((middleIndex1&&data[middleIndex+1]!=k)||middleIndex==length-1)
return middleIndex;
else
start=middleIndex+1;
}
else if(middleData1;
else
end=middleIndex-1;
return getlastk(data,length,k,start,end);
}
};
2.输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
class Solution {
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV) {
bool mark=false;
auto rush=pushV.begin();
auto pops=popV.begin();
int len=pushV.size();
stack<int> stacks;
if((pushV.size()!=popV.size())||(pushV.empty()))
return mark;
//stacks.push(*rush);
while((pops!=popV.end())){
while((stacks.empty()||(stacks.top()!=*pops))&&(rush!=pushV.end())){
stacks.push(*rush);
rush++;
}
if(stacks.top()!=*pops) break;
stacks.pop();
pops++;
}
if(stacks.empty()&&pops==popV.end()) mark=true;
return mark;
}
};
3.输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
这道题书本上的答案我感觉不太适合我自己,所以修改了一下然后通过了。
class Solution {
public:
bool VerifySquenceOfBST(vector<int> sequence) {
if(sequence.empty()) return false;
return solve(sequence,0,sequence.size());
}
bool solve(vector<int>& nums,int begin,int end){
if(nums.empty()||(end-begin)<=0) return false;
int root=nums[end-1];
int i=begin;
for( ;i1;i++){
if(nums[i]>root) break;
}
int j=i;
for(;j1;j++){
if(nums[j]return false;
}
bool left=true;
if(i>begin)left=solve(nums,begin,i);
bool right=true;
if(i+11)right=solve(nums,i+1,end);
return left&&right;
}
};
4.每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数….这样下去….直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
注意这里要用list,如果用vector的erase的话,其在删除后会自动往后走一格。
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
if(n<1||m<1) return -1;
list<int> nums;
for(int i=0;iauto it=nums.begin();
while(nums.size()>1){
for(int i=1;iif(it==nums.end()){
it=nums.begin();
}
}
auto next=++it;
if(next==nums.end()){
next=nums.begin();
}
it--;
nums.erase(it);
it=next;
}
return nums.front();
}
};
5.输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
注意set可以去重和排序
class Solution {
public:
set<string> result;
vector<string> Permutation(string str) {
if(str.empty()) return vector<string>(result.begin(),result.end());
permute(str,0);
return vector<string>(result.begin(),result.end());
}
void permute(string str,int begin){
if(begin==str.size()){
result.insert(str);
return ;
}
for(int i=begin;i//if(i!=begin&&str[i]==str[i-1])continue;
swap(str[begin],str[i]);
permute(str,begin+1);
swap(str[begin],str[i]);
}
}
};
6.小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
vector<vector<int>> result;
if(sum<3){
return result;
}
int small=1,big=2,middle=(1+sum)/2;
int cursum=small+big;
while(smallif(cursum==sum){
vector<int> res;
for(int i=small;i<=big;i++){
res.push_back(i);
}
result.push_back(res);
}
while(smallsum){
cursum-=small;
small++;
if(cursum==sum){
vector<int> res;
for(int i=small;i<=big;i++){
res.push_back(i);
}
result.push_back(res);
}
}
big++;
cursum+=big;
}
return result;
}
};
7.将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
输入描述:
输入一个字符串,包括数字字母符号,可以为空
输出描述:
如果是合法的数值表达则返回该数字,否则返回0
class Solution {
public:
int StrToInt(string str) {
if(str.empty()) return 0;
int i=0;
for(;i<str.size();i++){
if(str[i]!=' ') break;
}
str=str.substr(i);
int j;
for(j=str.size()-1;j>=0;j--){
if(str[j]!=' ') break;
}
str=str.substr(0,j+1);
long long num=0;
int mark=1;
i=0;
if(str[i]=='-') {mark=-1;i++;}
else if(str[i]=='+'){mark=1;i++;}
for(;i<str.size();i++){
if((str[i]<='9')&&(str[i]>='0')) num=(str[i]-'0')+num*10;
else return 0;
}
return num*mark;
}
};
8.在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
class Solution {
public:
// Parameters:
// numbers: an array of integers
// length: the length of array numbers
// duplication: (Output) the duplicated number in the array number
// Return value: true if the input is valid, and there are some duplications in the array number
// otherwise false
bool duplicate(int numbers[], int length, int* duplication) {
if(length<=0||numbers==NULL) return false;
vector<int> nums;
for(int i=0;iif(numbers[i]<0||numbers[i]>length-1){
return false;
}
nums.push_back(numbers[i]);
}
for(int i=0;iwhile(nums[i]!=i){
if(nums[i]==nums[nums[i]]){
*duplication=nums[i];
return true;
}
swap(nums[i],nums[nums[i]]);
}
}
return false;
}
};
9.一个链表中包含环,请找出该链表的环的入口结点。
思路:首先算出环的节点个数,就是快慢指针(一个每次走一步,一个走两步)第一次碰撞后,开始计数直到第二次碰撞,这个数就是环节点个数k。然后让快慢指针(一个先走k步,为快指针)从头开始走,都是每次走一步,直到他们碰撞就是环入口节点。因为快指针就是比慢指针快环的长度。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(!pHead) return NULL;
ListNode* head=pHead;
ListNode* fast=head,*slow=head;
while(fast&&fast->next){
fast=fast->next->next;
slow=slow->next;
if(fast==slow) break;
}
if((fast==NULL)||(fast->next==NULL)) return NULL;
int num=0;
while(1){
fast=fast->next->next;
slow=slow->next;
num++;
if(fast==slow) break;
}
fast=head;
slow=head;
while(num--){
fast=fast->next;
}
while(fast!=slow){
fast=fast->next;
slow=slow->next;
}
return fast;
}
};
10.给定一颗二叉搜索树,请找出其中的第k大的结点。例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中,按结点数值大小顺序第三个结点的值为4。
这道题按理说不难,就是中序遍历然后是第k个数,但是还是花了一些时间。因为忘记中序遍历怎么写了。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
TreeNode* result=NULL;
int begin=0;
TreeNode* KthNode(TreeNode* pRoot, int k)
{
if(!pRoot) return pRoot;
if(k==0) return NULL;
dfs(pRoot,k);
return result;
}
void dfs(TreeNode* root,int k){
if(!root) return ;
if(root->left) dfs(root->left,k);
begin++;
if(begin==k) {result=root;return;}
if(root->right) dfs(root->right,k);
}
};
11.给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
要分三种情况考虑
1.如果一个节点有右子树,那么他的下一个节点就是他的右子树中的最左子节点
2.如果其没有右子树,而且他是父节点的左子树,那么就是其父节点
3.如果没有右子节点,而且它还是其父节点的右子节点,那么就一直往上走,直到找到一个是它父节点的子节点的左子节点的节点。
/*
struct TreeLinkNode {
int val;
struct TreeLinkNode *left;
struct TreeLinkNode *right;
struct TreeLinkNode *next;
TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
}
};
*/
class Solution {
public:
TreeLinkNode* GetNext(TreeLinkNode* pNode)
{
TreeLinkNode* root=pNode;
if(!root) return NULL;
TreeLinkNode* nextnode=NULL;
if(root->right){
TreeLinkNode* rightnode=root->right;
while(rightnode->left)
rightnode=rightnode->left;
nextnode=rightnode;
}
else if(root->next){
TreeLinkNode* current=root;
TreeLinkNode* parent=root->next;
while(parent&¤t==parent->right){
current=parent;
parent=parent->next;
}
nextnode=parent;
}
return nextnode;
}
};
12.如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
这道题是别人做出来的。
class Solution {
priority_queue<int, vector<int>, less<int> > p;
priority_queue<int, vector<int>, greater<int> > q;
public:
void Insert(int num){
if(p.empty() || num <= p.top()) p.push(num);
else q.push(num);
if(p.size() == q.size() + 2) q.push(p.top()), p.pop();
if(p.size() + 1 == q.size()) p.push(q.top()), q.pop();
}
double GetMedian(){
return p.size() == q.size() ? (p.top() + q.top()) / 2.0 : p.top();
}
};