目录
1.剑指Offer
面试题9:用两个栈实现队列
题目描述:用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
思路:画图
代码:
class Solution
{
public:
void push(int node) {
stack1.push(node);
}
int pop() {
if(stack2.size()<=0){
while(stack1.size()){
int data=stack1.top();
stack1.pop();
stack2.push(data);
}
}
int head=stack2.top();
stack2.pop();
return head;
}
private:
stack<int> stack1;
stack<int> stack2;
};
leetcode
class MyQueue {
public:
/** Initialize your data structure here. */
MyQueue() {
}
stack<int> stk;
/** Push element x to the back of queue. */
void push(int x) {
stack<int> tmp;
while(!stk.empty()){
tmp.push(stk.top());
stk.pop();
}
stk.push(x);
while(!tmp.empty()){
stk.push(tmp.top());
tmp.pop();
}
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
int data=stk.top();
stk.pop();
return data;
}
/** Get the front element. */
int peek() {
return stk.top();
}
/** Returns whether the queue is empty. */
bool empty() {
return stk.empty();
}
};
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue* obj = new MyQueue();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->empty();
*/
面试题9:用两个队列实现栈
题目描述:
使用队列实现栈的下列操作:
- push(x) -- 元素 x 入栈
- pop() -- 移除栈顶元素
- top() -- 获取栈顶元素
- empty() -- 返回栈是否为空
注意:
- 你只能使用队列的基本操作-- 也就是
push to back
,peek/pop from front
,size
, 和is empty
这些操作是合法的。 - 你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
- 你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)。
代码:
class MyStack {
public:
/** Initialize your data structure here. */
MyStack() {
}
queue<int> queue1;
/** Push element x onto stack. */
void push(int x) {
queue<int> queue2;
while(!queue1.empty()){
queue2.push(queue1.front());
queue1.pop();
}
queue1.push(x);
while(!queue2.empty()){
queue1.push(queue2.front());
queue2.pop();
}
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int data=queue1.front();
queue1.pop();
return data;
}
/** Get the top element. */
int top() {
return queue1.front();
}
/** Returns whether the stack is empty. */
bool empty() {
return queue1.empty();
}
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack* obj = new MyStack();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->top();
* bool param_4 = obj->empty();
*/
面试题31:栈的压入、弹出序列
题目描述:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列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 flag=false;
if(!pushV.empty()&&!popV.empty()){
stack<int> stk;
int lenPush=pushV.size();
int lenPop=popV.size();
int i=0;
int j=0;
while(i<lenPop){
while(stk.empty()||stk.top()!=popV[i]){
if(j>lenPush){
break;
}
stk.push(pushV[j]);
j++;
}
if(stk.top()!=popV[i]){
break;
}
i++;
stk.pop();
}
if(stk.empty()&&i==lenPop){
flag=true;
}
}
return flag;
}
};
3.华为机试题
例1:简单错误记录
题目描述:
开发一个简单错误记录功能小模块,能够记录出错的代码所在的文件名称和行号。
处理:
1、 记录最多8条错误记录,循环记录,对相同的错误记录(净文件名称和行号完全匹配)只记录一条,错误计数增加;
2、 超过16个字符的文件名称,只记录文件的最后有效16个字符;
3、 输入的文件可能带路径,记录文件名称不能带路径。
输入描述:
一行或多行字符串。每行包括带路径文件名称,行号,以空格隔开。
输出描述:
将所有的记录统计并将结果输出,格式:文件名 代码行数 数目,一个空格隔开,如:
示例1
输入
E:\V1R2\product\fpgadrive.c 1325
输出
fpgadrive.c 1325 1
思路:结构体
代码:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <sstream>
using namespace std;
string getFileName(string path){
int pos = path.rfind('\\');
return path.substr(pos+1);
}
string modifyName(string filename){
int len=filename.length();
if(len>16){
return filename.substr(len-16);
}
return filename;
}
struct ErrRecord{
string filename;
int linenum;
int cnt;
ErrRecord(string filename, int linenum){
this->filename=filename;
this->linenum=linenum;
this->cnt=1;
}
bool operator == (const ErrRecord & a){
return (filename==a.filename)&&(linenum==a.linenum);
}
}; //结构体末尾要加;
int main(){
string fileName;
int lineNum;
vector<ErrRecord> vec;
while(cin >> fileName >> lineNum){ //输入文件
ErrRecord record(getFileName(fileName),lineNum);
auto res=find(vec.begin(),vec.end(),record);
if(res==vec.end()){
vec.push_back(record);
}
else{
res->cnt++;
}
}
int count=0;
for(auto item : vec){ //只输出最后8条,注意用for循环
if((count+8) >= vec.size()){
cout << modifyName(item.filename) << " " << item.linenum << " " << item.cnt << endl;
}
count++;
}
return 0;
}
例2:密码验证合格程序
题目描述:
密码要求:
1.长度超过8位
2.包括大小写字母.数字.其它符号,以上四种至少三种
3.不能有相同长度超2的子串重复
说明:长度超过2的子串
输入描述:
一组或多组长度超过2的子符串。每组占一行
输出描述:
如果符合要求输出:OK,否则输出NG
示例1
输入
021Abc9000
021Abc9Abc1
021ABC9000
021$bc9000
输出
OK NG NG OK
思路:后缀数组比较
时间复杂度O(n*
log
(n))->sort()
判断字符串中是否有长度超过m的重复子串的方法是后缀数组法
即统计每个单词的后缀数组,例如对字符串abcdefgabcbc:
a->abcdefgabcbc
b->bcdefgabcbc
...
a->abcbc
b->bcbc
之后在对这个数组进行排序:
a->abcdefgabcbc
a->abcbc
b->bcdefgabcbc
b->bcbc
再对相邻的数组比较前m个字段
代码:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
bool cmp(string a,string b){
return a[0]<b[0];
}
bool JudgeRepeatStr(string str,int m){
int len=str.length();
string* suffix=new string[len-m];
for(int i=0;i<len-m;i++){
suffix[i]=str.substr(i,len-i);
}
sort(suffix,suffix+len-m,cmp);
for(int i=0;i<len-m-1;i++){
if(suffix[i].substr(0,m+1)==suffix[i+1].substr(0,m+1)){
return true;
}
}
return false;
}
int main(){
string str;
while(cin>>str){
int len=str.length();
if(len<=8){
cout << "NG" << endl;
continue;
}
int mark[4]={0};
for(int i=0;i<len;i++){
if(str[i]>='A'&&str[i]<='Z'){
mark[0]++;
}
else if(str[i]>='a'&&str[i]<='z'){
mark[1]++;
}
else if(str[i]>='0'&&str[i]<='9'){
mark[2]++;
}
else{
mark[3]++;
}
}
int typeNum=(mark[0]>0)+(mark[1]>0)+(mark[2]>0)+(mark[3]>0);
if(typeNum>=3&&JudgeRepeatStr(str,2)==0){
cout << "OK" << endl;
}
else{
cout << "NG" << endl;
}
}
return 0;
}
例3:简单密码
题目描述:
密码是我们生活中非常重要的东东,我们的那么一点不能说的秘密就全靠它了。哇哈哈. 接下来渊子要在密码之上再加一套密码,虽然简单但也安全。
假设渊子原来一个BBS上的密码为zvbo9441987,为了方便记忆,他通过一种算法把这个密码变换成YUANzhi1987,这个密码是他的名字和出生年份,怎么忘都忘不了,而且可以明目张胆地放在显眼的地方而不被别人知道真正的密码。
他是这么变换的,大家都知道手机上的字母: 1--1, abc--2, def--3, ghi--4, jkl--5, mno--6, pqrs--7, tuv--8 wxyz--9, 0--0,就这么简单,渊子把密码中出现的小写字母都变成对应的数字,数字和其他的符号都不做变换,
声明:密码中没有空格,而密码中出现的大写字母则变成小写之后往后移一位,如:X,先变成小写,再往后移一位,不就是y了嘛,简单吧。记住,z往后移是a哦。
输入描述:
输入包括多个测试数据。输入是一个明文,密码长度不超过100个字符,输入直到文件结尾
输出描述:
输出渊子真正的密文
示例1
输入
YUANzhi1987
输出
zvbo9441987
代码:
#include<iostream>
using namespace std;
int table[26] = {2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9};
int main(){
string str;
while(cin>>str){
for(int i = 0; i < str.size(); ++i){
if(str[i] >= 'A' && str[i] < 'Z')
cout<<(char)(str[i]-'A'+'a'+1);
else if(str[i] == 'Z')
cout<<'a';
else if(str[i] >= 'a' && str[i] <= 'z')
cout<<table[str[i]-'a'];
else cout<<str[i];
}
cout<<endl;
}
return 0;
}
疑问:
用一个新string保存新的结果,无论是+或是push_back,都不能通过!
#include <iostream>
#include <string>
using namespace std;
int table[26]={2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9};
int main(){
string str;
while(cin>>str){
string str2="";
for(int i=0;i<str.length();i++){
if(str[i]>='A'&&str[i]<'Z'){
str2+=char(str[i]-'A'+'a'+1);
}
else if(str[i]=='Z'){
str2+='a';
}
else if(str[i]>='a'&&str[i]<='z'){
str2+=table[str[i]-'a'];
}
else{
str2+=str[i];
}
}
cout << str2 << endl;
}
return 0;
}
错误:
不通过
您的代码已保存
答案错误:您提交的程序没有通过所有的测试用例
case通过率为0.00%
用例:
CJFRR8pYzTjcMy860OS96WRU9C9XjNW178n1FnFmpNcUvrS
对应输出应该为:
dkgss87z9u52n9860pt96xsv9d9y5ox17861g6g67o2v87t
你的输出为:
dkgss8z un 860pt96xsv9d9yox1781ggovt
解析:
string中的push_back函数,作用是字符串之后插入一个字符。