程序员面试金典算法题

Posted 我是修电脑的

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了程序员面试金典算法题相关的知识,希望对你有一定的参考价值。

空格替换

题目描述

请编写一个方法,将字符串中的空格全部替换为“%20”。假定该字符串有足够的空间存放新增的字符,并且知道字符串的真实长度(小于等于1000),同时保证字符串由大小写的英文字母组成。 
给定一个string iniString 为原始的串,以及串的长度 int len, 返回替换后的string。 
测试样例: 
“Mr John Smith”,13 
返回:”Mr%20John%20Smith” 
”Hello World”,12 
返回:”Hello%20%20World”

classReplacement {
public:
    string replaceSpace(string iniString, intlength) {
        string temp;
        for(inti = 0; i < length; i++)
        {
            if(iniString[i] == ‘ ‘)
            {
                temp += "%20";
            }
            else
            {
                temp += iniString[i];
            }
        }
        returntemp;
    }
};

 

基本字符串压缩

题目描述

利用字符重复出现的次数,编写一个方法,实现基本的字符串压缩功能。比如,字符串“aabcccccaaa”经压缩会变成“a2b1c5a3”。若压缩后的字符串没有变短,则返回原先的字符串。 
给定一个string iniString为待压缩的串(长度小于等于3000),保证串内字符均由大小写英文字母组成,返回一个string,为所求的压缩后或未变化的串。 
测试样例 
“aabcccccaaa” 
返回:”a2b1c5a3” 
“welcometonowcoderrrrr” 
返回:”welcometonowcoderrrrr”

class Zipper {
public:
    string zipString(string iniString) {
        string temp;
        char c = iniString[0];
        int count = 1;
        for (int i = 1; i <= iniString.size(); i++)
        {
            if (iniString[i] != c || i == iniString.size())
            {
                temp += c;
                temp += int2str(count);
                c = iniString[i];
                count = 1;
            }
            else
            {
                count++;
            }
        }
        if (temp.size() >= iniString.size())
        {
            return iniString;
        }
        return temp;
    }

    string int2str(int n)
    {
        string temp;
        while (n)
        {
            temp += n % 10 + ‘0‘;
            n /= 10;
        }
        reverse(temp.begin(), temp.end());
        return temp;
    }
};
//以上程序有一定的副作用,核心部分可改为:
//string fun(string str)
//{
//    int i = 0;
//    string res = "";
//    while (i < str.length())
//    {
//        char cur = str[i];
//        int cnt = 0;
//        while (i < str.length() && str[i] == cur)
//        {
//            i++;
//            cnt++;
//        }
//        res += cur;
//        res += cnt + ‘0‘;
//    }
//
//    return res;
//}

 

确定字符互异

题目描述

请实现一个算法,确定一个字符串的所有字符是否全都不同。这里我们要求不允许使用额外的存储结构。 
给定一个string iniString,请返回一个bool值,True代表所有字符全都不同,False代表存在相同的字符。保证字符串中的字符为ASCII字符。字符串的长度小于等于3000。 
测试样例: 
“aeiou” 
返回:True 
“BarackObama” 
返回:False

class Different {
public:
    bool checkDifferent(string iniString) {
        int c[256] = {0};
        for (int i = 0; i < iniString.size(); i++)
        {
            if (c[iniString[i]] == 1)
            {
                return false;
            }
            else
            {
                c[iniString[i]] = 1;
            }
        }

        return true;
    }
};

 

原串翻转

题目描述

请实现一个算法,在不使用额外数据结构和储存空间的情况下,翻转一个给定的字符串(可以使用单个过程变量)。 
给定一个string iniString,请返回一个string,为翻转后的字符串。保证字符串的长度小于等于5000。 
测试样例: 
“This is nowcoder” 
返回:”redocwon si sihT”

class Reverse {
public:
    string reverseString(string iniString) {
        for (int i = 0, j = iniString.size() - 1; i < j; i++, j--)
        {
            char c = iniString[i];
            iniString[i] = iniString[j];
            iniString[j] = c;
        }
        return iniString;
    }
};

 

 

确定两串乱序同构

题目描述

