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

来源:互联网 发布:米尔网 知乎 编辑:程序博客网 时间:2024/05/23 12:21

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()的功能。


0 0