isaaxite / blog

I am a slow walker, but I never walk backwards.
35 stars 4 forks source link

LeetCode:题目记录 #268

Open isaaxite opened 5 years ago

isaaxite commented 5 years ago

大纲

01. 删列造序 02. 键盘行 03. 数组拆分 I 04. N叉树的最大深度 05. 最小差值 I 06. 将有序数组转换为二叉搜索树 07. 重复 N 次的元素 08. 斐波那契数列 09. 单值二叉树 10. 两个数组的交集 11. 反转字符串中的单词 III 12. 转置矩阵 13. Excel表列序号 14. 按奇偶排序数组 II 15. 独特的电子邮件地址 16. 车的可用捕获量 17. 字符的最短距离 18. 各位相加 19. 链表翻转 20. 棒球比赛 21. 查找常用字符 22. 子域名访问计数 23. 杨辉三角 24. 二进制表示中质数个计算置位 25. 岛屿的周长 26. 修剪二叉搜索树 27. 最长特殊序列 Ⅰ 28. 只出现一次的数字 29. 二叉树的层次遍历 II 30. 二叉树的层平均值 31. N叉树的层序遍历 32. 分糖果 33. 数组的相对排序 34. 写字符串需要的行数 35. 链表的中间结点 36. 特殊等价字符串组 37. 重塑矩阵 38. 三维形体投影面积 39, 托普利茨矩阵 40. 整数反转 41. 回文数 42. 罗马数字转整数 43. 最长公共前缀 44. 有效的括号 45. 合并两个有序链表

isaaxite commented 5 years ago

回到顶部

删列造序

给定由 N 个小写字母字符串组成的数组 A,其中每个字符串长度相等。

删除 操作的定义是:选出一组要删掉的列,删去 A 中对应列中的所有字符,形式上,第 n 列为 [A[0][n], A[1][n], ..., A[A.length-1][n]])。

比如,有 A = ["abcdef", "uvwxyz"],

image

要删掉的列为 {0, 2, 3},删除后 A 为["bef", "vyz"], A 的列分别为["b","v"], ["e","y"], ["f","z"]。

image

你需要选出一组要删掉的列 D,对 A 执行删除操作,使 A 中剩余的每一列都是 非降序 排列的,然后请你返回 D.length 的最小可能值。

 

示例 1:

输入:["cba", "daf", "ghi"] 输出:1 解释: 当选择 D = {1},删除后 A 的列为:["c","d","g"] 和 ["a","f","i"],均为非降序排列。 若选择 D = {},那么 A 的列 ["b","a","h"] 就不是非降序排列了。 示例 2:

输入:["a", "b"] 输出:0 解释:D = {} 示例 3:

输入:["zyx", "wvu", "tsr"] 输出:3 解释:D = {0, 1, 2}  

提示:

1 <= A.length <= 100 1 <= A[i].length <= 1000

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/delete-columns-to-make-sorted 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/**
 * 记录需要使用A的列排序达到非递减序列需要删除多少列
 * @param {string[]} A
 * @return {number}
 */
var minDeletionSize = function(A) {
    let count = 0;
    const strLen = A[0].length;
    const size = A.length;
    for (let i = 0; i < strLen; i += 1) {
        for (let j = 0; j < size - 1; j += 1) {
            const curStr = A[j][i];
            const nextStr = A[j+1][i];
            if (curStr > nextStr) {
                count += 1;
                break;
            }
        } 
    }
    return count;
};
isaaxite commented 5 years ago

回到顶部

键盘行

给定一个单词列表,只返回可以使用在键盘同一行的字母打印出来的单词。键盘如下图所示。

image

示例:

输入: ["Hello", "Alaska", "Dad", "Peace"] 输出: ["Alaska", "Dad"]  

注意:

你可以重复使用键盘上同一字符。 你可以假设输入的字符串将只包含字母。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/keyboard-row 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/**
 * @param {string[]} words
 * @return {string[]}
 */
var findWords = function(words) {
    const keyboard = ['qwertyuiop', 'asdfghjkl', 'zxcvbnm'].map((item) => item.split(''));
    return words.filter((word) => {
      const wordArr = word.toLowerCase().split('');
      const targetList = keyboard.filter((item) => item.includes(wordArr[0]))[0];
      return wordArr.every((char) => targetList.includes(char));
    });
};
isaaxite commented 5 years ago

回到顶部

数组拆分 I

给定长度为 2n 的数组, 你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) ,使得从1 到 n 的 min(ai, bi) 总和最大。

示例 1:

输入: [1,4,3,2]

输出: 4 解释: n 等于 2, 最大总和为 4 = min(1, 2) + min(3, 4). 提示:

n 是正整数,范围在 [1, 10000]. 数组中的元素范围在 [-10000, 10000].

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/array-partition-i 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/**
 * @param {number[]} nums
 * @return {number}
 */
// var arrayPairSum = function(nums) {
//   nums = nums.sort();
//   let sum = 0;
//   for (let i = 0, len = nums.length; i < len; i += 2) {
//     sum += nums[i];
//   }
//   return sum;
// };

// const quickSort = (arr) => {
//   if (arr.length < 2) return arr;
//   const midIdx = Math.ceil(arr.length / 2);
//   const midVal = arr[midIdx];
//   const lArr = [];
//   const mArr = [];
//   const rArr = [];
//   for (let i = 0, len = arr.length; i < len; i += 1) {
//     if (arr[i] < midVal) {
//       lArr.push(arr[i]);
//     } else if (arr[i] === midVal) {
//       mArr.push(arr[i]);
//     } else {
//       rArr.push(arr[i]);
//     }
//   }
//   arr = null;
//   return [...quickSort(lArr), ...mArr, ...quickSort(rArr)];
// };

const arrayPairSum = (nums) => {
    nums = nums.sort((prev, next) => prev - next);
    let sum = 0;
    for (let i = 0; i < nums.length; i += 2) {
        sum += nums[i];
    }
    return sum;
}
isaaxite commented 5 years ago

回到顶部

N叉树的最大深度

给定一个 N 叉树,找到其最大深度。

最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。

例如,给定一个 3叉树 :

image

我们应返回其最大深度,3。

说明:

树的深度不会超过 1000。 树的节点总不会超过 5000。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/maximum-depth-of-n-ary-tree 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/**
 * // Definition for a Node.
 * function Node(val,children) {
 *    this.val = val;
 *    this.children = children;
 * };
 */
/**
 * @param {Node} root
 * @return {number}
 */
var maxDepth = function(root) {
    if (!root) {
      return 0;
    } else if (!root.children || !root.children.length) {
      return 1;
    } else {
      const height = [];
      for (let i = 0, len = root.children.length; i < len; i += 1) {
        height.push(maxDepth(root.children[i]));
      }
      // console.log(root.children);
      return Math.max(...height) + 1;
    }
};
isaaxite commented 5 years ago

回到顶部

最小差值 I

给定一个整数数组 A,对于每个整数 A[i],我们可以选择任意 x 满足 -K <= x <= K,并将 x 加到 A[i] 中。

在此过程之后,我们得到一些数组 B。

返回 B 的最大值和 B 的最小值之间可能存在的最小差值。

示例 1:

输入:A = [1], K = 0 输出:0 解释:B = [1] 示例 2:

输入:A = [0,10], K = 2 输出:6 解释:B = [2,8] 示例 3:

输入:A = [1,3,6], K = 3 输出:0 解释:B = [3,3,3] 或 B = [4,4,4]  

提示:

  1. 1 <= A.length <= 10000
  2. 0 <= A[i] <= 10000
  3. 0 <= K <= 10000

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/smallest-range-i 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/**
 * max(B) = max(A) - K
 * min(B) = min(A) + K
 * @param {number[]} A
 * @param {number} K
 * @return {number}
 */
var smallestRangeI = function(A, K) {
  const min = Math.min(...A);
  const max = Math.max(...A);
  const res = Math.max(0, max - min - 2 * K);
  return res;
};
isaaxite commented 5 years ago

回到顶部

将有序数组转换为二叉搜索树

将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

示例:

给定有序数组: [-10,-3,0,5,9],

一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:

      0
     / \
   -3   9
   /   /
 -10  5

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/**
 * Definition for a binary tree node.
 */
function TreeNode(val) {
  this.val = val;
  this.left = this.right = null;
}

/**
 * @param {number[]} nums
 * @return {TreeNode}
 */
var sortedArrayToBST = function(nums) {
  if (!nums.length) {
    return null;
  }
  const midIdx = Math.floor(nums.length / 2);
  const mid = nums[midIdx];
  const root = new TreeNode(null);

  root.val = mid;
  root.left = sortedArrayToBST(nums.slice(0, midIdx));
  root.right = sortedArrayToBST(nums.slice(midIdx + 1));
  return root;
};
isaaxite commented 5 years ago

回到顶部

重复 N 次的元素

在大小为 2N 的数组 A 中有 N+1 个不同的元素,其中有一个元素重复了 N 次。

返回重复了 N 次的那个元素。

 

示例 1:

输入:[1,2,3,3]
输出:3

示例 2:

输入:[2,1,2,5,3,2]
输出:2

示例 3:

输入:[5,1,5,2,5,3,5,4]
输出:5

提示:

4 <= A.length <= 10000
0 <= A[i] < 10000
A.length 为偶数

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/n-repeated-element-in-size-2n-array 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/**
 * @param {number[]} A
 * @return {number}
 */
var repeatedNTimes = function(A) {
  const pool = [];
  for (let val of A) {
    if (pool.includes(val)) {
      return val;
    }
    pool.push(val);
  }
};
isaaxite commented 5 years ago

回到顶部

斐波那契数列

斐波那契数,通常用 F(n) 表示,形成的序列称为斐波那契数列。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:

F(0) = 0,   F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
给定 N,计算 F(N)。

 

示例 1:

输入:2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1.

示例 2:

输入:3
输出:2
解释:F(3) = F(2) + F(1) = 1 + 1 = 2.

示例 3:

输入:4
输出:3
解释:F(4) = F(3) + F(2) = 2 + 1 = 3.

提示

0 ≤ N ≤ 30

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/fibonacci-number 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


 // 方法一
 var fib = function(N) {
   if (N < 1) {
     return 0;
   } else if (N < 3) {
     return 1;
   }
   return fib(N - 1) + fib(N - 2);
 };

