面试考题之9.1:数组与字符串(C/C++版)

1.1  实现一个算法,确定一个字符串的所有字符是否全部不同。假如不允许使用额外的数据结构,又该如何处理?

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>
#include <cstring>   // strlen()
#include <cstdio>    // getchar()

using  namespace std;


/************************************************************************/
// 函数名称:isUniqueChars_1 (使用字符数组实现)
// 函数目的:判断字符串中所有字符是否全部不同
// 函数参数:str
// 函数返回:true:字符全部不同
// 使用条件:字符集为ASCII
/************************************************************************/

bool isUniqueChars_1( const  char* str)
{
     if (strlen(str) >  256return  false;

     char strFlag[ 256] = { 0};

     for (size_t i =  0; i < strlen(str); i++){
         int val = *(str + i);

         if (!strFlag[val]) strFlag[val] =  1;
         else  return  false;
     }

     return  true;
}


/************************************************************************/
// 函数名称:isUniqueChars_2 (使用位向量实现)
// 函数目的:判断字符串中所有字符是否全部不同
// 函数参数:str
// 函数返回:true:字符全部不同
// 使用条件:字符集为ASCII
/************************************************************************/

bool isUniqueChars_2( const  char* str)
{
     if (strlen(str) >  256return  false;

     char strBit[ 256/ 8 +  1] = { 0};

     for (size_t i =  0; i < strlen(str); i++){
         int val = *(str + i);

         int index   = val /  8;
         int mod     = val %  8;

         if ( (strBit[index] & ( 1 << mod)) >  0 ){
             return  false;
        }

        strBit[index] |= ( 1 << mod);
    }

     return  true;
}

int main()
{
     char str[]  =  "MyNameisJoh";
     char str2[] =  "MyNameisJohnnyHu";

    cout << str <<  " is " << (isUniqueChars_1(str) ?  "true" :  "false") << endl;
    cout << str2 <<  " is " << (isUniqueChars_1(str2) ?  "true" :  "false") << endl;

    cout << str <<  " is " << (isUniqueChars_2(str) ?  "true" :  "false") << endl;
    cout << str2 <<  " is " << (isUniqueChars_2(str2) ?  "true" :  "false") << endl;

    getchar();
     return  0;
}
运行结果:


思考体会:

1、 是否询问 “字符范围” ?

2、分析及计算(时间\空间)复杂度;

3、如果是Unicode字符该如果处理?

4、其他常规解法: 双for循环、排序等,他们复杂度多少


1.2 用C/C++实现void reverse(char* str)函数,即反转一个null结尾的字符串。

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <cstring>   // strlen()
#include <cstdio>    // getchar()

using  namespace std;

/************************************************************************/
// 函数名称:reverse
// 函数目的:反转一个null结尾的字符串
// 函数参数:str
// 函数返回:无
// 使用条件:
/************************************************************************/

void reverse( char* str)
{
    size_t length = strlen(str);

     for (size_t i =  0; i < length; i++){
         if ( i < length - 1 - i ){
             char ch = *(str + i);
            *(str + i ) = *(str + length - 1 - i);
            *(str + length - 1 - i) = ch;
        }
         else {  return; }
    }

     return;
}


int main()
{
     char str[]  =  "MyNameisJohnnyHu";

    cout <<  "str = "<< str << endl;
    cout <<  "call reverse() function, The result is:" << endl;
    reverse(str);
    cout <<  "str = " << str << endl;

    getchar();
     return  0;
}

运行结果:

思考体会:

1、如果不使用任何其他函数(比如:strlen)该怎么做?

2、注意对null字符的利用。


1.3 给定两个字符串,请编写程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <string>
#include <algorithm>     // std::sort

using  namespace std;

/************************************************************************/
// 函数名称:permutation
// 函数目的:确定两个字符串中字符是否相同(忽略顺序)
// 函数参数:s, t
// 函数返回:true:字符串中字符相同; false:不相同
// 使用条件:
/************************************************************************/

bool permutation( const string& s,  const string& t)
{
    string ss = s, tt = t;
    sort( ss.begin(), ss.end() );
    sort( tt.begin(), tt.end() );

     return ss == tt;
}

int main()
{
     char str[]   =  "MyNameisJohnnyHu";
     char str2[]  =  "NameisMyHuJohnny";

    cout <<  "str = "<< str << endl;
    cout <<  "str2 = " << str2 << endl;

    cout <<  "call permutation() function, The result is:" << endl;
    cout << ( permutation(str, str2) ?  "true" :  "false" ) << endl;

    getchar();
     return  0;
}

运行结果:

思考体会:

1、其他方法:可以检查两个字符串中各个字符数是否相同。字符集假设为ASCII。

2、用纯C语言去实现,使用qsort去排序。

2、最此题之前应确认一些细节。


1.4 . 编写一个方法,将字符串中的空格全部替换为“%20”。假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的“真实”长度。

示例:

输入: "Mr John Smith"

输出:Mr%20John%20Smith“

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <string>
#include <algorithm>   // std::replace

using  namespace std;

/************************************************************************/
// 函数名称:replaceChars
// 函数目的:确定两个字符串中字符是否相同(忽略顺序)
// 函数参数:str字符串,s原字符子串, t要替换的字符子串
// 函数返回:true:字符串中字符相同; false:不相同
// 使用条件:
/************************************************************************/

string replaceChars( const string& str,  const string& s,  const string& t)
{
    string strNew = str;

     while (strNew.find(s) != std::string::npos){
         strNew.replace(strNew.find(s),s.length(), t);
    }

     return strNew;
}

int main()
{
    string str;
    cout <<  "Please enter a string: " << endl;

    getline(std::cin, str);
    cout <<  "call replaceChars() function, The result is:" << endl;
    cout << replaceChars(str,  " ""%20") << endl;

    getchar();
     return  0;
}

运行结果:

思考体会:

1、用纯cC去怎么完成?

2、其他解法?


1.5  利用字符重复出现的次数,编写一个方法,实现基本的字符串压缩功能。比如,字符串“aabcccccaaa”会变成"a2b1c5a3"。 若“压缩”后的字符串没有变短,则返回原来的字符串。

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
#include <sstream>   // std::stringstream
#include <string>
#include <cstdio>    // getchar()

using  namespace std;

/************************************************************************/
// 函数名称:compressChars
// 函数目的:基本字符串压缩功能
// 函数参数:str要压缩的字符串
// 函数返回:压缩操作过的字符串
// 使用条件:
/************************************************************************/

string compressChars( const string& str)
{
     if (str.size() <=  2return str;

    string strPress;
    size_t sz =  0;
     char   ch = str[ 0];

     for (size_t i =  0; i < str.size(); i++){
         if (ch == str[i]){
            ch = str[i];  sz +=  1;
        }
         else {
            stringstream ss;  ss << sz;   // std::to_string在MinGW下有Bug
            strPress += ch + ss.str();

            ch = str[i];   sz =  1;
        }

         if (i == str.size() -  1){
            stringstream ss;  ss << sz;
            strPress += ch + ss.str();
        }
    }

     return ( (strPress.size() < str.size()) ?  strPress : str);
}

int main()
{
     char str[]  =  "aaaaabbccdddddeeeefgg";
     char str2[] =  "MyNameisJohnnyHuuu";
    cout <<  "str = "<< str <<  " ---->> " << compressChars(str) << endl;
    cout <<  "str2 = "<< str2 <<  " ---->> " << compressChars(str2) << endl;

    getchar();
     return  0;
}

运行结果:


思考体会:

1、其他解法?

2、分析(时间/空间)复杂度


1.6 给定一幅由NxN矩阵表示的图像,其中每个像素的大小为4字节,编写一个方法,将图像旋转90度,不占用额外的内存空间能否做到?

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>
#include <sstream>   // std::stringstream
#include <string>
#include <cstdio>    // getchar()

#define  N    4
using  namespace std;

/************************************************************************/
// 函数名称:rotateMatrix
// 函数目的:顺时针90度转置矩阵
// 函数参数:matrix
// 函数返回:无
// 使用条件:
/************************************************************************/

void rotateMatrix( int matrix[][N],  int rows = N)
{
     for (size_t layer =  0; layer < rows /  2; ++layer){
        size_t first = layer;
        size_t last = rows -  1 -layer;
         for (size_t i = first; i < last; ++i){
            size_t offest = i - first;

             // 存储上边
             int top = matrix[first][i];

             // 左到上
            matrix[first][i] = matrix[last - offest][first];

             // 下到左
            matrix[last - offest][first] = matrix[last][last - offest];

             // 右到下
            matrix[last][last - offest] = matrix[i][last];

             // 上到右
            matrix[i][last] = top;
        }
    }

     return;
}

int main()
{
     int matrix[N][N] = {
                    { 1,   2,   3,   4 },
                    { 5,   6,   7,   8 },
                    { 9,   101112},
                    { 13141516}
                    };

    cout <<  "初始矩阵:" << endl;
     for (size_t i =  0; i < N; i++){
         for (size_t j =  0; j < N; j++){
            cout << matrix[i][j] <<  "\t";
        }
        cout << endl;
    }

    rotateMatrix(matrix, N);

    cout <<  "顺时针转置90度后矩阵:" << endl;
     for (size_t i =  0; i < N; i++){
         for (size_t j =  0; j < N; j++){
            cout << matrix[i][j] <<  "\t";
        }
        cout << endl;
    }

    getchar();
     return  0;
}

运行结果:


思考体会:

1、该算法是参考的算法,算法设计很精妙,值得研究掌握。

2、本算法从外向内旋转,又如何从内向外旋转?

3、本算法的时间复杂度O(N^2), 


1.7 编写一个算法,若MxN矩阵中某个元素为0,则将其所在的行与列清零。

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
#include <sstream>   // std::stringstream
#include <string>
#include <cstdio>    // getchar()

#define  N    4
using  namespace std;

/************************************************************************/
// 函数名称:setZero
// 函数目的:把矩阵中元素为0的行/列清零
// 函数参数:matrix
// 函数返回:无
// 使用条件:row <= N
void setZero( int matrix[][N], size_t rows = N)
{
     int flag[N][N] = { { 0} };
     for (size_t row =  0; row < rows;  row++){
         for (size_t col =  0; col < N; col++)
             if (matrix[row][col] ==  0) flag[row][col] =  1;
    }

     // 行/列清零
     for (size_t row =  0; row < rows;  row++){
         for (size_t col =  0; col < N; col++)
             if (flag[row][col] ==  1) {
                 for (size_t c =  0; c < N; c++)      matrix[row][c] =  0;
                 for (size_t r =  0; r < rows;  r++)  matrix[r][col] =  0;
            }
    }

     return;
}


int main()
{
     int matrix[N][N] = {
                    { 1,   2,   3,   4 },
                    { 5,   0,   7,   8 },
                    { 9,   01112},
                    { 13141516}
                    };

    cout <<  "初始矩阵:" << endl;
     for (size_t i =  0; i < N; i++){
         for (size_t j =  0; j < N; j++){
            cout << matrix[i][j] <<  "\t";
        }
        cout << endl;
    }

   setZero(matrix, N);

    cout <<  "调用setZero后:" << endl;
     for (size_t i =  0; i < N; i++){
         for (size_t j =  0; j < N; j++){
            cout << matrix[i][j] <<  "\t";
        }
        cout << endl;
    }

    getchar();
     return  0;
}

运行结果:


思考体会:

1、注意题设的陷阱。

2、计算时间空间复杂度。


1.8 假定有一个方法isSubstring,可检查一个单词是否为其他字符串的子串。给定另个字符字符串s1和s2,请编写代码检查s2是否为s1旋转而成,要求只调用一次isSubstring.(比如,waterbottle是erbottlewat旋转后的字符串。
解决方案:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <string>
#include <cstdio>    // getchar()

using  namespace std;

/************************************************************************/
// 函数名称:isRotation_2
// 函数目的:判断字符串是否是转换字符串
// 函数参数:s1 s2
// 函数返回:true:是转置字符串
// 使用条件:
/************************************************************************/

bool isRotation_2( const string& s1,  const string& s2)
{
    size_t len = s1.length();
     if (len == s2.length() && len >  0){
        string s1s1 = s1 + s1;   // the key point
        size_t found = s1s1.find(s2);
         if ( found != std::string::npos )  return  true;
    }

     return  false;
}

int main()
{
     char s1[] =  "waterbottle";
     char s2[] =  "erbottlewat";

    cout <<  "s1 = " << s1 << endl;
    cout <<  "s2 = " << s2 << endl;

    cout <<  "调用转换字符函数isRotation_2()判断之后:" << endl;
    cout << (isRotation_2(s1, s2) ?  "true" :  "false") << endl;

    getchar();
     return  0;
}

运行结果:

思考体会:
1、本题解决需要一定技巧,相当了就很简单,想不到,就会没办法解决。
2、本题中的std::string::find 充当了题目中的isSubString()的功能。


猜你喜欢

转载自blog.csdn.net/JohnnyHu90/article/details/46375321