在牛客网刷剑指offer
2016-07-17 16:23
253 查看
重建二叉树
题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
分析:
前序遍历序列的第一个数字是根节点,在中序遍历序列中找到这个数字的位置,那么中序遍历序列中在这个数字左边的序列是左子树结点,右边的是右子树结点。而在前序遍历序列中从第二个数字开始有一段连续的序列是左子树结点,长度与在中序遍历中的一样。既然知道了左、右子树的前、中序遍历,那么通过递归实现即可,函数返回根节点。
code:
用两个栈实现队列
题目描述
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
解析
push操作:将数字放进stack1里,pop操作:弹出stack2.top元素即可,假如stack2为空,操作之前应将stack1所有元素内容放到stack2中。
旋转数组的最小数字
题目描述:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
解析:
这个二分挺好的,我写错了好多次,要千万注意二分的条件以及不同的情况下这个条件是否成立。
code:
树的子结构
题目描述:
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
解析:
直接遍历递归,时间复杂度为O(n*m)。有人说将它们先序遍历变成字符串,然后看b是否是a的子串,用kmp算法可达到时间复杂度为O(n+m)。但我觉得这样不行。举个例子:A是一个深度为2的二叉树,共3个结点,父结点值为1,左儿子结点值为2,右儿子结点值为3。B也是一个深度为2的二叉树,共2个结点,父结点值为1,右儿子结点为3。B是A的子树,但A的前序遍历为{1,2,3},而B的前序遍历为{1,3},后面的根本不是前面的子串,故不成立。不知道此题是否有更好的解法,还请各位大牛告知。
code:
顺时针打印矩阵
题目描述
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
分析
分四个方向走,走到不能走的地方90度转弯,遍历过的位置进行标记。其实用dfs挺好写的。
code:
栈的压入、弹出序列
题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
分析
模拟一下入栈出栈,其实就是两种情况,某个元素出栈后,那么下一次出栈的要么是接下来的栈顶,要么是还未进栈的元素
class Solution {
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV) {
stack<int> s1;
int index = 0;
for(int i=0; i<pushV.size(); i++) {
s1.push(pushV[i]);
while(!s1.empty() && s1.top() == popV[index]) {
s1.pop(); index++;
}
}
return s1.empty();
}
};
题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
分析:
前序遍历序列的第一个数字是根节点,在中序遍历序列中找到这个数字的位置,那么中序遍历序列中在这个数字左边的序列是左子树结点,右边的是右子树结点。而在前序遍历序列中从第二个数字开始有一段连续的序列是左子树结点,长度与在中序遍历中的一样。既然知道了左、右子树的前、中序遍历,那么通过递归实现即可,函数返回根节点。
code:
/** * Definition for binary tree * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: struct TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> in) { if(pre.size() <= 0) return NULL; TreeNode* T = new TreeNode(pre[0]); vector<int> prel, prer, inl, inr; int index = 0; for(int i=0; i<in.size(); i++) { if(in[i] == pre[0]) { index = i; break; } } for(int i=0; i<in.size(); i++) if(in[i] != pre[0]) { if(i < index) inl.push_back(in[i]); else inr.push_back(in[i]); } for(int i=1; i<pre.size(); i++) { if(i <= index) prel.push_back(pre[i]); else prer.push_back(pre[i]); } T->left = reConstructBinaryTree(prel,inl); T->right = reConstructBinaryTree(prer,inr); return T; } };
用两个栈实现队列
题目描述
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
解析
push操作:将数字放进stack1里,pop操作:弹出stack2.top元素即可,假如stack2为空,操作之前应将stack1所有元素内容放到stack2中。
class Solution { public: void push(int node) { stack1.push(node); } int pop() { if(stack2.empty()) { while(!stack1.empty()) { stack2.push(stack1.top()); stack1.pop(); } } int value = stack2.top(); stack2.pop(); return value; } private: stack<int> stack1; stack<int> stack2; };
旋转数组的最小数字
题目描述:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
解析:
这个二分挺好的,我写错了好多次,要千万注意二分的条件以及不同的情况下这个条件是否成立。
code:
class Solution { public: int minNumberInRotateArray(vector<int> v) { int l = 0, r = v.size()-1, mid; while(l < r) { mid = (l+r)/2; if(v[mid] > v[r]) l = mid+1; //这里一开始我写的是if(v[l] < v[mid])。当最小值在顶端时出错 else r = mid; } return v[l]; } };
树的子结构
题目描述:
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
解析:
直接遍历递归,时间复杂度为O(n*m)。有人说将它们先序遍历变成字符串,然后看b是否是a的子串,用kmp算法可达到时间复杂度为O(n+m)。但我觉得这样不行。举个例子:A是一个深度为2的二叉树,共3个结点,父结点值为1,左儿子结点值为2,右儿子结点值为3。B也是一个深度为2的二叉树,共2个结点,父结点值为1,右儿子结点为3。B是A的子树,但A的前序遍历为{1,2,3},而B的前序遍历为{1,3},后面的根本不是前面的子串,故不成立。不知道此题是否有更好的解法,还请各位大牛告知。
code:
/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } };*/ class Solution { bool isSame(TreeNode* p1, TreeNode* p2) { if(p2 == NULL) return true; //P2为空表示子树这条线路已经走完了 if(p1 == NULL) return false; //当子树的这条线路还没走完你A树的却走完了肯定不行 if(p1->val == p2->val) { if(isSame(p1->left,p2->left) && isSame(p1->right,p2->right)) { return true; } } return false; } public: bool HasSubtree(TreeNode* p1, TreeNode* p2) { if(p1 == NULL || p2 == NULL) return false; if(isSame(p1,p2) || HasSubtree(p1->left,p2) || HasSubtree(p1->right,p2)) return true; return false; } };
顺时针打印矩阵
题目描述
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
分析
分四个方向走,走到不能走的地方90度转弯,遍历过的位置进行标记。其实用dfs挺好写的。
code:
class Solution { public: vector<int> printMatrix(vector<vector<int> > matrix) { vector<int> v; int x = 0, y = 0, t = 0, n = matrix.size(), m = matrix[0].size(); while(t < n*m) { while(t < n*m && y < m && matrix[x][y] != -1) {v.push_back(matrix[x][y]); matrix[x][y++] = -1; t++;} y--, x++; while(t < n*m && x < n && matrix[x][y] != -1) {v.push_back(matrix[x][y]); matrix[x++][y] = -1; t++;} x--, y--; while(t < n*m && y >= 0 && matrix[x][y] != -1) {v.push_back(matrix[x][y]); matrix[x][y--] = -1; t++;} y++, x--; while(t < n*m && x >= 0 && matrix[x][y] != -1) {v.push_back(matrix[x][y]); matrix[x--][y] = -1; t++;} x++, y++; } return v; } };
栈的压入、弹出序列
题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
分析
模拟一下入栈出栈,其实就是两种情况,某个元素出栈后,那么下一次出栈的要么是接下来的栈顶,要么是还未进栈的元素
class Solution {
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV) {
stack<int> s1;
int index = 0;
for(int i=0; i<pushV.size(); i++) {
s1.push(pushV[i]);
while(!s1.empty() && s1.top() == popV[index]) {
s1.pop(); index++;
}
}
return s1.empty();
}
};
相关文章推荐
- javascript正则表达式 —— RegExp 对象
- javascript基础DOM操作
- 参考韩顺平老师的视频,用HTML写一个静态网页的邮箱
- jQuery Mobile 安装
- CSS3 nth 伪类选择器
- sort();方法
- 单调栈1001 POJ2796 Feel Good
- nodejs的调试
- 谈谈Js回调函数的那些事儿
- JS代码如何不被别人看到?
- JavaScript 运算符
- JavaScript-DOM
- js基础汇总
- 封装Jquery插件不再需要字符串拼接
- HTML兼容问题及高效开发工具
- [javascript权威指南][阅读笔记]八
- 经典继承方法实现(模拟extjs底层继承机制)
- OpenGL 利用framebuffer实现快速精确的点选拾取
- CSS3新特性2D、3D效果讲解
- CSS3滤镜