1. 程式人生 > >程式設計師面試金典演算法題

程式設計師面試金典演算法題

空格替換

題目描述

請編寫一個方法,將字串中的空格全部替換為“%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;
    }
};

迴文連結串列

題目描述

請編寫一個函式,檢查連結串列是否為迴文。
給定一個連結串列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;
    }
};

二進位制小數

題目描述

有一個介於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,代表所求的兩個數(小的在前)。保證答案存在。
測試樣例:
2
返回:[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;
    }
};

找出缺失的整數

題目描述

陣列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。
測試樣例:
3
返回: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,為相撞的概率。
測試樣例:
3
返回: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
返回: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;
    }
};