leetcode刷题记录(17)-简单

1.重复叠加字符串匹配

题目:

给定两个字符串 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;
};

2.最长同值路径

题目:

给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值。 这条路径可以经过也可以不经过根节点。

注意:两个节点之间的路径长度由它们之间的边数表示。

思路:同值路径,就是路径上同值的节点数-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
};

3.员工的重要性

题目:

给定一个保存员工信息的数据结构,它包含了员工唯一的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)
};

4.交替位二进制数

题目:给定一个正整数,检查他是否为交替位二进制数:换句话说,就是他的二进制数相邻的两个位数永不相等。

思路:转换为二进制数,然后比较

/**
 * @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;
};

5.计数二进制子串

题目:

给定一个字符串 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;
};

 

你可能感兴趣的:(leetcode-简单难度,重复叠加字符串匹配,最长同值路径,员工的重要性,技术二进制子串,交替位二进制数)