// 方法二
var fib = function(N) {
  if (N < 1) {
    return N;
  } else if (N < 3){
    return 1;
  }
  const temp = [1,1];
  for (let i = 3; i < N; i += 1) {
    temp[1] = temp[0] + temp[1];
    temp[0] = temp[1] - temp[0];
  }
  return temp[0] + temp[1];
};
isaaxite commented 5 years ago

回到顶部

单值二叉树

如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。

只有给定的树是单值二叉树时,才返回 true;否则返回 false。

示例 1: image

输入:[1,1,1,1,1,null,1]
输出:true

示例 2:

image

输入:[2,2,2,5,2]
输出:false

提示:

给定树的节点数范围是 [1, 100]。
每个节点的值都是整数,范围为 [0, 99] 。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/univalued-binary-tree 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isUnivalTree = function(root) {
  if (!root) {
    return true;
  }
  const isEqLeft = !root.left || root.val === root.left.val;
  const isEqRight = !root.right || root.val === root.right.val;
  return isEqLeft && isEqRight
    ? isUnivalTree(root.left) && isUnivalTree(root.right)
    : false;
};
isaaxite commented 5 years ago

回到顶部

两个数组的交集

给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2]

示例 2:

输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [9,4]

说明:

输出结果中的每个元素一定是唯一的。
我们可以不考虑输出结果的顺序。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/intersection-of-two-arrays 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersection = function(nums1, nums2) {
  const res = [];
  nums1.forEach((item) => {
    if (nums2.includes(item) && !res.includes(item)) {
      res.push(item);
    }
  });
  return res;
};

第二版

/*
 * @lc app=leetcode.cn id=349 lang=javascript
 *
 * [349] 两个数组的交集
 */

// @lc code=start
/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersection = function(arr1, arr2) {
  const interSet = new Set();
  const its = [arr1, arr2];
  if (arr1.length < arr2.length) {
    its.reverse();
  }
  for (const it of its[0]) {
    if (its[1].includes(it)) {
      interSet.add(it);
    }
  }
  return Array.from(interSet);
};
  • 60/60 cases passed (68 ms)
  • Your runtime beats 85.71 % of javascript submissions
  • Your memory usage beats 31.3 % of javascript submissions (35 MB)
isaaxite commented 5 years ago

回到顶部

反转字符串中的单词 III

给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

示例 1:

输入: "Let's take LeetCode contest"
输出: "s'teL ekat edoCteeL tsetnoc" 

注意:在字符串中,每个单词由单个空格分隔,并且字符串中不会有任何额外的空格。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/reverse-words-in-a-string-iii 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {string} s
 * @return {string}
 */
var reverseWords = function(s) {
  const sArr = s.split(' ');
  return sArr.map((str) => str.split('').reverse().join('')).join(' ');
};

执行用时 :136 ms, 在所有 JavaScript 提交中击败了31.19%的用户 内存消耗 :43.2 MB, 在所有 JavaScript 提交中击败了6.70%的用户

第二版

/**
 * @param {string} s
 * @return {string}
 */
var reverseWords = function(s) {
  let begin = 0;
  const res = [];
  for (let i = 0, len = s.length; i <= len; i += 1) {
    if (s[i] === ' ' || i === len) {
      let end = i - 1;
      const str = [];
      while (end >= begin) {
        str.push(s[end--])
      }
      res.push(str.join(''));
      begin = i + 1;
    }
  }
  return res.join(' ');
}

执行用时 :104 ms, 在所有 JavaScript 提交中击败了94.64%的用户 内存消耗 :41.9 MB, 在所有 JavaScript 提交中击败了82.89%的用户

isaaxite commented 5 years ago

回到顶部

转置矩阵

给定一个矩阵 A, 返回 A 的转置矩阵。

矩阵的转置是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引。

示例 1:

输入:[[1,2,3],[4,5,6],[7,8,9]]
输出:[[1,4,7],[2,5,8],[3,6,9]]

示例 2:

输入:[[1,2,3],[4,5,6]]
输出:[[1,4],[2,5],[3,6]]

提示:

1 <= A.length <= 1000
1 <= A[0].length <= 1000

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/transpose-matrix 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {number[][]} A
 * @return {number[][]}
 */
var transpose = function(A) {
  const arr = [];
  for (let i = 0, len = A[0].length; i < len; i += 1) {
    for (let j = 0, size = A.length; j < size; j += 1) {
      if (!arr[i]) {
        arr[i] = [];
      }
      arr[i].push(A[j][i]);
    }
  }
  return arr;
};

执行用时 : 104 ms, 在所有 JavaScript 提交中击败了70.06%的用户 内存消耗 : 37.7 MB, 在所有 JavaScript 提交中击败了14.08%的用户

isaaxite commented 5 years ago

回到顶部

Excel表列序号

给定一个Excel表格中的列名称,返回其相应的列序号。

例如,

A -> 1
B -> 2
C -> 3
...
Z -> 26
AA -> 27
AB -> 28 
...

示例 1:

输入: "A"
输出: 1

示例 2:

输入: "AB"
输出: 28

示例 3:

输入: "ZY"
输出: 701

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/excel-sheet-column-number 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {string} s
 * @return {number}
 */
var titleToNumber = function(s) {
  let sum = 0;
  const calcStr = (str) => str.charCodeAt() - 64;
  const sArr = s.split('');
  for (let len = sArr.length, i = len; i > 0; i -= 1) {
    const num = calcStr(sArr[i - 1]);
    sum += num * Math.pow(26, len - i);
  }
  return sum;
};

执行用时 : 96 ms, 在所有 JavaScript 提交中击败了82.97%的用户 内存消耗 : 34.8 MB, 在所有 JavaScript 提交中击败了51.33%的用户

第二版

/**
 * @param {string} s
 * @return {number}
 */
var titleToNumber = function(s) {
  let sum = 0;
  let bit = 1;
  const calcStr = (str) => str.charCodeAt() - 64;
  const sArr = s.split('');
  for (let len = sArr.length, i = len; i > 0; i -= 1) {
    const num = calcStr(sArr[i - 1]);
    sum += num * bit;
    bit *= 26;
  }
  return sum;
};

执行用时 : 96 ms, 在所有 JavaScript 提交中击败了82.97%的用户 内存消耗 : 34.7 MB, 在所有 JavaScript 提交中击败了62.00%的用户

第三版

/**
 * @param {string} s
 * @return {number}
 */
var titleToNumber = function(s) {
  let sum = 0;
  let bit = 1;
  let len = s.length;
  const calcStr = (str) => str.charCodeAt() - 64;
  while (len > 0) {
    sum += calcStr(s[len - 1]) * bit;
    bit *= 26;
    len -= 1;
  }
  return sum;
};

执行用时 : 96 ms, 在所有 JavaScript 提交中击败了82.97%的用户 内存消耗 : 36 MB, 在所有 JavaScript 提交中击败了10.66%的用户

isaaxite commented 5 years ago

回到顶部

按奇偶排序数组 II

给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。 对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。 你可以返回任何满足上述条件的数组作为答案。

示例:

输入:[4,2,5,7]
输出:[4,5,2,7]
解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。

提示:

2 <= A.length <= 20000
A.length % 2 == 0
0 <= A[i] <= 1000

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/sort-array-by-parity-ii 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {number[]} A
 * @return {number[]}
 */
var sortArrayByParityII = function(A) {
  const num1 = [];
  const num2 = [];
  const res = [];
  A.forEach((val) => {
    val % 2 ? num2.push(val) : num1.push(val);
  });
  for (let i = 0, len = num1.length; i < len; i += 1) {
    res.push(num1[i], num2[i]);
  }
  return res;
};

执行用时 : 152 ms, 在所有 JavaScript 提交中击败了51.54%的用户 内存消耗 : 41.7 MB, 在所有 JavaScript 提交中击败了14.15%的用户

第二版

/**
 * @param {number[]} A
 * @return {number[]}
 */
var sortArrayByParityII = function(A) {
  let oddIdx = 1;
  let evenIdx = 0;
  while (evenIdx !== A.length) {
    if (A[evenIdx] % 2 !== 0) {
      if (A[oddIdx] % 2 === 0) {
        A[evenIdx] = A[oddIdx] + A[evenIdx];
        A[oddIdx] = A[evenIdx] - A[oddIdx];
        A[evenIdx] = A[evenIdx] - A[oddIdx];
      }
      oddIdx += 2;
    } else {
      evenIdx += 2;
    }
  }
  return A;
};

执行用时 : 132 ms, 在所有 JavaScript 提交中击败了96.71%的用户 内存消耗 : 38.4 MB, 在所有 JavaScript 提交中击败了86.83%的用户

isaaxite commented 5 years ago

回到顶部

独特的电子邮件地址

每封电子邮件都由一个本地名称和一个域名组成,以 @ 符号分隔。

例如,在 alice@leetcode.com中, alice 是本地名称,而 leetcode.com 是域名。

除了小写字母,这些电子邮件还可能包含 '.' 或 '+'。

如果在电子邮件地址的本地名称部分中的某些字符之间添加句点('.'),则发往那里的邮件将会转发到本地名称中没有点的同一地址。例如,"alice.z@leetcode.com” 和 “alicez@leetcode.com” 会转发到同一电子邮件地址。 (请注意,此规则不适用于域名。)

如果在本地名称中添加加号('+'),则会忽略第一个加号后面的所有内容。这允许过滤某些电子邮件,例如 m.y+name@email.com 将转发到 my@email.com。 (同样,此规则不适用于域名。)

可以同时使用这两个规则。

给定电子邮件列表 emails,我们会向列表中的每个地址发送一封电子邮件。实际收到邮件的不同地址有多少?

示例:

输入:["test.email+alex@leetcode.com","test.e.mail+bob.cathy@leetcode.com","testemail+david@lee.tcode.com"]
输出:2
解释:实际收到邮件的是 "testemail@leetcode.com" 和 "testemail@lee.tcode.com"。

提示:

1 <= emails[i].length <= 100
1 <= emails.length <= 100
每封 emails[i] 都包含有且仅有一个 '@' 字符。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/unique-email-addresses 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {string[]} emails
 * @return {number}
 */
var numUniqueEmails = function(emails) {
  const set = new Set();  
  emails.forEach((item) => {
    const strArr = item.split('@');
    strArr[0] = (strArr[0].split('+')[0]).replace(/\./g, '');
    set.add(strArr.join('@'));
  });
  return set.size;
};

