程序员面试金典1

1.第k个数(丑数)

剑指offer里有此题,但是其认为1为第一个丑数。

牛客网上此题认为1不为丑数,但是如果要正确计算的话,那么必须设置第一个丑数为1,那么求第k个数就转化为求第k+1个数

class KthNumber {
public:
    int findKth(int k) {
        // write code here
        
        if(k<=0) 
            return 0;
        else if(1==k)
            return 3;
        else if(2==k)
            return 5;
        else if(3==k)
            return 7;
        else if(k>100)
            return 0;
        
        int index=1,min,res;
        int *num=new int[k+1];
        num[0]=1;
        
        int *multi3=num,*multi5=num,*multi7=num;
        while(index<k+1){
            min=minval(*multi3*3,*multi5*5,*multi7*7);
            num[index]=min;
            
            while(*multi3*3<=min)
                ++multi3;
            while(*multi5*5<=min)
                ++multi5;
            while(*multi7*7<=min)
                ++multi7;
            ++index;
        }
        
        res=num[index-1];
        delete[] num;
        num=NULL;
        return res;
    }
    
private:
    int minval(const int& num1,const int& num2,const int& num3){
        int min=num1<num2?num1:num2;
        return min<num3?min:num3;
    }
};
View Code

2.字符的全排列(很重要,结果做一次错一次,还是使用递归)

class Permutation {
public:
    
    static bool compare(const string& s1,const string& s2){
        return s1 < s2 ? false : true;
    }
    
    //此题为不重复的全排列
    vector<string> getPermutation(string A) {
        
        vector<string> res;
        int len=A.length();
        if(len<=1) {
            res.push_back(A);
            return res;
        }
        
        PermutationStr(A,0,len-1,res);
        sort(res.begin(),res.end(),compare);
        return res;
    }
       
private:    
    void PermutationStr(string& str,int k,int m,vector<string>& res){
        
        if(k==m){
            res.push_back(str);return;
        }
        
        for(int i=k;i<=m;++i){
            if(isswap(str,k,i)){
                swap(str[k],str[i]);
                PermutationStr(str,k+1,m,res);
                swap(str[k],str[i]);
            }
        }
    }
    
    bool isswap(string& str,const int& left,const int& right){
        if(left>right)
            return false;
        
        for(int i=left;i<right;++i)
            if(str[i]==str[right])
                return false;
        return true;
    }
    
    void swap(char& a,char& b){
        char t=a;a=b;b=t;
    }
};
View Code

3.旋转字符串里搜寻数据

这个比剑指offer里寻找第一个数字要有难度,首先寻找规律,然后通过递归去寻找,简直了

class Finder {
public:
    
    //此题保证了数据是不重复的,如果允许重复就要考虑顺序查找
    int findElement(vector<int> A, int n, int x) {
        
        int len=A.size();
        if(len!=n||len<=0)
            return 0;
        else if(1==len){
            if(A[0]==x) return 0;
            else return -1;
        } 
        
        return search(A,0,len-1,x); 
    }
    
private:
    int search(vector<int>& a,const int left,const int right,const int x){
        int mid=(left+right)>>1;
        if(x==a[mid]) 
            return mid;
        if(right<left)
            return -1;
        
        //左半边或右半边必有一边是正常排序的
        if(a[left]<a[mid]){ //左半边为正常排序
            if(x>=a[left]&&x<=a[mid])
                return search(a,left,mid-1,x);
            else return search(a,mid+1,right,x);
        }else if(a[mid]<a[left]){ //右半边为正常排序
            if(x>=a[mid]&&x<=a[right])
                return search(a,mid+1,right,x);
            else return search(a,left,mid-1,x);
        }else if(a[left]==a[mid]){ //左半边都为重复元素
            if(a[mid]!=a[right])
                return search(a,mid+1,right,x);
            else { //搜索两边
                int res=search(a,left,mid-1,x);
                if(-1==res){
                    return search(a,mid+1,right,x);
                }else return res;
            }
        }
        
        return -1;
    }
};
View Code

我照着写,都能把程序写错,也是简直了

4.求素数小程序

