剑指offer刷题记录2
来源:互联网 发布:python财经数据接口包 编辑:程序博客网 时间:2024/05/17 08:11
第二篇是后面的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((middleIndex<length-1&&data[middleIndex+1]!=k)||middleIndex==length-1) return middleIndex; else start=middleIndex+1; } else if(middleData<k) start=middleIndex+1; 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( ;i<end-1;i++){ if(nums[i]>root) break; } int j=i; for(;j<end-1;j++){ if(nums[j]<root) return false; } bool left=true; if(i>begin)left=solve(nums,begin,i); bool right=true; if(i+1<end-1)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;i<n;i++){ nums.push_back(i); } auto it=nums.begin(); while(nums.size()>1){ for(int i=1;i<m;i++){ it++; if(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<str.size();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(small<middle){ if(cursum==sum){ vector<int> res; for(int i=small;i<=big;i++){ res.push_back(i); } result.push_back(res); } while(small<middle&&cursum>sum){ 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;i<length;i++){ if(numbers[i]<0||numbers[i]>length-1){ return false; } nums.push_back(numbers[i]); } for(int i=0;i<length;i++){ while(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(); }};
- 剑指offer刷题记录2
- 剑指offer刷题记录1
- 剑指offer 日常刷题记录
- 牛客剑指offer刷题记录(一)
- 牛客剑指offer刷题记录(二)
- 牛客剑指offer刷题记录(三)
- 牛客剑指offer刷题记录(四)
- 牛客剑指offer刷题记录(五)
- 牛客剑指offer刷题记录(六)
- 牛客剑指offer刷题记录(七)
- 剑指offer 牛客网错题记录 四
- 牛客网 剑指offer系列 错题记录一
- 牛客网 剑指offer系列 错题记录二
- BZOJ 刷题记录 PART 2
- bzoj刷题记录2017.4.2-4.4
- 刷题记录-codevs2144 砝码称重 2
- OI刷题记录
- OI刷题记录~
- Spring4.3x教程之三AOP详解
- chatterbot初步使用
- JuniperSRX---------rpm配合track完成双线主备
- bzoj 1483: [HNOI2009]梦幻布丁 线段树合并
- oracle做了update的误操作,怎么恢复之前数据
- 剑指offer刷题记录2
- 计算经纬度距离
- spring boot mybatis
- PDO中包含三个预定义的类--PDO、PDOStatement和PDOException
- Oracle复杂查询案例
- 进制之间相互转换工具
- spring-boot项目在外部tomcat环境下部署
- 文章标题 linux 系统性能查看即监控详解
- OData demo 2