执行用时 : 132 ms, 在所有 JavaScript 提交中击败了53.60%的用户 内存消耗 : 41.6 MB, 在所有 JavaScript 提交中击败了45.83%的用户

第二版

var numUniqueEmails = function(emails) {
  const set = new Set();  
  emails.forEach((item) => {
    const strArr = item.split('@');
    strArr[0] = strArr[0].replace(/\.|(\+.*)/g, '');
    set.add(strArr.join('@'));
  });
  return set.size;
};

执行用时 : 112 ms, 在所有 JavaScript 提交中击败了84.00%的用户 内存消耗 : 39.8 MB, 在所有 JavaScript 提交中击败了78.12%的用户

isaaxite commented 5 years ago

回到顶部

车的可用捕获量

在一个 8 x 8 的棋盘上,有一个白色车(rook)。也可能有空方块,白色的象(bishop)和黑色的卒(pawn)。它们分别以字符 “R”,“.”,“B” 和 “p” 给出。大写字符表示白棋,小写字符表示黑棋。

车按国际象棋中的规则移动:它选择四个基本方向中的一个(北,东,西和南),然后朝那个方向移动,直到它选择停止、到达棋盘的边缘或移动到同一方格来捕获该方格上颜色相反的卒。另外,车不能与其他友方(白色)象进入同一个方格。

返回车能够在一次移动中捕获到的卒的数量。   示例 1:

image

输入:

[
  [".",".",".",".",".",".",".","."],
  [".",".",".","p",".",".",".","."],
  [".",".",".","R",".",".",".","p"],
  [".",".",".",".",".",".",".","."],
  [".",".",".",".",".",".",".","."],
  [".",".",".","p",".",".",".","."],
  [".",".",".",".",".",".",".","."],
  [".",".",".",".",".",".",".","."]
]

输出:3 解释: 在本例中,车能够捕获所有的卒。

示例 2:

image

输入:

[
  [".",".",".",".",".",".",".","."],
  [".","p","p","p","p","p",".","."],
  [".","p","p","B","p","p",".","."],
  [".","p","B","R","B","p",".","."],
  [".","p","p","B","p","p",".","."],
  [".","p","p","p","p","p",".","."],
  [".",".",".",".",".",".",".","."],
  [".",".",".",".",".",".",".","."]
]

输出:0 解释: 象阻止了车捕获任何卒。

示例 3:

image

输入:

[
  [".",".",".",".",".",".",".","."],
  [".",".",".","p",".",".",".","."],
  [".",".",".","p",".",".",".","."],
  ["p","p",".","R",".","p","B","."],
  [".",".",".",".",".",".",".","."],
  [".",".",".","B",".",".",".","."],
  [".",".",".","p",".",".",".","."],
  [".",".",".",".",".",".",".","."]
]

输出:3 解释: 车可以捕获位置 b5,d6 和 f5 的卒。  

提示:

board.length == board[i].length == 8
board[i][j] 可以是 'R','.','B' 或 'p'
只有一个格子上存在 board[i][j] == 'R'

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/available-captures-for-rook 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {character[][]} board
 * @return {number}
 */
var numRookCaptures = function(board) {
  const findRook = () => {
    for (let i = 0, len = board.length; i < len; i += 1) {
      const row = board[i];
      const colIdx = row.indexOf('R');
      if (colIdx > -1) {
        return [i, colIdx];
      }
    }
  };

  let sum = 0;
  let directs = [[-1, 0], [1, 0], [0, -1], [0, 1]];
  const rookPoint = findRook();
  for (let i = 0, len = directs.length; i < len; i += 1) {
    let x = rookPoint[0];
    let y = rookPoint[1];
    const direct = directs[i];
    while (0 < x && x < 7 && 0 < y && y < 7) {
      x += direct[0];
      y += direct[1];
      const item = board[x][y];
      if (['B', 'P', 'b'].includes(item)) {
        break;
      } else if (item === 'p') {
        sum += 1;
        break;
      }
    }
  }
  return sum;
};

执行用时 : 72 ms, 在所有 JavaScript 提交中击败了79.41%的用户 内存消耗 : 33.7 MB, 在所有 JavaScript 提交中击败了25.45%的用户

isaaxite commented 5 years ago

回到顶部

字符的最短距离

给定一个字符串 S 和一个字符 C。返回一个代表字符串 S 中每个字符到字符串 S 中的字符 C 的最短距离的数组。

示例 1:

输入: S = "loveleetcode", C = 'e'
输出: [3, 2, 1, 0, 1, 0, 0, 1, 2, 2, 1, 0]

说明:

字符串 S 的长度范围为 [1, 10000]。
C 是一个单字符,且保证是字符串 S 里的字符。
S 和 C 中的所有字母均为小写字母。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/shortest-distance-to-a-character 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

  /**
 * @param {string} S
 * @param {character} C
 * @return {number[]}
 */
var shortestToChar = function(S, C) {
    let pos = 0;
    const res = [];
    const len = S.length;
    const cPos = [];
    while(pos < len) {
      if (S[pos] === C) {
        cPos.push(pos);
      }
      pos += 1;
    }
    const minDis = (pos) => {
      const disList = cPos.map((item) => Math.abs(pos - item));
      return Math.min(...disList);
    }
    pos = 0;
    while(pos < len) {
      res.push(minDis(pos));
      pos += 1;
    }
    return res;
};

执行用时 : 112 ms, 在所有 JavaScript 提交中击败了33.33%的用户 内存消耗 : 37.4 MB, 在所有 JavaScript 提交中击败了10.53%的用户

第二版

  /**
 * @param {string} S
 * @param {character} C
 * @return {number[]}
 */
var shortestToChar = function(S, C) {
  let targetIdx = 0;
  const res = [];
  const len = S.length;
  const targetPosArr = [];
  for (let pos = 0; pos < len; pos += 1) {
    if (S[pos] === C) {
      targetPosArr.push(pos);
    }
  }
  for (let pos = 0; pos < len; pos += 1) {
    const prev = typeof targetPosArr[targetIdx - 1] !== 'undefined' ? targetPosArr[targetIdx - 1] : -Infinity;
    const next = typeof targetPosArr[targetIdx] !== 'undefined' ? targetPosArr[targetIdx] : Infinity;
    const distance = Math.min(pos - prev, next - pos);
    res.push(distance);
    if (next === pos) {
      targetIdx += 1;
    }
  }
  return res;
}

执行用时 : 92 ms, 在所有 JavaScript 提交中击败了89.52%的用户 内存消耗 : 35.6 MB, 在所有 JavaScript 提交中击败了73.68%的用户

isaaxite commented 5 years ago

回到顶部

各位相加

给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。

示例:

输入: 38
输出: 2 
解释: 各位相加的过程为:3 + 8 = 11, 1 + 1 = 2。 由于 2 是一位数,所以返回 2。

进阶: 你可以不使用循环或者递归,且在 O(1) 时间复杂度内解决这个问题吗?

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/add-digits 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {number} num
 * @return {number}
 */
var addDigits = function(num) {
    const numStr = num + '';
    if (numStr.length < 2) {
      return +num;
    }
    const numArr = numStr.split('');
    const sum = numArr.reduce((sum, val) => {
      sum += +val;
      return sum;
    }, 0);
    return addDigits(sum);
};

第二版

时间复杂度为O(1)的解法:

除个位外,每一位上的值都是通过(9+1)进位的过程得到的,想一下拨算盘进位 把整数n看成n样物品,原本是以10个1份打包的,现在从这些10个1份打包好的里面,拿出1个,让它们以9个为1份打包。 这样就出现了两部分的东西: 原本10个现在9个1份的,打包好的物品,这些,我们不用管 零散的物品,它们还可以分成: 从原来打包的里面拿出来的物品,它们的总和 =》 原来打包好的份数 =》 10进制进位的次数 =》 10进制下,除个位外其他位上的值的总和 以10个为1份打包时,打不进去的零散物品 =》 10进制个位上的值 如上零散物品的总数,就是第一次处理num后得到的累加值 如果这个累加值>9,那么如题就还需要将各个位上的值再相加,直到结果为个位数为止。也就意味着还需要来一遍如上的过程。 那么按照如上的思路,似乎可以通过n % 9得到最后的值 但是有1个关键的问题,如果num是9的倍数,那么就不适用上述逻辑。原本我是想得到n被打包成10个1份的份数+打不进10个1份的散落个数的和。通过与9取模,去获得那个不能整除的1,作为计算份数的方式,但是如果可以被9整除,我就无法得到那个1,也得不到个位上的数。 所以需要做一下特殊处理,(num - 1) % 9 + 1 可以这么做的原因:原本可以被完美分成9个为一份的n样物品,我故意去掉一个,那么就又可以回到上述逻辑中去得到我要的n被打包成10个一份的份数+打不进10个一份的散落个数的和。而这个减去的1就相当于从,在10个1份打包的时候散落的个数中借走的,本来就不影响原来10个1份打包的份数,先拿走再放回来,都只影响散落的个数,所以没有关系。

/**
 * @param {number} num
 * @return {number}
 */
var addDigits = function(num) {
  return (num - 1) % 9 + 1;
};

执行用时 : 88 ms, 在所有 JavaScript 提交中击败了97.16%的用户 内存消耗 : 35.5 MB, 在所有 JavaScript 提交中击败了50.78%的用户

isaaxite commented 5 years ago

回到顶部

反转链表

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

进阶: 你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/reverse-linked-list 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/**
 * Definition for singly-linked list.
 */
function ListNode(val) {
  this.val = val;
  this.next = null;
}

第一版

/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var reverseList = function(head) {
  if (!head || !head.next) {
    return head;
  }
  const newList = reverseList(head.next);
  head.next.next = head;
  head.next = null;
  return newList;
};

执行用时 : 84 ms, 在所有 JavaScript 提交中击败了73.65%的用户 内存消耗 : 35.2 MB, 在所有 JavaScript 提交中击败了25.79%的用户

第二版

/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var reverseList = function(head) {
  if (!head || !head.next) {
    return head;
  }
  let prev = head;
  let curr = prev.next;
  while (curr) {
    const temp = curr.next;
    curr.next = prev;
    prev = curr;
    curr = temp;
  }
  head.next = null;
  return prev;
}

执行用时 : 80 ms, 在所有 JavaScript 提交中击败了86.27%的用户 内存消耗 : 34.9 MB, 在所有 JavaScript 提交中击败了46.54%的用户