bool judgeprime(int n)
{
    if (n < 2) return false;
    else if (2 == n) return true;

    int i, n = (int)sqrt(n);
    for (i = 3;i < n;i += 2)
    {
        if (n%i == 0)
            return false;
    }
    return true;
}

写着玩的

5.词频统计(牛客网上提交的是另外一份简易代码,自己用hash_map实现了下,支持重复查找)

class  SetupDictionary
{
public:
    SetupDictionary() {}
    ~SetupDictionary() {}

public:
    void setDictionary(vector<string>& book)
    {
        table.clear();

        int len = book.size();
        if (len <= 0) return;

        hash_map<string, int>::iterator itr;
        for each ( auto tmp in book)
        {
            itr = table.find(tmp);
            if (table.end() == itr)
            {
                table.insert(pair<string, int>(tmp, 1));
            }
            else {
                ++(itr->second);
            }
        }
    }

    int getFrequency(string& word) 
    {
        if (0 == table.size() || word.length() <= 0)
            return -1;
        hash_map<string, int>::iterator itr;
        itr = table.find(word);
        if (itr == table.end())
            return -1;
        else return itr->second;
    }

private:
    hash_map<string, int> table;
};
View Code

尚未做什么鲁棒性检查和优化,不过觉得蛮好玩的,算是自己写代码以来最喜欢的代码吧

6.整数对个数统计

class FindPair {
public:

    //此处应该是默认数据不重复,否则此种解法不适用
    int countPairs(vector<int> A, int n, int sum) {

        int i,left, right, num = 0, len = A.size(), currsum;
        if (len<2) return num;

        sort(A.begin(), A.end());
        if (A[0] + A[1]>sum)
            return 0;
        if (A[len - 1] + A[len - 2]<sum)
            return 0;

        left = 0;right = len - 1;
        while (left<right) {
            currsum = A[left] + A[right];
            if (currsum == sum) {
                ++num;
                //从左至右统计
                for (i = left + 1;i < right;++i) 
                {
                    if (A[i] + A[right] == sum)
                        ++num;
                    else break;
                }
                for (i = right - 1; i > left; --i)
                {
                    if (A[i] + A[left] == sum)
                        ++num;
                    else break;
                }
                ++left;--right;
            }
            else if (currsum<sum) {
                ++left;
            }
            else {
                --right;
            }
        }
        return num;
    }
};
View Code

与程序员面试金典一书的解法不同,做了对重复数据的补充计算。

7.加法运算替代

虽然不知道这个有什么作用,不过还是做出来了。。。

class AddSubstitution {
public:
    int calc(int a, int b, int type) {
        // write code here
        
        int i,num=0;
        if(1==type){
            if(0==a||0==b)
                return 0;
            else{
                if(b<0){
                    for(i=0;i<absval(b);++i){
                        num+=a;
                    }
                    if(a<0) return num;
                    else return negate(num);
                }else{
                    for(i=0;i<b;++i){
                        num+=a;
                    }
                    return num;
                }
            }
        }else if(0==type){
            if(0==a||0==b) return 0;
            
            bool signa=a<0?true:false;
            bool signb=b<0?true:false;
            int absa=absval(a),absb=absval(b),res=0;
            
            if(absa<absb)
                return 0;
            else{
                for(res=0;num<=absa;res++){
                    num+=absb;
                }
            }
            
            if(signa==signb){
                return res+(-1);
            }else return negate(res)+1;
        }else if(-1==type){
            
            if(0==a)
                return b;
            else if(0==b)
                return a;
                
            return a+negate(b);
        }else{
            return 0;
        }
    }
    
private:
    int negate(int x){
        int num=0,d=x<0?1:-1;
        while(x){
            x+=d;
            num+=d;
        }
        return num;
    }
    
    int absval(int x){
        if(x<0){
            return negate(x);
        }else return x;
    }
};
View Code

8.找出字符串