给定两个字符串,请编写程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。这里规定大小写为不同字符,且考虑字符串重点空格。 
给定一个string stringA和一个string stringB,请返回一个bool,代表两串是否重新排列后可相同。保证两串的长度都小于等于5000。 
测试样例: 
“This is nowcoder”,”is This nowcoder” 
返回:true 
“Here you are”,”Are you here” 
返回:false

class Same {
public:
    bool checkSam(string stringA, string stringB) {
        int count[256] = {0};
        for (int i = 0; i < stringA.size(); i++)
        {
            count[stringA[i]]++;
        }
        for (int j = 0; j < stringB.size(); j++)
        {
            if (count[stringB[j]] > 0)
            {
                count[stringB[j]]--;
            }
            else
            {
                return false;
            }
        }

        int sum = 0;
        for (int i = 0; i < 256; i++)
        {
            sum += count[i];
        }

        return sum == 0;
    }
};

 

像素翻转

题目描述

有一副由NxN矩阵表示的图像,这里每个像素用一个int表示,请编写一个算法,在不占用额外内存空间的情况下(即不使用缓存矩阵),将图像顺时针旋转90度。 
给定一个NxN的矩阵,和矩阵的阶数N,请返回旋转后的NxN矩阵,保证N小于等于500,图像元素小于等于256。 
测试样例: 
[[1,2,3],[4,5,6],[7,8,9]],3 
返回:[[7,4,1],[8,5,2],[9,6,3]] 
解析:首先沿对角线折叠,然后交换列

class Transform {
public:
    vector<vector<int> > transformImage(vector<vector<int> > mat, int n) {
        for (int i = 0; i < n; i++)
        {
            for (int j = i + 1; j < n; j++)
            {
                swap(mat[i][j], mat[j][i]);
            }
        }

        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n / 2; j++)
            {
                swap(mat[i][j], mat[i][n - j - 1]);
            }
        }

        return mat;
    }
};

 

清除行列

题目描述

请编写一个算法,若MxN矩阵中某个元素为0,则将其所在的行与列清零。 
给定一个MxN的int[][]矩阵(C++中为vector>)mat和矩阵的阶数n,请返回完成操作后的int[][]矩阵(C++中为vector>),保证n小于等于300,矩阵中的元素为int范围内。 
测试样例: 
[[1,2,3],[0,1,2],[0,0,1]] 
返回:[[0,0,3],[0,0,0],[0,0,0]]

class Clearer {
public:
    vector<vector<int> > clearZero(vector<vector<int> > mat, int n) {
        bool *row = new bool[n];
        bool *col = new bool[n];
        memset(row, 0, n);
        memset(col, 0, n);
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (mat[i][j] == 0)
                {
                    row[i] = true;
                    col[j] = true;
                }
            }
        }

        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (row[i] || col[j])
                {
                    mat[i][j] = 0;
                }
            }
        }

        return mat;
    }
};

 

翻转子串

题目描述

假定我们都知道非常高效的算法来检查一个单词是否为其他字符串的子串。请将这个算法编写成一个函数,给定两个字符串s1和s2,请编写代码检查s2是否为s1旋转而成,要求只能调用一次检查子串的函数。 
给定两个字符串s1,s2,请返回bool值代表s2是否由s1旋转而成。字符串中字符为英文字母和空格,区分大小写,字符串长度小于等于1000。 
测试样例: 
“Hello world”,”worldhello ” 
返回:false 
“waterbottle”,”erbottlewat” 
返回:true

class ReverseEqual {
public:
    bool checkReverseEqual(string s1, string s2) {
        int len = s1.size();
        if (len != s2.size())
        {
            return false;
        }
        for (int i = 0; i < len; i++)
        {
            bool b = true;
            for (int j = 0; j < len; j++)
            {
                if (s1[j] != s2[(j + i) % len])
                {
                    b = false;
                    break;
                }
            }
            if (b)
            {
                return b;
            }
        }

        return false;
    }
};

 

 

访问单个节点的删除

题目描述