isaaxite commented 5 years ago

回到顶部

棒球比赛

你现在是棒球比赛记录员。 给定一个字符串列表,每个字符串可以是以下四种类型之一: 1.整数(一轮的得分):直接表示您在本轮中获得的积分数。

  1. "+"(一轮的得分):表示本轮获得的得分是前两轮有效 回合得分的总和。
  2. "D"(一轮的得分):表示本轮获得的得分是前一轮有效 回合得分的两倍。
  3. "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之间。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/baseball-game 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {string[]} ops
 * @return {number}
 */
var calPoints = function(ops) {
  const sum = [];
  for (let i = 0, len = ops.length; i < len; i += 1) {
    const score = ops[i];
    if (['C', 'D', '+'].includes(score)) {
      let len = 0;
      let curScore = 0;
      switch (score) {
        case '+':
          len = sum.length;
          curScore = (sum[len - 1] || 0) + (sum[len - 2] || 0);
          sum.push(curScore);
          break;
        case 'C':
          sum.pop();
          break;
        default:
          len = sum.length;
          curScore = (sum[len - 1] || 0) * 2;
          sum.push(curScore);
      }
    } else {
      sum.push(+score);
    }
  }
  return sum.reduce((_sum, _val) => {
    _sum += _val;
    return _sum;
  }, 0);
};

执行用时 : 84 ms, 在所有 JavaScript 提交中击败了64.74%的用户 内存消耗 : 35.4 MB, 在所有 JavaScript 提交中击败了23.42%的用户

第二版

/**
 * @param {string[]} ops
 * @return {number}
 */
var calPoints = function(ops) {
  let idx = 0;
  let sum = 0;
  while (idx < ops.length) {
    const score = ops[idx];
    switch (score) {
      case '+':
        ops[idx] = (ops[idx - 1] || 0) + (ops[idx - 2] || 0);
        sum += ops[idx];
        break;
      case 'C':
        sum -= ops[idx - 1] || 0;
        ops.splice(idx - 1, 2);
        idx -= 2;
        break;
      case 'D':
        ops[idx] = (ops[idx - 1] || 0) * 2;
        sum += ops[idx];
        break;
      default:
        ops[idx] = +ops[idx];
        sum += ops[idx];
    }
    idx += 1;
  }
  return sum;
}

执行用时 : 80 ms, 在所有 JavaScript 提交中击败了80.45%的用户 内存消耗 : 35.1 MB, 在所有 JavaScript 提交中击败了52.53%的用户

isaaxite commented 5 years ago

回到顶部

查找常用字符

给定仅有小写字母组成的字符串数组 A,返回列表中的每个字符串中都显示的全部字符(包括重复字符)组成的列表。例如,如果一个字符在每个字符串中出现 3 次,但不是 4 次,则需要在最终答案中包含该字符 3 次。

你可以按任意顺序返回答案。 

示例 1:

输入:["bella","label","roller"]
输出:["e","l","l"]

示例 2:

输入:["cool","lock","cook"]
输出:["c","o"]

提示:

1. 1 <= A.length <= 100
2. 1 <= A[i].length <= 100
3. A[i][j] 是小写字母

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/find-common-characters 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {string[]} A
 * @return {string[]}
 */
var commonChars = function(A) {
  const res = [];
  let firstSet = new Set();;
  for (let i = 0, len = A[0].length; i < len; i += 1) {
    firstSet.add(A[0][i]);
  }
  firstSet = Array.from(firstSet);
  firstSet.forEach((char) => {
    let charCount = A[0].length;
    for (let i = 0, len = A.length; i < len; i += 1) {
      let count = 0;
      const strItem = A[i];
      for (let j = 0, strItemLen = strItem.length; j < strItemLen; j += 1) {
        if (strItem[j] === char) {
          count += 1;
        }
      }
      charCount = Math.min(charCount, count);
    }
    charCount && res.push(...new Array(charCount).fill(char));
  });
  return res;
};

执行用时 : 112 ms, 在所有 JavaScript 提交中击败了56.07%的用户 内存消耗 : 35.4 MB, 在所有 JavaScript 提交中击败了100.00%的用户

第二版

/**
 * @param {string[]} A
 * @return {string[]}
 */
var commonChars = function(A) {
  const res = [];
  const firstSet = [];
  const len = A[0].length;
  for (let i = 0; i < len; i += 1) {
    if (!firstSet.includes(A[0][i])) {
      let charCount = len;
      const char = A[0][i];
      firstSet.push(char);

      for (let i = 0, len = A.length; i < len; i += 1) {
        let count = 0;
        const strItem = A[i];
        for (let j = 0, strItemLen = strItem.length; j < strItemLen; j += 1) {
          if (strItem[j] === char) {
            count += 1;
          }
        }
        if (!count) {
          charCount = 0;
          break;
        }
        charCount = Math.min(charCount, count);
      }
      charCount && res.push(...new Array(charCount).fill(char));
    }
  }
  return res;
};

执行用时 : 104 ms, 在所有 JavaScript 提交中击败了68.20%的用户 内存消耗 : 35.7 MB, 在所有 JavaScript 提交中击败了100.00%的用户

第三版

/**
 * @param {string[]} A
 * @return {string[]}
 */
var commonChars = function(A){
  let res = A[0].split(’‘);
  for(let i = 1; i < A.length; i++){
    const strArr = A[i].split('');
    res = res.filter((str) => {
      const pos = strArr.indexOf(str);
      // 将已经计算过的字符设为非A[0]的子字符
      return pos > -1 ? strArr[pos] = '!' : false;
    });
  }
  return res;
};

执行用时 : 80 ms, 在所有 JavaScript 提交中击败了98.33%的用户 内存消耗 : 36.9 MB, 在所有 JavaScript 提交中击败了81.82%的用户

isaaxite commented 5 years ago

回到顶部

子域名访问计数

一个网站域名,如"discuss.leetcode.com",包含了多个子域名。作为顶级域名,常用的有"com",下一级则有"leetcode.com",最低的一级为"discuss.leetcode.com"。当我们访问域名"discuss.leetcode.com"时,也同时访问了其父域名"leetcode.com"以及顶级域名 "com"。

给定一个带访问次数和域名的组合,要求分别计算每个域名被访问的次数。其格式为访问次数+空格+地址,例如:"9001 discuss.leetcode.com"。

接下来会给出一组访问次数和域名组合的列表cpdomains 。要求解析出所有域名的访问次数,输出格式和输入格式相同,不限定先后顺序。

示例 1:

输入: 
["9001 discuss.leetcode.com"]
输出: 
[
  "9001 discuss.leetcode.com",
  "9001 leetcode.com",
  "9001 com"
]
说明: 
例子中仅包含一个网站域名:"discuss.leetcode.com"。按照前文假设,子域名"leetcode.com"和"com"
都会被访问,所以它们都被访问了9001次。

示例 2

输入: 
["900 google.mail.com", "50 yahoo.com", "1 intel.mail.com", "5 wiki.org"]
输出: 
[
  "901 mail.com",
  "50 yahoo.com",
  "900 google.mail.com",
  "5 wiki.org",
  "5 org",
  "1 intel.mail.com",
  "951 com"
]
说明: 
按照假设,会访问
"google.mail.com" 900次,
"yahoo.com" 50次,
"intel.mail.com" 1次,
"wiki.org" 5次。
而对于父域名,会访问"mail.com" 900+1 = 901次,"com" 900 + 50 + 1 = 951次,和 "org" 5 次。

注意事项:

cpdomains 的长度小于 100。
每个域名的长度小于100。
每个域名地址包含一个或两个"."符号。
输入中任意一个域名的访问次数都小于10000。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/subdomain-visit-count 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {string[]} cpdomains
 * @return {string[]}
 */
var subdomainVisits = function(cpdomains) {
  const cache = cpdomains.reduce((obj, val) => {
    const [count, domains] = val.split(' ');
    const parts = domains.split('.');
    for (let i = 0, len = parts.length; i < len; i += 1) {
      const key = parts.slice(i).join('.');
      if (obj[key]) {
        obj[key] += +count;
      } else {
        obj[key] = +count;
      }
    }
    return obj;
  }, {});
  return Object.entries(cache).map(([key, count]) => `${count} ${key}`);
};

执行用时 : 152 ms, 在所有 JavaScript 提交中击败了18.52%的用户 内存消耗 : 38.8 MB, 在所有 JavaScript 提交中击败了42.10%的用户

isaaxite commented 5 years ago

回到顶部

杨辉三角

给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。

image

在杨辉三角中,每个数是它左上方和右上方的数的和。

示例:

输入: 5
输出:
[
     [1],
    [1,1],
   [1,2,1],
  [1,3,3,1],
 [1,4,6,4,1]
]

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/pascals-triangle 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {number} numRows
 * @return {number[][]}
 */
var generate = function(n) {
  if (n < 3) {
    return [[1], [1, 1]].slice(0, n);
  } else {
    const newItem = [1];
    const arr = generate(n - 1);
    const lastItem = arr[arr.length - 1];
    for (let i = 0, len = lastItem.length; i < len - 1; i += 1) {
      newItem.push(lastItem[i] + lastItem[i + 1]);
    }
    newItem.push(1);
    arr.push(newItem);
    return arr;
  }
};

执行用时 : 76 ms, 在所有 JavaScript 提交中击败了66.35%的用户 内存消耗 : 33.7 MB, 在所有 JavaScript 提交中击败了48.83%的用户

第二版

/**
 * @param {number} numRows
 * @return {number[][]}
 */
var generate = function(n) {
  const res = [[1], [1, 1]];
  if (n < 3) {
    return res.slice(0, n);
  } else {
    for (let i = 2; i < n; i += 1) {
      const newItem = [1];
      const lastItem = res[res.length - 1];
      for (let i = 0, len = lastItem.length; i < len - 1; i += 1) {
        newItem.push(lastItem[i] + lastItem[i + 1]);
      }
      newItem.push(1);
      res.push(newItem);
    }
  }
  return res;
};

执行用时 : 80 ms, 在所有 JavaScript 提交中击败了47.99%的用户 内存消耗 : 33.7 MB, 在所有 JavaScript 提交中击败了45.82%的用户

isaaxite commented 5 years ago

回到顶部

二进制表示中质数个计算置位

