周二题目
- leetcode: 面试题 04.05. 合法二叉搜索树
解题思路: 首先二叉搜索树代表的是根节点比左叶节点大,比右节点数值小。根据中序排列,排列后如果是升序排列,就说明是合法的二叉树,反之则不是。
/** * Definition for a binary tree node. * function TreeNode(val) { * this.val = val; * this.left = this.right = null; * } */ /** * @param {TreeNode} root * @return {boolean} */ var isValidBST = function(root) { if(!root)return true; let stack = [],res=[]; let cur = root; while(stack.length || cur) { if(cur) { stack.push(cur); cur = cur.left; } else { // --> 弹出 中 cur = stack.pop(); res.push(cur.val); // 右 cur = cur.right; } }; let flag = true; for (let i = 0; i< res.length; i++) { if(i > 0) { if(res[i] <= res[i-1]) { flag = false; } } } return flag; }; - leetcode: 二叉搜索树中第K小的元素
解题思路:上次题目中要求求k大的元素,目前看k小,就是先看左子树,再看右子树,就是中序排列
/** * @param {TreeNode} root * @param {number} k * @return {number} */ var kthSmallest = function(root, k) { let ans; const inOrderTraverse = function(node) { if(node!=null && k>0) { inOrderTraverse(node.left); if(--k==0) ans = node.val; inOrderTraverse(node.right); } } inOrderTraverse(root); return ans; }; - leetcode: 二叉树的右视图
解题思路: 层序遍历的时候,判断是否遍历到单层的最后面的元素,如果是,就放进result数组中,随后返回result就可以了
var rightSideView = function(root) { //二叉树右视图 只需要把每一层最后一个节点存储到res数组 let res=[],queue=[root]; while(queue.length&&root!==null){ // 记录当前层级节点个数 let length=queue.length; while(length--){ let node=queue.shift(); //length长度为0的时候表明到了层级最后一个节点 if(!length){ res.push(node.val); } node.left&&queue.push(node.left); node.right&&queue.push(node.right); } } return res; }; - leetcode: 相同的树
解题思路:2颗树进行递归,如果相同的话,每个节点都会相同,如果不同,则不是相同的树
/** * @param {TreeNode} p * @param {TreeNode} q * @return {boolean} */ var isSameTree = function(p, q) { if(p===null && q===null){ return true ; } if(p=== null || q=== null){ return false; } if(p.val !== q.val){ return false; } return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); }; - leetcode: 对称二叉树
解题思路:根据题意,使用迭代法进行书写
var isSymmetric = function(root) { //迭代方法判断是否是对称二叉树 //首先判断root是否为空 if(root===null){ return true; } let queue=[]; queue.push(root.left); queue.push(root.right); while(queue.length){ let leftNode=queue.shift();//左节点 let rightNode=queue.shift();//右节点 if(leftNode===null&&rightNode===null){ continue; } if(leftNode===null||rightNode===null||leftNode.val!==rightNode.val){ return false; } queue.push(leftNode.left);//左节点左孩子入队 queue.push(rightNode.right);//右节点右孩子入队 queue.push(leftNode.right);//左节点右孩子入队 queue.push(rightNode.left);//右节点左孩子入队 } return true; };
周四题目
- leetcode: 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先
解题思路:由于是二叉搜索树,所以如果一个比我小,一个比我大就返回我;都比我大就递归我的右边,都比我小就递归我的左边
var lowestCommonAncestor = function(root, p, q) { if(!root || root===p || root===q || (root.val > p.val && root.val < q.val) || (root.val < p.val && root.val > q.val)) return root; if(root.val > p.val && root.val > q.val) return lowestCommonAncestor(root.left, p, q); if(root.val < p.val && root.val < q.val) return lowestCommonAncestor(root.right, p, q); }; - leetcode: 二叉树中的最大路径和
解题思路:路径每到一个节点,都会有3种情况,1)停在当前 2)往左侧走 3)往右侧走。 2和3之后,又是这3种情况。但是不能返回,返回不符合题意。所以停在当前最大收益root.val,情况2: root.val+ dfs(root.left) 情况3: root.val+dfs(root.right); 而最大收益就是root.val+max(0, dfs(root.left), dfs(root.right))
const maxPathSum = (root) => { let maxSum = Number.MIN_SAFE_INTEGER; // 最大路径和 const dfs = (root) => { if (root == null) { // 遍历到null节点,收益0 return 0; } const left = dfs(root.left); // 左子树提供的最大路径和 const right = dfs(root.right); // 右子树提供的最大路径和 const innerMaxSum = left + root.val + right; // 当前子树内部的最大路径和 maxSum = Math.max(maxSum, innerMaxSum); // 挑战最大纪录 const outputMaxSum = root.val + Math.max(0, left, right); // 当前子树对外提供的最大和 // 如果对外提供的路径和为负,直接返回0。否则正常返回 return outputMaxSum < 0 ? 0 : outputMaxSum; }; dfs(root); // 递归的入口 return maxSum; }; - leetcode: 前 K 个高频元素
解题思路:先判断给定元素其中某个值出现的次数,再根据出现的次数进行排序,截取前k个高频元素,就得到以下的程序代码。
/** * @param {number[]} nums * @param {number} k * @return {number[]} */ var topKFrequent = function(nums, k) { if(!nums.length ){ return nums; } let m = new Map(); nums.forEach(i=>{ let count =1; if(m.has(i)){ count=m.get(i); count++; } m.set(i,count); }); let r = []; for (let [key, value] of m) { r.push({key,value}); } r= r.sort((a,b)=>b.value-a.value).splice(0,k).map(i=>i.key); return r; }; - leetcode: 最接近原点的 K 个点
解题思路:首先了解欧几里德距离。定义:欧几里得度量(euclidean metric)(也称欧氏距离)是一个通常采用的距离定义,指在m维空间中两个点之间的真实距离,或者向量的自然长度(即该点到原点的距离)。在二维和三维空间中的欧氏距离就是两点之间的实际距离。二维公式是:Math.hypot(x1 - x0, y1 - y0);
/** * @param {number[][]} points * @param {number} k * @return {number[][]} */ var kClosest = function(points, k) { // 由于是距离远点之间的距离,可以之间简写成如下 let pp = []; points.forEach((p)=>{ const distance = Math.hypot(p[0], p[1]); pp.push({ d:distance, i:p }); }) pp = pp.sort((a,b)=>a.d-b.d).splice(0,k).map(i=>i.i); return pp; }; - leetcode: 根据字符出现频率排序
解题思路:和第3题的思路比较相似,先把字符串转成数组,再对比第三题的循环塞入一个新的数组,再转成字符串。
/** * @param {string} s * @return {string} */ var frequencySort = function(s) { if(!s.length ){ return s; } let m = new Map(); let sN = s.split(""); sN.forEach(i=>{ let count =1; if(m.has(i)){ count=m.get(i); count++; } m.set(i,count); }); let r = []; for (let [key, value] of m) { for(let i=0;i<value;i++){ r.push({key,value}); } } r= r.sort((a,b)=>b.value-a.value).map(i=>i.key); return r.join(""); };