实现一个算法,删除单向链表中间的某个结点,假定你只能访问该结点。 
给定带删除的节点,请执行删除操作,若该节点为尾节点,返回false,否则返回true

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Remove {
public:
    bool removeNode(ListNode* pNode) {
        ListNode *p = pNode->next;
        if (p == NULL)
        {
            return false;
        }
        else
        {
            pNode->val = p->val;
            pNode->next = p->next;
            delete p;
        }
        return true;
    }
};

链表分割

题目描述

编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前 
给定一个链表的头指针 ListNode* pHead,请返回重新排列后的链表的头指针。

class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        ListNode *head1 = NULL;
        ListNode *tail1 = NULL;
        ListNode *head2 = NULL;
        ListNode *tail2 = NULL;
        while (pHead != NULL)
        {
            if (pHead->val < x)
            {
                if (head1 == NULL)
                {
                    head1 = pHead;
                    tail1 = pHead;
                }
                else
                {
                    tail1->next = pHead;
                    tail1 = pHead;
                }
            }
            else
            {
                if (head2 == NULL)
                {
                    head2 = pHead;
                    tail2 = pHead;
                }
                else
                {
                    tail2->next = pHead;
                    tail2 = pHead;
                }
            }
            pHead = pHead->next;
        }
        if (tail2 != NULL)
        {
            tail2->next = NULL;
        }

        if (tail1 != NULL)
        {
            tail1->next = head2;
            return head1;
        }

        return head2;
    }
};

 

链式A+B

题目描述

有两个用链表表示的整数,每个结点包含一个数位。这些数位是反向存放的,也就是个位排在链表的首部。编写函数对这两个整数求和,并用链表形式返回结果。 
给定两个链表ListNode* A,ListNode* B,请返回A+B的结果(ListNode*)。 
测试样例: 
{1,2,3},{3,2,1} 
返回:{4,4,4}

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Plus {
public:
    ListNode* plusAB(ListNode* a, ListNode* b) {
        ListNode *head = NULL;
        ListNode *cur;
        int sum = 0;
        while (a != NULL || b != NULL)
        {
            if (a != NULL)
            {
                sum += a->val;
                a = a->next;
            }
            if (b != NULL)
            {
                sum += b->val;
                b = b->next;
            }

            if (head == NULL)
            {
                head = new ListNode(sum % 10);
                cur = head;
            }
            else
            {
                ListNode *newnode = new ListNode(sum % 10);
                cur->next = newnode;
                cur = newnode;
            }
            sum /= 10;
        }

        if (sum != 0)
        {
            ListNode *newnode = new ListNode(sum);
            cur->next = newnode;
        }

        return head;
    }
};
  • 1

回文链表

题目描述

请编写一个函数,检查链表是否为回文。 
给定一个链表ListNode* pHead,请返回一个bool,代表链表是否为回文。 
测试样例: 
{1,2,3,2,1} 
返回:true 
{1,2,3,2,3} 
返回:false

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Palindrome {
public:
    bool isPalindrome(ListNode* pHead) {
        stack<int> s;
        ListNode *p = pHead;
        while (p != NULL)
        {
            s.push(p->val);
            p = p->next;
        }
        p = pHead;
        while (!s.empty())
        {
            int n = s.top();
            s.pop();
            if (n != p->val)
            {
                return false;
            }
            p = p->next;
        }
        return true;
    }

};

 

双栈排序

题目描述

请编写一个程序,按升序对栈进行排序(即最大元素位于栈顶),要求最多只能使用一个额外的栈存放临时数据,但不得将元素复制到别的数据结构中。 
给定一个int[] numbers(C++中为vector),其中第一个元素为栈顶,请返回排序后的栈。请注意这是一个栈,意味着排序过程中你只能访问到第一个元素。 
测试样例: 
[1,2,3,4,5] 
返回:[5,4,3,2,1]

class TwoStacks {
public:
    vector<int> twoStacksSort(vector<int> numbers) {
        stack<int> s;
        int top = 0;
        int num;
        while (top != numbers.size())
        {
            num = numbers[top++];
            while (!s.empty() && s.top() > num)
            {
                numbers[--top] = s.top();
                s.pop();
            }
            s.push(num);
        }

        top = 0;
        while (!s.empty())
        {
            numbers[top++] = s.top();
            s.pop();
        }

        return numbers;
    }
};

 