class Finder {
public:
    int findString(vector<string> str, int n, string x) {
        
        int len=str.size();
        if(n!=len||n<=0) 
            return -1;
        
        int left=0,right=len-1,mid;
        while(left<=right){
            
            mid=(right-left)/2+left;
            
            if(str[mid].length()!=0){ //非空字符串比较
                
                if(str[mid]==x){
                    return mid;
                }else{
                    if(str[mid]>x)
                        right=mid-1;
                    else left=mid+1;
                }
            }else{ //空字符串处理
                
                int temp=mid;
                while(temp>=left&&str[temp].length()==0){
                    --temp;
                }
                
                if(temp<left) left=mid+1; //此处是最容易忽略的地方
                else if(str[temp]==x) return temp;
                else if(str[temp]<x) left=mid+1;
                else right=temp-1;
            }
        }
        
        return -1;
    }
};
View Code

9.变位词排序

题目:请编写一个方法,对一个字符串数组进行排序,将所有变位词合并,保留其字典序最小的一个串。

        这里的变位词指变换其字母顺序所构成的新的词或短语。例如"triangle"和"integral"就是变位词。

第一次使用map,感觉真的很好使用,不过使用过程中发现键值可能存在冲突,后续查看相关资料。

class SortString {
public:
    vector<string> sortStrings(vector<string> str, int n) {

        vector<string> res;
        int i, len = str.size(), pos = 0;
        if (len != n || n <= 0) return res;

        string temp;        
        map<string, string> stemp; //排完序的单词对应的变位词
        for (i = 0;i<len;++i) {
            temp = str[i];
            sort(temp.begin(), temp.end());
            if (stemp.find(temp) == stemp.end() || stemp[temp] > str[i])
            {
                //此处的temp即为key,而stemp[temp]则是根据key寻找到的value值
                stemp[temp] = str[i];
            }
        }

        for each (auto var in stemp)
        {
            res.push_back(var.second);
        }
        sort(res.begin(), res.end());
        return res;
    }
};

10.像素设定(此题考查位操作,需很谨慎)

参考他人代码完成,后续需要自己再联系

class Render {
public:
    vector<int> renderPixel(vector<int> screen, int x, int y) {

        int len = screen.size();
        if (x > y || x<0 || (y / 8)>len || len <= 0) return screen;

        int i, numx = x / 8, numy = y / 8, endx = x % 8, endy = y % 8;

        int mask = 1;
        if (numx == numy)
        {
            mask = mask << endx;
            for (i = endx; i <= endy; i++)
            {
                screen[numx] = screen[numx] | mask;
                mask = mask << 1;
            }
        }
        else
        {
            mask = mask << endx;
            for (i = endx;i < 8;++i) {
                screen[numx] |= mask;
                mask = mask << 1;
            }
            for (i = 0, mask = 1;i <= endy;++i) {
                screen[numy] |= mask;
                mask = mask << 1;
            }
            for (i = numx + 1;i <= numy - 1;++i) //绘制中间区域
                screen[i] = 255;
        }
        return screen;
    }
};

11.洪水

此题甚是巧妙,不用递归也能巧妙解决,赞

class Flood {
public:
    int floodFill(vector<vector<int>> map, int n, int m) {

        int row = map.size(), col = map[0].size();
        if ((1 == n - 1 && 0 == m) || (1 == m - 1 && 0 == n)) return 1;
        if (1 == n - 1 && 1 == m - 1) return 2;

        int i, j, res = 0;
        for (i = 0;i < row;++i) {
            for (j = 0;j < col;++j) {
                if (map[i][j] == 1)
                    map[i][j] = INT_MAX;
                else map[i][j] = -1;
            }
        }

        map[0][0] = 0;
        while (map[row - 1][col - 1] == -1) {
            res++;
            for (i = 0;i < res&&i < row;++i) {
                for (j = 0;j < res - i&&j < col;++j) {
                    if (map[i][j] == res - 1) {
                        if (i + 1 < row && (map[i + 1][j] == -1 || (map[i + 1][j] != INT_MAX&&map[i + 1][j] > res)))
                            map[i + 1][j] = res;
                        if (j + 1 < col && (map[i][j + 1] == -1 || (map[i][j + 1] != INT_MAX&&map[i][j + 1] > res)))
                            map[i][j + 1] = res;
                    }
                }
            }
        }
        return res;
    }
};

代码不好理解,最好配合调试输出进行理解。

原文地址:https://www.cnblogs.com/jason1990/p/4746100.html