zoukankan      html  css  js  c++  java
  • 《程序员面试金典》习题解答(C/C++)

    一.数据结构

    1.数组与字符串

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

    /*
    假设字符集为ASCII字符串,那么字符串至多有256个字符,因为一旦大于256个则必定有两个是相同的
    */
    #include<iostream>
    #include<string>
    using namespace std;
    
    bool isUniqueChars(string str){
        if (str.size() > 256)
            return false;
        bool char_set[256];
        for(int i = 0; i < str.size; ++i) {
            int val = str[i];    //获取字符对应得ASCII码
            if (char_set[val])    //这个字符已经在字符串中出现
                return false;
            char_set[val] = 1;
        }
        return true;
    }
    
    /*
    假如输入的字符只含有小写字母a到z,则我们只需要用一个int型变量
    */
    
    bool isUniqueChar2(string str) {
        int flag = 0;
        if (str.size() > 26)
            return false;
        for (int i = 0; i < 26; ++i) {
            int val = str[i] - 'a';
            if (flag&(1 << val) > 0)
                return false;
            flag |= (1 << val);
        }
        return true;
    }

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

    /*假设原地反转,不分配额外空间,下面为C语言实现*/
    #include<stdio.h>
    
    void reverse(char* str) {
        char* end = str;    
        char* start = str;
        char tmp;
        if (str) {
            while (*end)
                ++end;
        }
        --end;    /*回退一个字符,因为最后的字符为null*/
    
        /*从首尾开始交换*/
        while (start < end) {
            tmp = *end;
            *end = *start;
            *start = tmp;
            ++start;
            --end;
        }
    }

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

    /*给定两个字符串,请编写程序,确定其中一个字符串的字符重新排列后,能否变成另外一个字符串。*/
    /*假设字符区分大小写,空白字符也考虑在内,以下是两种解法,使用C++*/
    #include<iostream>
    #include<string>
    #include <algorithm>
    using namespace std;
    
    /*解法一:排序字符串,将两个字符串进行排序后再进行比较*/
    bool permutation1(string s, string t) {
        if (s.size() != t.size())
            return false;
        string s1 = s;
        string t1 = t;
        /*进行排序*/
        sort(s1.begin(), s1.end());    
        sort(t1.begin(), t1.end());
        if (s1 == t1)
            return true;
        return false;
    }
    
    
    /*解法二:比较两个字符串各字符数是否相同*/
    bool permutation2(string s, string t) {
        if (s.size() != t.size())
            return false;
        int count[256] = { 0 };
        /*计算s中各个字符出现的次数*/
        for (string::size_type i = 0; i !=s.size(); ++i) {
            int val = (int)s[i];
            count[val]++;
        }
        for (string::size_type j = 0; j != t.size(); ++j) {
            int c = (int) t[j];
            if (--count[c] < 0)
                return false;
        }
        return true;
    }

    1.4  编写一个方法,将字符串中的空格全部替换成“%20”。假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的真实长度。例如,输入:"Mr Jone Smith",输出:“Mr20%Jone20%Smith”。

    /*编写一个方法,将字符串中的空格全部替换成“%20”。假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的真实长度。*/
    /*例如,输入:"Mr Jone Smith",输出:“Mr20%Jone20%Smith”。*/
    
    #include<iostream>
    #include<string>
    using namespace    std;
    
    void replaceSpaces(char* str,int length) {
        int spaceCount = 0;
        for (int i = 0; i < length; ++i) {
            if (str[i] == ' ')
                ++spaceCount;
        }
        int newLength = length + spaceCount * 2;
        str[newLength] = '';
        int p = length - 1;
        int q = newLength - 1;
        while (p < q) {
            if (str[p] != ' ')
                str[q--] = str[p--];
            else
            {
                str[q--] = '0';
                str[q--] = '2';
                str[q--] = '%';
                p--;
            }
        }
    
    }

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

    #include<iostream>
    #include<string>
    using namespace std;
    
    string compress(string str) {
        if (str.empty())
            return NULL;
        string str1;
        char last = str[0];
        int count = 1;
        for (string::size_type i = 1; i < str.size(); ++i) {
            if (str[i] == last)
                ++count;
            else {
                str1.push_back(last);
                str1+=to_string(count);
                last = str[i];
                count = 1;
            }
        }
        /*因为最后一组重复字符还未放入压缩字符串中就退出循环,所以还要更新最后一组字符*/
        str1.push_back(last);
        str1+=to_string(count);
    
        return str1.size() < str.size() ? str1: str;
     }

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

    /*假设顺时针旋转,*/
    #include<iostream>
    using namespace std;
    
    void rotate(int** matrix, int n) {
        for (int layer = 0; layer < n / 2; ++layer) {
            int first = layer;
            int last = n - 1 - layer;
            for (int i = first; i < last; ++i) {
                int offset = i - first;
                //存储上边
                int top = matrix[first][i];
    
                //左到上
                matrix[first][i] = matrix[last - offset][first];
    
                //下到左
                matrix[last - offset][first] = matrix[last][last - offset];
    
                //右到下
                matrix[last][last - offset] = matrix[i][last];
    
                //上到右
                matrix[i][last = top;
            }
        }
    }

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

    void setZeros(vector<vector<int> > matrix) {
        bool *row= new bool[matrix.size()];
        bool *column= new bool[matrix[0].size()];
    
        //为保险起见首先初始化为false
        for (int i = 0; i < matrix.size(); ++i) {
            for (int j = 0; j < matrix[0].size(); ++j) {
                row[i] = false;
                column[j] = false;
            }
        }
        //记录值为0的元素所在的行的索引和列的索引
        for (int i = 0; i < matrix.size(); ++i) {
            for (int j = 0; j < matrix[0].size(); ++j) {
                if (matrix[i][j] == 0)
                {
                    row[i] = true;
                    column[j] = true;
                }
            }
        }
    
        //若行i或列j有个元素为0,则matrix[i][j]置为0
        for (int i = 0; i < matrix.size(); ++i) {
            for (int j = 0; j < matrix[0].size(); ++j) {
                if(row[i]||column[j])
                    matrix[i][j] = 0;
            }
        }
        
    }

    1.8  假定有一个方法isSubstring,可检查一个单词是否为其他字符串的子串。给定两个字符串s1和s2,请编写代码检查s2是否为s1旋转而成,要求只能调用一次isSubstring。(比如,waterbottle是erbottlewat旋转后的字符串)

    /*
    *假设s2由s1旋转而成,那么我们可以找出旋转点在哪。例如,若以wat旋转waterbottle,就会得到erbottlewat。
    *我们把字符串s1切分为两部分x和y,并将它们重新组合成s2.
    *s1=xy=waterbottle
    *x=wat
    *yerbottle
    *s2=yx=erbottlewat
    *我们需要确认的是有没有办法将s1切分成xy=s1,yx=s2。不论xy的分割点在何处,xy都是xyxy的子串。也即s2是s1s1的子串
    */
    #include<iostream>
    using namespace std;
    
    bool isRotation(string s1, string s2) {
        int len = s1.size();
        //检查s1和s2是否等长且不为空
        if (len == s1.size() && len > 0) {
            //凭借s1和s1,放入新字符串中
            string s1s1 = s1 + s1;
            return isSubstring(s1s1, s2);
        }
        return false;
    }

    2.链表

    2.1  编写代码,移除为排序链表中的重复节点。进阶:如果不得使用临时缓冲区,该怎么解决?

    #include<iostream>
    #include<map>
    using namespace std;
    
    //链表节点定义
    struct Node {
        Node* next = NULL;
        int data;
    };
    
    /*解法一:采用散列表来存储节点的值是否出现过,若重复,则删除该节点。*/
    void deleteDups1(Node *phead) {
        map<int, bool> imap;
        Node* previous = phead;
        Node* p = phead;
    
        while (p != NULL) {
            if (imap[p->data])
            {
                previous->next =p->next;
            }
            else {
                imap[p->data] = true;
                previous = p;
    
            }
            p = p->next;
        }
    }
    
    /*解法二:进阶不使用额外缓冲区,使用两个指针来迭代:current迭代访问整个列表,runner用于检查后续的节点是否重复*/
    void deleteDups2(Node* phead) {
        if (phead == NULL)
            return;
        Node* current = phead;
        while (current != NULL) {
            Node* runner = current;
            while (runner->next != NULL) {
                if (current->data == runner->next->data) {
                    current->next = runner->next->next;
                }
                else {
                    runner = runner->next;
                }
                current = current->next;
            }
        }
    }
  • 相关阅读:
    Java----自增,自减运算符
    Java----运算符
    Java---变量,常量,作用域
    Java--类型转换
    图像压缩
    最大熵对应的概率分布
    Python matplotlib画图时图例说明(legend)放到图像外侧详解
    pytorch persistent_workers
    RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation
    Pytorch中出现的奇怪错误
  • 原文地址:https://www.cnblogs.com/maluning/p/8721321.html
Copyright © 2011-2022 走看看