给定两个整数 L 和 R ,找到闭区间 [L, R] 范围内,计算置位位数为质数的整数个数。

(注意,计算置位代表二进制表示中1的个数。例如 21 的二进制表示 10101 有 3 个计算置位。还有,1 不是质数。)

示例 1:

输入: L = 6, R = 10
输出: 4
解释:
6 -> 110 (2 个计算置位,2 是质数)
7 -> 111 (3 个计算置位,3 是质数)
9 -> 1001 (2 个计算置位,2 是质数)
10-> 1010 (2 个计算置位,2 是质数)

示例 2:

输入: L = 10, R = 15
输出: 5
解释:
10 -> 1010 (2 个计算置位, 2 是质数)
11 -> 1011 (3 个计算置位, 3 是质数)
12 -> 1100 (2 个计算置位, 2 是质数)
13 -> 1101 (3 个计算置位, 3 是质数)
14 -> 1110 (3 个计算置位, 3 是质数)
15 -> 1111 (4 个计算置位, 4 不是质数)

注意:

L, R 是 L <= R 且在 [1, 10^6] 中的整数。
R - L 的最大值为 10000。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/prime-number-of-set-bits-in-binary-representation 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {number} L
 * @param {number} R
 * @return {number}
 */
var countPrimeSetBits = function(L, R) {
  let count = 0;
  const isPrime = (num) => {
    if (num <= 3) {
      return num > 1;
    }
    if (num % 6 != 1 && num % 6 != 5) {
      return false;
    }
    const sqrt = Math.sqrt(num);
    for (let i = 2; i <= sqrt; i += 1) {
      if (!(num % i)) {
        return false;
      }
    }
    return true;
  };
  for (let i = L; i <= R; i += 1) {
    const num = i.toString(2).split('').reduce((sum, val) => {
      sum += +val;
      return sum;
    }, 0);
    if (isPrime(num)) {
      count += 1;
    }
  }
  return count;
};

执行用时 : 492 ms, 在所有 JavaScript 提交中击败了52.94%的用户 内存消耗 : 36.7 MB, 在所有 JavaScript 提交中击败了47.83%的用户

第二版

/**
 * @param {number} L
 * @param {number} R
 * @return {number}
 */
var countPrimeSetBits = function(L, R) {
  let count = 0;
  const primes = [0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1];
  for (let i = L; i <= R; i += 1) {
    const num = i.toString(2).split('').reduce((sum, val) => {
      sum += +val;
      return sum;
    }, 0);
    count += primes[num];
  }
  return count;
};

执行用时 : 488 ms, 在所有 JavaScript 提交中击败了52.94%的用户 内存消耗 : 36.8 MB, 在所有 JavaScript 提交中击败了39.13%的用户

isaaxite commented 5 years ago

回到顶部

岛屿的周长

给定一个包含 0 和 1 的二维网格地图,其中 1 表示陆地 0 表示水域。

网格中的格子水平和垂直方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。

岛屿中没有“湖”(“湖” 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。

 

示例 :

输入:
[[0,1,0,0],
 [1,1,1,0],
 [0,1,0,0],
 [1,1,0,0]]

输出: 16

解释: 它的周长是下面图片中的 16 个黄色的边:

image

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/island-perimeter 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {number[][]} grid
 * @return {number}
 */
var islandPerimeter = function(grid) {
  let count = 0;
  for (let r = 0, rLen = grid.length; r < rLen; r += 1) {
    for (let c = 0, cLen = grid[r].length; c < cLen; c += 1) {
      if (grid[r][c]) {
        // top
        count -= grid[r - 1] ? grid[r - 1][c] || 0 : 0;
        // right
        count -= grid[r][c + 1] || 0;
        // bottom
        count -= grid[r + 1] ? grid[r + 1][c] || 0 : 0;
        // left
        count -= grid[r][c - 1] || 0;
        count += 4;
      }
    }
  }
  return count;
};

执行用时 : 316 ms, 在所有 JavaScript 提交中击败了50.49%的用户 内存消耗 : 44.8 MB, 在所有 JavaScript 提交中击败了33.33%的用户

isaaxite commented 5 years ago

回到顶部

修剪二叉搜索树

给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>=L) 。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。

示例 1:

输入: 
    1
   / \
  0   2

  L = 1
  R = 2

输出: 
    1
      \
       2

示例 2:

输入: 
    3
   / \
  0   4
   \
    2
   /
  1

  L = 1
  R = 3

输出: 
      3
     / 
   2   
  /
 1

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/trim-a-binary-search-tree 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/**
 * 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) {
  const trim = (root) => {
    if (root.val < L) {
      if (root.right) {
        root = trim(root.right);
      } else {
        root = null;
      }
    } else if (R < root.val) {
      if (root.left) {
        root = trim(root.left);
      } else {
        root = null;
      }
    } else {
      if (root.left) {
        root.left = trim(root.left);
      }
      if (root.right) {
        root.right = trim(root.right);
      }
    }
    return root;
  };
  return trim(root);
};

执行用时 : 100 ms, 在所有 JavaScript 提交中击败了63.24%的用户 内存消耗 : 39.1 MB, 在所有 JavaScript 提交中击败了76.47%的用户

第二版

/**
 * @param {TreeNode} root
 * @param {number} L
 * @param {number} R
 * @return {TreeNode}
 */
var trimBST = function(root, L, R) {
  if (root == null) {
    return root;
  }
  if (root.val > R) {
    return trimBST(root.left, L, R);
  }
  if (root.val < L) {
    return trimBST(root.right, L, R);
  }
  root.left = trimBST(root.left, L, R);
  root.right = trimBST(root.right, L, R);
  return root;
}

执行用时 : 80 ms, 在所有 JavaScript 提交中击败了98.53%的用户 内存消耗 : 39.4 MB, 在所有 JavaScript 提交中击败了11.76%的用户

isaaxite commented 5 years ago

回到顶部

最长特殊序列 Ⅰ

给定两个字符串,你需要从这两个字符串中找出最长的特殊序列。最长特殊序列定义如下:该序列为某字符串独有的最长子序列(即不能是其他字符串的子序列)。

子序列可以通过删去字符串中的某些字符实现,但不能改变剩余字符的相对顺序。空序列为所有字符串的子序列,任何字符串为其自身的子序列。

输入为两个字符串,输出最长特殊序列的长度。如果不存在,则返回 -1。

示例 :

输入: "aba", "cdc"
输出: 3
解析: 最长特殊序列可为 "aba" (或 "cdc")

说明:

两个字符串长度均小于100。
字符串中的字符仅含有 'a'~'z'。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/longest-uncommon-subsequence-i 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {string} a
 * @param {string} b
 * @return {number}
 */
var findLUSlength = function(a, b) {
  return a === b
    ? -1 : a.length === b.length
      ? a.length : a.length > b.length
        ? a.length : b.length;
};

执行用时 : 72 ms, 在所有 JavaScript 提交中击败了81.25%的用户 内存消耗 : 33.7 MB, 在所有 JavaScript 提交中击败了21.05%的用户

isaaxite commented 5 years ago

回到顶部

只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,1]
输出: 1

示例 2:

输入: [4,1,2,1,2]
输出: 4

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/single-number 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function(nums) {
  nums.sort((p, n) => p - n);
  for (let i = 0, len = nums.length; i < len; i += 1) {
    if (nums[i - 1] !== nums[i] && nums[i] !== nums[i + 1]) {
      return nums[i];
    }
  }
};

执行用时 : 132 ms, 在所有 JavaScript 提交中击败了34.59%的用户 内存消耗 : 36.7 MB, 在所有 JavaScript 提交中击败了33.13%的用户

第二版

/**
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function(nums) {
  const hash = {};
  nums.forEach((val) => {
    if (!hash[val]) {
      hash[val] = 1;
    } else {
      hash[val] += 1;
    }
  });
  for (let key in hash) {
    if (hash[key] === 1) {
      return key;
    }
  }
};

执行用时 : 84 ms, 在所有 JavaScript 提交中击败了77.72%的用户 内存消耗 : 38.1 MB, 在所有 JavaScript 提交中击败了7.85%的用户

第三版

/**
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function(nums) {
  const sum = (arr) => arr.reduce((_sum, _val) => {
    _sum += _val;
    return _sum;
  }, 0);
  return 2 * sum(Array.from(new Set(nums))) - sum(nums);
};

执行用时 : 84 ms, 在所有 JavaScript 提交中击败了77.72%的用户 内存消耗 : 37.6 MB, 在所有 JavaScript 提交中击败了18.53%的用户

第四版

概念

如果我们对 0 和二进制位做 XOR 运算,得到的仍然是这个二进制位 a⊕0=a 如果我们对相同的二进制位做 XOR 运算,返回的结果是 0 a⊕a=0 XOR 满足交换律和结合律 a⊕b⊕a=(a⊕a)⊕b=0⊕b=b

/**
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function(nums) {
  let res = nums[0];
  for (let i = 1, len = nums.length; i < len; i += 1) {
    res = res ^ nums[i];
  }
  return res;
};

执行用时 : 92 ms, 在所有 JavaScript 提交中击败了59.39%的用户 内存消耗 : 35.4 MB, 在所有 JavaScript 提交中击败了63.85%的用户

isaaxite commented 5 years ago

回到顶部

二叉树的层次遍历 II

给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

例如: 给定二叉树 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回其自底向上的层次遍历为:

[
  [15,7],
  [9,20],
  [3]
]

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/**
 * Definition for a binary tree node.
 */
function TreeNode(val) {
  this.val = val;
  this.left = this.right = null;
}

第一版

/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var levelOrderBottom = function(root) {
  const res = [];
  (function order(_root, idx) {
    if (!_root) {
      return _root;
    }
    if (!res[idx]) {
      res[idx] = [];
    }
    res[idx].push(_root.val);
    idx += 1;
    order(_root.left, idx);
    order(_root.right, idx);
  })(root, 0);
  return res.reverse();
};

执行用时 : 88 ms, 在所有 JavaScript 提交中击败了40.74%的用户 内存消耗 : 34.6 MB, 在所有 JavaScript 提交中击败了52.80%的用户

isaaxite commented 5 years ago

回到顶部

二叉树的层平均值

给定一个非空二叉树, 返回一个由每层节点平均值组成的数组.

示例 1: 输入:

    3
   / \
  9  20
    /  \
   15   7

输出: [3, 14.5, 11]

解释:

