剑指offer算法题JS实现

1、在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

function Find(target, array)
{
    var rows=array.length;
    var cols=array[0].length;
    if(rows==0&&cols==0){
        return false;
    }
    var i=0;
    var j=cols-1;
    while(i<=rows-1&&j>=0){
        if(array[i][j]>target){
            j--;
        }else if(array[i][j]<target){
            i++;
        }else{
            return true;
        }
    }
}

分析:在二维数组中,查找某一个整数,要找出该数对应的行和列才能确定其数值,所以在本例中,行是数组的长度即arr.length,列是arr[i].length,然后用(i<=rows.length;j>=0)循环整个二维数组,判断arr[i] [j]的值是否等于target。由于行和列都是递增的,所以第一次循环,当target大于第一行最后一列的整数时,i++;反之,j–,直到找到对应的整数值。

2、请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

function replaceSpace(str)
{
    return str.replace(/\s/g,"%20");
}

分析:在正则表达式中,/s匹配任何空白字符,/g全文匹配

3、输入一个链表,从尾到头打印链表每个节点的值。

function printListFromTailToHead(head)
{
    var arr=[];
    if(head==null)
    {
        return false;
    }
    while(head){
        arr.unshift(head.val);
        head=head.next;
    }
    return arr;
}

分析:借助数组用unshift()方法实现在数组的前端添加链表的节点值。

4、输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

 function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} 
function reConstructBinaryTree(pre, vin)
{
    if(pre.length==0||vin.length==0){
        return null;
    }
    var binaryTree=new TreeNode(pre[0]);
    var pre_left=[],pre_right=[],vin_left=[],vin_right=[];
    var index=vin.indexOf(pre[0]);
    pre_left=pre.slice(1,index+1);
    pre_right=pre.slice(index+1);
    vin_left=vin.slice(0,index);
    vin_right=vin.slice(index+1);
    binaryTree.left=reConstructBinaryTree(pre_left,vin_left);
    binaryTree.right=reConstructBinaryTree(pre_right,vin_right);
    return binaryTree;
}

分析:首先定义一个空链表function TreeNode(){}
然后用递归函数实现二叉树的重建:
1)、判断给定序列长度是否为0
2)、确定根节点 及其位置 (前序的第一个节点是根节点,该节点把中序分为左右子树节点)
var binaryTree=new TreeNode(pre[0]);
var index=vin.indexOf(pre[0]);
3)、用slice方法找到前序和中序对应的左子树节点和右子树节点
var pre_left=pre.slice(1,index+1);
var pre_right=pre.slice(index+1);
var vin_left=vin.slice(0,index);
var vin_right=vin.slice(index+1);
4)、然后进一步递归实现每一个左子树的左右子节点和右子树的左右子节点。

5、用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

var stack1=[],stack2=[];
function push(node)
{
    stack1.push(node);
}
function pop()
{
    if(stack2.length==0){
        if(stack1.length==0){
            return null;
        }else{
            var len=stack1.length;
            for(var i=0;i<len;i++){
                stack2.push(stack1.pop());
            }
            return stack2.pop();
        }
    }else{
        return stack2.pop();
    }
}

分析:用两个栈实现队列的效果,其中一个栈用于push操作,另一栈用于pop操作。

6、把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

function minNumberInRotateArray(rotateArray)
{
    // write code here
    var len=rotateArray.length;
    if(len<=1){
        return len=0?0:rotateArray[0];
    }else{
        var low=0;
        var high=len-1;
        while(high-low>1){
            var mid=parseInt((high+low)/2);

if(rotateArray[low]==rotateArray[mid]&&rotateArray[low]==rotateArray[mid]){
                var result=rotateArray[high];
                for(var i=low+1;i<high;i++){
                    if(result>rotateArray[i]){
                        result=rotateArray[i];
                    }
                }
            }
            if(rotateArray[mid]>=rotateArray[low]){
                low=mid;
            }  
            if(rotateArray[mid]<=rotateArray[high]){
                high=mid;
            }
        }
        return rotateArray[high];
    }
}

分析:用二分查找法,确定最小值。
1)、mid=(low+high)/2,当mid大于第一个数值,则最小元素在mid的后端元素中,此时low=mid;
2)、当mid小于最后一个数值,则最小元素在mid的前短元素中,此时high=mid;
3)、依次循环数组,直到high -low<=1;
4)、返回rotateArray[high]就是数组中的最小元素。

7、大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。
n<=39

function Fibonacci(n)
{
    if(n<=1){
        return n;
    }else{
        var f0=0,f1=1;
        for(var i=2;i<=n;i++){
            fn=f0+f1;
            f0=f1;
            f1=fn;
        }
        return fn;
    }
}

8、输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

function NumberOf1(n)
{
    // write code here
    var count=0;
    while(n!=0){
        n=n&(n-1);
        ++count;
    }
    return count;
}

