https://www.nowcoder.com/ta/coding-interviews
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];
}
};