字符串相关的高频面试题
2017-06-27 16:12
459 查看
1. 给定一个字符串str,将其中所有空格字符替换成“%20”,假设str后面有足够的空间。
方法为遍历str,发现空格的数量为s,所以str在替换后 ,长度为 原来的长度+2*s。
然后从下标为原来的长度+2*s-1的地方开始拷贝的过程,从后向前拷贝!!
class Replacement {
public:
string replaceSpace(string iniString, int length) {
// write code here
int count=0;
for(int i=0;i<length;i++){
if(iniString[i]==' ')
count++;
}//这里是统计空格的数量
int end1=length+2*count-1;//count代表空格的数量,end为替换后的字符串的长度-1
int end2=length-1;
for(int j=length;j<=end1;j++)
iniString=iniString+' ';//必须要将iniString中需要额外添加的空间进行初始化,否则的话iniSstring的长度就是length,如果访问end2的话就会数组越界
//对于上面的初始化来说,如果iniString的长度就是length的话,那么久不可以用下标的方式访问大于length长度的字符,也就是说初始化的时候不可以使用
//iniString[length]=' ',这样是错误的!!!!!!这里可以用拼接的方式
while(end2>=0){
if(iniString[end2]!=' '){
iniString[end1]=iniString[end2];
end2--;
end1--;
}else {
end2--;
iniString[end1--]='0';
iniString[end1--]='2';
iniString[end1--]='%';
}
}
return iniString;
}
};
对于上面的程序来说,一定更要注意数组越界的问题。
2. 给定给一个字符串str,判断是不是整体有效的括号字符串。
这道题的最优解可以做到时间复杂度为o(n),额外空间复杂度为o(1)。
思路为首先,整形变量num,代表'('出现次数与')'出现次数的差值。
遍历的过程中,如果遇到‘(’则num++;
遍历的过程中,如果遇到‘)’则num--;
遍历的过程中如果num<0,则直接返回false;说明左括号的数量小于右括号,右括号多了!
如果一直没有出现上面的情况,则一直遍历下去;
遍历完成后,如果num==0,则返回true,否则返回false。
class Parenthesis {
public:
bool chkParenthesis(string A, int n) {
// write code here
int lcount=0;//统计( 的数量,遇到)就会减一
for(int i=0;i<n;i++){
if(A[i]=='(')
lcount++;
else if(A[i]==')'){
lcount--;
if(lcount<0){
break;
}
}else
return false;
}
return lcount==0;
}
};
注意上面的程序一定更要注意有非()字符的情况,这种能够情况直接放回false。
3. 给定一个字符串str返回str的最长无重复字符子串的长度。
这道题的最后解为时间复杂度o(n),额外空间复杂度为o(n)。
主要思路为从左到右,依次求出以str中每个字符结尾的情况下,向左最远的最长无重复字符子串的长度,并在其中找出最大值返回。
在求以s[i]位置处的变量为结尾的向左最长无重复子串长度的时候需要借助于两个变量:
第一是哈希表,记录每种字符之前出现的位置;
第二是pre,代表以s[i-1]结尾的情况下,向左最长无重复子串的长度。
首先从哈希表中取出map.get(s[i])也就是s[i]上次出现的位置A;
然后找到pre记为位置B;
A/B中取最大的那个,也就是靠右的那个。
最后s[i]的位置在哈希表中更新;
根据当前最长无重复字符子串的长度更新pre。
class DistinctSubstring {
public:
int longestSubstring(string A, int n) {
// write code here
map<char,int> position;//哈希表里面存放的是字符和该字符上次出现的位置!!!
int *pre=new int
;
pre[0]=1;//代表当前包括i在内的向左最长无重复子串的长度
int positionA;//表示用hash表查出的上一次A[i]出现的位置
int positionB;//表示用pre记录的最左边的A[i-1]的最长无重复子串的位置,是位置下标不是长度,也就是
//从A[i-1]开始向左能到的最左的位置,这之间都是无重复的字符
position.insert(pair<char,int>(A[0],0));
map<char,int>::iterator iter;
for(int i=1;i<n;i++){
if(position.find(A[i]) == position.end()){//说明A[i]之前没有出现过
position.insert(pair<char,int>(A[i],i));
positionA=-1;
} else{
iter=position.find(A[i]);
positionA=iter->second+1;//查找到的上一个A[i]出现的位置的下一个位置
position[A[i]]=i;//即使找到了也要进行更新,不过这里不是使用insert插入,而是修改原来哈希表中存在的值
}
if(i>0)
positionB=i-pre[i-1];
else
positionB=0;
int m=positionA;
if(positionB>m)
m=positionB;
pre[i]=i-m+1;
}
int max=pre[0];
for(int i=0;i<n;i++){
if(pre[i]>max)
max=pre[i];
}
return max;
}
};
上面的程序中主要是对hash表的操作,十分重要,增加记录(insert)、修改记录(直接用下标)、以及查找记录find等。其中用find的返回的值是一个迭代器的指针,这个指针指向的值是一个pair类型的,通过map对象的方法获取的iterator数据类型是一个std::pair对象,包括两个数据 iterator->first 和 iterator->second 分别代表关键字和存储的数据
。
方法为遍历str,发现空格的数量为s,所以str在替换后 ,长度为 原来的长度+2*s。
然后从下标为原来的长度+2*s-1的地方开始拷贝的过程,从后向前拷贝!!
class Replacement {
public:
string replaceSpace(string iniString, int length) {
// write code here
int count=0;
for(int i=0;i<length;i++){
if(iniString[i]==' ')
count++;
}//这里是统计空格的数量
int end1=length+2*count-1;//count代表空格的数量,end为替换后的字符串的长度-1
int end2=length-1;
for(int j=length;j<=end1;j++)
iniString=iniString+' ';//必须要将iniString中需要额外添加的空间进行初始化,否则的话iniSstring的长度就是length,如果访问end2的话就会数组越界
//对于上面的初始化来说,如果iniString的长度就是length的话,那么久不可以用下标的方式访问大于length长度的字符,也就是说初始化的时候不可以使用
//iniString[length]=' ',这样是错误的!!!!!!这里可以用拼接的方式
while(end2>=0){
if(iniString[end2]!=' '){
iniString[end1]=iniString[end2];
end2--;
end1--;
}else {
end2--;
iniString[end1--]='0';
iniString[end1--]='2';
iniString[end1--]='%';
}
}
return iniString;
}
};
对于上面的程序来说,一定更要注意数组越界的问题。
2. 给定给一个字符串str,判断是不是整体有效的括号字符串。
这道题的最优解可以做到时间复杂度为o(n),额外空间复杂度为o(1)。
思路为首先,整形变量num,代表'('出现次数与')'出现次数的差值。
遍历的过程中,如果遇到‘(’则num++;
遍历的过程中,如果遇到‘)’则num--;
遍历的过程中如果num<0,则直接返回false;说明左括号的数量小于右括号,右括号多了!
如果一直没有出现上面的情况,则一直遍历下去;
遍历完成后,如果num==0,则返回true,否则返回false。
class Parenthesis {
public:
bool chkParenthesis(string A, int n) {
// write code here
int lcount=0;//统计( 的数量,遇到)就会减一
for(int i=0;i<n;i++){
if(A[i]=='(')
lcount++;
else if(A[i]==')'){
lcount--;
if(lcount<0){
break;
}
}else
return false;
}
return lcount==0;
}
};
注意上面的程序一定更要注意有非()字符的情况,这种能够情况直接放回false。
3. 给定一个字符串str返回str的最长无重复字符子串的长度。
这道题的最后解为时间复杂度o(n),额外空间复杂度为o(n)。
主要思路为从左到右,依次求出以str中每个字符结尾的情况下,向左最远的最长无重复字符子串的长度,并在其中找出最大值返回。
在求以s[i]位置处的变量为结尾的向左最长无重复子串长度的时候需要借助于两个变量:
第一是哈希表,记录每种字符之前出现的位置;
第二是pre,代表以s[i-1]结尾的情况下,向左最长无重复子串的长度。
首先从哈希表中取出map.get(s[i])也就是s[i]上次出现的位置A;
然后找到pre记为位置B;
A/B中取最大的那个,也就是靠右的那个。
最后s[i]的位置在哈希表中更新;
根据当前最长无重复字符子串的长度更新pre。
class DistinctSubstring {
public:
int longestSubstring(string A, int n) {
// write code here
map<char,int> position;//哈希表里面存放的是字符和该字符上次出现的位置!!!
int *pre=new int
;
pre[0]=1;//代表当前包括i在内的向左最长无重复子串的长度
int positionA;//表示用hash表查出的上一次A[i]出现的位置
int positionB;//表示用pre记录的最左边的A[i-1]的最长无重复子串的位置,是位置下标不是长度,也就是
//从A[i-1]开始向左能到的最左的位置,这之间都是无重复的字符
position.insert(pair<char,int>(A[0],0));
map<char,int>::iterator iter;
for(int i=1;i<n;i++){
if(position.find(A[i]) == position.end()){//说明A[i]之前没有出现过
position.insert(pair<char,int>(A[i],i));
positionA=-1;
} else{
iter=position.find(A[i]);
positionA=iter->second+1;//查找到的上一个A[i]出现的位置的下一个位置
position[A[i]]=i;//即使找到了也要进行更新,不过这里不是使用insert插入,而是修改原来哈希表中存在的值
}
if(i>0)
positionB=i-pre[i-1];
else
positionB=0;
int m=positionA;
if(positionB>m)
m=positionB;
pre[i]=i-m+1;
}
int max=pre[0];
for(int i=0;i<n;i++){
if(pre[i]>max)
max=pre[i];
}
return max;
}
};
上面的程序中主要是对hash表的操作,十分重要,增加记录(insert)、修改记录(直接用下标)、以及查找记录find等。其中用find的返回的值是一个迭代器的指针,这个指针指向的值是一个pair类型的,通过map对象的方法获取的iterator数据类型是一个std::pair对象,包括两个数据 iterator->first 和 iterator->second 分别代表关键字和存储的数据
。
相关文章推荐
- Java数据结构和算法总结-字符串相关高频面试题算法
- 字符串相关面试题(整理)
- 字符串相关面试题
- 字符串相关面试题
- 字符串高频面试题。
- 概率相关高频面试题 如何求最大公约数
- 位运算相关高频面试题
- 一道面试题 不用long的相关api将数字字符串转换成long
- 【程序员面试宝典】字符串相关面试题
- 字符串相关面试题
- 面试题42—相关题目(字符串的左旋转)
- 数组,字符串相关面试题
- javascript字符串相关的面试题总结
- 【我解C语言面试题系列】010 从相应位置开始删除指定字符串的相应个字符
- [面试题]翻转字符串中的单词
- 随机产生一个跟时间相关的字符串
- 【我解C语言面试题系列】011 删除指定字符串的相应字符
- 有关UNICODE、ANSI字符集和相关字符串操作的总结!
- Symbian-Descriptor/String 字符串相关
- 【我解C语言面试题系列】011 删除指定字符串的相应字符