文章目录
61、序列化二叉树
题目描述
请实现两个函数,分别用来序列化和反序列化二叉树
思路
- 序列化,将节点值存入数组中,空节点则使用特殊标记存入数组中。
- 反序列化,从数组中获取元素,为number类型则生成节点,为特殊标记,则为空节点
代码
二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。
通过文件内容重建原来的二叉树过程叫做二叉树反序列化。
例子采用先序遍历
var arr=[];
function Serialize(pRoot)
{
// write code here
if(pRoot==null){
arr.push('#') //特殊标记
return;
}
arr.push(pRoot.val);
Serialize(pRoot.left) //先左节点
Serialize(pRoot.right) //后右节点
}
function Deserialize(s)
{
// write code here
if(arr==null){
return null;
}
if(arr.length<1){
return null;
}
var root=null;
//shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。
var temp=arr.shift();
if(typeof temp=='number'){
root=new TreeNode(temp);
root.left=Deserialize(arr);
root.right=Deserialize(arr);
}
return root;
}
62、二叉搜索树的第k个结点
题目描述
给定一颗二叉搜索树,请找出其中的第k大的结点。例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中,按结点数值大小顺序第三个结点的值为4。
思路
二叉搜索树,若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;任意节点的左、右子树也分别为二叉查找树;
所以采用中序遍历的方法,遍历后的结果就是从小到大顺序的结果
代码
function KthNode(pRoot, k)
{
// write code here
var arr=[];
if(pRoot===null||k<1){
return null;
}
function midInorder(root){//中序排序
if(root.left!==null){
midInorder(root.left);
}
arr.push(root);
if(root.right!==null){
midInorder(root.right);
}
}
midInorder(pRoot);
return arr[k-1];
}
63、数据流中的中位数
题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
思路一
代码
var arr=[]
function Insert(num)
{
// write code here
arr.push(num);
arr.sort()//数值排序
}
function GetMedian(){
// write code here
var len=arr.length;
if(len%2!=0){
return arr[Math.floor(len/2)];
}else{
return (arr[len/2-1]+arr[len/2])/2
}
}
思路二
大小顶堆,数据流传输时,第偶个数,存入大顶堆中,然后将大顶堆中最大元素取出放入小顶堆中,第奇个数,存入小顶堆,然后将小顶堆中最小元素取出放入大顶堆中。最后小顶堆存放的元素都大于大顶堆存放元素。
当数量为偶数时候,访问大顶堆中最大元素和小顶堆中最小元素平均值,当数量为奇数时,访问小顶堆中最小元素。
代码
var arr1=[],arr2=[],count=0;
function Insert(num)
{
// write code here
if(count%2==0){//第偶个数,存入大顶堆中
arr1.push(num);
//从小到大排序
arr1.sort(function(a,b){
return a-b;
})
arr2.push(arr1.pop());
//从大到小排序
arr2.sort(function(a,b){
return b-a;
})
}else{//第奇个数,存入小顶堆
arr2.push(num);
arr2.sort(function(a,b){
return b-a;
})
arr1.push(arr2.pop());
arr1.sort(function(a,b){
return a-b;
})
}
count++
}
function GetMedian(){
// write code here
if(count%2!=0){
return arr2[arr2.length-1]
}else{
return (arr1[arr1.length-1]+arr2[arr2.length-1])/2
}
}
64、滑动窗口的最大值
题目描述
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
思路
算出滑动窗口个数=数组元素个数-滑动窗口大小+1,然后遍历循环,将队列头元素取出,存入新元素。
代码
求出给定参数中最大的数——Math.max.apply(obj,parms);//这个obj对象将代替Function类里this对象,第二个传进来的是参数——加入apply解决数组的调用
function maxInWindows(num, size)
{
// write code here
if(size==0) return[];
var result=[],windows=[];
for(var i=0;i<size;i++){
windows.push(num[i])
};
var len=num.length-size+1;//滑动窗口大小
for(var i=0,j=size;i<len;i++){
result.push(Math.max.apply(null,windows));
windows.shift();
windows.push(num[j++]);//迭代加入后一个值
}
return result;
}
65、矩阵中的路径
题目描述
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 a b c e s f c s a d e e 矩阵中包含一条字符串”bcced”的路径,但是矩阵中不包含”abcb”路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
思路
回溯法
回溯法思路的简单描述是:把问题的解空间转化成了图或者树的结构表示,然后使用深度优先搜索策略进行遍历,遍历的过程中记录和寻找所有可行解或者最优解
代码
function hasPathCore(matrix, rows, cols, row, col, path, pathIndex, visited) {
var hasPath = false;
if (row < rows && col < cols && row >= 0 && col >= 0 && visited[row][col] === false) {
if (matrix[row * cols + col] === path[pathIndex]) {
visited[row][col] = true;
if (pathIndex === path.length - 1) {
hasPath = true;
} else {
hasPath = hasPathCore(matrix, rows, cols, row - 1, col, path, pathIndex + 1, visited) ||
hasPathCore(matrix, rows, cols, row + 1, col, path, pathIndex + 1, visited) ||
hasPathCore(matrix, rows, cols, row, col - 1, path, pathIndex + 1, visited) ||
hasPathCore(matrix, rows, cols, row, col + 1, path, pathIndex + 1, visited);
if (!hasPath) {
visited[row][col] = false;
}
}
}
}
return hasPath;
}
function hasPath(matrix, rows, cols, path)
{
// write code here
if (path.length <= 0) {
return true;
}
var visited = [];
var temp = [];
var i, j;
for (i = 0; i < rows; i++) {
temp = [];
for (j = 0; j < cols; j++) {
temp.push(false);
}
visited.push(temp);
}
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
if (hasPathCore(matrix, rows, cols, i, j, path, 0, visited)) {
return true;
}
}
}
return false;
}
66、机器人的运动范围
题目描述
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
思路
回溯法
代码
function movingCount(threshold, rows, cols)
{
// write code here
var count=0;
if(threshold<1||rows<1||cols<1){
return count;
}
var visited=[];
for(var i=0; i<rows; i++){
visited[i]=[];
for(var j=0; j<cols; j++){
visited[i][j]=false;
}
}
count = movingCountSum(threshold,0,0,rows,cols,visited);
return count;
}
function movingCountSum(threshold,m,n,rows,cols,visited){
var count = 0;
if(m>=0&&m<rows&&n>=0&&n<cols&&!visited[m][n]&&getSum(m,n)<=threshold){
visited[m][n]=true;
count = 1+movingCountSum(threshold,m,n-1,rows,cols,visited)+
movingCountSum(threshold,m,n+1,rows,cols,visited)+
movingCountSum(threshold,m-1,n,rows,cols,visited)+
movingCountSum(threshold,m+1,n,rows,cols,visited);
}
return count;
}
function getSum(m,n){
var str = [].concat(m,n).join('');
var sum=0;
for(var i=0; i<str.length; i++){
sum+=Number(str[i]);
}
return sum;
}
结言:看到这里,说明你得到初步胜利了,但是战争还是没有胜利,这些算法还是要反复刷,增强自己对代码的感觉!!!