二叉树平衡检查

题目描述

实现一个函数,检查二叉树是否平衡,平衡的定义如下,对于树中的任意一个结点,其两颗子树的高度差不超过1。 
给定指向树根结点的指针TreeNode* root,请返回一个bool,代表这棵树是否平衡。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/

class Balance {
public:
    bool isBalance(TreeNode* root) {
        if (root == NULL)
        {
            return true;
        }
        int diff = height(root->left) - height(root->right);
        if (diff < -1 || diff > 1)
        {
            return false;
        }
        return true;
    }

    int height(TreeNode* root)
    {
        if (root == NULL)
        {
            return 0;
        }
        int left = height(root->left);
        int right = height(root->right);
        return left > right ? left + 1 : right + 1;
    }
};

 

输出单层结点

题目描述

对于一棵二叉树,请设计一个算法,创建含有某一深度上所有结点的链表。 
给定二叉树的根结点指针TreeNode* root,以及链表上结点的深度,请返回一个链表ListNode,代表该深度上所有结点的值,请按树上从左往右的顺序链接,保证深度不超过树的高度,树上结点的值为非负整数且不超过100000。

class TreeLevel {
public:
    ListNode* getTreeLevel(TreeNode* root, int dep) {
        if (root == NULL)
        {
            return NULL;
        }
        queue<TreeNode*> q;
        q.push(root);
        int n;
        for (int i = 1; i < dep; i++)
        {
            n = q.size();
            while (n--)
            {
                TreeNode *p = q.front();
                q.pop();
                if (p->left != NULL)
                {
                    q.push(p->left);
                }
                if (p->right != NULL)
                {
                    q.push(p->right);
                }
            }
        }
        n = q.size();
        ListNode *head = new ListNode(q.front()->val);
        q.pop();
        ListNode *pre = head;
        while (!q.empty())
        {
            ListNode *newnode = new ListNode(q.front()->val);
            q.pop();
            pre->next = newnode;
            pre = newnode;
        }

        return head;
    }
};

 

检查是否为BST

题目描述

请实现一个函数,检查一棵二叉树是否为二叉查找树。 
给定树的根结点指针TreeNode* root,请返回一个bool,代表该树是否为二叉查找树。

class Checker {
public:
    bool checkBST(TreeNode* root) {
        if (root == NULL)
        {
            return true;
        }
        bool b1 = true;
        bool b2 = true;
        if (root->left != NULL)
        {
            b1 = root->val >= root->left->val;
        }
        if (root->right != NULL)
        {
            b2 = root->val <= root->right->val;
        }

        return b1 && b2 && checkBST(root->left) && checkBST(root->right);
    }
};

 

寻找下一个结点

题目描述

请设计一个算法,寻找二叉查找树中指定结点的下一个结点(即中序遍历的后继)。 
给定树的根结点指针TreeNode* root和结点的值int p,请返回值为p的结点的后继结点的值。保证结点的值大于等于零小于等于100000且没有重复值,若不存在后继返回-1。

class Successor {
public:
    int findSucc(TreeNode* root, int p) {
        stack<TreeNode*> s;
        TreeNode *cur = root;
        bool b = false;
        while (cur != NULL || !s.empty())
        {
            while (cur != NULL)
            {
                s.push(cur);
                cur = cur->left;
            }
            if (!s.empty())
            {
                cur = s.top();
                s.pop();
                if (b)
                {
                    return cur->val;
                }
                if (cur->val == p)
                {
                    b = true;
                }
                cur = cur->right;
            }
        }

        return -1;
    }
};

 

二进制插入

题目描述

有两个32位整数n和m,请编写算法将m的二进制数位插入到n的二进制的第j到第i位,其中二进制的位数从低位数到高位且以0开始。 
给定两个数int n和int m,同时给定int j和int i,意义如题所述,请返回操作后的数,保证n的第j到第i位均为零,且m的二进制位数小于等于j-i+1。 
测试样例: 
1024,19,2,6 
返回:1100

