• CrackCode 题目整理 (第一章)


    CrackCode Interview 书籍链接地址

    /*
    * Chapter 1
    * Question: Implement an algorithm to determine if a string has all unique characters.
    * What if you can not use addtional data structures?
    * 实现一个算法用于判断一个字符串所包含的所有字符是各不相同的。
    * 尽量不使用额外空间
    */

    #include<iostream>
    using namespace std;
    /*
     * 假设为ASCII编码,字符数值范围为0~255,因此开设256大小的bool数据进行记录
     */
    bool solution1(const char * str){
        bool exist[256] = {false};
        while(*str != '\0'){
            if (exist[*str] == true) return false; 
            exist[*str] = true;
            str++;
        }
        return true;
    }
    
    /*
     * 上述解法,浪费了空间,因为对应每个字符只有0和1两个状态,可以用bit来记录
     * 因此可以开设8*32的bit空间,用位操作解决问题
     */
    
    struct char_set{
        int arr[8]; // 32bit * 8 = 256bit
        char_set(){
            for(int i=0;i<8;i++) arr[i] = 0;
        }
    };
    
    bool solution2(const char * str) {
        char_set charset;
        int one = 1;
        while(*str != '\0'){
            int index = (*str) / 32;
            int position = (*str) % 32;
            if ((charset.arr[index] & (one << position)) > 0) return false;
            charset.arr[index] |= (one << position);
            str ++;
        }
        return true;
    }
    
    /*
     *如果完全不是用额外空间,可以考虑使用排序,然后从头到尾遍历一下即可。时间复杂度O(nlogn)
     */
    
    int main(){
        char str [] = "zhangli";
        char str2 [] = "zhanglixin";
        cout<<solution1(str)<<endl;
        cout<<solution2(str)<<endl;
        cout<<solution1(str2)<<endl;
        cout<<solution2(str2)<<endl;
        return 0;
    }

    /*
    * Chapter 1.2
    * Question:Write code to reverse a c-Style String,
    * (C-style means that "abcd" is represented as five characters,including the null character)
    * 反转字符串
    */

    #include<iostream>
    #include<string.h>
    using namespace std;
    
    /*
     * 两种考虑,如果可以使用strlen函数,则可以省略找最后一个字符的工作
     * 否则,需要自己写
     */
    void solution(char * str){
        int len = strlen(str);
        int i = 0;
        char temp;
        while(i < len/2){
            temp = str[i];
            str[i] = str[len-i-1];
            str[len-i-1] = temp;
            i++;
        }
    }
    
    void solution2(char * str) {
        char * end = str;
        char temp;
        while(*end != '\0'){
            end ++;
        }
        end --;
        while(str < end){
            temp = *str;
            *str = *end;
            *end = temp;
            str++;
            end--;
        }
    }
    
    int main(){
        char s1[] = "hello world";
        char s2[] = "1234567890";
        solution(s1);
        solution2(s2);
        cout<<s1<<endl;
        cout<<s2<<endl;
        return 0;
    }

    /*
    * Chapter 1.3
    * Question:Design an algorithm and write code to remove the duplication characters in a string
    * without using any addtional buffer. NOTE:One or two addtional variables are fine.
    * An extra copy of the array is not.
    * FOLLOW UP
    * Write the test cases for this method.
    * 设计一个算法,用来移除一个字符串中重复的字符,并且不允许使用任何额外的空间(少量变量可以)
    * 不允许额外的拷贝
    * 接下来,为这个方法写一些测试用例
    */

    #include<iostream>
    #include<string.h>
    
    using namespace std;
    /*
     * 由于不允许使用额外空间,导致不能用1.1中类似的方法判断是否重复
     * 因此,采用遍历枚举的方式,方法如下:
     * 对于str[i],枚举0~tail之间是否已存在该元素,其中0到tail之间字符不重复
     * 如果存在,则跳过,否则str[tail]更新为新元素str[i]
     */
    void solution(char * str){
        if (str == NULL) return ;
        int len = strlen(str);
        int tail = 1;
        int j;
        for(int i=1;i<len;i++){
            for(j=0;j<tail;j++){
                if (str[i] == str[j]) break;
            }
            if(j == tail) {
                str[tail] = str[i];
                tail++;
            }
        }
        str[tail] = '\0';
    }
    
    /*
     * Test Cases:
     * 1. 不包含任何重复字符 abcd
     * 2. 所有的字符均重复 aaaa
     * 3. NULL
     * 4. 连续重复的字符串,如aaabbb
     * 5. 非连续重复的字符串 abcabcddeef
     */
    
    int main(){
        char s [] = "abcdeagsdgabc";
        solution(s);
        cout<<s<<endl;
        return 0;
    }

    /*
    * Chapter 1.4
    * Question: Write a method to decide if two strings are anagrams or not .
    * 判断两个字符串是否为易位够词,即排序之后相同的两个词
    * http://en.wikipedia.org/wiki/Anagram
    */

    #include<iostream>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    
    /*
     * 通过抽象定义,直接對两个string进行排序,然后判断下就可以了
     * 时间复杂度O(nlogn)
     */
    
    bool solution(char * s1, char * s2){
        sort(s1,s1+strlen(s1));
        sort(s2,s2+strlen(s2));
        int cmp = strcmp(s1,s2);
        if( cmp == 0) return true;
        return false;
    }
    
    /*
     * 由于方法1具有数据侵入性,即改遍了s1和s2中原有的数据位置,因此不是很好的解决办法。
     * 利用空间换时间,用char_count统计s1中每个字符出现的次数
     * 然后遍历s2中的每个字符,對char_count进行更新,即对应的char_count减1
     * 如果某个字符对应的char_count减为-1,则判定为false
     * 若字符数不相等也判定为false
     */
    
    bool solution2(char * s1, char * s2){
        int char_count[256] = {0};
        int len1=0,len2=0;
        while(*s1 != '\0') {
            char_count[*s1] ++;
            s1++;
            len1++;
        }
        while(*s2 != '\0') {
            char_count[*s2] --;
            if(char_count[*s2] < 0) return false;
            s2++;
            len2++;
        }
        if(len1 != len2) return false;
        return true;
    }
    
    int main(){
        char s1 [] = "hello";
        char s2 [] = "lloeh";
        cout<<solution(s1,s2);
        cout<<solution2(s1,s2);
        return 0;
    }

    /*
    * Chapter 1.5
    * Question:Write a method to replace all spaces in a string with '%20'
    * 写一个方法用'%20'替换字符串中的所有空格
    */

    #include<iostream>
    #include<string.h>
    using namespace std;
    
    /*
     * 这应该算是比较典型的字符串移位的问题
     * 首先,如果我们知道了字符串中包含的space数量count,那么替换后的最终长度比原始长度增加了count*2
     * 在进行替换过程中,如果从头开始替换,势必在替换过程中,需要對后面的字符进行位置移动,显然这是开销很大的。
     * 由于我们已经知道了替换后的最终长度,那么便可以从后往前进行替换,这样不会對前面的字符产生影响。
     * 另外,由于字符串的最终长度增加了,那么在原有内存上进行操作,可能会造成字符串的访问越界。
     * 因此,最好的方法应该时新建一个string,再返回,这样的话,就无所谓替换的顺序了。
     */
    
    void solution(char * str){
        //我们假设str申请的空间很大,不会产生越界问题
        int count = 0;
        int len = 0;
        char * pstr = str;
        while(*pstr != '\0'){
            if (*pstr == ' ') count++;
            len ++;
            pstr++;
        }
        int final_len = len + 2 * count;
        str[final_len] = '\0';
        int pos = final_len - 1;
        int j = len - 1;
        while(j>=0){
            if(str[j] != ' ') str[pos--] = str[j];
            else{
                str[pos - 2] = '%';
                str[pos - 1] = '2';
                str[pos] = '0';
                pos -=3;
            }
            j--;
        }
    }
    
    int main(){
        char str [100];
        strcpy(str," hello world python ");
        solution(str);
        cout<<str<<endl;
        return 0;
    }

    /*
    * Write an algorithm such that if an element in an M*N matrix is 0, its entire row and column is set to 0.
    * 写一个算法用于实现如果一个M*N的矩阵中某个元素为0.则将该行和该列所有元素设置为0
    */

    #include<iostream>
    using namespace std;
    
    /*
     * 由于,不能在查找0的时候,进行相应行和列的更新0,因为这样会导致整个矩阵变为0矩阵了
     * 那么就需要记录每个0的位置,然后再统一进行行和列的0替换
     * 方法1:开两个数组row[i],column[j],记录第i行与第j列是否为0
     * 方法2:建立一个struct,记录row 和 column,用链表形式记录,这样可以最小化存储空间
     * 方法3:num = row*MAXCOLUMN + column的方式进行0元素的位置存储
     */
    
    
    void solution(int arr[][3], int maxcolumns, int maxrows) {
        bool * row = new bool[maxrows]; 
        bool * column = new bool[maxcolumns];
        for(int i=0;i<maxrows;i++){
            for(int j=0;j<maxcolumns;j++){
                if(arr[i][j] == 0){
                    row[i] = true;
                    column[i] = true;
                }
            }
        }
        for(int i=0;i<maxrows;i++){
            for(int j=0;j<maxcolumns;j++){
                if(row[i] | column[j]) arr[i][j] = 0;
            }
        }
    }
    
    
    int main(){
        int arr[3][3] = {{1,2,3},{4,0,6},{7,8,9}};
        solution(arr,3,3);
        int maxrows = 3;
        int maxcolumns = 3;
        for(int i=0;i<maxrows;i++){
            for(int j=0;j<maxcolumns;j++){
                cout<<arr[i][j]<<'\t';
            }
            cout<<endl;
        }
       
        return 0;
    }

    /*
    * Chapter 1.8
    * Question:Assume you have a method isSubstring which checks if one word is substring of
    * another. Given two strings s1 and s2, write code to check if s2 is a rotation of s1 using
    * only one call to isSubString(i.e."waterbottle" is a rotation of "erbottlewat")
    * 假设你有一个方法可以用来检测一个单词是否为一个另一个的子串。现在给你两个字符串并且只能进行一次substring的调用,判断s2是否为s1的转动形式。
    */

    #include<iostream>
    #include<string.h>
    #include<assert.h>
    using namespace std;
    
    
    bool isSubstring(const char * s1, const char * s2){
        assert(s1 != NULL && s2 != NULL);
        return strstr(s1,s2) == NULL ? false : true;
    }
    
    /*
     * 首先应该检查s1与s2的长度,如果不想等,则直接判定为false
     * 对于字符串s1,s1s1则包含了s1转动后的所有形式,因此只要用isSubstring判断s2是否为s1s1的子串即可
     */
    
    bool solution(const char * s1, const char * s2){
        int len1 = strlen(s1);
        int len2 = strlen(s2);
        if(len1 != len2) return false;
        char * temp = new char[len1*2];
        strcpy(temp,s1);
        strcpy(temp+len1,s1);
        bool res = isSubstring(temp,s2);
        delete [] temp;
        return res;
    }
    int main(){
        char s1 [] = "waterbottle";
        char s2 [] = "erbotdlewat";
        cout<<solution(s1,s2)<<endl;
    }
  • 相关阅读:
    java链接linux服务器,命令操作
    linux中php项目无法发送邮件:PEAR mail package is not installed
    linux下部署php项目-Apache、php、mysql关联
    MyEclipse黑色主题
    MyEclipse优化-六步攻略
    致产品
    万物归宗
    【产品渗透:移动端平台与纯应用APP产品的相互嵌入】
    【异类--一万小时定律】
    【活法】
  • 原文地址:https://www.cnblogs.com/coser/p/2979509.html
Copyright © 2020-2023  润新知