第0层的平均值是 3,  第1层是 14.5, 第2层是 11. 因此返回 [3, 14.5, 11].

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/average-of-levels-in-binary-tree 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/**
 * Definition for a binary tree node.
 */
function TreeNode(val) {
  this.val = val;
  this.left = this.right = null;
}

第一版

/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var averageOfLevels = function(root) {
  let level = [];
  (function average(_root, _idx) {
    if (!_root) {
      return ;
    }
    level[_idx] ? level[_idx].push(_root.val) : level[_idx] = [_root.val];
    _idx += 1;
    average(_root.left, _idx);
    average(_root.right, _idx);
  })(root, 0);
  return level.map((item) => {
    return item.reduce((sum, val) => {
      sum += val;
      return sum;
    }, 0) / item.length;
  });
};

执行用时 : 112 ms, 在所有 JavaScript 提交中击败了42.02%的用户 内存消耗 : 38.5 MB, 在所有 JavaScript 提交中击败了23.53%的用户

isaaxite commented 5 years ago

回到顶部

N叉树的层序遍历

给定一个 N 叉树,返回其节点值的层序遍历。 (即从左到右,逐层遍历)。

例如,给定一个 3叉树 :

image

返回其层序遍历:

[
     [1],
     [3,2,4],
     [5,6]
]
 ```

说明:

树的深度不会超过 1000。 树的节点总数不会超过 5000。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

```js
/**
 *  Definition for a Node.
 */
function Node(val,children) {
  this.val = val;
  this.children = children;
};

第一版

/**
 * @param {Node} root
 * @return {number[][]}
 */
var levelOrder = function(root) {
  const res = [];
  (function order(_root, _idx) {
    if (!_root) {
      return ;
    }
    res[_idx] ? res[_idx].push(_root.val) : res[_idx] = [_root.val];
    _idx += 1;
    _root.children.forEach((child) => order(child, _idx));
  })(root, 0);
  return res;
};

执行用时 : 932 ms, 在所有 JavaScript 提交中击败了74.58%的用户 内存消耗 : 81.3 MB, 在所有 JavaScript 提交中击败了42.10%的用户

第二版

var levelOrder = function(root) {
  if (!root) return [];
  const res = [];
  const queue = [root];
  while (queue.length) {
    let size = queue.length;
    const level = [];
    while (size--) {
      const node = queue.shift();
      level.push(node.val);
      for (const child of node.children) {
        queue.push(child);
      }
    }
    res.push(level);
  }
  return res;
};

执行用时 : 944 ms, 在所有 JavaScript 提交中击败了67.23%的用户 内存消耗 : 81.3 MB, 在所有 JavaScript 提交中击败了43.42%的用户

isaaxite commented 5 years ago

回到顶部

分糖果

给定一个偶数长度的数组,其中不同的数字代表着不同种类的糖果,每一个数字代表一个糖果。你需要把这些糖果平均分给一个弟弟和一个妹妹。返回妹妹可以获得的最大糖果的种类数。

示例 1:

输入: candies = [1,1,2,2,3,3]
输出: 3
解析: 一共有三种种类的糖果,每一种都有两个。
     最优分配方案:妹妹获得[1,2,3],弟弟也获得[1,2,3]。这样使妹妹获得糖果的种类数最多。

示例 2 :

输入: candies = [1,1,2,3]
输出: 2
解析: 妹妹获得糖果[2,3],弟弟获得糖果[1,1],妹妹有两种不同的糖果,弟弟只有一种。这样使得妹妹可以获得的糖果种类数最多。

注意:

数组的长度为[2, 10,000],并且确定为偶数。
数组中数字的大小在范围[-100,000, 100,000]内。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/distribute-candies 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {number[]} candies
 * @return {number}
 */
var distributeCandies = function(candies) {
  const half = candies.length / 2;
  const noRepeat = [];
  for (const val of candies) {
    noRepeat.includes(val) || noRepeat.push(val);
    if (noRepeat.length >= half) {
      return half;
    }
  }
  return noRepeat.length;
};

执行用时 : 1360 ms, 在所有 JavaScript 提交中击败了11.11%的用户 内存消耗 : 43.3 MB, 在所有 JavaScript 提交中击败了90.28%的用户

第二版

/**
 * @param {number[]} candies
 * @return {number}
 */
var distributeCandies = function(candies) {
  const set = new Set(candies);
  const size = set.size;
  const half = candies.length / 2;
  return size >= half ? half : size; 
};

执行用时 : 172 ms, 在所有 JavaScript 提交中击败了89.35%的用户 内存消耗 : 43.6 MB, 在所有 JavaScript 提交中击败了70.83%的用户

isaaxite commented 5 years ago

回到顶部

数组的相对排序

给你两个数组,arr1 和 arr2

arr1 中的元素进行排序,使 arr1 中项的相对顺序和 arr2 中的相对顺序相同。未在 arr2 中出现过的元素需要按照升序放在 arr1 的末尾。

示例:

输入:arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6]
输出:[2,2,2,1,4,3,3,9,6,7,19]

提示:

arr1.length, arr2.length <= 1000
0 <= arr1[i], arr2[i] <= 1000
arr2 中的元素 arr2[i] 各不相同
arr2 中的每个元素 arr2[i] 都出现在 arr1 中

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/relative-sort-array 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {number[]} arr1
 * @param {number[]} arr2
 * @return {number[]}
 */
var relativeSortArray = function(arr1, arr2) {
  const res = [];
  const others = [];
  const cache = [];
  arr1.forEach((val) => {
    arr2.includes(val)
      ? cache[val] 
        ? cache[val].push(val)
        : cache[val] = [val]
      : others.push(val);
  });
  others.sort((p, n) => p - n);
  arr2.forEach((key) => res.push(...cache[key]));
  res.push(...others);
  return res;
};

执行用时 : 88 ms, 在所有 JavaScript 提交中击败了48.25%的用户 内存消耗 : 33.7 MB, 在所有 JavaScript 提交中击败了100.00%的用户

isaaxite commented 5 years ago

回到顶部

写字符串需要的行数

我们要把给定的字符串 S 从左到右写到每一行上,每一行的最大宽度为100个单位,如果我们在写某个字母的时候会使这行超过了100 个单位,那么我们应该把这个字母写到下一行。我们给定了一个数组 widths ,这个数组 widths[0] 代表 'a' 需要的单位, widths[1] 代表 'b' 需要的单位,..., widths[25] 代表 'z' 需要的单位。

现在回答两个问题:至少多少行能放下S,以及最后一行使用的宽度是多少个单位?将你的答案作为长度为2的整数列表返回。

示例 1:

输入: 
widths = [10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10]
S = "abcdefghijklmnopqrstuvwxyz"
输出: [3, 60]

解释:

所有的字符拥有相同的占用单位10。所以书写所有的26个字母,
我们需要2个整行和占用60个单位的一行。

示例 2:

输入: 
widths = [4,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10]
S = "bbbcccdddaaa"
输出: [2, 4]
解释: 
除去字母'a'所有的字符都是相同的单位10,并且字符串 "bbbcccdddaa" 将会覆盖 9 * 10 + 2 * 4 = 98 个单位.
最后一个字母 'a' 将会被写到第二行,因为第一行只剩下2个单位了。
所以,这个答案是2行,第二行有4个单位宽度。

注:

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/number-of-lines-to-write-string 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {number[]} widths
 * @param {string} S
 * @return {number[]}
 */
var numberOfLines = function(widths, S) {
  let idx = 0;
  let rowSize = 0;
  let deep = 1;
  const cache = {};
  const len = S.length;
  const baseCode = String('a').charCodeAt();
  const getWidIdx = (char) => char.charCodeAt() - baseCode;
  while (idx < len) {
    const char = S[idx];
    const size = widths[getWidIdx(char)];
    rowSize += size;
    if (rowSize === 100) {
      deep += 1;
      rowSize = 0;
    } else if (rowSize > 100) {
      deep += 1;
      rowSize = size;
    }
    idx += 1;
  }
  return [deep, rowSize];
};

执行用时 : 64 ms, 在所有 JavaScript 提交中击败了100.00%的用户 内存消耗 : 34.4 MB, 在所有 JavaScript 提交中击败了92.31%的用户

isaaxite commented 5 years ago

回到顶部

链表的中间结点

给定一个带有头结点 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

示例 1:

输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.

示例 2:

输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。

提示:

给定链表的结点数介于 1 和 100 之间。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/middle-of-the-linked-list 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/**
 * Definition for singly-linked list.
 */
function ListNode(val) {
  this.val = val;
  this.next = null;
}

第一版

/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var middleNode = function(head) {
  let len = 0;
  let node = head;
  while(node) {
    node = node.next;
    len += 1;
  }
  let idx = 0;
  const midIdx = Math.floor(len / 2);
  node = head;
  while (idx < midIdx) {
    node = node.next;
    idx += 1;
  }
  return node;
};

执行用时 : 80 ms, 在所有 JavaScript 提交中击败了44.09%的用户 内存消耗 : 33.6 MB, 在所有 JavaScript 提交中击败了60.32%的用户

第二版

/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var middleNode = function(head) {
  let slow = head;
  let fast = head;
  while (fast && fast.next) {
    slow = slow.next;
    fast = fast.next.next;
  }
  return slow;
};

执行用时 : 72 ms, 在所有 JavaScript 提交中击败了81.50%的用户 内存消耗 : 33.7 MB, 在所有 JavaScript 提交中击败了30.16%的用户

isaaxite commented 5 years ago

回到顶部

特殊等价字符串组

你将得到一个字符串数组 A。

如果经过任意次数的移动,S == T,那么两个字符串 S 和 T 是特殊等价的。

一次移动包括选择两个索引 i 和 j,且 i % 2 == j % 2,交换 S[j] 和 S [i]。

现在规定,A 中的特殊等价字符串组是 A 的非空子集 S,这样不在 S 中的任何字符串与 S 中的任何字符串都不是特殊等价的。

返回 A 中特殊等价字符串组的数量。

示例 1:

输入:["a","b","c","a","c","c"]
输出:3
解释:3 组 ["a","a"],["b"],["c","c","c"]

示例 2:

输入:["aa","bb","ab","ba"]
输出:4
解释:4 组 ["aa"],["bb"],["ab"],["ba"]

示例 3:

