乐趣区

算法小日常04

先来回忆一下相关概念吧~
二叉搜索树
二叉搜索树是一棵二叉树
二叉搜索树的特点:对于树中的每个节点 X,它的左子树中所有关键字值小于 X 的关键字值,而它的右子树中所有关键字值大于 X 的关键字值。
根据这个性质,对一个二叉树进行中序遍历,如果是单调递增的,则可以说明这个树是二叉搜索树
前序遍历:根节点 -> 左子树 -> 右子树
中序遍历:左子树 -> 根节点 -> 右子树
后序遍历:左子树 -> 右子树 -> 根节点
已知前序和中序,后序和中序遍历序列之后,可以唯一确定一棵二叉树。但是,只知道前序和后序遍历序列,是无法知道哪个结点是左子树还算右子树。

因此可以利用二叉搜索树中序遍历方法,合法二叉搜索树的中序遍历序列为一个递增的序列

【230】二叉搜索树中第 K 小的元素

var kthSmallest = function(root, k) {let res = [];
    function lnr(node){if(node && res.length<k){lnr(node.left);
            res.push(node.val);
            lnr(node.right);
        }
    }
    lnr(root);  
    return res[k-1];
};


【236】二叉树的最近公共祖先

最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

 注意 p,q 必然存在树内, 且所有节点的值唯一!!!
递归思想, 对以 root 为根的 (子) 树进行查找 p 和 q, 如果 root == null || p || q 直接返回 root
表示对于当前树的查找已经完毕, 否则对左右子树进行查找, 根据左右子树的返回值判断:

左右子树的返回值都不为 null, 由于值唯一左右子树的返回值就是 p 和 q, 此时 root 为 LCA
如果左右子树返回值只有一个不为 null, 说明只有 p 和 q 存在与左或右子树中, 最先找到的那个节点为 LCA
左右子树返回值均为 null, p 和 q 均不在树中, 返回 null


var lowestCommonAncestor = function(root, p, q) {if(root == null || root == p || root == q) return root;
    var left = new TreeNode();
    var right = new TreeNode();
    left = lowestCommonAncestor(root.left,p,q);
    right = lowestCommonAncestor(root.right,p,q);
    if(left == null && right == null) return null;
    else if(left != null && right !=null) return root;
    else return left == null ?right:left;

};


【215】数组中的第 K 个最大元素

本题应该是考察排序,那种排序性能最高,
最基本的要会冒泡排序

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var findKthLargest = function(nums, k) {
    var num = nums;
    for(var i = 0; i < num.length; i++){for(var j=i; j<num.length; j++){if(num[i] < num[j]){var t = num[i];
                num[i] = num[j];
                num[j] = t;
            }
        }
    }
    console.log(num)
    return num[k-1]
};

有一种更简便的方法 利用数组的 sort 方法

var findKthLargest = function(nums, k) {var data = nums.sort((a, b) => b - a);
    return data[k - 1];
};

【46】全排列

给定一个 没有重复 数字的序列,返回其所有可能的全排列。
回溯法解决
回溯的本质在于“选择”和“撤销选择”。如果把回溯过程看成树的话,整个过程类似决策树。
网上大神给出了这种回溯法解题的通用方法,快来取经 https://leetcode.com/problems/combination-sum/discuss/16502/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partitioning))
? 是思路过程,借鉴 LeetCode 的一位大神的题解。

  • 回溯法
  • backtrack 解题公式
function backtrack(list, tempList, nums) {if (tempList.length === nums.length) return list.push([...tempList]);
    for(let i = 0; i < nums.length; i++) {if (tempList.includes(nums[i])) continue;
        tempList.push(nums[i]);
        backtrack(list, tempList, nums);
        tempList.pop();}
}
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var permute = function(nums) {const list = [];
    backtrack(list, [], nums)
    return list
};
退出移动版