9、输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

function reOrderArray(array)
{
    // write code here
    var arr1=[],arr2=[];
    for(var i=0;i<array.length;i++){
        if(array[i]%2==0){
            arr2.push(array[i]);
        }else{
            arr1.push(array[i]);
        }
    }
    return arr1.concat(arr2);
}

10、输入一个链表,输出该链表中倒数第k个结点。

function FindKthToTail(head, k)
{
     if (head == null) {
        return false;
    }
    var arr = [];
    while (head) {
        arr.unshift(head);
        head = head.next;
    }
    return arr[k-1];
}

11、输入一个链表,反转链表后,输出链表的所有元素。

function ReverseList(pHead)
{
    // write code here
    if(!pHead){
        return null;
    }
    var pre=null;
    var next=null;
    while(pHead){
        next=pHead.next;
        pHead.next=pre;
        pre=pHead;
        pHead=next;
    }
    return pre;
}

12、输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

function Merge(pHead1, pHead2)
{
    // write code here
    if(!pHead1){
        return pHead2;
    }
    if(!pHead2){
        return pHead1;
    }
    var head=null;
    if(pHead1.val<pHead2.val){
        head=pHead1;
        head.next=Merge(pHead1.next,pHead2);
    }else{
        head=pHead2;
        head.next=Merge(pHead2.next,pHead1);
    }
    return head;
}

分析:给定的两个有序递增数列,要合并成一个非递减的有序数列。

首先对两个数列h1和h2的第一个节点的val值进行比较,若h1.val小于h2.val,则将head空指针指向h1,h1=h1.next,head.next进行递归判断,即head.next=Merge(h1.next,h2);反之若h1.val>h2.val,则将head指针指向h2,h2=h2.next,head.next进行递归判断,即head.next=Merge(h1,h2.next),依次进行上述序列的判断,直到链表的最后一个节点。

13、输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

function HasSubtree(pRoot1, pRoot2)
{
    // write code here
    var h1=pRoot1,h2=pRoot2;
    var result=false;
    if(h1!=null&&h2!=null){
        if(h1.val==h2.val){
            result=isSubTree(h1,h2);
        }
        if(!result){
            result=HasSubtree(h1.left,h2);
        }
        if(!result){
            result=HasSubtree(h1.right,h2);
        }
    }
    return result;
}
function isSubTree(h1,h2){
    if(h1==null&&h2!=null) return false;
    if(h2==null) return true;
    if(h1.val!=h2.val) return false;
    return isSubTree(h1.left,h2.left)&&isSubTree(h1.right,h2.right);
}

14、操作给定的二叉树,将其变换为源二叉树的镜像。

function Mirror(root)
{
    // write code here
    if(root==null){
        return null;
    }
    if(root.left==null&root.right==null){
        return root;
    }
    var temp=root.left;
    root.left=root.right;
    root.right=temp;
    Mirror(root.left);
    Mirror(root.right);
}

15、输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 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.

function printMatrix(matrix){
    var rows=matrix.length;
    var cols=matrix[0].length;
    var result=[];
    var left=0,right=cols-1;
    var top=0,bottom=rows-1;
    while(left<=right&&top<=bottom){
        for(var i=left;i<=right;i++){
            result.push(matrix[top][i]);
        }
        for(var j=top+1;j<=bottom;j++){
            result.push(matrix[j][right]);
        }
        if(top!=bottom){
            for(var i=right-1;i>=left;i--){
                result.push(matrix[bottom][i]);
            }
        }
        if(left!=right){
            for(var i=bottom-1;i>top;i--){
                result.push(matrix[i][left]);
            }
        }
        left++;
        top++;
        right--;
        bottom--;
    }
    return result;
}

16、定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。

var stack=[];
function push(node)
{
    // write code here
    stack.push(node);
}
function pop()
{
    // write code here
    return stack.length==0?null:stack.pop();
}
function top()
{
    // write code here
    return stack.length==0?null:stack[0];
}
function min()
{
    // write code here
    return Math.min.apply(this,stack);
}

17、输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

function IsPopOrder(pushV, popV)
{
    // write code here
    var stack=[];
    var index=0;
    for(var i=0;i<pushV.length;i++){
        stack.push(pushV[i]);
        while(stack.length&&stack[stack.length-1]==popV[index]){
            stack.pop();
            index++;
        }
    }
    return stack.length==0;
}

18、从上往下打印出二叉树的每个节点,同层节点从左至右打印。

/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
function PrintFromTopToBottom(root)
{
    // write code here
    var arr=[];
    var data=[];
    if(root!=null){
        arr.push(root);
    }
    while(arr.length!=0){
        var node=arr.shift();
        if(node.left!=null){
            arr.push(node.left);
        }
        if(node.right!=null){
            arr.push(node.right);
        }
        data.push(node.val);
    }
    return data;
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值