题目:
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
思路:递归或者迭代皆可,记录上一轮的值即可
/**
* @param {TreeNode} root
* @return {string[]}
*/
var binaryTreePaths = function (root) {
if (!root) return [];
const str = `${root.val}`;
const res = [];
if (!root.left && !root.right) {
return [str];
}
binaryTreePathsDeep(root.left, str, res);
binaryTreePathsDeep(root.right, str, res);
return res;
};
var binaryTreePathsDeep = (root, str, res) => {
if (!root) return;
str += `->${root.val}`;
if (!root.left && !root.right) {
res.push(str);
}
if (root.left) {
binaryTreePathsDeep(root.left, str, res);
}
if (root.right) {
binaryTreePathsDeep(root.right, str, res);
}
};
/**
* @param {TreeNode} root
* @return {string[]}
*/
var binaryTreePaths = function (root) {
if (!root) return [];
const stack = [];
const res = [];
stack.push({
str: "",
node: root,
});
while (stack.length) {
const item = stack.shift();
const str = item.str ? `${item.str}->${item.node.val}` : `${item.node.val}`;
if (!item.node.left && !item.node.right) {
res.push(str);
} else {
if (item.node.left) {
stack.push({
str,
node: item.node.left,
});
}
if (item.node.right) {
stack.push({
str,
node: item.node.right,
});
}
}
}
return res;
};
/**
* @param {TreeNode} root
* @return {string[]}
*/
var binaryTreePaths = function (root, str) {
if (!root) return [];
str = str ? `${str}->${root.val}` : `${root.val}`;
const res = [];
if (!root.left && !root.right) {
return [str];
}
return binaryTreePaths(root.left, str).concat(
binaryTreePaths(root.right, str)
);
};
题目:给定一个非负整数 num
,反复将各个位上的数字相加,直到结果为一位数。
进阶:
你可以不使用循环或者递归,且在 O(1) 时间复杂度内解决这个问题吗?
思路:首先是递归或者循环
var addDigits = function(num) {
const s = `${num}`;
let res = 0;
for (const i of s) {
res += +i;
}
return res < 10 ? res : addDigits(res);
};
然后试试进阶。
不使用递归或者循环,那么就要观察。
假设一个四位数abcd,abcd分别是每一位上的数字。那么这个数可以表示为 a*1000+b*100+c*10+d*1,也可以表示为a*999+a+b*99+b+c*9+c+d,最后我们得到了a+b+c+d。
这代表什么意思呢?这个数对9取余的结果等于a+b+c+d,也就是各位数之和。也就是说,a+b+c+d就是第一次的结果。同理,这个值我们再对9取余,最终就是结果。
有个小小的问题,即使,结果是0,说明结果是9.所以我们要对0特殊处理。如以下这两种。
/**
* @param {number} num
* @return {number}
*/
var addDigits = function(num) {
if(!num)return 0
return num%9 || 9;
};
/**
* @param {number} num
* @return {number}
*/
var addDigits = function(num) {
return (num-1)%9 +1
};
题目:
编写一个程序判断给定的数是否为丑数。
丑数就是只包含质因数 2, 3, 5
的正整数。
思路:我们把结果对2,35分别相除,如果没有一个的结果是整数,且值大于1,则不是丑数。否则是丑数
/**
* @param {number} num
* @return {boolean}
*/
const a = [2, 3, 5];
var isUgly = function (num) {
if (!num) return false;
let count = 0;
a.forEach((i) => {
if (!(num % i)) {
num /= i;
count++;
}
});
if (num == 1) return true;
if (!count) return false;
return isUgly(num);
};
题目:给定一个包含 0, 1, 2, ..., n
中 n 个数的序列,找出 0 .. n 中没有出现在序列中的那个数。
思路:我们可以直接求和,然后依次相减,结果就是缺的那个数
/**
* @param {number[]} nums
* @return {number}
*/
var missingNumber = function(nums) {
const sum = (0 + nums.length)*(nums.length+1) / 2;
return nums.reduce((sum, i) => {
return sum - i;
}, sum);
};
题目:
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
思路:首先呢,我们先用简单的,即依次遍历
/**
* @param {function} isBadVersion()
* @return {function}
*/
var solution = function(isBadVersion) {
/**
* @param {integer} n Total versions
* @return {integer} The first bad version
*/
return function(n) {
while(n){
if(!isBadVersion(n)){
return n+1
}
n--
}
return 1
};
};
缺点就是时间复杂度太高,是On。
这种查找,其实最好的是二分法,时间复杂度是log2。这和排序数组找某个数是类似的
/**
* @param {function} isBadVersion()
* @return {function}
*/
var solution = function(isBadVersion) {
/**
* @param {integer} n Total versions
* @return {integer} The first bad version
*/
return function(n) {
if (n == 1) return n;
let left = 1;
if(isBadVersion(left))return left
while (n!==left+1) {
const middle = Math.floor((left + n) / 2);
if (isBadVersion(middle)) {
n = middle;
} else {
left = middle;
}
}
return n;
};
};