牛客网算法学习记录-字符串

来源:互联网 发布:交换机环路端口关闭 编辑:程序博客网 时间:2024/05/23 14:31

 

对于两棵彼此独立的二叉树A和B,请编写一个高效算法,检查A中是否存在一棵子树与B树的拓扑结构完全相同。

给定两棵二叉树的头结点AB,请返回一个bool值,代表A中是否存在一棵同构于B的子树。

方法1:通过树的遍历进行。


bool check(TreeNode *A,TreeNode *B){

        
        if(A&&B&&A->val == B ->val){
            bool left = check(A->left,B->left);
            bool right = check(A->right,B->right);
            return left&&right;
        }
else if(A == NULL &&B==NULL){
            return true;
        }        
        else{
            return false;
        }
    }
    
    bool chkIdentical(TreeNode* A, TreeNode* B) {
        // write code here
        if(A ==NULL && B == NULL){
            return true;
        }
        else if (A==NULL ||B== NULL){
            return false;
        }
        else{
            return check(A,B)|| chkIdentical(A->left,B)||chkIdentical(A->right,B);
        }
    }

    


方法二:二叉树转字符串然后处理。

但是代码没过,因为自己对C++的东西不熟悉,所以有些语法报错不明白。先放这

string treeToString(TreeNode*A) {


if (A == NULL) {
return "#";
}
string strA;
strA += A->val;
strA += treeToString(A->left);
strA += treeToString(A->right);


return strA;
}


void getNext(char * treeString, int* next, int length){


int i, j;
next[0] = -1;
j = -1;
i = 0;
while (j<length) {


if (j == -1 || treeString[i] == treeString[j]) {
i++;
j++;
next[i] = j;
}
else {
j = next[j];
}


}
}






bool KMP(char * treeA, char * treeB, int pos,int *next,int treeAlength,int treeBlength) {


int i = 0;
int j = 0;
while (i<treeAlength&&j<treeBlength) {
if (j == -1 || treeA[i] == treeB[j]) {
i++;
j++;
}
else {
j = next[j];
}
}
if (j>= treeBlength) {
return true;
}
else {
return false;
}


}


bool chkIdentical(TreeNode* A, TreeNode* B) {
// write code here
string treeA;
string treeB;
treeA = treeToString(A);
char *Astr = new char[treeA.size()];

treeA.copy(Astr, treeA.size(), 0);
treeB = treeToString(B);
char *Bstr = new char[treeB.size()];
treeB.copy(Bstr,treeB.size(),0);
int next[treeB.size()];
getNext(Bstr, next, treeB.size());

return KMP(Astr, Bstr, 0,next, treeA.size(), treeB.size());

}


对于两个字符串A和B,如果A和B中出现的字符种类相同且每种字符出现的次数相同,则A和B互为变形词,请设计一个高效算法,检查两给定串是否互为变形词。

给定两个字符串AB及他们的长度,请返回一个bool值,代表他们是否互为变形词。

测试样例:
"abc",3,"bca",3
返回:true
这种通常使用哈希表的形式进行,由于只需要计数,所以就通过建立数组的形式计数,下标就是各个字符对应的ASCII码,通常ASCII有256个所以建立的大小为256

bool chkTransform(string A, int lena, string B, int lenb) {
        // write code here
        
        if (lena != lenb)
return false;


int hashA[256];
int hashB[256];


for (int i = 0; i < 256;i++) { //如果不初始化,数组内会有脏数据
hashA[i] = 0;
hashB[i] = 0;
}


for (int i = 0;i<lena;i++) {


hashA[((int)A[i])]++;  //字符转INT
hashB[((int)B[i])]++;
}
for (int i = 0; i<256;i++) {
//printf("%d: %d,%d\n ",i,hashA[i],hashB[i]);
if (hashA[i] != hashB[i])
return false;
}
return true;
    }

    

对于一个字符串,请设计一个算法,只在字符串的单词间做逆序调整,也就是说,字符串由一些由空格分隔的部分组成,你需要将这些部分逆序。

给定一个原字符串A和他的长度,请返回逆序后的字符串。

测试样例:
"dog loves pig",13
返回:"pig loves dog"
先将局部字符串进行reverse,然后再reverse总的字符串即可
string reverseSentence(string A, int n) {
        // write code here
        int pos = 0 ;
        while(pos<n){
            
            int next = A.find(' ',pos);
            if(next == -1){
                
                reverseWord(A,pos,n-1);
                break;
            }
            else{
                reverseWord(A,pos,next-1);
                pos = next+1;
            }
            
        }
        reverseWord(A,0,n-1);
        return A;
    }
    
    void reverseWord(string &str,int begin,int end){
        
        while(begin<end){
            swap(str[begin++],str[end--]);  //比用FOR循环计算I和Length-1-I
        }
        
    }


