这是 Leetcode 的 JS 实现——Easy 篇的后半部分,前半部分可以点击这里 查看
介绍 Leetcode 地址:https://leetcode.com/problemset/algorithms/,本文不会贴出题目,可以点击标题链接查看原题目 
排序方式:按照本难度中题目的 accepted 统计
JS 代码实现 方法一:动态规划 1 2 3 4 5 6 7 8 9 10 11 12 13 var  maxProfit = function (prices ) {    var  maxPro = 0 ;     var  minPrice = prices[0 ];     for (var  i = 0  ,n = prices.length ; i<n;i++){         minPrice = Math .min (minPrice, prices[i]);         maxPro = Math .max (maxPro, prices[i] - minPrice);     }     return  maxPro; }; 
方法二:Kadane’s Algorithm 1 2 3 4 5 6 7 8 9 10 11 12 var  maxProfit = functon (pris)    var  maxCur = 0 , maxSoFar = 0 ;     for (var  i = 1 ,n = prices.length ;i<n; i++) {         maxCur = Math .max (0 , maxCur += prices[i] - prices[i-1 ])         maxSoFar = Math .max (maxCur, maxSoFar);     }     return  maxSoFar; }; 
方法一:Floyd Cycle detection algorithm 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 var  isHappy = function (n ) {    var  slow, fast;     slow = fast = n;     do  {         slow = digitSquareSum (slow);         fast = digitSquareSum (fast);         fast = digitSquareSum (fast);     } while (slow != fast);     if  (slow == 1 ) {return  true ;}     else  {return  false ;} }; var  digitSquareSum = function (n ){    var  sum = 0 , tmp;     while  (n) {         tmp = n % 10 ;         sum += tmp * tmp;         n = Math .floor (n / 10 );     }     return  sum; }; 
方法二:O(1)space,如果快 = 慢,证明陷入了死循环 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 var  isHappy = function (n ) {    var  x = n,y = n;     while (x>1 ){         x = cal (x) ;         if (x==1 ) {return  true ;}         y = cal (cal (y));                     if (y==1 ) {return  true  ;}         if (x==y) {return  false ;}     }             return  true ; }; var  cal = function (n ){    var  sum = 0 , tmp;     while  (n) {         tmp = n % 10 ;         sum += tmp * tmp;         n = Math .floor (n / 10 );     }     return  sum; }; 
方法三:Using fact all numbers in [2, 6] are not happy (and all not happy numbers end on a cycle that hits this interval) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 var  isHappy = function (n ) {    while (n>6 ){         var  next = 0 ;         while (n){             next+=(n%10 )*(n%10 );              n = Math .floor (n/10 );         }         n = next;     }     return  n==1 ; }; 
方法一:递归 1 2 3 4 5 6 7 var  isPowerOfThree = function (n ) {    return  n>0  && (n==1  || (n%3 ===0  && isPowerOfThree (n/3 ))); }; 
方法二:迭代 1 2 3 4 5 6 7 8 9 var  isPowerOfThree = function (n ) {    if (n>1 )         while (n%3 ===0 ) {n /= 3 ;}     return  n==1 ; }; 
方法三:int 型数字中最大的 3 的幂为 1162261467 1 2 3 4 5 6 7 var  isPowerOfThree = function (n ) {    return  n > 0  && (1162261467  % n === 0 ); }; 
方法四:对 n 取根值 1 2 3 4 5 6 7 var  isPowerOfThree = function (n ) {    return  (Math .log10 (n) / Math .log10 (3 )) % 1  === 0 ; }; 
方法五:正则表达式 1 2 3 4 5 6 7 8 var  isPowerOfThree = function (n ) {    var  reg = new  RegExp ("^10*$" ,"" );     return  reg.test (n.toString (3 )); }; 
方法一:Power of 2 means only one bit of n is ‘1’, so use the trick n&(n-1)==0 to judge whether that is the case 1 2 3 4 5 6 7 8 var  isPowerOfTwo = function (n ) {    if (n<=0 ) {return  false ;}     return  !(n&(n-1 )); }; 
方法二:同样利用二进制数字中只有 1 个 “1” 的特性,用 replace() 方法求二进制数字中 1 的数目 1 2 3 4 5 6 7 var  isPowerOfTwo = function (n ) {    return  n>0  && n.toString (2 ).replace (/0/g ,'' ).length  == 1 ; }; 
方法三:迭代 1 2 3 4 5 6 7 8 9 var  isPowerOfTwo = function (n ) {    if (n===0 ) {return  false ;}     while (n%2 ===0 ) n/=2 ;     return  (n==1 ); }; 
方法四:递归 1 2 3 4 5 6 7 var  isPowerOfTwo = function (n ) {    return  n>0  && (n==1  || (n%2 ===0  && isPowerOfTwo (n/2 ))); }; 
方法五:利用 int 型数字中最大的 2 的幂 1 2 3 4 5 6 7 var  isPowerOfTwo = function (n ) {    return  n>0  && (1073741824  % n === 0 ); }; 
方法一:递归 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 var  deleteDuplicates = function (head ) {    if (head === null  || head.next  === null ) {return  head;}     head.next  = deleteDuplicates (head.next );     return  head.val  == head.next .val  ? head.next  : head; }; 
方法一:斐波那契数列 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var  climbStairs = function (n ) {    if (n <= 0 ) return  0 ;     if (n == 1 ) return  1 ;     if (n == 2 ) return  2 ;          var  one_step_before = 2 ;     var  two_steps_before = 1 ;     var  all_ways = 0 ;          for (var  i=2 ; i<n; i++){     	all_ways = one_step_before + two_steps_before;     	two_steps_before = one_step_before;         one_step_before = all_ways;     }     return  all_ways; }; 
方法二:从终点向前循环,利用两个指针,a 代表到达当前步所有可能方式的个数,b 代表到达下一步所有可能方式的个数 1 2 3 4 5 6 7 8 9 10 var  climbStairs = function (n ) {    a = b = 1 ;     while  (n--)         a = (b += a) - a;     return  a; }; 
方法一:Basically, keep adding each integer to the sequence until the sum drops below 0.If sum is negative, then should reset the sequence. 1 2 3 4 5 6 7 8 9 10 11 12 13 var  maxSubArray = function (nums ) {    var  ans=nums[0 ],i,j,sum=0 ;     for (i=0 ;i<nums.length ;i++){         sum+=nums[i];                     ans=Math .max (sum,ans);         sum=Math .max (sum,0 );     }     return  ans; }; 
方法二:动态规划 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 var  maxSubArray = function (nums ) {    var  n = nums.length ;     var  dp = [];     dp[0 ] = nums[0 ];     var  max = dp[0 ];     for (var  i = 1 ; i < n; i++){         dp[i] = nums[i] + (dp[i - 1 ] > 0  ? dp[i - 1 ] : 0 );         max = Math .max (max, dp[i]);     }     return  max; }; 
方法一:用哈希表来建立所有的前缀路径之和跟其个数之间的映射,然后看子路径之和有没有等于给定值的 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 var  pathSum = function (root, sum ) {    var  map = [];     map[0 ] = 1 ;       return  backtrack (root, 0 , sum, map);  }; var  backtrack = function (root,sum,target,map ){    if (root === null ) {return  0 ;}     sum += root.val ;     var  res = map[sum-target] === undefined  ? 0  : map[sum-target];     map[sum] = (map[sum] === undefined  ? 0  : map[sum])+1 ;     res += backtrack (root.left , sum, target, map) + backtrack (root.right , sum, target, map);     map[sum]--;        return  res; }; 
方法二:利用前序遍历,对于每个遍历到的节点进行处理,维护一个变量 pre 来记录之前路径之和,然后 cur 为 pre 加上当前节点值,如果 cur 等于 sum,那么返回结果时要加 1,然后对当前节点的左右子节点调用递归函数求解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 var  pathSum = function (root, sum ) {    if  (root === null ) {return  0 ;}     return  sumUp (root, 0 , sum) + pathSum (root.left , sum) + pathSum (root.right , sum); }; var  sumUp = function (node,pre,sum ){    if  (node === null ) {return  0 ;}     var  cur = pre + node.val ;     return  (cur == sum) + sumUp (node.left , cur, sum) + sumUp (node.right , cur, sum); }; 
方法一:Morris traversal(二叉树遍历方法,参考链接 ) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 var  currVal,    currCount = 0 ,     maxCount = 0 ,     modeCount = 0 ,     modes = [];    var  findMode = function (root ) {    inorder (root);     modes = new  Array (modeCount);     modeCount = 0 ;     currCount = 0 ;     inorder (root);     return  modes; }; var  handleValue = function (val ) {    if  (val != currVal) {         currVal = val;         currCount = 0 ;     }     currCount++;     if  (currCount > maxCount) {         maxCount = currCount;         modeCount = 1 ;     } else  if  (currCount == maxCount) {         if  (modes !== null )             modes[modeCount] = currVal;         modeCount++;     } }; var  inorder = function (root ) {    var  node = root;         while  (node !== null ) {             if  (node.left  === null ) {                 handleValue (node.val );                 node = node.right ;             } else  {                 var  prev = node.left ;                 while  (prev.right  !== null  && prev.right  != node)                     prev = prev.right ;                 if  (prev.right  === null ) {                     prev.right  = node;                     node = node.left ;                 } else  {                     prev.right  = null ;                     handleValue (node.val );                     node = node.right ;                 }             }         } }; 
方法二:先用递归得到有多少个 modes,然后再申请空间保证 O(1) 的空间复杂度 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 var  currentModes = 0 ;var  currentValue = 0 ;var  currentCount = 0 ;var  modes = [];var  maxCount = 0 ;  var  findMode = function (root ) {    helper (root);     modes = new  Array (currentModes);     currentModes = 0 ;     currentCount = 0 ;     helper (root);     return  modes; }; var  helper = function  (root ) {    if  (root === null ) return ;     helper (root.left );     if  (root.val  != currentValue) {         currentCount = 1 ;         currentValue = root.val ;     } else  {         currentCount++;     }     if  (currentCount > maxCount) {         maxCount = currentCount;         currentModes = 1 ;     } else  if  (currentCount == maxCount) {         if  (modes !== null ){             modes[currentModes] = root.val ;             currentModes++;         }     }     helper (root.right ); }; 
方法一:利用 toString(2) 和 replace() 1 2 3 4 5 6 7 var  hammingWeight = function (n ) {    return  n.toString (2 ).replace (/0/g ,'' ).length ; }; 
方法二:利用 n=n&(n-1) 1 2 3 4 5 6 7 8 9 10 var  hammingWeight = function (n ) {    var  count = 0 ;     for  (;n!==0 ;n = n & (n-1 ))         count++;     return  count; }; 
方法三:位运算 1 2 3 4 5 6 7 8 9 10 11 12 var  hammingWeight = function (n ) {    var  ones = 0 ;     while (n!==0 ) {     	ones = ones + (n & 1 );     	n = n>>>1 ;     }     return  ones; }; 
方法一:按部就班遍历 1 2 3 4 5 6 7 8 9 10 11 12 13 var  searchInsert = function (nums, target ) {    for (var  i=0 ,n=nums.length ;i<n;i++){         if (target<=nums[i]){             return  i;         }     }     return  n; }; 
方法二:二分查找 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 var  searchInsert = function (nums, target ) {    var  low = 0 , high = nums.length -1 ;     while (low<=high){         var  mid = Math .floor ((low+high)/2 );         if (nums[mid] == target) {return  mid;}         else  if (nums[mid] > target) {high = mid-1 ;}         else  {low = mid+1 ;}     }     return  low; }; 
暂无
方法一:根据丑陋数的定义,我们将给定数除以 2、3、5,直到无法整除,也就是除以 2、3、5 的余数不再为 0 时停止。这时如果得到 1,说明是所有因子都是 2 或 3 或 5,如果不是 1,则不是丑陋数。 1 2 3 4 5 6 7 8 9 10 var  isUgly = function (num ) {    for  (var  p of  [2 , 3 , 5 ])     while  (num && num % p === 0 )         num /= p;     return  num == 1 ; }; 
方法一:The idea is that when we see a character in str  that matches the very first character of str , we can start to hoping that str  is a built by copies of the substring composed by all characters before the reappearance of the its first character. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 var  repeatedSubstringPattern = function (s ) {    var  l = s.length ;     if (l == 1 ) {         return  false ;     }     var  sb = '' ;     var  first = s.charAt (0 );     sb += first;     var  i = 1 ;     while (i <= l / 2 ) {         var  c = s.charAt (i++);         if (c == first && isCopies (s, sb)) {             return  true ;         }else  {             sb += c;         }     }     return  false ; }; var  isCopies = function (str,substr ) {    if (str.length  % substr.length  !== 0 ) {         return  false ;     }     for (var  i = substr.length ; i < str.length ; i += substr.length ){         if (str.substring (i).slice (0 ,substr.length ) !== substr){             return  false ;         }     }     return  true ; }; 
其他方法仍在思考实现中
方法一:递归 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 var  mergeTwoLists = function (l1, l2 ) {    if (l1 === null ) return  l2;     if (l2 === null ) return  l1;     if (l1.val  < l2.val ) {         l1.next  = mergeTwoLists (l1.next , l2);         return  l1;     } else  {         l2.next  = mergeTwoLists (l2.next , l1);         return  l2;     } }; 
方法一:递归 因为这是一棵二叉搜索数,所以两个节点分别与共同的祖先节点相减所得的差应该是异号或等于0的,否则就根据节点与当前根节点的大小比较对其左子树或右子树进行递归
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 var  lowestCommonAncestor = function (root, p, q ) {    while  ((root.val  - p.val ) * (root.val  - q.val ) > 0 )         root = p.val  < root.val  ? root.left  : root.right ;     return  root; }; 
方法二:迭代,和递归类似,只不过代码更加简化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var  lowestCommonAncestor = function (root, p, q ) {    return  (root.val  - p.val ) * (root.val  - q.val ) < 1  ? root :            lowestCommonAncestor (p.val  < root.val  ? root.left  : root.right , p, q); }; 
方法一:根据房间数的奇偶进行分类存储最大值,并且有以下规律 f(0) = nums[0] f(1) = max(num[0], num[1]) f(k) = max( f(k-2) + nums[k], f(k-1) )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var  rob = function (nums ) {    var  a = 0 ,         b = 0 ;     for  (var  i=0 ; i<nums.length ; i++)     {         if  (i%2 ===0 )         {             a = Math .max (a+nums[i], b);         }         else          {             b = Math .max (a, b+nums[i]);         }     }     return  Math .max (a, b); }; 
方法一:因为能被 4 整除的数用二进制表示的话有且只有一个 1 在奇数位上 1 2 3 4 5 6 7 var  isPowerOfFour = function (num ) {    return  num > 0  && (num&(num-1 )) === 0  && (num & 0x55555555 ) !== 0 ; }; 
方法二:很好用的 replace().length 1 2 3 4 5 6 7 var  isPowerOfFour = function (num ) {    return  num.toString (2 ).replace (/0/g ,'' ).length  === 1  && num.toString (2 ).length %2  ===1 ; }; 
方法三:利用 2 的倍数减 1 无法整除 3 而 4 的倍数减 1 可以整除 3 的特性 1 2 3 4 5 6 7 var  isPowerOfFour = function (num ) {    return  num > 0  && (num & (num - 1 )) === 0  && (num - 1 ) % 3  === 0 ; }; 
方法一:利用二分法和替代数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 var  reverseVowels = function (s ) {    if (s.length  <= 1 ){return  s;}     var  arr = ['a' ,'e' ,'i' ,'o' ,'u' ,'A' ,'E' ,'I' ,'O' ,'U' ],         res = new  Array (s.length );         left = 0 ,         right = s.length  -1 ;     while (left<=right){         if (arr.indexOf (s[left]) < 0 ){             res[left] = s[left];             left++;         }         if (arr.indexOf (s[right]) < 0 ){             res[right] = s[right];             right--;         }         if (arr.indexOf (s[left]) >=0  && arr.indexOf (s[right]) >=0 ){             res[left] = s[right];             res[right] = s[left];             left++;             right--;         }     }     return  res.join ('' ); }; 
方法一:完全平方数一定是 1+3+5+7……O(sqrt(N)) 1 2 3 4 5 6 7 8 9 10 11 var  isPerfectSquare = function (num ) {    if  (num < 1 ) {return  false ;}     for  (var  i = 1 ; num > 0 ; i += 2 ){         num -= i;     }     return  num === 0 ; }; 
方法二:二分查找,O(logN) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var  isPerfectSquare = function (num ) {    if  (num < 1 ) {return  false ;}     var  left = 1 , right = num;     while  (left <= right) {         var  mid = Math .floor (left + (right - left) / 2 );         var  t = mid * mid;         if  (t > num) {           right = mid - 1 ;         } else  if  (t < num) {           left = mid + 1 ;         } else  {           return  true ;         }     }     return  false ; }; 
1 2 3 4 5 6 7 8 9 10 11 12 var  isPerfectSquare = function (num ) {    if  (num < 1 ) {return  false ;}     var  t = Math .floor (num / 2 );     while  (t * t > num) {         t = Math .floor ((t + num / t) / 2 );     }     return  t * t == num || num === 1 ; }; 
方法一:在获得剩余长度的同时生成新数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 var  removeElement = function (nums, val ) {    var  cnt = 0 ;     for (var  i = 0  ; i < nums.length  ; ++i) {         if (nums[i] == val)             cnt++;         else              nums[i-cnt] = nums[i];     }     return  nums.length -cnt; }; 
方法二:既短又快 1 2 3 4 5 6 7 8 9 10 11 12 13 14 var  removeElement = function (nums, val ) {    var  l = nums.length ;     for  (var  i=0 ; i<l; i++) {         if  (nums[i] == val) {             nums[i--] = nums[l-- -1 ];         }     }     return  l; }; 
方法一:通过另外一个方法判断其左右子树是否都是”镜像数” 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 var  isSymmetric = function (root ) {    if (root===null ) {return  true ;}     return  isMirror (root.left ,root.right ); }; var  isMirror = function (p,q ){    if (p===null  && q===null ) return  true ;     if (p===null  || q===null ) return  false ;     return  (p.val ==q.val ) && isMirror (p.left ,q.right ) && isMirror (p.right ,q.left ); }; 
方法二:通过队列(在 JS 中通过数组模拟) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 var  isSymmetric = function (root ) {    var  q = [];     if (root === null ) return  true ;     q.push (root.left );     q.push (root.right );     while (q.length  > 1 ){         var  left = q.shift (),             right = q.shift ();         if (left=== null && right === null ) continue ;         if (left=== null  ^ right === null ) return  false ;         if (left.val  != right.val ) return  false ;         q.push (left.left );         q.push (right.right );         q.push (left.right );         q.push (right.left );                 }     return  true ; }; 
方法一:从 n-1 开始遍历,然后用一个变量表示前面一位是否进位 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var  plusOne = function (digits ) {    var  j=0 ,k;     for (var  n=digits.length ,i=n-1 ;i>=0 ;i--){         k = i==n-1  ? 1 :0 ;         var  old = digits[i];         digits[i] = (old + j + k)%10 ;         j = Math .floor ((old + j + k)/10 );     }     if (j == 1 ){         digits.unshift (1 );     }     return  digits; }; 
方法一:单独用一个方法生成某一行,再 push 进数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 var  generate = function (numRows ) {    var  arr = [];     for (var  i=0 ;i<numRows;i++){         var  item = f (i+1 );         arr.push (item);     }     console .info (f (1 ));     return  arr; }; var  f = function (n ){    var  a = new  Array (n);     if (n==1 ){return  [1 ];}     else  if (n==2 ){return  [1 ,1 ];}     else {         var  arr = f (n-1 );         for (var  i=0 ;i<n-1 ;i++){             a[i+1 ] = arr[i]+arr[i+1 ];         }         a[0 ] = a[n-1 ] = 1 ;         return  a;     } }; 
方法二:直接对二维数组进行赋值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var  generate = function (numRows ) {    var  r = [];     for (var  k=0 ;k<numRows;k++){             r[k]= [];       }     for  (var  i = 0 ; i < numRows; i++) {         r[i][0 ] = r[i][i] = 1 ;         for  (var  j = 1 ; j < i; j++){             r[i][j] = r[i - 1 ][j - 1 ] + r[i - 1 ][j];         }     }     return  r; }; 
方法一:先去掉首尾空格再将非空格替换成空字符 1 2 3 4 5 6 7 8 var  countSegments = function (s ) {    var  str = s.replace (/^\s+|\s+$/g ,'' );     return  str.length  === 0  ? 0  : str.replace (/\s+/g ,' ' ).replace (/\S/g ,'' ).length  +1 ; }; 
方法二:先在首尾加一个空格,然后将非空格替换成空字符 1 2 3 4 5 6 7 var  countSegments = function (s ) {    return  (" "  + s + " " ).replace (/\s+/g ,' ' ).replace (/\S/g ,'' ).length  - 1 ; }; 
方法一:某节点的高度等于该节点的左子树和右子树的高度中的较大值再加一,O(N^2) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 var  isBalanced = function (root ) {    if  (root === null ) return  true ;     var  left=depth (root.left );     var  right=depth (root.right );     return  Math .abs (left - right) <= 1  && isBalanced (root.left ) && isBalanced (root.right ); }; var  depth = function (root ){    if  (root === null ) return  0 ;     return  Math .max (depth (root.left ), depth  (root.right )) + 1 ; }; 
方法二:从底部向上遍历,O(N) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 var  isBalanced = function (root ) {    return  dfsHeight (root) != -1 ; }; var  dfsHeight = function (root ) {    if  (root === null ) return  0 ;     var  leftHeight = dfsHeight  (root.left );     if  (leftHeight == -1 ) return  -1 ;     var  rightHeight = dfsHeight (root.right );     if  (rightHeight == -1 ) return  -1 ;     if  (Math .abs (leftHeight - rightHeight) > 1 )  return  -1 ;     return  Math .max (leftHeight, rightHeight) + 1 ; }; 
暂无
方法一:根据公式直接求解 (x * ( x + 1)) / 2 <= n 1 2 3 4 5 6 7 var  arrangeCoins = function (n ) {    return  Math .floor (((-1  + Math .sqrt (1  + 8  *n)) / 2 )); }; 
方法二:先根据根值确定大致范围,然后二分查找 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 var  arrangeCoins = function (n ) {    var  start = 0 ,         end = n,         mid = 0 ;     while  (start <= end){         mid = (start + end) >>> 1 ;         if  ((0.5  * mid * mid + 0.5  * mid ) <= n){             start = mid + 1 ;         }else {             end = mid - 1 ;         }     }     return  start - 1 ; }; 
方法一:递归,直接计算 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var  getRow = function (rowIndex ) {    var  A = [];     A[0 ] = 1 ;     for (var  i=1 ; i<rowIndex+1 ; i++){         for (var  j=i; j>=1 ; j--){             if (isNaN (A[j])){                 A[j] = 0 ;             }             if (isNaN (A[j-1 ])){                 A[j-1 ] = 0 ;             }             A[j] += A[j-1 ];         }     }          return  A; }; 
方法二:根据公式 a(k+1) = a(k) * (n-k)/(k+1),其中 a(0)=1 和 a(1)=n 很容易发现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 var  getRow = function (rowIndex ) {    if (rowIndex === 0 ) {return  [1 ];}       var  A=[];       A[0 ]=1 ;       A[1 ]=rowIndex;       for (var  i=2 ;i<=rowIndex;i++) {           A[i]=Math .floor (A[i-1 ]*(rowIndex-(i-1 ))/i);      }       return  A;  }; 
参见我的另外一篇文章:JS实现复杂数据结构 
方法一:一个快指针,一个慢指针 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 var  hasCycle = function (head ) {    if (head===null ) return  false ;     var  walker = head,runner = head;     while (runner.next !==null  && runner.next .next !==null ) {         walker = walker.next ;         runner = runner.next .next ;         if (walker==runner) return  true ;     }     return  false ; }; 
方法一:遇到不同的元素时才进行赋值 1 2 3 4 5 6 7 8 9 10 11 var  removeDuplicates = function (nums ) {    if  (nums.length ===0 ) return  0 ;     var  j=0 ;     for  (var  i=0 ; i<nums.length ; i++)         if  (nums[i]!=nums[j]) nums[++j]=nums[i];     return  ++j; }; 
方法二:用一个变量记录当前重复元素数量 1 2 3 4 5 6 7 8 9 10 11 12 var  removeDuplicates = function (nums ) {    var  count = 0 ;     for (var  i = 1 ; i < nums.length ; i++){         if (nums[i] == nums[i-1 ]) count++;         else  nums[i-count] = nums[i];     }     return  nums.length -count; }; 
方法一:产生 0 的可能性只有 2*5,所以需要计算 n! 里有几个 5,2 是足够多的 1 2 3 4 5 6 7 var  trailingZeroes = function (n ) {    return  n === 0  ? 0  : Math .floor (n / 5 ) + trailingZeroes (n / 5 ); }; 
方法一:二分查找 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 var  isPalindrome = function (x ) {    var  str = ""  + x,left=0 ,right=str.length -1 ;     while (right-left>=1 ){         if (str[left] == str[right]){             left++;             right--;         }else {             return  false ;         }     }     return  true ; }; 
方法二:比较前一半数字和后一半数字是否相等 1 2 3 4 5 6 7 8 9 10 11 12 13 var  isPalindrome = function (x ) {    if  (x<0  || (x!==0  && x%10 ===0 )) return  false ;     var  rev = 0 ;     while  (x>rev){     	rev = rev*10  + x%10 ;     	x = Math .floor (x/10 );     }     return  (x==rev || x==Math .floor (rev/10 )); }; 
方法一:二分查找(这道题不能用 JS,所以答案并没有在 leetcode 上验证) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var  guessNumber = function (n ){    var  low = 1 ;     while (low <= n){         var  mid = Math .floor (low + (n-low) / 2 );         var  res = guess (mid);         if (res == 0 )             return  mid;         else  if (res == -1 )             n = mid - 1 ;         else          low = mid + 1 ;     }     return  -1 ; } 
暂无
方法一:知道 sum 和 root.val,看左子树或右子树是否能够满足 sum-root.val 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var  hasPathSum = function (root, sum ) {    if  (root === null ) return  false ;     if  (root.val  == sum && root.left  === null  && root.right  === null ) return  true ;     return  hasPathSum (root.left , sum-root.val ) || hasPathSum (root.right , sum-root.val ); }; 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 var  countAndSay = function (n ) {    if (n == 1 ) {return  '1' ;}     else {         var  s = countAndSay (n-1 ),res='' ,a=1 ;         for (var  i=0 ,len=s.length ;i<len;i++){             if (s[i+1 ] == s[i]){                 a++;             }else {                 res += a + s[i];                 a=1 ;             }         }         return  res;     } }; 
方法一:用哈希表判断重复出现的位置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 var  isIsomorphic = function (s, t ) {    return  phic (s,t) && phic (t,s); }; var  phic = function (s,t ){    var  arr = [];     for (var  i=0 ,n=s.length ;i<n;i++){         var  code = s[i].charCodeAt () - 65 ;         if (arr[code] === undefined ){             arr[code] = i;         }else {             if (t[i] != t[arr[code]]){                 return  false ;             }         }     }     return  true ; }; 
方法二:用一个数组保存重复元素第一次出现的位置 1 2 3 4 5 6 7 8 9 10 11 12 13 var  isIsomorphic = function (s, t ) {    var  m = [];     for  (var  i = 0 ; i < s.length ; i++) {         if  (m[s.charCodeAt (i)] != m[t.charCodeAt (i)+256 ]) {return  false ;}         m[s.charCodeAt (i)] = m[t.charCodeAt (i)+256 ] = i+1 ;     }     return  true ; }; 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 var  isValid = function (s ) {    var  p = [];     for (var  i = 0 ; i < s.length ; i++) {         var  q = "(){}[]" .indexOf (s.substring (i, i + 1 ));         if (q % 2  == 1 ) {             if (p.length  === 0  || p.shift () != q - 1 ) return  false ;         } else  p.unshift (q);     }     return  !p.length ; }; 
方法一:We need to add the smaller one of the child depths - except if that’s zero, then add the larger one. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 var  minDepth = function (root ) {    if  (!root) return  0 ;     var  L = minDepth (root.left ), R = minDepth (root.right );     return  1  + (Math .min (L, R) || Math .max (L, R)); }; 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 var  wordPattern = function (pattern, str ) {    var  arr = str.split (" " ),mid = [];          for (var  i=0 ,n=pattern.length ;i<n;i++){         var  char = pattern[i].charCodeAt () - 97 ;         if (mid[char] === undefined ){             if (inArray (arr[i],mid)){                 return  false ;             }else {                 mid[char] = arr[i];             }         }else {             if (mid[char] != arr[i]){                 return  false ;             }         }     }     return  true  && (pattern.length  == arr.length ); }; var  inArray = function (item,arr ) {    for (var  i=0 ,n=arr.length ;i<n;i++){         if (arr[i] === item){             return  true ;         }     }     return  false ; }; 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 var  isPalindrome = function (head ) {    if (head === null ) {         return  true ;     }     var  p1 = head,p2 = head,p3 = p1.next ,pre = p1;          while (p2.next  !== null  && p2.next .next  !== null ) {         p2 = p2.next .next ;         pre = p1;         p1 = p3;         p3 = p3.next ;         p1.next  = pre;     }          if (p2.next  === null ) {         p1 = p1.next ;     }     else  {        }          while (p3 !== null ) {         if (p1.val  != p3.val ) {             return  false ;         }         p1 = p1.next ;         p3 = p3.next ;     }     return  true ; }; 
方法一:双层循环(其实应该用哈希表,但是 JS 中没有,需要额外实现) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 var  twoSum = function (nums, target ) {    for (var  i=0 ,n=nums.length ;i<n;i++){         for (var  j=i+1 ;j<n;j++){             if ((nums[i] + nums[j]) == target){                 return  [i,j];             }         }     }     return  false ; }; 
方法一:只要读懂题意就差不多了,哈希表及时更新 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var  containsNearbyDuplicate = function (nums, k ) {    var  arr = [],res = false ;     for (var  i=0 ,n=nums.length ;i<n;i++){         var  item = nums[i];         if (arr[item] === undefined ){             arr[item] = i;         }else {             if (Math .abs (arr[item] - i) <= k){                 return  true ;             }             arr[item] = i;         }     }     return  false ; }; 
参考我的另一篇文章JS实现复杂数据结构 
方法一:模仿归并排序,从后往前比较 1 2 3 4 5 6 7 8 9 10 var  merge = function (nums1, m, nums2, n ) {    while (n>0 ) nums1[m+n-1 ] = (m===0 ||nums2[n-1 ] > nums1[m-1 ]) ? nums2[--n] : nums1[--m]; }; 
方法一:递归 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var  removeElements = function (head, val ) {    if  (head === null ) return  null ;     head.next  = removeElements (head.next , val);     return  head.val  == val ? head.next  : head; }; 
方法一:利用 split,需要提前去掉前后空格 1 2 3 4 5 6 7 var  lengthOfLastWord = function (s ) {    return   s.replace (/^\s+|\s+$/g ,'' ).split (' ' )[s.replace (/^\s+|\s+$/g ,'' ).split (' ' ).length  - 1 ].length ; }; 
方法一:先求根值,因为根值是遍历的界限 1 2 3 4 5 6 7 8 9 10 11 12 13 14 var  checkPerfectNumber = function (num ) {    var  sqrt = Math .sqrt (num),res = 0 ;     for (var  i=1 ;i<=sqrt;i++){         if (num%i === 0 ){             res += i+ num/i;         }     }     console .info (res);     return  num>1  && res==2 *num; }; 
方法一:对两个字符串循环遍历,同时用一个变量保存进位情况 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var  addBinary = function (a, b ) {    var  s = "" ;     var  c = 0 , i = a.length  - 1 , j = b.length  - 1 ;     while (i >= 0  || j >= 0  || c == 1 )     {         c += i >= 0  ? a[i --] - '0'  : 0 ;         c += j >= 0  ? b[j --] - '0'  : 0 ;         s = c % 2  + s;         c = Math .floor (c / 2 );     }     return  s; }; 
方法一:对数组进行遍历,用 indexOf 判断字符串的前缀 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 var  longestCommonPrefix = function (strs ) {    if (strs === null  || strs.length  === 0 )    return  "" ;     var  pre = strs[0 ],i = 1 ;     while (i < strs.length ){         while (strs[i].indexOf (pre) !== 0 ){             pre = pre.substring (0 ,pre.length -1 );         }         i++;     }     return  pre; }; 
方法一:用两个指针进行遍历,循环结束条件为指针相等 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 var  getIntersectionNode = function (headA, headB ) {    var  cur1 = headA,cur2 = headB;     while (cur1 != cur2){         cur1 = cur1?cur1.next :headB;         cur2 = cur2?cur2.next :headA;     }     return  cur1; }; 
方法一:步骤为:确定数字是几位数->确定具体数字->返回这个数字的第几位数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 var  findNthDigit = function (n ) {    n -= 1 ;     var  digits = 1 , first = 1 ;     while  (Math .floor (n / 9  / first / digits) >= 1 ) {         n -= 9  * first * digits;         digits++;         first *= 10 ;     }     return  (first + Math .floor (n/digits) + "" ).charAt (n%digits) - '0' ; }; 
方法一:在对房子进行循环的过程中移动加热器的指针 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 var  findRadius = function (houses, heaters ) {    var  house = houses.sort (function (a,b ){return  a-b;}),         heater= heaters.sort (function (a,b ){return  a-b;}),         i = 0 ,          res = 0 ;     for  (var  j=0 ,n=house.length ;j<n;j++) {         while  (i < heater.length  - 1  && heater[i] + heater[i + 1 ] <= house[j] * 2 ) {             i++;         }         res = Math .max (res, Math .abs (heater[i] - house[j]));     }     return  res; }; 
方法一:利用数组的 reverse() 进行反转 1 2 3 4 5 6 7 8 9 10 11 12 13 var  reverseBits = function (n ) {    var  zero = 32 - n.toString (2 ).length ;     var  bit = n.toString (2 ).split ("" ).reverse ().join ("" );     while (zero>0 ){         bit += '0' ;         zero--;     }     return  parseInt (bit,2 ); }; 
方法一:用一个数组保存前面元素之和 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 var  NumArray  = function (nums ) {    for (var  i = 1 ; i < nums.length ; i++)         nums[i] += nums[i - 1 ];          this .nums  = nums; }; NumArray .prototype  .sumRange  = function (i, j ) {    if (i === 0 ) {return  this .nums [j];}     return  this .nums [j] - this .nums [i - 1 ]; }; 
方法一:利用 JS 中的 indexOf() 1 2 3 4 5 6 7 8 var  strStr = function (haystack, needle ) {    return  haystack.indexOf (needle); }; 
方法二:老老实实遍历 1 2 3 4 5 6 7 8 9 10 11 12 13 14 var  strStr = function (haystack, needle ) {    for  (var  i = 0 ; ; i++) {     for  (var  j = 0 ; ; j++) {       if  (j == needle.length ) return  i;       if  (i + j == haystack.length ) return  -1 ;       if  (needle.charAt (j) != haystack.charAt (i + j)) break ;     }   } }; 
方法一:从 x/2 开始遍历(复杂度高,而且有可能会超时,不建议这种方法) 1 2 3 4 5 6 7 8 9 10 11 var  mySqrt = function (x ) {    var  t = Math .floor (x/2 );       while (t*t>x && t>=0 ){         t--;     }     return  x==1  ? 1  : t; }; 
方法二:二分查找 1 2 3 4 5 6 7 8 9 10 11 12 13 14 var  mySqrt = function (x ) {    var  begin = 0 ,end = x,result = 1 ,mid = 1 ;       while (Math .abs (result-x) > 0.000001 ){           mid = (begin+end)/2 ;           result = mid*mid;           if (result > x)   {end = mid;}         else  {begin = mid; }     }       return  Math .floor (mid); }; 
1 2 3 4 5 6 7 8 9 10 var  mySqrt = function (x ) {    r = x;     while  (r*r > x)         r = ((r + x/r) / 2 ) | 0 ;     return  r; }; 
参考我的另一篇文章JS实现复杂数据结构 
方法一:遍历比较 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 var  thirdMax = function (nums ) {    var  max1 = null ,max2 = null ,max3 = null ;     for  (var  i=0 ,len=nums.length ;i<len;i++) {         var  n = nums[i];         if  (n == max1 || n == max2 || n == max3) continue ;         if  (max1 === null  || n > max1) {             max3 = max2;             max2 = max1;             max1 = n;         } else  if  (max2 === null  || n > max2) {             max3 = max2;             max2 = n;         } else  if  (max3 === null  || n > max3) {             max3 = n;         }     }     return  max3 === null  ? max1 : max3; }; 
方法二:先将数组排序再遍历 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var  thirdMax = function (nums ) {    nums.sort (function (a,b ){         return  b-a;     });     max1 = nums[0 ],i = 1 ,j=1 ;     while (nums[i] == max1&&nums[i] !== undefined ){         i++;         j++;     }     max2 = nums[i];     while (nums[j] == max2&&nums[j] !== undefined ){         j++;     }     max3 = nums[j];     return  max3 === undefined  ? max1 : max3; }; 
方法一:两个指针,一个指针用来遍历,另一个指针用来寻找对应数字 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var  findPairs = function (nums, k ) {    var  ans = 0 ;     nums.sort (function (a,b ){         return  a-b;     });     for  (var  i = 0 , j = 0 ; i < nums.length ; i++) {         for  (j = Math .max (j, i + 1 ); j < nums.length  && nums[j] - nums[i] < k; j++) ;         if  (j < nums.length  &&  nums[j] - nums[i] == k) ans++;         while  (i + 1  < nums.length  && nums[i] == nums[i + 1 ]) {i++;}     }     return  ans; }; 
方法一:质数(素数)判断思路->对正整数 n,如果用 2 到根号 n 之间的所有整数去除,均无法整除,则 n 为质数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 var  countPrimes = function (n ) {    if  (n < 3 ) return  0 ;     var  f = [],count = Math .floor (n / 2 );     for  (var  i = 3 ; i * i < n; i += 2 ) {         if  (f[i]) {continue ;}         for  (var  j = i * i; j < n; j += 2  * i) {             if  (!f[j]) {                 --count;                 f[j] = true ;             }         }     }     return  count; }; 
方法一:二分查找 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 var  isPalindrome = function (s ) {    if (s === '' ){return  true ;}     var  low = s.replace (/\W/g ,'' ).toLowerCase ();     console .log (low);     var  left=0 ,right=low.length -1 ;     while (left<=right){         if (low[left] != low[right]){             return  false ;         }         left++;         right--;     }     return  true ; }; 
方法一:利用 ASCII 码进行递归,为了让余数为 0-25,需要每次递归前将 n 减 1 1 2 3 4 5 6 7 8 9 10 11 12 13 var  convertToTitle = function (n ) {    var  res = '' ;     while (n>0 ){         n--;         res =  String .fromCharCode (n % 26  + 65 )+res;         n = Math .floor (n/26 );     }     return  res; }; 
方法一:很常用的二分查找 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 var  solution = function (isBadVersion ) {         return  function (n ) {         var  left = 1 ,right=n;         while (left<right){             min = Math .floor ((left+right)/2 );             if (isBadVersion (min)){                 right = min;             }else {                 left=min+1 ;             }         }         return  left;     }; }; 
方法一:利用数组的 reverse() 方法,需要注意的是符号位和 int 型溢出的处理 1 2 3 4 5 6 7 8 9 10 11 var  reverse = function (x ) {    var  res = Math .floor ((''  + Math .abs (x)).split ('' ).reverse ().join ().replace (/,/g ,'' ));     if (res > (Math .pow (2 ,31 )-1 )){         return  0 ;     }     return  x>0  ? res : 0 - res; }; 
方法二:利用数学计算进行反转 1 2 3 4 5 6 7 8 9 10 11 12 13 var  reverse = function (x ) {    var  rev= 0 ,pos = Math .abs (x);     while ( pos !== 0 ){         rev= rev*10  + pos % 10 ;         pos= Math .floor (pos/10 );         if (Math .abs (rev)>Math .pow (2 ,31 )-1 ) return  0 ;     }     return  x>0  ? Math .floor (rev) : 0 - Math .floor (rev); }; 
方法一:利用数组的 pop() 和 unshift() 方法
1 2 3 4 5 6 7 8 9 10 11 12 var  rotate = function (nums, k ) {    var  len = nums.length ;     while (k>0 ){         nums.unshift (nums.pop ());         k--;     } }; 
方法二:三次反转 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 var  rotate = function (nums, k ) {    k %= nums.length ;     reverse (nums, 0 , nums.length  - 1 );     reverse (nums, 0 , k - 1 );     reverse (nums, k, nums.length  - 1 ); }; var  reverse = function (nums,start,end ) {    while  (start < end) {         var  temp = nums[start];         nums[start] = nums[end];         nums[end] = temp;         start++;         end--;     } }; 
方法三:非常巧妙的一种方式,看不懂的可以点击这里 看作者的解释 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 var  rotate = function (nums, k ) {    if (nums.length  <= 1 ){         return ;     }          var  step = k % nums.length ;          var  gcd = findGcd (nums.length , step),position, count;          for (var  i = 0 ; i < gcd; i++){                  position = i;                  count = Math .floor (nums.length  / gcd) - 1 ;         for (var  j = 0 ; j < count; j++){             position = (position + step) % nums.length ;                          nums[i] ^= nums[position];             nums[position] ^= nums[i];             nums[i] ^= nums[position];         }     } }; var  findGcd = function (a,b ){    return  (a === 0  || b === 0 ) ? a + b : findGcd (b, a % b); };