题目:
给定两个字符串 A 和 B, 寻找重复叠加字符串A的最小次数,使得字符串B成为叠加后的字符串A的子串,如果不存在则返回 -1。
举个例子,A = "abcd",B = "cdabcdab"。
答案为 3, 因为 A 重复叠加三遍后为 “abcdabcdabcd”,此时 B 是其子串;A 重复叠加两遍后为"abcdabcd",B 并不是其子串。
/**
* @param {string} A
* @param {string} B
* @return {number}
*/
var repeatedStringMatch = function(A, B) {
const endLen = B.length + A.length * 2;
for (let count = 1, repeatA = A; repeatA.length <= endLen; count++, repeatA += A) {
if (repeatA.includes(B)) return count;
}
return -1;
};
题目:
给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值。 这条路径可以经过也可以不经过根节点。
注意:两个节点之间的路径长度由它们之间的边数表示。
思路:同值路径,就是路径上同值的节点数-1。路径可以连接某个节点的左树和右树,所以这题适合递归处理,最长的路径的节点数就是某个节点左路径最大值+右路径最大值+当前节点。如果节点值和左节点值不等,那么左节点值就作为0,同理右节点。最后每次求出子树的路径之和都和当前最大值比较一下。
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
var longestUnivaluePath = function(root) {
let length = 0;
const longestUnivaluePathAA = (root) => {
if (!root) return 0;
let left = longestUnivaluePathAA(root.left);
let right = longestUnivaluePathAA(root.right);
if (!root.left || root.left.val !== root.val) left = 0;
if (!root.right || root.right.val !== root.val) right = 0;
length = Math.max(length, 1 + left + right);
return 1 + Math.max(left , right);
};
longestUnivaluePathAA(root);
return length && length - 1
};
题目:
给定一个保存员工信息的数据结构,它包含了员工唯一的id,重要度 和 直系下属的id。
比如,员工1是员工2的领导,员工2是员工3的领导。他们相应的重要度为15, 10, 5。那么员工1的数据结构是[1, 15, [2]],员工2的数据结构是[2, 10, [3]],员工3的数据结构是[3, 5, []]。注意虽然员工3也是员工1的一个下属,但是由于并不是直系下属,因此没有体现在员工1的数据结构中。
现在输入一个公司的所有员工信息,以及单个员工id,返回这个员工和他所有下属的重要度之和。
思路:递归或迭代都行。先遍历一遍数组,用map记录id和员工数据的映射关系。然后维护一个id队列,根据id找到员工信息,然后把下属的id推入队列
迭代:
/**
* Definition for Employee.
* function Employee(id, importance, subordinates) {
* this.id = id;
* this.importance = importance;
* this.subordinates = subordinates;
* }
*/
/**
* @param {Employee[]} employees
* @param {number} id
* @return {number}
*/
var GetImportance = function (employees, id) {
const map = new Map();
const idStack = [id];
let sum = 0;
for (const i of employees) {
map.set(i.id, i);
}
while (idStack.length) {
const id = idStack.shift();
const emplo = map.get(id);
sum += emplo.importance;
idStack.push(...emplo.subordinates);
}
return sum;
};
递归:
/**
* Definition for Employee.
* function Employee(id, importance, subordinates) {
* this.id = id;
* this.importance = importance;
* this.subordinates = subordinates;
* }
*/
/**
* @param {Employee[]} employees
* @param {number} id
* @return {number}
*/
var GetImportance = function (employees, id) {
const map = new Map();
for (const i of employees) {
map.set(i.id, i);
}
const GetImportanceAA=(i,map)=>{
return i.reduce((sum,id)=>{
const emplo = map.get(id);
sum += emplo.importance;
return sum+=GetImportanceAA(emplo.subordinates,map)
},0)
}
return GetImportanceAA([id],map)
};
题目:给定一个正整数,检查他是否为交替位二进制数:换句话说,就是他的二进制数相邻的两个位数永不相等。
思路:转换为二进制数,然后比较
/**
* @param {number} n
* @return {boolean}
*/
var hasAlternatingBits = function(n) {
const s = n.toString(2);
for (let i = 0, l = s.length; i < l; i++) {
if (s[i] === s[i + 1]) return false;
}
return true;
};
题目:
给定一个字符串 s,计算具有相同数量0和1的非空(连续)子字符串的数量,并且这些子字符串中的所有0和所有1都是组合在一起的。
重复出现的子串要计算它们出现的次数。
思路:首先,思路就是遍历字符串,遇到0和1数量相等的记录。然后根据长度,跳到下一次开始遍历的位置
/**
* @param {string} s
* @return {number}
*/
var countBinarySubstrings = function(s) {
let n = 0;
const count = (s) => {
const l = s.length;
if (l < 2) return 1;
let v = s[0];
let v0 = 1;
let v1 = 0;
let flag = false;
for (let i = 1; i < l; i++) {
if (s[i] === v) {
if (flag) return 1;
v0++;
} else {
v1++;
if (v1 == v0) {
n += v1;
return v1;
}
flag = true;
}
}
return 1;
};
for (let l = s.length, i = 0; i < l; ) {
i += count(s.slice(i));
}
return n;
};
上面的思路有一个很大的问题,就是每次都重复遍历了一次中间的字符串,最终是遍历了两次整个字符串。
仔细观察可知,这题的结果其实就是连续的字符作为一组,取相邻两组的长度的最小值,然后依次累加
/**
* @param {string} s
* @return {number}
*/
var countBinarySubstrings = function(s) {
const l = s.length;
if (l < 2) return 0;
let count = 0;
let v = s[0];
let preL = 0;
let curL = 1;
for (let i = 1; i < l; i++) {
if (s[i] === v) {
curL++;
} else {
count += Math.min(curL, preL);
v = s[i];
preL = curL;
curL = 1;
}
}
count += Math.min(curL, preL);
return count;
};