对于一个字符串,请设计一个算法,将字符串的长度为len的前缀平移到字符串的最后。

给定一个字符串A和它的长度,同时给定len,请返回平移后的字符串。

测试样例:
"ABCDE",5,3
返回:"DEABC"
方法:第一个部分翻转,再翻转第二部分,最后翻转整个字符串,就可以将前缀平移。


  1. template <class T> void swap ( T& a, T& b )  
  2. {  
  3.   T c(a); a=b; b=c;  
&表示传递引用, 所以后面的交换就是在交换原来的数据


对于一个给定的字符串数组,请找到一种拼接顺序,使所有小字符串拼接成的大字符串是所有可能的拼接中字典序最小的。

给定一个字符串数组strs,同时给定它的大小,请返回拼接成的串。

测试样例:
["abc","de"],2
"abcde"
这题不太会..感觉要把所有的排列组合都弄出来才可以,参考答案通过两两组合,将字典序在组合的基础上对元素进行排序,让小的在前,大的在后,两两组合的方式保证了每种组合都呈现了出来。
参考答案:

string findSmallest(vector<string> strs, intn) {
        // write code here
        sort(strs.begin(), strs.end(), cmp);
        string res;
        for(auto item : strs) //AUTO会根据后面要访问的类型,进行自动的类型定义
            res += item;
        returnres;
    }
 

    staticbool cmp(conststring & str1, conststring & str2){
        returnstr1 + str2 < str2 + str1;
    }


请编写一个方法,将字符串中的空格全部替换为“%20”。假定该字符串有足够的空间存放新增的字符,并且知道字符串的真实长度(小于等于1000),同时保证字符串由大小写的英文字母组成。

给定一个string iniString 为原始的串,以及串的长度 int len, 返回替换后的string。

测试样例:
"Mr John Smith”,13
返回:"Mr%20John%20Smith"
”Hello  World”,12
返回:”Hello%20%20World”
一开始遍历找到数组中的空格,然后计算插入覆盖后总的长度,


string replaceSpace(string iniString, int length) {
        // write code here
        int numberOfBlank = 0;
        for(int i = 0 ;i<length;i++){
            if(iniString[i] == ' '){
                
                numberOfBlank++;
                
            }
        }
        
        int n = length + numberOfBlank*2;
        string str(n,0);
        for(int i = length - 1;i>=0;i--){
            
            if(iniString[i] != ' '){
                str[--n] = iniString[i];
            }
            else{
                str[--n] = '0';
                str[--n] = '2';
                str[--n] = '%';
            }
        }
        return str;
    }


对于一个字符串,请设计一个算法,判断其是否为一个合法的括号串。

给定一个字符串A和它的长度n,请返回一个bool值代表它是否为一个合法的括号串。

测试样例:
"(()())",6
返回:true
测试样例:
"()a()()",7
返回:false
测试样例:
"()(()()",7
返回:false
bool chkParenthesis(string A, int n) {
        // write code here
        int left=0;
        for(int i = 0 ; i<n;i++){
            if(A[i] == '('){
                left++;
            }
            else if(A[i] == ')'){
                left --;
                if(left <0){
                    return false;
                }
            }
            else{
                return false;
            }
        }
        if(left>0){    //<0的情况已经在for中判断过了
            return false;
        }
        return true;
    }


对于一个字符串,请设计一个高效算法,找到字符串的最长无重复字符的子串长度。

给定一个字符串A及它的长度n,请返回它的最长无重复字符子串长度。保证A中字符全部为小写英文字符,且长度小于等于500。

测试样例:
"aabcb",5
返回:3
对于最长无重复字符串,先用一个数组作为字符的标记,记录当前字符前一次出现的位置,并和当前字符的前一个字符的字符标记做比较,选出位置靠后的字符标记的下标进行做差,然后和已经求得的长度进行比较。

int longestSubstring(string A, int n) {
        // write code here
        if(n == 0){
            return 0;
        }
        int map[256];  //根据ASCII形成的标记
        for(int i = 0 ; i<256;i++){
            map[i] = -1;
        }
        int prePosition = -1; //由于数组从0开始,所以要设置pre为-1,那样第一次求得的长度才正确,如对于第一个字符的长度来说, 0 - (-1) = 1 而不是0-0 = 0 。
        int cur=0;
        int result=-1;
        for(int i = 0 ;i<n;i++){
            
            prePosition = max(prePosition,map[(int)A[i]]);  //找出当前pos的前一个字符上次出现的位置和当前字符上次出现的位置哪一个更靠后。
            cur = i - prePosition;
          result = max(result,cur);
            map[A[i]] = i;//由于访问过了,那么对于后一次出现的当前字符,则需要刷新MAP为i。
        }
        return result;
    }

0 0
原创粉丝点击