程序员面试金典算法题

空格替换

题目描述

请编写一个方法,将字符串中的空格全部替换为“%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;
    }
};
时间: 2024-08-06 12:05:38

程序员面试金典算法题的相关文章

LeetCode题解分类汇总(包括剑指Offer和程序员面试金典,持续更新)

LeetCode题解汇总(持续更新,并将逐步迁移到本博客列表中) 剑指Offer 数据结构 链表 序号 题目 难度 06 从尾到头打印链表 简单 18 删除链表的节点 简单 22 链表中倒数第k个节点 简单 二叉树 序号 题目 难度 07 重建二叉树 中等 栈和队列 序号 题目 难度 09 用两个栈实现队列 简单 图 序号 题目 难度 12 矩阵中的路径 中等 13 机器人的运动范围 中等 算法 动态规划 序号 题目 难度 10- I 斐波那契数列 简单 10- II 青蛙跳台阶问题 简单 查找

程序员面试、算法研究、编程艺术、红黑树、数据挖掘5大系列集锦

程序员面试.算法研究.编程艺术.红黑树.数据挖掘5大系列集锦

《PHP程序员面试笔试真题解析》——新书上线

你好,是我--琉忆.很高兴可以跟你分享我的新书. 很高兴,在出版了PHP程序员面试笔试宝典后迎来了我的第二本书出版--<PHP程序员面试笔试真题解析>. 如果你是一个热爱PHP的程序员,刚踏入PHP职场,你值得拥有这本书来自学一番,再去尝试找PHP相关的工作,对你帮助绝对不是一般的大!! PS:宝典和真题解析其实是一套的~ 以下简单的对我的新书做个介绍~ 前言 本书的适用群体:刚接触PHP,自学一段时间PHP后打算去找PHP相关的PHP面试工作的群体.这部分群体可以尝试着去练习这部分企业中经常

C/C++程序员面试易错题

c部分::::::::::::::::::::::::::::::::::: 27. 关键字volatile有什么含意? 并给出三个不同的例子.[参考答案]一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了.精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份.下面是volatile变量的几个例子:1). 并行设备的硬件寄存器(如:状态寄存器)2). 一个中断服务子程序中会访问到的非自动变量

程序员面试宝典第一题判断字符串是否相同

题目: (编程题) 请实现一个算法,确定一个字符串的所有字符是否全都不同.这里我们要求不允许使用额外的存储结构. 给定一个string iniString,请返回一个bool值,True代表所有字符全都不同,False代表存在相同的字符.保证字符串中的字符为ASCII字符.字符串的长度小于等于3000. 测试样例: "aeiou"返回:True"BarackObama"返回:False 解析:首先需要注意的是,若全部不相同,该字符串最多只有257位,因为为ascii

程序员面试金典-面试题 01.01. 判定字符是否唯一

题目: https://leetcode-cn.com/problems/is-unique-lcci/ 实现一个算法,确定一个字符串 s 的所有字符是否全都不同. 示例 1: 输入: s = "leetcode"输出: false 示例 2: 输入: s = "abc"输出: true限制: 0 <= len(s) <= 100如果你不使用额外的数据结构,会很加分. 分析: 哈希做法,开辟数组,统计对应位置的字符出现数量,遍历字符串,当数量为1时,表示

程序员面试金典-面试题 04.02. 最小高度树

题目: 给定一个有序整数数组,元素各不相同且按升序排列,编写一个算法,创建一棵高度最小的二叉搜索树. 示例:给定有序数组: [-10,-3,0,5,9], 一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树: 0 / \ -3   9 /     / -10  5 分析: 因为数组中元素已经有序,我们可以将数组中最中间的元素作为根节点,然后递归构建二分搜索树,当前结点的左子树由中间元素左边的的元素构成,右子树则由右边元素,递归构建即可. 程序: /**

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

题目: 设计一个算法,算出 n 阶乘有多少个尾随零. 示例 1: 输入: 3输出: 0解释: 3! = 6, 尾数中没有零.示例 2: 输入: 5输出: 1解释: 5! = 120, 尾数中有 1 个零.说明: 你算法的时间复杂度应为 O(log n) . 分析: 计算阶乘后0的个数实际上就是在数5,一个5和一个偶数相乘就会产生一个0,而25会产生两个0,所以对于n大于0时,数它的5有多少个,除以5,如果还大于0就继续除以5,也就是在数25有几个,反复执行下去. 程序: class Soluti

程序员面试金典-面试题 16.20. T9键盘

题目: 在老式手机上,用户通过数字键盘输入,手机将提供与这些数字相匹配的单词列表.每个数字映射到0至4个字母.给定一个数字序列,实现一个算法来返回匹配单词的列表.你会得到一张含有有效单词的列表.映射如下图所示: 示例 1: 输入: num = "8733", words = ["tree", "used"] 输出: ["tree", "used"] 示例 2: 输入: num = "2"