《JS刷剑指Offer》题解系列JZ16-JZ20

274 阅读1分钟

JZ16 合并两个排序的链表

题目描述

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

解法一

无递归。构造一个链表头,指向每次比较中较小的那个。如果最后某串链表还有多余,则指向剩下的那串链表。

function Merge(pHead1, pHead2)
{
    var head = new ListNode(0);
    var pHead = head;
    while(pHead1 != null && pHead2!= null)
    {
        if(pHead1.val < pHead2.val)
        {
            head.next = pHead1;
            pHead1 = pHead1.next;
        }else{
            head.next = pHead2;
            pHead2 = pHead2.next;
        }
        head = head.next;
    }
    if(pHead1 === null)
    {
        head.next = pHead2;
    }
    if(pHead2 === null)
    {
        head.next = pHead1;
    }
    return pHead.next;
}

解法二

递归法,很好理解。每次要得到下一个位置就进行递归计算

function Merge(pHead1, pHead2) {
    let p = null;
    if(!pHead1) return pHead2;//pHead1已经遍历完毕
    if(!pHead2) return pHead1;
    if(pHead1.val < pHead2.val)
    {
        p = pHead1;
        p.next = Merge(pHead1.next, pHead2);//本次选取phead1,phead1前进
    }else{
        p = pHead2;
        p.next = Merge(pHead1, pHead2.next);
    }
    return p;
}

JZ17 树的子结构

题目描述

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

解法

子结构定义:树A和树B的根结点相等,并且树A的左子树和树B的左子树相等,树A的右子树和树B的右子树相等

主要是进行每个节点的匹配,首先找基准点,看以当前为根节点向下匹配是否能成功,不能的话就以左子树为基准点,再不能,以右子树为基准点

/**
 * @return {boolean}
 */
function HasSubtree(pRoot1, pRoot2)
{
    // write code here
    var result = false;
    if(pRoot1 != null && pRoot2 != null)//如果root为零,直接返回false
    {
        //看以当前根节点作为基准是否和root2一致,如果不一致找左子树,再找右子树
        return (doeTreeHaveSubTree(pRoot1, pRoot2) || HasSubtree(pRoot1.left, pRoot2) || HasSubtree(pRoot1.right, pRoot2));
    }
    return result;
}
function doeTreeHaveSubTree(node1, node2) {
    if(node2 === null)
    {
        return true;//要找的树已经遍历完了,ok
    }
    if(node1 === null)
    {
        return false;
    }
    if(node1.val !== node2.val)
    {
        return false;//没匹配上
    }
    return doeTreeHaveSubTree(node1.left, node2.left) && doeTreeHaveSubTree(node1.right, node2.right);//分别匹配左右子树
}

JZ18 二叉树的镜像

题目描述

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

解法

记住每次递归都是你想要的值,那么你只要把左子树定义为右边递归的值,右子树赋值为左边递归的值即可。

function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
}

function Mirror(root) {
    if (!root) return null;
    var temp = root.left;
    root.left = Mirror(root.right);
    root.right = Mirror(temp);
    return root;
}

JZ19 顺时针打印矩阵

题目描述

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 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)
{
    // write code here
    var low = 0;
    var high = matrix.length-1;
    var left = 0;
    var right = matrix[0].length-1;
    var ret = [];
    while(low <= high && left <= right)
    {
        for(let i = left; i <= right; i++)
        {
            ret.push(matrix[low][i]);//从左到右
        }
        if(low === high){break;}//只有一行,默认执行完从左到右后就不再执行了
        for(let j = low+1; j <= high; j++)
        {
            ret.push(matrix[j][right]);//从上到下
        }
        if(left === right){break;}//只有一列,默认执行完从上到下后就不再执行了
        for(let m = right-1; m >= left; m--)
        {
            ret.push(matrix[high][m]);//从右到左
        }
        for(let n = high-1; n >= low+1; n--)
        {
            ret.push(matrix[n][left]);//从下到上
        }
        low++;
        high--;
        left++;
        right--;
    }
    return ret;
}

JZ20 包含min函数的栈

题目描述

定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))

解法

这个好像没什么好说,求最小值可以用math库的函数

    let stack = [];
    function push(node)
    {
        // write code here
        return stack.push(node);
    }
    function pop()
    {
        // write code here
        return stack.pop();
    }
    function top()
    {
        // write code here
        return stack.pop();
    }
    function min()
    {
        // write code here
        return Math.min(...stack);
        //也可以return Math.min.apply(this, stack)
    }