1.给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。
分析:
- 字符'a'-'z'(如果有大写转化为小写即可)
- 使用大小为26的整型数Num_char组int Num_char[26]]存储每个字符出现的次数(初始化为0)
- 使用大小为26的整型数组int Pos_char[26]存储字符串中出现的每个字符出现的最早位置(初始化为-1)
- 遍历字符串更新Num_char和Pos_char数组
- 遍历Num_char和Pos_char数组,找到Num_char[i]=1且Pos_char[i]最小的i,返回
代码:
int main()
{
string s="";
char c=cin.get();
while(c!='\n'){
if(c=='\''||c==','||c=='.'||c==' '){
s=s; }else{ s+=c; } c=cin.get(); } int n=s.size(); int Pos_start[26]; int num_char[26]; for(int i=0;i<26;i++){ Pos_start[i]=-1; num_char[i]=0; } for(int i=0;i<n;i++){ int tmp=s[i]-'a'; num_char[tmp]++; if(Pos_start[tmp]==-1){ Pos_start[tmp]=i; } } int index=n; for(int i=0;i<26;i++){ if(num_char[i]==1){ if(Pos_start[i]<index){ index=Pos_start[i]; } } } cout<<index<<endl; return 0; }
2.最长可整合子数组的长度
题目描述
先给出可整合数组的定义:如果一个数组在排序之后,每相邻两个数的差的绝对值都为1,或者该数组长度为1,则该数组为可整合数组。例如,[5, 3, 4, 6, 2]排序后为[2, 3, 4, 5, 6],符合每相邻两个数差的绝对值都为1,所以这个数组为可整合数组
给定一个数组arr, 请返回其中最大可整合子数组的长度。例如,[5, 5, 3, 2, 6, 4, 3]的最大可整合子数组为[5, 3, 2, 6, 4],所以请返回5
[要求]
时间复杂度为
O(n^2)O(n2),空间复杂度为O(n)O(n)
输入描述:
第一行一个整数N,表示数组长度
第二行N个整数,分别表示数组内的元素
输出描述:
输出一个整数,表示最大可整合子数组的长度
分析:
- 求排序后最长递增且间隔为1的子序列的长度
- 使用set<int> A有序且无重复存储数组
- 定义一维数组dp[A.size()],dp[i]存储的是该位置前最长递增且间隔为1的子序列的长度。
- 如果(A[i]-A[i-1]==1) dp[i]=dp[i-1]+1;否则dp[i]=1;
代码:
#include <iostream> #include<set> using namespace std; int main() { int N; cin>>N; set<int> A; int a; for(int i=0;i<N;i++){ cin>>a; A.insert(a); } int len=A.size(); if(len<=1){ cout<<len<<endl; return 0; } int dp[len]; dp[0]=1; int res=1; set<int>::iterator it=A.begin(); it++; int i=1; for(;it!=A.end();it++,i++){ if(*(it--)-*it==1){ dp[i]=dp[i-1]+1; if(dp[i]>res){ res=dp[i]; } }else{ dp[i]=1; } it++; } cout<<res<<endl; return 0; }
3.不重复打印排序数组中相加和为给定值的所有二元组
题目描述
给定排序数组arr和整数k,不重复打印arr中所有相加和为k的不降序二元组
例如, arr = [-8, -4, -3, 0, 1, 2, 4, 5, 8, 9], k = 10,打印结果为:
1, 9
2, 8
[要求]
时间复杂度为
O(n)O(n),空间复杂度为O(1)O(1)
输入描述:
第一行有两个整数n, k
接下来一行有n个整数表示数组内的元素
输出描述:
输出若干行,每行两个整数表示答案
按二元组从小到大的顺序输出(二元组大小比较方式为每个依次比较二元组内每个数)
分析:
- 数组有序,所以可以用两个指针i,j分别从首尾遍历数组A[n];
- 如果A[i]+A[j]>给定值k,说明后面的指针应该往前移,使和减小,j--;
- 如果A[i]+A[j]<给定值k,说明前面的指针i应该往后移,使和增大,i++;
- 如果A[i]+A[j]=给定值k,输出A[i] A[j];同时看数组中是否有和A[i]、A[j]值相同的元素,有则跳过。
代码:
#include <iostream> #include<vector> using namespace std; int main() { int n,k; cin>>n>>k; vector<int> A(n); for(int i=0;i<n;i++){ cin>>A[i]; } int low=0; int high=n-1; while(low<high){ if(A[low]+A[high]==k){ cout<<A[low]<<" "<<A[high]<<endl; while(low+1<n&&A[low]==A[low+1])low++; while(high-1>=0&&A[high]==A[high-1])high--; low++; high--; }else if(A[low]+A[high]>k){ high--; }else{ low++; } } return 0; }
4、设计getMin功能的栈
题目描述
实现一个特殊功能的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。
输入描述:
第一行输入一个整数N,表示对栈进行的操作总数。
下面N行每行输入一个字符串S,表示操作的种类。
如果S为"push",则后面还有一个整数X表示向栈里压入整数X。
如果S为"pop",则表示弹出栈顶操作。
如果S为"getMin",则表示询问当前栈中的最小元素是多少。
示例1
输入
6 push 3 push 2 push 1 getMin pop getMin
输出
1 2
分析:
- 需要两个栈,一个用来存储所有元素main_stack,一个用来存储最小元素min_stack(min_stack的栈顶元素始终是main_stack栈中的最小元素)
- push操作,向main_stack栈中添加一个元素;当添加元素小于等于min_stack栈顶元素时或者min_stack为空时,则将该元素也加入min_stack中;
- pop操作,main_stack栈顶元素出栈,如果main_stack出栈的元素等于min_stack的栈顶元素,则,min_stack栈顶元素出栈。
- getMin操作,返回min_stack的栈顶元素
代码:
#include <iostream> #include<stack> using namespace std; class SStack{ public: stack<int> main_stack; stack<int> min_stack; public: void push(int a){ main_stack.push(a); if(min_stack.empty()||min_stack.top()>=a){ min_stack.push(a); } } void pop(){ if(main_stack.top()==min_stack.top()){ min_stack.pop(); } main_stack.pop(); } int getMin(){ if(!min_stack.empty()) return min_stack.top(); else{ return -1; } } }; int main() { SStack ss; int n; cin>>n; string op; int a; for(int i=0;i<n;i++){ cin>>op; if(op=="push"){ cin>>a; ss.push(a); }else if(op=="pop"){ ss.pop(); }else if(op=="getMin"){ cout<<ss.getMin()<<endl; } } return 0; }
5、由两个栈组成队列
题目描述
用两个栈实现队列,支持队列的基本操作。
输入描述:
第一行输入一个整数N,表示对队列进行的操作总数。
下面N行每行输入一个字符串S,表示操作的种类。
如果S为"add",则后面还有一个整数X表示向队列尾部加入整数X。
如果S为"poll",则表示弹出队列头部操作。
如果S为"peek",则表示询问当前队列中头部元素是多少。
输出描述:
对于每一个为"peek"的操作,输出一行表示当前队列中头部元素是多少。
示例1
输入
6 add 1 add 2 add 3 peek poll peek
输出
1 2
分析:
- 栈s1负责进队,栈s2负责出队
- add操作,栈s1进栈
- poll操作,栈s2出栈;栈s2为空时,先将栈s1的元素依次弹出并压入栈s2,再对栈s2执行弹出操作
- peek操作,获取栈s2栈顶的元素;栈s2为空时,先将栈s1的元素依次弹出并压入栈s2,再对栈s2执行返回栈顶元素操作
代码:
#include <iostream> #include<stack> using namespace std; class QQue{ public: stack<int> s1; stack<int> s2; public: void add(int a){ s1.push(a); } void poll(){ if(s2.empty()){ while(!s1.empty()){ s2.push(s1.top()); s1.pop(); } } s2.pop(); } int peek(){ if(s2.empty()){ while(!s1.empty()){ s2.push(s1.top()); s1.pop(); } } if(s2.empty()){ return -1; } return s2.top(); } }; int main() { int n; cin>>n; QQue qq; string s; int a; for(int i=0;i<n;i++){ cin>>s; if(s=="add"){ cin>>a; qq.add(a); }else if(s=="poll"){ qq.poll(); }else if(s=="peek"){ cout<<qq.peek()<<endl; } } return 0; }
6、用递归函数和栈逆序一个栈
题目描述
一个栈依次压入1,2,3,4,5,那么从栈顶到栈底分别为5,4,3,2,1。将这个栈转置后,从栈顶到栈底为1,2,3,4,5,也就是实现栈中元素的逆序,但是只能用递归函数来实现,不能用其他数据结构。
输入描述:
输入数据第一行一个整数N为栈中元素的个数。
接下来一行N个整数X_iXi表示从栈顶依次到栈底的每个元素。
输出描述:
输出一行表示栈中元素逆序后的每个元素
示例1
输入
5
1 2 3 4 5
输出
5 4 3 2 1
分析:
- 首先输入是从栈顶到栈底的元素,那么首先要把这些元素从栈底到栈顶存储
- 打印栈时,先打印栈底元素,再打印栈顶元素(递归实现,对于栈中每个元素,先打印其底部的元素,再打印该元素)
代码:
#include <iostream> #include<stack> using namespace std; void f(stack<int> s){ if(s.empty()) return; else{ int a=s.top(); s.pop(); f(s); cout<<a<<" "; } } int main() { int n; cin>>n; stack<int> s; int A[n]; for(int i=0;i<n;i++){ cin>>A[i]; } for(int i=n-1;i>=0;i--){ s.push(A[i]); } f(s); cout<<endl; return 0; }