class BinInsert {
public:
    int binInsert(int n, int m, int j, int i) {
        m <<= j;
        return n | m;
    }
};
  • 1

二进制小数

题目描述

有一个介于0和1之间的实数,类型为double,返回它的二进制表示。如果该数字无法精确地用32位以内的二进制表示,返回“Error”。 
给定一个double num,表示0到1的实数,请返回一个string,代表该数的二进制表示或者“Error”。 
测试样例: 
0.625 
返回:0.101

class BinDecimal {
public:
    string printBin(double num) {
        string temp = "0.";
        int i = 0;
        while (i++ < 32 && num != 0)
        {
            num *= 2;
            temp += (int)num + ‘0‘;
            num = num - (int)num;
        }

        if (i > 32)
        {
            temp = "Error";
        }

        return temp;
    }
};

 

最接近的数

题目描述

有一个正整数,请找出其二进制表示中1的个数相同、且大小最接近的那两个数。(一个略大,一个略小) 
给定正整数int x,请返回一个vector,代表所求的两个数(小的在前)。保证答案存在。 
测试样例: 

返回:[1,4]

class CloseNumber {
public:
    vector<int> getCloseNumber(int x) {
        vector<int> res;
        int bit = getbit(x);
        for (int i = x - 1; i > 0; i--)
        {
            if (getbit(i) == bit)
            {
                res.push_back(i);
                break;
            }
        }
        for (int i = x + 1; i <= 0x7fffffff; i++)
        {
            if (getbit(i) == bit)
            {
                res.push_back(i);
                break;
            }
        }

        return res;
    }

    int getbit(int x)
    {
        int n = 0;
        while (x)
        {
            ++n;
            x &= x - 1;
        }
        return n;
    }
};

 

整数转化

题目描述

编写一个函数,确定需要改变几个位,才能将整数A转变成整数B。 
给定两个整数int A,int B。请返回需要改变的数位个数。 
测试样例: 
10,5 
返回:4

//计算有几个位不相等即可
class Transform {
public:
    int calcCost(int A, int B) {
        int c = 0;
        for (int i = 1; i != 0; i <<= 1)
        {
            c += (A & i) != (B & i);
        }
        return c;
    }
};

 

奇偶位交换

题目描述

请编写程序交换一个数的二进制的奇数位和偶数位。(使用越少的指令越好) 
给定一个int x,请返回交换后的数int。 
测试样例: 
10 
返回:5

class Exchange {
public:
    int exchangeOddEven(int x) {
        int n = 0;
        for (int i = 0; i < 30; i += 2)
        {
            int b1 = x & 1 << i;
            int b2 = x & 1 << i + 1;
            n |= b1 << 1;
            n |= b2 >> 1;
        }
        return n;
    }
};

 

  • 14

找出缺失的整数

题目描述

数组A包含了0到n的所有整数,但其中缺失了一个。对于这个问题,我们设定限制,使得一次操作无法取得数组number里某个整数的完整内容。唯一的可用操作是询问数组中第i个元素的二进制的第j位(最低位为第0位),该操作的时间复杂度为常数,请设计算法,在O(n)的时间内找到这个数。 
给定一个数组number,即所有剩下的数按从小到大排列的二进制各位的值,如A[0][1]表示剩下的第二个数二进制从低到高的第二位。同时给定一个int n,意义如题。请返回缺失的数。 
测试样例: 
[[0],[0,1]] 
返回:1

class Finder {
public:
    int findMissing(vector<vector<int> > numbers, int n) {
        int miss = 0;
        for (int i = 0; i < numbers.size(); i++)
        {
            int n = 0;
            for (int j = numbers[i].size() - 1; j >= 0; j--)
            {
                n = 2 * n + numbers[i][j];
            }
            miss ^= i ^ n;
        }
        return miss ^ n;
    }
};

像素设定

题目描述

