字符串相关的高频面试题

来源:互联网 发布:毕加索美工钢笔 编辑:程序博客网 时间:2024/05/18 02:10

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[n];
        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 分别代表关键字和存储的数据 。


原创粉丝点击