1. 程式人生 > >牛客網劍指Offer習題集題解0

牛客網劍指Offer習題集題解0

覆蓋 file print mta 題解 -m urn 打表 劍指offer

https://www.nowcoder.com/ta/coding-interviews

牛客個人界面歡迎互fo

0x00 二維數組中的查找

沒啥難得,直接上二分就好了。註意二分別寫挫了。
時間復雜度為\(O(nlogn)\)

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        int siz = (int)array.size();
        for(int i=0;i<siz;++i){
            int l=0,r=(int)array[i].size();
            while( l < r){
                int m = l+r>>1;
                if(array[i][m]==target) return true;
                if(array[i][m] > target) r = m;
                else l = m + 1;
            }
        }
        return false;
    }
};

0x01 替換空格

最開始以為直接輸出就好了呢,結果是更改字符串中的內容(尷尬)。
倒序更改就可以了,註意特殊情況。
時間復雜度為\(O(n)\)

class Solution {
public:
    void replaceSpace(char *str,int length) {
        if( str == NULL || length <= 0 ) return;
        int cnt = 0 , len = 0;
        for(int i=0;str[i];++i){
            len++;
            cnt += (str[i]==‘ ‘);
        }
        int newlength = len + 2*cnt;
        if(newlength > length) return;
        for(int j=newlength,i=len;i>=0;--i){
            if(str[i]!=‘ ‘) str[j--]=str[i];
            else {
                str[j--]=‘0‘;
                str[j--]=‘2‘;
                str[j--]=‘%‘;
            }
        }
    }
};

0x02 從尾到頭打印鏈表

返回值為vector,很容易想到遍歷一遍鏈表把值推進vector裏。
時間復雜度\(O(n)\)

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int> res;
        res.clear();
        if( head == NULL ) return res;
        while(head != NULL){
            res.push_back(head->val);
            head = head->next;
        }
        reverse(res.begin(),res.end());
        return res;
    }
};

0x03 重建二叉樹

根節點插入到樹中,再分成左右子樹遞歸即可,poj原題。
時間復雜度\(O(n)\),因為每個節點都遞歸遍歷過一次。

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        if( pre.size() <= 0 ) return NULL;
        int root = pre[0],en = -1;
        TreeNode * Node = new TreeNode(root);
        if( pre.size() == 1 ) return Node;
        vector<int> pp,vv;
        for(int i=0;i<(int)vin.size();++i) {
            if( vin[i]==root ) {
                en = i;
                break;
            }
            pp.push_back(pre[i+1]);
            vv.push_back(vin[i]);
        }
        Node -> left = reConstructBinaryTree(pp,vv);
        pp.clear(),vv.clear();
        for(int i=en+1;i<(int)vin.size();++i){
            pp.push_back(pre[i]);
            vv.push_back(vin[i]);
        }
        Node -> right = reConstructBinaryTree(pp,vv);
        return Node;
    }
};

0x04 用兩個棧實現隊列

stack1實現Push操作,要Pop的時候就清空stack1,塞滿stack2,這時候stack2正常Pop就好了。
時間復雜度為均攤\(O(1)\)。雖然看上去復雜度很高,但實際上\(O(n)\)的“倒騰”操作的次數不會很多。

class Solution
{
public:
    void push(int node) {
        stack1.push(node);
        return ;
    }

    int pop() {
        if((int)stack2.size()==0){
            while(stack1.size()){
                stack2.push(stack1.top());
                stack1.pop();
            }
        }
        int res = stack2.top();
        stack2.pop();
        return res;
    }

private:
    stack<int> stack1;
    stack<int> stack2;
};

0x05 旋轉數組的最小數字

題目說的很繞,其實就是求數組的最小值,\(O(n)\)跑一遍求解就好了。

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        int siz = (int)rotateArray.size();
        if(siz == 0) return 0;
        int mini = INT_MAX;
        for(int i=0;i<siz;++i)
            mini = mini < rotateArray[i] ? mini : rotateArray[i];
        return mini;
    }
};

0x06 斐波那契數列

經典題目,我就隨便寫個遞歸就過去了,常數有點高。
時間復雜度為\(O(n)\)
能打表就好了啊

class Solution {
public:
    int Fibonacci(int n) {
        if(n==0) return 0;
        else if(n==1 || n==2) return 1;
        return Fibonacci(n-1)+Fibonacci(n-2);
    }
};

0x07 跳臺階

經典題目,杭電oj裏面有。其實就是斐波那契數列的變種。
很明顯在第n個臺階只能從n-1階和n-2階走過來,所以 \(dp[n] = dp[n-1] + dp[n-2]\)
時間復雜度為\(O(n)\),手懶可以寫遞歸比如我

class Solution {
public:
    int jumpFloor(int number) {
        if(number == 1 || number == 0) return 1;
        return jumpFloor(number-1) + jumpFloor(number-2);
    }
}; 

0x08 變態跳臺階

這回的遞推公式就是從0到n-1了。
\(\begin{equation*} dp[n] = \sum_{i=1}^n dp[n-i] \end{equation*}\)
其實這題就是母函數,有興趣可以看一眼。
時間復雜度為\(O(n^2)\)

class Solution {
public:
    int jumpFloorII(int number) {
       if(number <= 1) return 1;
       int a[20]={0}; 
       a[0]=a[1]=1;
       for(int i=2;i<=number;++i)
           for(int j=1;j<=i;++j)
               a[i]+=a[i-j];
       return a[number];
    }
};

0x09 矩形覆蓋

同樣是斐波那契的變種,在紙上畫畫就出來了。POJ原題,杭電oj上也有。
時間復雜度為\(O(n)\)

class Solution {
public:
    int rectCover(int number) {
        int a[40];
        a[1]=1,a[2]=2;
        for(int i=3;i<=number;++i)
            a[i]=a[i-1]+a[i-2];
        return a[number];
    }
};

牛客網劍指Offer習題集題解0