有一个单色屏幕储存在一维数组中,其中数组的每个元素代表连续的8位的像素的值,请实现一个函数,将第x到第y个像素涂上颜色(像素标号从零开始),并尝试尽量使用最快的办法。 
给定表示屏幕的数组screen(数组中的每个元素代表连续的8个像素,且从左至右的像素分别对应元素的二进制的从低到高位),以及int x,int y,意义如题意所述,保证输入数据合法。请返回涂色后的新的屏幕数组。 
测试样例: 
[0,0,0,0,0,0],0,47 
返回:[255,255,255,255,255,255]

class Render {
public:
    vector<int> renderPixel(vector<int> screen, int x, int y) {
        int a1 = x / 8;
        int b1 = x % 8;
        int a2 = y / 8;
        int b2 = y % 8;
        for (int i = a1 + 1; i < a2; i++)
        {
            screen[i] = 255;
        }
        for (int i = b1; i < 8; i++)
        {
            screen[a1] |= 1 << i;
        }
        if (a2 != a1)
        {
            for (int i = 0; i <= b2; i++)
            {
                screen[a2] |= 1 << i;
            }
        }

        return screen;
    }
};

 

或者

class Render {
public:
    vector<int> renderPixel(vector<int> screen, int x, int y) {
        while (x <= y)
        {
            int a = x / 8;
            int b = x % 8;
            screen[a] |= 1 << b;
            x++;
        }

        return screen;
    }
};

 

第k个数

题目描述

有一些数的素因子只有3、5、7,请设计一个算法,找出其中的第k个数。 
给定一个数int k,请返回第k个数。保证k小于等于100。 
测试样例: 

返回:7 
解析: 
1. 初始化结果res=1和队列q3,q5,q7 
2. 分别往q3,q5,q7插入1*3,1*5,1*7 
3. 求出三个队列的队头元素中最小的那个x,更新结果res=x 
4. 如果x在: 
q3中,那么从q3中移除x,并向q3,q5,q7插入3*x,5*x,7*x 
q5中,那么从q5中移除x,并向q5,q7插入5*x,7*x 
q7中,那么从q7中移除x,并向q7插入7*x 
5. 重复步骤3-5,直到找到第k个满足条件的数

class KthNumber {
public:
    int findKth(int k) {
        queue<int> q3;
        queue<int> q5;
        queue<int> q7;
        q3.push(3);
        q5.push(5);
        q7.push(7);
        int small;
        for (int i = 0; i < k; i++)
        {
            small = min(min(q3.front(), q5.front()), q7.front());
            if (small == q3.front())
            {
                q3.pop();
                q3.push(3 * small);
                q5.push(5 * small);
            }
            else if (small == q5.front())
            {
                q5.pop();
                q5.push(5 * small);
            }
            else if (small == q7.front())
            {
                q7.pop();
            }
            q7.push(7 * small);
        }

        return small;
    }
};

 

碰撞的蚂蚁

题目描述

在n个顶点的多边形上有n只蚂蚁,这些蚂蚁同时开始沿着多变形的边爬行,请求出这些蚂蚁相撞的概率。(这里的相撞是指存在任意两只蚂蚁会相撞) 
给定一个int n(3<=n<=10000),代表n变形和n只蚂蚁,请返回一个double,为相撞的概率。 
测试样例: 

返回:0.75

//所有的都顺时针或者逆时针
class Ants {
public:
    double antsCollision(int n) {
        double b = 1 << n;
        double a = 2 / b;
        return 1 - a;
    }
};

 

上楼梯

题目描述

有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶、3阶。请实现一个方法,计算小孩有多少种上楼的方式。为了防止溢出,请将结果Mod 1000000007 
给定一个正整数int n,请返回一个数,代表上楼的方式数。保证n小于等于100000。 
测试样例: 

返回:1

//超时
class GoUpstairs {
public:
    int countWays(int n) {
        if (n == 1) return 1;
        if (n == 2) return 2;
        if (n == 3) return 4;
        return countWays(n - 1) + countWays(n - 2) + countWays(n - 3); 
    }
};

 

AC代码:

class GoUpstairs {
public:
    int countWays(int n) {
        vector<int> num(n + 1, 0);
        num[0] = 1;
        num[1] = 1;
        num[2] = 2;
        for (int i = 3; i <= n; i++)
        {
            num[i] += num[i - 1]; num[i] %= 1000000007;
            num[i] += num[i - 2]; num[i] %= 1000000007;
            num[i] += num[i - 3]; num[i] %= 1000000007;
        }
        return num[n];
    }
};

 