输入:["abc","acb","bac","bca","cab","cba"]
输出:3
解释:3 组 ["abc","cba"],["acb","bca"],["bac","cab"]

示例 4:

输入:["abcd","cdab","adcb","cbad"]
输出:1
解释:1 组 ["abcd","cdab","adcb","cbad"]

提示:

1 <= A.length <= 1000
1 <= A[i].length <= 20
所有 A[i] 都具有相同的长度。
所有 A[i] 都只由小写字母组成。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/groups-of-special-equivalent-strings 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {string[]} A
 * @return {number}
 */
var numSpecialEquivGroups = function(A) {
  const baseCode = 'a'.charCodeAt();
  const seen = new Set();
  for (const S of A) {
    let count = {};
    for (let i = 0; i < S.length; i += 1) {
      const key = S.charCodeAt(i) - baseCode + 26 * (i % 2);
      count[key] ? count[key] += 1 : count[key] = 1;
    }
    seen.add(JSON.stringify(count));
  }
  return seen.size;
}

执行用时 : 108 ms, 在所有 JavaScript 提交中击败了86.96%的用户 内存消耗 : 37.5 MB, 在所有 JavaScript 提交中击败了40.00%的用户

第二版

/**
 * @param {string[]} A
 * @return {number}
 */
var numSpecialEquivGroups = function(A) {
  const set = new Set();
  for (let i = 0, len = A.length; i < len; i += 1) {
    const str = A[i];
    const odd = [];
    const even = [];
    for (let j = 0, strLen = str.length; j < strLen; j += 2) {
      even.push(str[j]);
      str[j + 1] && odd.push(str[j + 1]);
    }
    odd.sort((p, n) => p.charCodeAt() - n.charCodeAt());
    even.sort((p, n) => p.charCodeAt() - n.charCodeAt());
    set.add(even.join('') + odd.join(''));
  }
  return set.size;
}

执行用时 : 124 ms, 在所有 JavaScript 提交中击败了34.78%的用户 内存消耗 : 37 MB, 在所有 JavaScript 提交中击败了80.00%的用户

isaaxite commented 5 years ago

回到顶部

重塑矩阵

在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据。

给出一个由二维数组表示的矩阵,以及两个正整数r和c,分别表示想要的重构的矩阵的行数和列数。

重构后的矩阵需要将原始矩阵的所有元素以相同的行遍历顺序填充。

如果具有给定参数的reshape操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

示例 1:

输入: 
nums = 
[[1,2],
 [3,4]]
r = 1, c = 4
输出: 
[[1,2,3,4]]
解释:
行遍历nums的结果是 [1,2,3,4]。新的矩阵是 1 * 4 矩阵, 用之前的元素值一行一行填充新矩阵。

示例 2:

输入: 
nums = 
[[1,2],
 [3,4]]
r = 2, c = 4
输出: 
[[1,2],
 [3,4]]
解释:
没有办法将 2 * 2 矩阵转化为 2 * 4 矩阵。 所以输出原矩阵。

注意:

给定矩阵的宽和高范围在 [1, 100]。
给定的 r 和 c 都是正数。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/reshape-the-matrix 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {number[][]} nums
 * @param {number} r
 * @param {number} c
 * @return {number[][]}
 */
var matrixReshape = function(nums, r, c) {
  if (nums.length * nums[0].length < r * c) {
    return nums;
  }
  const res = [];
  const cache = nums.reduce((arr, val) => {
    arr.push(...val);
    return arr;
  }, []);
  for (let i = 0; i < r; i += 1) {
    const start = i * c;
    res.push(cache.slice(start, start + c));
  }
  return res;
};

执行用时 : 112 ms, 在所有 JavaScript 提交中击败了96.15%的用户 内存消耗 : 39.6 MB, 在所有 JavaScript 提交中击败了93.75%的用户

第二版

/**
 * @param {number[][]} nums
 * @param {number} r
 * @param {number} c
 * @return {number[][]}
 */
var matrixReshape = function(nums, r, c) {
  if (nums.length * nums[0].length < r * c) {
    return nums;
  }
  let rIdx = 0;
  const res = [[]];
  const rLen = nums.length;
  const cLen = nums[0].length;
  for (let i = 0; i < rLen; i += 1) {
    for (let j = 0; j < cLen; j += 1) {
      if (res[rIdx].length >= c) {
        rIdx += 1;
        res[rIdx] = [];
      }
      res[rIdx].push(nums[i][j]);
    }
  }
  return res;
}

执行用时 : 104 ms, 在所有 JavaScript 提交中击败了100.00%的用户 内存消耗 : 40.4 MB, 在所有 JavaScript 提交中击败了68.75%的用户

第三版

/**
 * @param {number[][]} nums
 * @param {number} r
 * @param {number} c
 * @return {number[][]}
 */
var matrixReshape = function(nums, r, c) {
  const rLen = nums.length;
  const cLen = nums[0].length;
  if (rLen * cLen < r * c) {
    return nums;
  }
  let count = 0;
  const res = [];
  for (let i = 0; i < rLen; i += 1) {
    for (let j = 0; j < cLen; j += 1) {
      const rIdx = Math.floor(count / c);
      const cIdx = count % c;
      res[rIdx] ? res[rIdx][cIdx] = nums[i][j] : res[rIdx] = [nums[i][j]];
      count += 1;
    }
  }
  return res;
}

执行用时 : 128 ms, 在所有 JavaScript 提交中击败了61.54%的用户 内存消耗 : 40.2 MB, 在所有 JavaScript 提交中击败了68.75%的用户

isaaxite commented 5 years ago

回到顶部

三维形体投影面积

在 N  N 的网格中,我们放置了一些与 x,y,z 三轴对齐的 1 1 * 1 立方体。

每个值 v = grid[i][j] 表示 v 个正方体叠放在单元格 (i, j) 上。

现在,我们查看这些立方体在 xy、yz 和 zx 平面上的投影。

投影就像影子,将三维形体映射到一个二维平面上。

在这里,从顶部、前面和侧面看立方体时,我们会看到“影子”。

返回所有三个投影的总面积。

示例 1:

输入:[[2]]
输出:5

示例 2:

输入:[[1,2],[3,4]]
输出:17
解释:
这里有该形体在三个轴对齐平面上的三个投影(“阴影部分”)。

image

示例 3:

输入:[[1,0],[0,2]]
输出:8

示例 4:

输入:[[1,1,1],[1,0,1],[1,1,1]]
输出:14

示例 5:

输入:[[2,2,2],[2,1,2],[2,2,2]]
输出:21

提示:

1 <= grid.length = grid[0].length <= 50
0 <= grid[i][j] <= 50

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/projection-area-of-3d-shapes 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一版

/**
 * @param {number[][]} grid
 * @return {number}
 */
var projectionArea = function(grid) {
  let xArea = 0;
  let zArea = 0;
  const yArr = [];
  grid.forEach((item) => {
    xArea += Math.max(...item);
    item.forEach((val, index) => {
      zArea += +(!!val);
      if (val > (yArr[index] || 0)) {
        yArr[index] = val;
      }
    });
  });
  const yArea = yArr.reduce((sum, val) => {
    sum += val;
    return sum;
  }, 0);
  return xArea + yArea + zArea;
};

执行用时 : 84 ms, 在所有 JavaScript 提交中击败了63.89%的用户 内存消耗 : 34.8 MB, 在所有 JavaScript 提交中击败了55.56%的用户

isaaxite commented 4 years ago

回到顶部

托普利茨矩阵

如果一个矩阵的每一方向由左上到右下的对角线上具有相同元素,那么这个矩阵是托普利茨矩阵。

给定一个 M x N 的矩阵,当且仅当它是托普利茨矩阵时返回 True。

示例 1:

输入: 
matrix = [
  [1,2,3,4],
  [5,1,2,3],
  [9,5,1,2]
]
输出: True
解释:
在上述矩阵中, 其对角线为:
"[9]", "[5, 5]", "[1, 1, 1]", "[2, 2, 2]", "[3, 3]", "[4]"。
各条对角线上的所有元素均相同, 因此答案是True。

示例 2:

输入:
matrix = [
  [1,2],
  [2,2]
]
输出: False
解释: 
对角线"[1, 2]"上的元素不同。

说明:

matrix 是一个包含整数的二维数组。
matrix 的行数和列数均在 [1, 20]范围内。
matrix[i][j] 包含的整数在 [0, 99]范围内。

进阶:

如果矩阵存储在磁盘上,并且磁盘内存是有限的,因此一次最多只能将一行矩阵加载到内存中,该怎么办? 如果矩阵太大以至于只能一次将部分行加载到内存中,该怎么办?

第一版

/**
 * @param {number[][]} matrix
 * @return {boolean}
 */
const isToeplitzMatrix = (matrix) => {
  const rowLen = matrix.length;
  const colLen = matrix[0].length;
  for (let i = 0; i < rowLen - 1; i += 1) {
    for (let j = 0; j < colLen - 1; j += 1) {
      if (matrix[i][j] !== matrix[i + 1][j + 1]) {
        return false;
      }
    }
  }
  return true;
};

执行用时 : 76 ms, 在所有 javascript 提交中击败了89.61%的用户 内存消耗 : 35.5 MB, 在所有 javascript 提交中击败了34.61%的用户

isaaxite commented 4 years ago

回到顶部

整数反转

给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

示例 1:

输入: 123
输出: 321

示例 2:

输入: -123
输出: -321

示例 3:

输入: 120
输出: 21

注意: 假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。

第一版

/*
 * @lc app=leetcode.cn id=7 lang=javascript
 *
 * [7] 整数反转
 */

// @lc code=start
/**
 * @param {number} x
 * @return {number}
 */
var reverse = function(x) {
  let res;
  const str = x + '';
  const range = [-Math.pow(2, 31), Math.pow(2, 31) - 1];
  const isValid = (val) => range[0] <= val && val <= range[1];
  if (['-'].includes(str[0])) {
    const rest = str.split('').slice(1).reverse().join('');
    res = str[0] + (+rest);
  } else {
    res = +(str.split('').reverse().join(''));
  }
  return isValid(res) ? res : 0;
};
  • 1032/1032 cases passed (88 ms)
  • Your runtime beats 89.22 % of javascript submissions
  • Your memory usage beats 14.01 % of javascript submissions (36.1 MB)
isaaxite commented 4 years ago

回到顶部

回文数

判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

示例 1:

输入: 121
输出: true

示例 2:

