题目:
给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>=L) 。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。
思路:递归处理即可。对每一课树,判断节点的值是否在边界内。如果在边界内,则返回对这个根节点,且左右子树分别递归修剪。如果小于L,则返回左子树的修剪结果,因为此时右子树的所有值肯定不满足。如果大于R,则返回右子树的修剪结果
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {number} L
* @param {number} R
* @return {TreeNode}
*/
var trimBST = function(root, L, R) {
if (!root) return root;
if (root.val < L) return trimBST(root.right, L, R);
if (root.val > R) return trimBST(root.left, L, R);
root.left = trimBST(root.left, L, R);
root.right = trimBST(root.right, L, R);
return root;
};
题目:
给定一个非空特殊的二叉树,每个节点都是正数,并且每个节点的子节点数量只能为 2 或 0。如果一个节点有两个子节点的话,那么该节点的值等于两个子节点中较小的一个。
思路:递归处理树。首先,记录根节点的值。我们要先明确一点:如果某个节点的子节点不等于根节点的值,那么这课子节点的树的所有节点的最小值就是这个子节点的值,且这个值肯定比根节点的值更大。所以这个值要作为可能的结果比较。
如果等于根节点的值,那么就先判断是否有子节点,没有子节点返回undefined,有子节点再递归处理。
我们的目标就是找到子树中不等于根节点的最小值
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
var findSecondMinimumValue = function(root) {
if (!root) return -1;
const search = (root, val) => {
if (!root) return;
if (root.val === val) {
if (!root.left) return;
const left = search(root.left, val);
const right = search(root.right, val);
if (!left || !right) {
return left || right;
} else {
return Math.min(left, right);
}
} else {
return root.val;
}
};
const left = search(root.left, root.val);
const right = search(root.right, root.val);
if (!left || !right) {
return left || right || -1;
} else {
return Math.min(left, right);
}
};
题目:
给定一个未经排序的整数数组,找到最长且连续的的递增序列,并返回该序列的长度。
思路:遍历,记录上一次递归数列开始的数字的下标,每次遇到降序时计算下标差,注意在遍历结束之后也要做一次计算
/**
* @param {number[]} nums
* @return {number}
*/
var findLengthOfLCIS = function(nums) {
let length = 0;
let index = 1;
nums.unshift(-Infinity)
const l = nums.length;
for (let i = 1; i < l; i++) {
if (nums[i] <= (nums[i - 1])) {
length = Math.max(i - index, length);
index = i;
}
}
return Math.max(l - index, length);
};
题目:给定一个非空字符串 s
,最多删除一个字符。判断是否能成为回文字符串。
思路:删除字符,可能删除左字符也可能删除右字符,所以做个分支处理。为了复用逻辑,可以记录删除的次数,用双指针实现
/**
* @param {string} s
* @return {boolean}
*/
var validPalindrome = function(s) {
const valdate = (s, count) => {
let left = 0;
let right = s.length - 1;
while (left < right) {
if (count > 1) return false;
if (s[left] === s[right]) {
left++;
right--;
} else {
if (!count) {
return (
valdate(s.slice(left + 1, right + 1), 1) ||
valdate(s.slice(left, right), 1)
);
} else {
return false;
}
}
}
return true;
};
return valdate(s, 0);
};
题目:
你现在是棒球比赛记录员。
给定一个字符串列表,每个字符串可以是以下四种类型之一:
1.整数(一轮的得分):直接表示您在本轮中获得的积分数。
2. "+"(一轮的得分):表示本轮获得的得分是前两轮有效 回合得分的总和。
3. "D"(一轮的得分):表示本轮获得的得分是前一轮有效 回合得分的两倍。
4. "C"(一个操作,这不是一个回合的分数):表示您获得的最后一个有效 回合的分数是无效的,应该被移除。
每一轮的操作都是永久性的,可能会对前一轮和后一轮产生影响。
你需要返回你在所有回合中得分的总和。
示例 1:
输入: ["5","2","C","D","+"]
输出: 30
解释:
第1轮:你可以得到5分。总和是:5。
第2轮:你可以得到2分。总和是:7。
操作1:第2轮的数据无效。总和是:5。
第3轮:你可以得到10分(第2轮的数据已被删除)。总数是:15。
第4轮:你可以得到5 + 10 = 15分。总数是:30。
示例 2:
输入: ["5","-2","4","C","D","9","+","+"]
输出: 27
解释:
第1轮:你可以得到5分。总和是:5。
第2轮:你可以得到-2分。总数是:3。
第3轮:你可以得到4分。总和是:7。
操作1:第3轮的数据无效。总数是:3。
第4轮:你可以得到-4分(第三轮的数据已被删除)。总和是:-1。
第5轮:你可以得到9分。总数是:8。
第6轮:你可以得到-4 + 9 = 5分。总数是13。
第7轮:你可以得到9 + 5 = 14分。总数是27。
注意:
输入列表的大小将介于1和1000之间。
列表中的每个整数都将介于-30000和30000之间。
思路:创建一个数组,存储每一次有效回合的得分,最后对数组进行累加即可
/**
* @param {string[]} ops
* @return {number}
*/
var calPoints = function(ops) {
const scores = [];
for (const s of ops) {
switch (s) {
case "+":
scores.push(
(scores[scores.length - 1] || 0) + (scores[scores.length - 2] || 0)
);
break;
case "D":
scores.push((scores[scores.length - 1] || 0) * 2);
break;
case "C":
scores.pop();
break;
default:
scores.push(+s);
}
}
return scores.reduce((res, i) => res + i, 0);
};