机器人走方格I

题目描述

有一个XxY的网格,一个机器人只能走格点且只能向右或向下走,要从左上角走到右下角。请设计一个算法,计算机器人有多少种走法。 
给定两个正整数int x,int y,请返回机器人的走法数目。保证x+y小于等于12。 
测试样例: 
2,2 
返回:2

class Robot {
public:
    int countWays(int x, int y) {
        vector<vector<int>> step(x, vector<int>(y, 1));
        for (int i = 1; i < x; i++)
        {
            for (int j = 1; j < y; j++)
            {
                step[i][j] = step[i - 1][j] + step[i][j - 1];
            }
        }
        return step[x - 1][y - 1];
    }
};

 

机器人走方格II

题目描述

有一个XxY的网格,一个机器人只能走格点且只能向右或向下走,要从左上角走到右下角。请设计一个算法,计算机器人有多少种走法。注意这次的网格中有些障碍点是不能走的。 
给定一个int[][] map(C++ 中为vector >),表示网格图,若map[i][j]为1则说明该点不是障碍点,否则则为障碍。另外给定int x,int y,表示网格的大小。请返回机器人从(0,0)走到(x - 1,y - 1)的走法数,为了防止溢出,请将结果Mod 1000000007。保证x和y均小于等于50

class Robot {
public:
    int countWays(vector<vector<int> > map, int x, int y) {
        vector<vector<int>> n(x, vector<int>(y, 0));
        n[0][0] = map[0][0] == 1 ? 1 : 0;
        for (int i = 0; i < x; i++)
        {
            for (int j = 0; j < y; j++)
            {
                if (map[i][j] == 1)
                {
                    if (i > 0)
                    {
                        n[i][j] += n[i - 1][j];
                    }
                    if (j > 0)
                    {
                        n[i][j] += n[i][j - 1];
                    }
                }
            }
        }

        return n[x - 1][y - 1];
    }
};

 

魔术索引I

题目描述

在数组A[0..n-1]中,有所谓的魔术索引,满足条件A[i]=i。给定一个升序数组,元素值各不相同,编写一个方法,判断在数组A中是否存在魔术索引。请思考一种复杂度优于o(n)的方法。 
给定一个int数组A和int n代表数组大小,请返回一个bool,代表是否存在魔术索引。 
测试样例: 
[1,2,3,4,5] 
返回:false

class MagicIndex {
public:
    bool findMagicIndex(vector<int> A, int n) {
        for (int i = 0; i < A.size(); i++)
        {
            if (A[i] == i)
            {
                return true;
            }
            if (A[i] > i)
            {
                return false;
            }
        }
    }
};

 

魔术索引II

题目描述

在数组A[0..n-1]中,有所谓的魔术索引,满足条件A[i]=i。给定一个不下降序列,元素值可能相同,编写一个方法,判断在数组A中是否存在魔术索引。请思考一种复杂度优于o(n)的方法。 
给定一个int数组A和int n代表数组大小,请返回一个bool,代表是否存在魔术索引。 
测试样例: 
[1,1,3,4,5] 
返回:true

class MagicIndex {
public:
    bool findMagicIndex(vector<int> A, int n) {
        for (int i = 0; i < A.size(); i++)
        {
            if (A[i] == i)
            {
                return true;
            }
        }
        return false;
    }
};

 

 

 
 

以上是关于程序员面试金典算法题的主要内容,如果未能解决你的问题,请参考以下文章

《程序员面试金典(第6版)》面试题 08.04. 幂集(回溯算法,位运算,C++)不断更新

程序员面试金典面试题 01.08. 零矩阵

程序员面试金典面试题 01.08. 零矩阵

《程序员面试金典(第6版)》面试题 08.08. 有重复字符串的排列组合(回溯算法,全排列问题)C++

算法 | 第4章 树与图相关《程序员面试金典》#yyds干货盘点#

程序员面试金典-面试题 16.05. 阶乘尾数