输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

示例 3:

输入: 10
输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。

进阶: 你能不将整数转为字符串来解决这个问题吗?

第一版

/*
 * @lc app=leetcode.cn id=9 lang=javascript
 *
 * [9] 回文数
 */

// @lc code=start
/**
 * @param {number} x
 * @return {boolean}
 */
var isPalindrome = function(x) {
  const str = x + '';
  const revStr = str.split('').reverse().join('');
  return str === revStr;
};
  • 11509/11509 cases passed (236 ms)
  • Your runtime beats 86.95 % of javascript submissions
  • Your memory usage beats 58.34 % of javascript submissions (45.7 MB)
isaaxite commented 4 years ago

回到顶部

罗马数字转整数

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符          数值
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

示例 1:

输入: "III"
输出: 3

示例 2:

输入: "IV"
输出: 4

示例 3:

输入: "IX"
输出: 9

示例 4:

输入: "LVIII"
输出: 58
解释: L = 50, V= 5, III = 3.

示例 5:

输入: "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.

第一版

/*
 * @lc app=leetcode.cn id=13 lang=javascript
 *
 * [13] 罗马数字转整数
 */

// @lc code=start
/**
 * @param {string} s
 * @return {number}
 */
var romanToInt = function(s) {
  const num = {
    'I': 1,
    'V': 5,
    'X': 10,
    'L': 50,
    'C': 100,
    'D': 500,
    'M': 1000
  };
  const chars = s.split('');
  const speNums = ['IV', 'IX', 'XL', 'XC', 'CD', 'CM'];
  const res = chars.reduce((sum, char, idx) => {
    const nextChar = chars[idx + 1];
    sum = speNums.includes(char + nextChar)
      ? sum - num[char]
      : sum + num[char];
    return sum;
  }, 0);
  return res;
};
  • 3999/3999 cases passed (224 ms)
  • Your runtime beats 66.22 % of javascript submissions
  • Your memory usage beats 30.86 % of javascript submissions (40.6 MB)
isaaxite commented 4 years ago

回到顶部

最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""。

示例 1:

输入: ["flower","flow","flight"]
输出: "fl"

示例 2:

输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。

说明:

所有输入只包含小写字母 a-z 。

第一版

/*
 * @lc app=leetcode.cn id=14 lang=javascript
 *
 * [14] 最长公共前缀
 */

// @lc code=start
/**
 * @param {string[]} strs
 * @return {string}
 */
var longestCommonPrefix = function(strs) {
  const prefix = [];
  if (!strs || !strs.length) {
    return '';
  }
  for (let i = 0; i < strs[0].length; i += 1) {
    let temp = strs[0][i];
    for (let j = 1; j < strs.length; j += 1) {
      if (temp !== strs[j][i]) {
        return prefix.join('');
      }
    }
    prefix.push(strs[0][i]);
  }
  return prefix.join('');
};
  • 118/118 cases passed (76 ms)
  • Your runtime beats 74.29 % of javascript submissions
  • Your memory usage beats 47.4 % of javascript submissions (34.9 MB)
isaaxite commented 4 years ago

回到顶部

有效的括号

给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。 注意空字符串可被认为是有效字符串。

示例 1:

输入: "()"
输出: true

示例 2:

输入: "()[]{}"
输出: true

示例 3:

输入: "(]"
输出: false

示例 4:

输入: "([)]"
输出: false

示例 5:

输入: "{[]}"
输出: true

第一版

/*
 * @lc app=leetcode.cn id=20 lang=javascript
 *
 * [20] 有效的括号
 */

// @lc code=start
/**
 * @param {string} s
 * @return {boolean}
 */
var isValid = function(s) {
  const chars = ['({[', ')}]'];
  const strs = s.split('');
  const stack = [];
  for (let i = 0; i < strs.length; i += 1) {
    const str = strs[i];
    if (chars[1].includes(str)) {
      const pos = chars[0].indexOf(stack.pop());
      const excepted = chars[1][pos];
      if (str !== excepted) {
        return false;
      }
    } else if (chars[0].includes(str)) {
      stack.push(str);
    }
  }
  return !stack.length;
};
  • 76/76 cases passed (68 ms)
  • Your runtime beats 86.48 % of javascript submissions
  • Your memory usage beats 40.65 % of javascript submissions (34.8 MB)
isaaxite commented 4 years ago

回到顶部

合并两个有序链表

将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
// @lc code=start
/**
 * Definition for singly-linked list.
 */
function ListNode(val) {
  this.val = val;
  this.next = null;
}

第一版

/*
 * @lc app=leetcode.cn id=21 lang=javascript
 *
 * [21] 合并两个有序链表
 */
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
var mergeTwoLists = function(l1, l2) {
  let last;
  let newList;
  if (!l1 || !l2) {
    return l1 ? l1 : l2;
  }
  if (l1.val < l2.val) {
    newList = l1;
    l1 = l1.next;
  } else {
    newList = l2;
    l2 = l2.next;
  }
  last = newList;
  while (l1 && l2) {
    if (l1.val < l2.val) {
      last.next = l1;
      l1 = l1.next;
    } else {
      last.next = l2;
      l2 = l2.next;
    }
    last = last.next;
  }

  if (l1) {
    last.next = l1; 
  }
  if (l2) {
    last.next = l2;
  }
  return newList;
};
  • 208/208 cases passed (76 ms)
  • Your runtime beats 88.77 % of javascript submissions
  • Your memory usage beats 64.88 % of javascript submissions (35.3 MB)
isaaxite commented 4 years ago

回到顶部

删除排序数组中的重复项

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例 1:

给定数组 nums = [1,1,2], 

函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 

你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,0,1,1,1,2,2,3,3,4],

函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。

你不需要考虑数组中超出新长度后面的元素。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}

第一版

/*
 * @lc app=leetcode.cn id=26 lang=javascript
 *
 * [26] 删除排序数组中的重复项
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @return {number}
 */
var removeDuplicates = function(nums) {
  let len = nums.length;
  while (len--) {
    const temp = nums.pop();
    if (nums[0] !== temp) {
      nums.unshift(temp);
    }
  }
};
  • 161/161 cases passed (112 ms)
  • Your runtime beats 53.31 % of javascript submissions
  • Your memory usage beats 82.21 % of javascript submissions (36.6 MB)
isaaxite commented 4 years ago

回到顶部

移除元素

给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:

给定 nums = [3,2,2,3], val = 3,

函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。

你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,1,2,2,3,0,4,2], val = 2,

函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。

注意这五个元素可为任意顺序。

你不需要考虑数组中超出新长度后面的元素。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}

第一版

/*
 * @lc app=leetcode.cn id=27 lang=javascript
 *
 * [27] 移除元素
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @param {number} val
 * @return {number}
 */
var removeElement = function(nums, val) {
  let len = nums.length; 
  while (len--) {
    const temp = nums.pop();
    if (temp !== val) {
      nums.unshift(temp);
    }
  }
};
  • 113/113 cases passed (56 ms)
  • Your runtime beats 98.59 % of javascript submissions
  • Your memory usage beats 32.4 % of javascript submissions (33.7 MB)
isaaxite commented 4 years ago

回到顶部

实现 strStr()

实现 strStr() 函数。

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

示例 1:

输入: haystack = "hello", needle = "ll"
输出: 2

示例 2:

输入: haystack = "aaaaa", needle = "bba"
输出: -1

说明:

当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。

第一版

/*
 * @lc app=leetcode.cn id=28 lang=javascript
 *
 * [28] 实现 strStr()
 */

// @lc code=start
/**
 * @param {string} haystack
 * @param {string} needle
 * @return {number}
 */
var strStr = function(haystack, needle) {
  if (!needle) return 0;
  for (let i = 0; i < haystack.length - needle.length + 1; i += 1) {
    if (haystack.substr(i, needle.length) === needle) {
      return i;
    }
  }
  return -1;
};

注意循环条件i < haystack.length - needle.length + 1,很容易就会写成i < haystack.length - needle.length,在haystack = 'x', needle='x'就会出错,输出是-1,而期望是0

  • 74/74 cases passed (60 ms)
  • Your runtime beats 95.97 % of javascript submissions
  • Your memory usage beats 60.72 % of javascript submissions (33.7 MB)
isaaxite commented 4 years ago

回到顶部

搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

示例 1:

输入: [1,3,5,6], 5
输出: 2

示例 2:

输入: [1,3,5,6], 2
输出: 1

示例 3:

输入: [1,3,5,6], 7
输出: 4

示例 4:

输入: [1,3,5,6], 0
输出: 0

第一版

/*
 * @lc app=leetcode.cn id=35 lang=javascript
 *
 * [35] 搜索插入位置
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var searchInsert = function(nums, target) {
  if (target < nums[0]) {
    return 0;
  }
  for (let i = 0; i < nums.length; i += 1) {
    if (nums[i] === target) {
      return i;
    } else if (nums[i] < target && target < nums[i + 1]) {
      return i + 1;
    }
  }
  return nums.length;
};
  • 62/62 cases passed (68 ms)
  • Your runtime beats 80.57 % of javascript submissions
  • Your memory usage beats 19.21 % of javascript submissions (34.6 MB)
isaaxite commented 4 years ago

回到顶部

报数

报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:

1.     1
2.     11
3.     21
4.     1211
5.     111221

1 被读作 "one 1" ("一个一") , 即 11。 11 被读作 "two 1s" ("两个一"), 即 21。 21 被读作 "one 2", "one 1" ("一个二" , "一个一") , 即 1211。

给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。

注意:整数顺序将表示为一个字符串。

示例 1:

输入: 1
输出: "1"

示例 2:

输入: 4
输出: "1211"

第一版

/*
 * @lc app=leetcode.cn id=38 lang=javascript
 *
 * [38] 报数
 */

// @lc code=start
/**
 * @param {number} n
 * @return {string}
 */
var countAndSay = function(n) {
  let list = [1];
  while (--n) {
    const temp = [];
    let count = 1;
    for (let i = 0; i < list.length; i += 1) {
      if (list[i] === list[i + 1]) {
        count += 1;
      } else {
        temp.push(count, list[i]);
        count = 1;
      }
    }
    list = temp;
  }
  return list.join('');
};
  • 18/18 cases passed (84 ms)
  • Your runtime beats 48.45 % of javascript submissions
  • Your memory usage beats 87.66 % of javascript submissions (34.8 MB)