剑指offer刷题
JZ3 数组中重复的数:
unordered_map与桶并不是很难想。有趣的是题解里的原地踏步法。
桶和unordered_map的话都需要额外的O(n)的空间去找是否有重复的值,但是原地踏步法的是用了数组的值只在0-n之间的这个性质,在原数组上进行操作。
其主要思想就是,把当前位置上的值放到对应的位置上
因为值在0-n-1之间,数组长度为n,那么意味着每个值都会有其对应在数组中的位置(0在0位置,1在1位置)。
代码如下:
int duplicate(vector<int>& numbers) {
for (int i = 0; i < numbers.size(); ++ i) {
if (i != numbers[i]) {
if (numbers[i] == numbers[numbers[i]]) {
return numbers[i];
}
swap(numbers[i], numbers[numbers[i]]);
i --;
}
}
return -1;
}
JZ4 二维数组中的查找:
这道题也十分有趣,一开始想用二分套二分的,但是发现了其实这个不满足二分套二分的性质,也就是假设给你一个target,你当前位置是(posn, posm),并且array(posn, posm)是大于target,那么现在有两个选择,要么往上去找,要么往左去找,但是你无法确定是上还是左,因为上面和左边都是小于array(posn, posm)。
看了题解,发现解法十分巧妙,利用了数组类似二叉搜索树的性质,先从右上角出发,如果target大于当前的话,就当前行 ++, 小于就当前列 --。等于就直接返回。
妙哉!
代码如下:
bool Find(int target, vector<vector<int> > array) {
if (array.size() == 0) return false;
int n = array.size();
int m = array[0].size();
int curn = 0;
int curm = m-1;
while (curn < n && curm >= 0) {
if (array[curn][curm] == target) return true;
else if (array[curn][curm] > target) {
-- curm;
}
else {
++ curn;
}
}
return false;
}
JZ5 替换空格 :
这道题有点小笨,就直接新开个string按照规则模拟就好了。不放代码了。
JZ6 从尾到头打印链表:
这道题一看我就觉得用递归写,但是居然只超过了百分之一的人。
之后换成顺序遍历 + reverse 也是很慢。
之后又换成了栈,结果还是很慢。
点开了榜一大哥的代码,哦~,原来是vector的push_back太慢了。
先预留空间就超快了。
没啥好放代码的。