牛客網劍指Offer習題集題解0
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