LeetCode的刷题之路(javascript版本,持续更新)

目录

    • 数组
      • 1. Two Sum
      • 26. 删除排序数组中的重复项
      • 27. 移除元素
      • 35. 搜索插入位置
      • 53. 最大子序和
      • 66. 加一
      • 88. 合并两个有序数组
      • 118. 杨辉三角
      • 119. 杨辉三角 II
      • 122. 买卖股票的最佳时机 II
      • 167. 两数之和 II - 输入有序数组
      • 169. 求众数
      • 189. 旋转数组
      • 217. 存在重复元素
      • 219. 存在重复元素 II
      • 268. 缺失数字
      • 283.移动零
      • 414. 第三大的数
      • 239. 滑动窗口最大值
      • 448. 找到所有数组中消失的数字
      • 485. 最大连续1的个数
      • 509. Fibonacci Number
      • 532. 数组中的K-diff数对
      • 561. 数组拆分 I
      • 566. 重塑矩阵
      • 581. 最短无序连续子数组
      • 605. 种花问题
      • 628. 三个数的最大乘积
      • 643. 子数组最大平均数 I
      • 661. 图片平滑器
      • 20.有效的括号
      • 155.最小栈
      • 225.用队列实现栈
      • 682.棒球比赛
      • 844. 比较含退格的字符串
      • 331. 验证二叉树的前序序列化
      • 946. 验证栈序列
      • 71. 简化路径
      • 856. 括号的分数
      • 402.移掉K位数字
      • 901. 股票价格跨度
      • 503. 下一个更大元素 II
      • 232. 用栈实现队列
    • 哈希表
      • 242. 有效的字母异位词
      • 100. 相同的树
      • 101. 对称二叉树
      • 04. 二叉树的最大深度
      • 107. 二叉树的层次遍历 II
      • 108. 将有序数组转换为二叉搜索树
      • 110. 平衡二叉树
      • 111. 最小二叉树
    • 二分查找
      • 69. x 的平方根
    • trie树
      • 208. 实现 Trie (前缀树)
    • 位运算
      • 191. 位1的个数
    • 动态规划
      • 70. 爬楼梯
    • 脑筋急转弯
      • 292. Nim游戏
      • 319. 灯泡开关

刷题思路:按照标签,从简单到困难,依次刷过去。

数组

1. Two Sum

题目

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    for(var i=0,l=nums.length;i<l;i++){
        var j = nums.indexOf(target-nums[i]);
        if(j != -1 && j != i){
            return [i,j];
        }
    }
    return false;
};
//优化后解法
var twoSum = function(nums, target) {
  var ans = [];
  var exist = {};
  for (var i = 0; i < nums.length; i++){
      if (typeof(exist[target-nums[i]]) !== 'undefined'){
          return [exist[target - nums[i]], i];
      }
      exist[nums[i]] = i;
  }
};

LeetCode的刷题之路(javascript版本,持续更新)_第1张图片
优化后解法:
LeetCode的刷题之路(javascript版本,持续更新)_第2张图片

26. 删除排序数组中的重复项

题目

/**
 * @param {number[]} nums
 * @return {number}
 */
var removeDuplicates = function(nums) {
    if(nums.length == 0) return 0;
    var i = 0;
    for(var j = 1; j < nums.length; j++){
        if(nums[j] != nums[i]){
            i++;
            nums[i] = nums[j];
        }
    }
    return i+1;
};

LeetCode的刷题之路(javascript版本,持续更新)_第3张图片

27. 移除元素

题目

/**
 * @param {number[]} nums
 * @param {number} val
 * @return {number}
 */
var removeElement = function(nums, val) {
    var i = 0;
    for(var j=0,len=nums.length;j<len;j++){
        if(nums[j] != val){
            nums[i] = nums[j];
            i++;
        }
    }
    return i;
};

35. 搜索插入位置

题目

//O(n)
var searchInsert = function(nums, target) {
    for(var i=0,len=nums.length; i<len;i++){
        if(nums[i] >= target){
            return i;
        }
    }
    return len;
};
//优化写法,二分法 O(log n)
var searchInsert = function(nums, target) {
    let low = 0,
        high = nums.length - 1;
    while(low <= high) {
        let 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 high + 1;
};

LeetCode的刷题之路(javascript版本,持续更新)_第4张图片

53. 最大子序和

题目

    var currentSum = totalSum = nums[0];
    for(var i=1; i<nums.length; i++) {
        currentSum = Math.max(nums[i], currentSum+nums[i]);
        totalSum = Math.max(totalSum, currentSum);
    }
    return totalSum;
};
//另一种写法,扩展运算符( spread )是三个点(…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
var maxSubArray = function(nums) {
    for (let i = 1; i < nums.length; i++){
        nums[i] = Math.max(nums[i], nums[i] + nums[i - 1]);
    }
    return Math.max(...nums);
};

LeetCode的刷题之路(javascript版本,持续更新)_第5张图片

66. 加一

题目

var plusOne = function(digits) {
    for(var i = digits.length - 1; i >= 0; i--){
        if(++digits[i] > 9) digits[i] = 0;
        else return digits;
    }
    digits.unshift(1);
    return digits;
};

此题目题意有点水。。
LeetCode的刷题之路(javascript版本,持续更新)_第6张图片

88. 合并两个有序数组

题目

/**
 * @param {number[]} nums1
 * @param {number} m
 * @param {number[]} nums2
 * @param {number} n
 * @return {void} Do not return anything, modify nums1 in-place instead.
 */
var merge = function(nums1, m, nums2, n) {
    this.stack = [];
    for(var i=0,j=0;i<nums1.length;){
        if(nums1[i] === 0){
            if(j == n) break;
            this.stack.push(nums2[j]);
            j++;
            i++;
        }else{
            if(nums1[i] < nums2[j]){
                this.stack.push(nums1[i]);
                i+=1;
            }else if(nums1[i] > nums2[j]){
                this.stack.push(nums2[j]);
                j+=1;
            }else{
                this.stack.push(nums1[i]);
                i+=1;
                this.stack.push(nums2[j]);
                j+=1;
            }
        }
    }
    //return this.stack;//该题目仅允许nums1进行操作,不需要返回值。
};
//优化写法
var merge = function(nums1, m, nums2, n) {
    var len = m + n;
    m--;
    n--;
    while (len--) {
        if (n < 0 || nums1[m] > nums2[n]) {
            nums1[len] = nums1[m--];
        } else {
            nums1[len] = nums2[n--];
        }
    }
};

LeetCode的刷题之路(javascript版本,持续更新)_第7张图片

118. 杨辉三角

题目

/**
 * @param {number} numRows
 * @return {number[][]}
 */
var generate = function(numRows) {
    var res = [];
    for(var i=0;i<numRows;i++){
        for(var j=0,arr=[];j<i+1;j++){
            if(j == 0 || j == i){
                arr.push(1);
            }else{
                arr.push(res[i-1][[j-1]] + res[i-1][j]);
            }
        }
        res.push(arr);
    }
    return res;
};

LeetCode的刷题之路(javascript版本,持续更新)_第8张图片

119. 杨辉三角 II

题目

/**
 * @param {number} rowIndex
 * @return {number[]}
 */
var getRow = function(rowIndex) {
    var row = [1];
    for(var i = 1; i <= rowIndex; i++){
        for(var j = i; j > 0 ; j--){
            if(j == i){
                row[j] = 1;
            }else{
                row[j] = row[j-1] + row[j];
            }
        }
    }
    return row;
};

Runtime: 68 ms

122. 买卖股票的最佳时机 II

题目

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function(prices) {
    var max = 0;
    for(let i=1,len=prices.length;i<len;i++){
        if(prices[i] > prices[i-1]){
            max += prices[i] - prices[i-1];
        }
    }
    return max;
};

可以简单地继续在斜坡上爬升并持续增加从连续交易中获得的利润,而不是在谷之后寻找每个峰值。最后,我们将有效地使用峰值和谷值,但我们不需要跟踪峰值和谷值对应的成本以及最大利润,但我们可以直接继续增加加数组的连续数字之间的差值,如果第二个数字大于第一个数字,我们获得的总和将是最大利润。这种方法将简化解决方案。

Runtime: 76 ms, faster than 59.42% of JavaScript online submissions for Best Time to Buy and Sell Stock II.

167. 两数之和 II - 输入有序数组

题目

/**
 * @param {number[]} numbers
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(numbers, target) {
  var l=numbers.length, i=0, j=l-1;
  while (numbers[i]+numbers[j] !== target) {
    numbers[i]+numbers[j] < target ? i++ : j--;
  }
  return [i+1, j+1];
};

Runtime: 72 ms, faster than 64.98% of JavaScript online submissions for Two Sum II - Input array is sorted.

169. 求众数

题目

/**
 * @param {number[]} nums
 * @return {number}
 */
var majorityElement = function(nums) {
    let len = nums.length;
    if(len == 1) return nums[0]; 
    nums.sort();
    return nums[parseInt(len/2)];
};
//Runtime: 96 ms, faster than 21.26% of JavaScript online submissions for Majority Element.
//其他做法
var majorityElement = function(nums) {
  let hash = {};
  for (let num of nums) {
    hash[num] = ++hash[num] || 1;
    if (hash[num] > nums.length / 2) {
      return num;
    }
  }
//Runtime: 84 ms, faster than 43.82% of JavaScript online submissions for Majority Element.  
//TODO 3.分置法(logN)
};

189. 旋转数组

题目

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var rotate = function(nums, k) {
     let length = nums.length;
     nums = nums.concat(nums);   //双倍数组
     let count = k%length +1;
     let arr = nums.slice(count, count+length);
     return arr;
 };
 //网站上没通过,本地通过了
 //别人的做法
var rotate = function(nums, k) {
    k = k % nums.length;
    if (k === 0 || nums.length === 1) return;
    function reverse(start, finish) {
        for (let i = start, j = finish - 1; i < Math.floor((start + finish) / 2); i++, j--) {
            let temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
    }
    reverse(0, nums.length);
    reverse(0, k);
    reverse(k, nums.length);
};
//Runtime: 92 ms, faster than 57.98% of JavaScript online submissions for Rotate Array.

var rotate = function(nums, k) {
    k = k >= nums.length ? k % nums.length : k;
    nums.splice(0,nums.length-k).forEach(
        el => nums.push(el)
    );
};
Runtime: 80 ms, faster than 62.26% of JavaScript online submissions for Rotate Array.

217. 存在重复元素

题目

/**
 * @param {number[]} nums
 * @return {boolean}
 */
//暴力枚举
var containsDuplicate = function(nums) {
    let arr = [];
    for(let i=0,len=nums.length;i<len;i++){
        if(arr.indexOf(nums[i]) != -1){
            return true;
        }else{
            arr.push(nums[i]);
        }
    }
    return false;
};
//Runtime: 1892 ms, faster than 8.89% of JavaScript online submissions for Contains Duplicate.
var containsDuplicate = function(nums) {
    var obj = {};
    for(var i = 0; i < nums.length; i++){
        obj[nums[i]] = obj[nums[i]] + 1 || 1;
        if(obj[nums[i]] > 1) return true;
    }
    return false;
};
//Runtime: 96 ms, faster than 33.15% of JavaScript online submissions for Contains Duplicate.
var containsDuplicate = function(nums) {
    return nums.length>new Set(nums).size
};
//Set和Map类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在Set中,没有重复的key。

//Runtime: 80 ms, faster than 48.94% of JavaScript online submissions for Contains Duplicate.

219. 存在重复元素 II

题目

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {boolean}
 */
var containsNearbyDuplicate = function(nums, k) {
    let ind = {}, len = nums.length;
    for (let i = 0; i < len; i++) {
        if (nums[i] in ind && i - ind[nums[i]] <= k) {
            return true;
        }
        ind[nums[i]] = i;
    }
    return false;
};
//Runtime: 92 ms, faster than 38.50% of JavaScript online submissions for Contains Duplicate II.

268. 缺失数字

题目

/**
 * @param {number[]} nums
 * @return {number}
 */
var missingNumber = function(nums) {
    let sum = 0;
    let expectedSum = nums.length;
    for (var i = 0; i < nums.length; i++) {
        sum += nums[i];
        expectedSum += i;
    }
    return expectedSum - sum;
}
//Runtime: 76 ms, faster than 38.37% of JavaScript online submissions for Missing Number.
};

283.移动零

题目

/**
 * @param {number[]} nums
 * @return {void} Do not return anything, modify nums in-place 		 instead.
 */
var moveZeroes = function(nums) {
    let len = nums.length;
    let j = 0;
    for (let i=0; i<len; i++) {
  	    if (nums[i] !== 0) {
            nums[j] = nums[i];
            j++;
        }
    }
    for (let k=j; k < len; k++){
        nums[k] = 0;
    }
};
//Runtime: 88 ms, faster than 14.41% of JavaScript online submissions for Move Zeroes.
var moveZeroes = function(nums) {       
    for(var i = nums.length;i--;){
        if(nums[i]===0){
            nums.splice(i,1)
            nums.push(0);
        }
    }
};
//Runtime: 80 ms, faster than 19.01% of JavaScript online submissions for Move Zeroes.

414. 第三大的数

题目

//自己的写法
/**
 * @param {number[]} nums
 * @return {number}
 */
var thirdMax = function(nums) {
    let len = nums.length;
    let arr = [];
    compare = function(a,b){
        return a-b;
    }
    for(let i=0;i<len;i++){
        if(arr.indexOf(nums[i]) == -1){
            arr.push(nums[i]);
        }
    }
    arr = arr.sort(compare);
    let len2 = arr.length;
    if(len2< 3){
        return arr[len2-1];
    }else{
        return arr[len2-3];
    }
};
//Runtime: 164 ms, faster than 5.71% of JavaScript online submissions for Third Maximum Number.
//优化写法
var thirdMax = function(nums) {
    let max1 = max2 = max3 = Number.NEGATIVE_INFINITY
    nums.forEach(e => {
        if(e != max1 && e != max2 && e != max3) {
            if(e > max1)
                [max3, max2, max1] = [max2, max1, e]
            else if(e > max2)
                [max3, max2] = [max2, e]
            else if (e > max3)
                max3 = e
        }
    })
    return max3 === Number.NEGATIVE_INFINITY ? max1 : max3
}
//Runtime: 76 ms, faster than 40.82% of JavaScript online submissions for Third Maximum Number.
var thirdMax = function(nums) {
    let max = -Infinity;
    let second = -Infinity;
    let third = -Infinity;
    nums.forEach(num => {
        if (num > max){
            third = second;
            second = max;
            max = num;
        } else if (num > second && num < max){
            third = second;
            second = num;
        } else if (num > third && num < second){
            third = num;
        }
    });
    return third !== -Infinity ? third : max;
}
//Runtime: 72 ms, faster than 44.49% of JavaScript online submissions for Third Maximum Number.

239. 滑动窗口最大值

题目

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var maxSlidingWindow = function(nums, k) {
    if(!nums || nums.length === 0) return [];
    const results = [];
    for(let i = 0; i <= nums.length-k; i++) {
       results.push(Math.max(...nums.slice(i, i+k)));
    }
    return results;
};
//Runtime: 204 ms, faster than 21.70% of JavaScript online submissions for Sliding Window Maximum.
//优化写法
var maxSlidingWindow = function(nums, k) {
    if(!nums) return [];
    let window = [], res = [];
    nums.forEach((value, index)=>{  
        if(index >= k && index-k >= window[0]) window.shift();
        while(window && nums[window[window.length-1]] <= value){
            window.pop();
        }
        window.push(index);
        if(index >= k-1) res.push(nums[window[0]]);
    });
    return res;
};
//Runtime: 108 ms, faster than 50.00% of JavaScript online submissions for Sliding Window Maximum.

448. 找到所有数组中消失的数字

题目

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var findDisappearedNumbers = function(nums) {
    const len = nums.length+1;
    let res = [];
    for(let i=1;i<len;i++){
        if(nums.indexOf(i) == -1){
            res.push(i);
        }
    }
    return res;
};
//Runtime: 7800 ms, faster than 13.74% of JavaScript online submissions for Find All Numbers Disappeared in an Array.
var findDisappearedNumbers = function(nums) {
    const length = nums.length;
    let arr = [];
    for (let i = 0; i < length; i++) {
        arr[i] = i+1;
    }
    for (v of nums) {
        arr[v-1] = -1;
    }
    return arr.filter( i => (i > 0) );
};
//Runtime: 132 ms, faster than 61.47% of JavaScript online submissions for Find All Numbers Disappeared in an Array.

var findDisappearedNumbers = function(nums) {
    const a= {};
    const result=[];
    for(let n of nums){
        if(!a[n]){
            a[n] = true;
        }
    }
    for(let i =1;i<nums.length+1;i++){
      if(!a[i]){
          result.push(i)
      }  
    }
    return result;
};
//Runtime: 160 ms, faster than 40.79% of JavaScript online submissions for Find All Numbers Disappeared in an Array.

485. 最大连续1的个数

题目

/**
 * @param {number[]} nums
 * @return {number}
 */
var findMaxConsecutiveOnes = function(nums) {
    if(!nums) return 0;
    let arr = [-1];
    let max = 0;
    let len = nums.length;
    for(let i=0;i<len;i++){
        if(nums[i] == 0){
            arr.push(i);
        }
    }
    arr.push(len);
    for(let i=0,len=arr.length-1;i<len;i++){
        max = Math.max(max,arr[i+1]-arr[i]);
    }
    return max-1;
};
//Runtime: 88 ms, faster than 11.13% of JavaScript online submissions for Max Consecutive Ones.

509. Fibonacci Number

题目

/**
 * @param {number} N
 * @return {number}
 */
var fib = function(N) {
    if(N <= 1) return N;
    return fib(N-1) + fib(N-2);
};
//Runtime: 92 ms, faster than 31.01% of JavaScript online submissions for Fibonacci Number.
//优化写法
var fib = function(N) {
    let table = [0, 1];
    for(let i = 2; i <= N; ++i){
        table[i] = table[i-1] + table[i-2];
   	}
    return table[N];
};
//Runtime: 68 ms, faster than 76.13% of JavaScript online submissions for Fibonacci Number.
var fib = function(N) {
    let a=0,b=1;
    let tmp=0;
    for (let i=0; i<=N; i+=1) {
        b=a+b;
        tmp=b;
        b=a;
        a=tmp;   
    }
    return b;
};
//Runtime: 68 ms, faster than 76.13% of JavaScript online submissions for Fibonacci Number.

532. 数组中的K-diff数对

题目

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var findPairs = function(nums, k) {
    if (k < 0) return 0;
    let set = new Set(), res = new Set();
    for(let i = 0; i < nums.length; i++) {
        if (set.has(nums[i]+k)) res.add(nums[i]+k);
        if (set.has(nums[i]-k)) res.add(nums[i]);
        set.add(nums[i]);
    }
    return res.size;    
};
//Runtime: 84 ms, faster than 59.60% of JavaScript online submissions for K-diff Pairs in an Array.

561. 数组拆分 I

题目

/**
 * @param {number[]} nums
 * @return {number}
 */
var arrayPairSum = function(nums) {
    let max = 0;
    nums = nums.sort((x, y) => x - y);
    for(let i=0,len=nums.length;i<len;i+=2){
        max += nums[i];
    }
    return max;
};
//Runtime: 140 ms, faster than 24.13% of JavaScript online submissions for Array Partition I.

566. 重塑矩阵

题目

/**
 * @param {number[][]} nums
 * @param {number} r
 * @param {number} c
 * @return {number[][]}
 */
var matrixReshape = function(nums, r, c) {
    let num = 0;
    let len0 = 0;
    let array = [];
    let result = [];
    for(let i=0,len=nums.length;i<len;i++){
        len0 = Number(nums[i].length);
        num += len0;
        for(let j=0;j<len0;j++){
            array.push(nums[i][j]);
        }
    }
    if(num < r*c){
        return nums;
    }else{
        for(let i=0;i<r; i++){
            result.push(array.splice(0,c));
        }
        return result;
    }
};
//Runtime: 108 ms, faster than 100.00% of JavaScript online submissions for Reshape the Matrix.

581. 最短无序连续子数组

题目

/**
 * @param {number[]} nums
 * @return {number}
 */
var findUnsortedSubarray = function(nums) {
    let array = nums.slice();
    let indexArray = [];
    nums.sort(function(a,b){return a-b;});
    for(let i=0,len=array.length;i<len;i++){
        if(nums[i] != array[i]){
            indexArray.push(i);
        }
    }
    if(indexArray.length <= 1){
        return indexArray.length;
    }else{
        return indexArray[indexArray.length-1] - indexArray[0] +1;
    }
};
//Runtime: 132 ms, faster than 100.00% of JavaScript online submissions for Shortest Unsorted Continuous Subarray.
//优化写法
var findUnsortedSubarray = function(nums) {
    let n = nums.length,beg = -1,end = -2, min = nums[n-1],max = nums[0];
    for (let i=1;i<n;i++) {
        max = Math.max(max, nums[i])
        min = Math.min(min, nums[n-1-i]);
        if (nums[i] < max) end = i;
        if (nums[n-1-i] > min) beg = n-1-i; 
    }
    return end - beg + 1;
};
//Runtime: 88 ms, faster than 100.00% of JavaScript online submissions for Shortest Unsorted Continuous Subarray.

605. 种花问题

题目

/**
 * @param {number[]} flowerbed
 * @param {number} n
 * @return {boolean}
 */
var canPlaceFlowers = function(flowerbed, n) {
    let count = 0;
    for(let i=0,len=flowerbed.length;i<len;i++){
        if((flowerbed[i-1] == undefined || flowerbed[i-1] == 0) && (flowerbed[i+1] == undefined || flowerbed[i+1] == 0) && flowerbed[i] == 0){
            flowerbed[i] = 1;
            count +=1;
        }
    }
    return (n <= count);
};
//Runtime: 88 ms, faster than 100.00% of JavaScript online submissions for Can Place Flowers.
//优化写法
var canPlaceFlowers = function(flowerbed, n) {
    let count = 0;
    for(let i = 0; i < flowerbed.length && count < n; i++) {
        if(flowerbed[i] == 0) {
            let next = (i == flowerbed.length - 1) ? 0 : flowerbed[i + 1]; 
            let prev = (i == 0) ? 0 : flowerbed[i - 1];
            if(next == 0 && prev == 0) {
                flowerbed[i] = 1;
                count++;
            }
        }
    }
    return n == count;
};
//Runtime: 84 ms, faster than 100.00% of JavaScript online submissions for Can Place Flowers.

628. 三个数的最大乘积

题目
唯一需要注意的是存在负数。所以结果应为“最大三个数的乘积”与“最大数与最小两个数的乘积”中较大的那个。

/**
 * @param {number[]} nums
 * @return {number}
 * 最省心,但需要排序的方法。因为使用了sort,所以时间开销为O(nlogn)。
 */
var maximumProduct = function(nums) {
    let len = nums.length;
    nums = nums.sort(function(a, b){ return a-b; });
    return Math.max(nums[0] * nums[1] * nums[len-1], nums[len-1] * nums[len-2] * nums[len-3]);
};
//Runtime: 132 ms, faster than 23.59% of JavaScript online submissions for Maximum Product of Three Numbers.
//Memory Usage: 38.2 MB, less than 100.00% of JavaScript online submissions for Maximum Product of Three Numbers.
/**
 * @param {number[]} nums
 * @return {number}
 * 记录极值的方法。时间开销为O(n)。
 */
var maximumProduct = function(nums) {
    let max1 = max2 = max3 = Number.NEGATIVE_INFINITY;
    let min1 = min2 = Number.POSITIVE_INFINITY;
    for (var i = 0; i < nums.length; i++) {
        var n = nums[i];
        if(n >= max1) {
            max3 = max2;
            max2 = max1;
            max1 = n;
        } else if (n >= max2) {
            max3 = max2;
            max2 = n;
        } else if (n >= max3) {
            max3 = n;
        }
        if(n <= min1) {
            min2 = min1;
            min1 = n;
        } else if (n <= min2) {
            min2 = n;
        }
    };
    const product1 = max1 * max2 * max3;
    const product2 = max1 * min2 * min1;
    return product1 > product2 ? product1 : product2;
};
//Runtime: 84 ms, faster than 80.51% of JavaScript online submissions for Maximum Product of Three Numbers.
//Memory Usage: 37.5 MB, less than 100.00% of JavaScript online submissions for Maximum Product of Three Numbers.

643. 子数组最大平均数 I

题目

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var findMaxAverage = function(nums, k) {
    let sum = 0;
    for(let i=0; i<k; i++){
        sum += nums[i];
    }
    let max = sum;
    for(let i=k,len=nums.length; i<len; i++){
        sum += nums[i] - nums[i-k];
        max = Math.max(max, sum);
    }
    return max/k;
};
//Runtime: 112 ms, faster than 62.86% of JavaScript online submissions for Maximum Average Subarray I.
//Memory Usage: 42.6 MB, less than 100.00% of JavaScript online submissions for Maximum Average Subarray I.

661. 图片平滑器

题目

/**
 * @param {number[][]} M
 * @return {number[][]}
 */
var imageSmoother = function(M) {
    let res = [];
    let rows = M.length;
    let cols = M[0].length;
    for(let i = 0; i< rows; i++){
        res[i] = new Array(cols)
    }
    for(let i = 0; i<rows; i++){
        for(let j = 0; j<cols; j++){
            //循环内部
            let sum = 0;
            let count = 0;
            for(let x = Math.max(0, i-1); x <= Math.min(rows-1, i+1); x++){
                for(let y = Math.max(0, j-1); y <= Math.min(cols-1, j+1); y++){
                    sum += M[x][y];
                    count++;
                }
            }
            res[i][j] = Math.floor(sum/count);
        }
    }
    return res;
};
//Runtime: 168 ms, faster than 55.22% of JavaScript online submissions for Image Smoother.
//Memory Usage: 42.4 MB, less than 100.00% of JavaScript online submissions for Image Smoother.

20.有效的括号

LeetCode的刷题之路(javascript版本,持续更新)_第9张图片

155.最小栈

// An highlighted block
/**
 * initialize your data structure here.
 */
var MinStack = function() {
    this.valueStack = [];
    this.minStack = [];
};

/** 
 * @param {number} x
 * @return {void}
 */
MinStack.prototype.push = function(x) {
    this.valueStack.push(x);
    if(this.minStack.length === 0 || x < this.getMin()){
        this.minStack.push({
            val:x,
            start:this.valueStack.length
        })
    }
};

/**
 * @return {void}
 */
MinStack.prototype.pop = function() {
    if(this.top() === this.getMin() && this.minStack.length > 0 && this.minStack[this.minStack.length-1].start === this.valueStack.length){
        this.minStack.pop();
    }
    this.valueStack.pop();
};

/**
 * @return {number}
 */
MinStack.prototype.top = function() {
    return this.valueStack[this.valueStack.length-1];
};

/**
 * @return {number}
 */
MinStack.prototype.getMin = function() {
    if(this.minStack.length === 0){
        return this.valueStack[0];
    }
    return this.minStack[this.minStack.length-1].val;
};

225.用队列实现栈

/**
 * Initialize your data structure here.
 */
var MyStack = function() {
    this.valueStack = [];
};

/**
 * Push element x onto stack. 
 * @param {number} x
 * @return {void}
 */
MyStack.prototype.push = function(x) {
    this.valueStack.push(x);
};

/**
 * Removes the element on top of the stack and returns that element.
 * @return {number}
 */
MyStack.prototype.pop = function() {
    return this.valueStack.pop();
};

/**
 * Get the top element.
 * @return {number}
 */
MyStack.prototype.top = function() {
    return this.valueStack[this.valueStack.length-1];
};

/**
 * Returns whether the stack is empty.
 * @return {boolean}
 */
MyStack.prototype.empty = function() {
    return this.valueStack.length === 0;
};

682.棒球比赛

/**
 * @param {string[]} ops
 * @return {number}
 */
var calPoints = function(ops) {
    var nums = [];
    for(var op of ops){
        switch(op){
            case '+':
                nums.push(Number(nums[nums.length - 1]) + Number(nums[nums.length - 2]));
                break;
            case 'D':
                nums.push(nums[nums.length-1] * 2);
                break;
            case 'C':
                nums.pop();
                break;
            default:
                nums.push(op);
        }
    }
    var sum = 0;
    for (var num of nums) {
        sum += parseInt(num);
    }
    return sum;
};

844. 比较含退格的字符串

/**
 * @param {string} S
 * @param {string} T
 * @return {boolean}
 */
var backspaceCompare = function(S, T) {
    this.sStack = [];
    this.tStack = [];
    for(var i = 0; i< S.length; i++){
        if(S[i] === '#' && this.sStack.length >0){
            this.sStack.pop();
        }else{
            if(S[i] !== '#'){
               this.sStack.push(S[i]);
            }
        }
    }
    for(var i = 0; i< T.length; i++){
        if(T[i] === '#' && this.tStack.length >0){
            this.tStack.pop();
        }else{
            if(T[i] !== '#'){
               this.tStack.push(T[i]);
            }
        }
    }
    if(this.sStack.join() == this.tStack.join()){
        return true;
    }
    return false;
};

//其他人的做法
var backspaceCompare = function(S, T) {
    return backspace(S) == backspace(T);
};
function backspace(str) {
  let backspaceStr = '';
  for(let i = 0;i < str.length;i++) {
    backspaceStr = str[i] != "#" ? backspaceStr + str[i] :  backspaceStr.slice(0,-1);
  }
  return backspaceStr;
}

331. 验证二叉树的前序序列化

/**
 * @param {string} preorder
 * @return {boolean}
 */
var isValidSerialization = function(preorder) {
    this.dif = 1;
    this.arr = preorder.split(',');
    for(var i=0;i<this.arr.length; i++){
        if(--this.dif < 0){
             return false;
        }
        if(this.arr[i] !== '#'){
            this.dif +=2;
        }
    }
    return this.dif == 0;
};

946. 验证栈序列

/**
 * @param {number[]} pushed
 * @param {number[]} popped
 * @return {boolean}
 */
var validateStackSequences = function(pushed, popped) {
  let stack = [];
  let popIndex = 0;
  for (let pushItem of pushed) {
    stack.push(pushItem);
    while (stack.length && stack.slice(-1)[0] === popped[popIndex]) {
      stack.pop();
      popIndex ++;
    }
  }
  if (stack.length) {
    return false;
  } else {
    return true;
  }
};

71. 简化路径

/**
 * @param {string} path
 * @return {string}
 */
var simplifyPath = function(path) {
    this.pathStack = path.split('/');
    this.valueStack = [];
    this.shortenPath = '/';
    for(var i=0;i<this.pathStack.length;i++){
        if(this.pathStack[i]){
            if(this.pathStack[i] === '..'){
                this.valueStack.pop();
            }else if(this.pathStack[i] != '.'){
                this.valueStack.push(this.pathStack[i]);
            }
        }
    }
    return this.shortenPath + String(this.valueStack.join('/'));
};

856. 括号的分数

链接 (理解不完全)

/**
 * @param {string} S
 * @return {number}
 */
var scoreOfParentheses = function(S) {
    var scoreStack = [];
    var c = '';
    for(var i=0;i<S.length;i++){
        c = S[i];
        if(c == '('){
            scoreStack.push(-1);
        }else{
            var score = 0;
            while(scoreStack[scoreStack.length-1] != -1){
                score += scoreStack.pop();
            }
            scoreStack.pop();
            if(score === 0){
                scoreStack.push(1);
            }else{
                scoreStack.push(2*score);
            }
        }
    }
    var totalScore = 0;
    for(var i=0;i<scoreStack.length; i++){
       totalScore += scoreStack[i]; 
    }
    return totalScore;
};

402.移掉K位数字

未实现

901. 股票价格跨度

未通过

var StockSpanner = function() {
    this.stackArray = [];
};
/** 
 * @param {number} price
 * @return {number}
 */
StockSpanner.prototype.next = function(price) {
    var res = 1;
    this.stackArray.push(price);
    for(var i=0;i<this.stackArray.length;i++){
        if(this.stackArray[i] < price){ 
            res += 1;
        }
    }
    return res;
};

503. 下一个更大元素 II

/** 暴力破解
 * @param {number[]} nums
 * @return {number[]}
 */
var nextGreaterElements = function(nums) {
    this.stackArray = [];
    for(var i=0,length=nums.length; i<length; ++i){
        this.stackArray.push(-1);
        for(var j = i+1; j<length + i; ++j){
            var num = nums[j%length];
            if(num> nums[i]){
                this.stackArray[i] = num;
                break;
            }
        }
    }
    return this.stackArray;
};

LeetCode的刷题之路(javascript版本,持续更新)_第10张图片
出现延时较长的问题,优化如下:

	

232. 用栈实现队列

链接

/**
 * Initialize your data structure here.
 */
var MyQueue = function() {
    this.inbox = [];
    this.outbox = [];
};

/**
 * Push element x to the back of queue. 
 * @param {number} x
 * @return {void}
 */
MyQueue.prototype.push = function(x) {
    this.inbox.push(x);
};

/**
 * Removes the element from in front of queue and returns that element.
 * @return {number}
 */
MyQueue.prototype.pop = function() {
    while (this.inbox.length) {
        this.outbox.push(this.inbox.pop());
    }
    var first = this.outbox.pop();
    while (this.outbox.length) {
        this.inbox.push(this.outbox.pop());
    }
    return first;
};

/**
 * Get the front element.
 * @return {number}
 */
MyQueue.prototype.peek = function() {
    return this.inbox[0];
};

/**
 * Returns whether the queue is empty.
 * @return {boolean}
 */
MyQueue.prototype.empty = function() {
    return this.inbox.length === 0;
};

/** 
 * Your MyQueue object will be instantiated and called as such:
 * var obj = Object.create(MyQueue).createNew()
 * obj.push(x)
 * var param_2 = obj.pop()
 * var param_3 = obj.peek()
 * var param_4 = obj.empty()
 */

哈希表

242. 有效的字母异位词

题目

//快排,按顺序排序字符,比较两个排序后的字符串是否一致。NlogN
/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
var isAnagram = function(s, t) {
    s = s.split('').sort().join('');
    t = t.split('').sort().join('');
    return s == t;
};
//Runtime: 132 ms, faster than 13.11% of JavaScript online submissions for Valid Anagram.
//比较每个字母出现的个数Map
/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
var isAnagram = function(s, t) {
    if(s.length == t.length){
        let dic1 = {},dic2={};
        for (let i in s) {
            dic1[s[i]] = (dic1[s[i]]||0) + 1;
            dic2[t[i]] = (dic2[t[i]]||0) + 1;
        }
        for(let i=0,len=s.length;i<len;i++){
            if(dic1[s[i]] != dic2[s[i]]) {
                return false;  
            }
        }
        return true;
    }
    return false;
};
//Runtime: 104 ms, faster than 37.50% of JavaScript online submissions for Valid Anagram.

100. 相同的树

题目

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {boolean}
 */
var isSameTree = function(p, q) {
    if(p===null) return q===null;
    if(q===null) return p===null;
    if(p.val!==q.val) return false;
    return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
};
//Runtime: 68 ms, faster than 100.00% of JavaScript online submissions for Same Tree.

101. 对称二叉树

题目

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isSymmetric = function(root) {
    if (!root) return true;
    function isMirror(s, t) {
        if (!s && !t) return true;
        if (!s || !t || s.val !== t.val) return false;
        return isMirror(s.left, t.right) && isMirror(s.right, t.left);
    }
    return isMirror(root.left, root.right);
};
//Runtime: 80 ms, faster than 86.71% of JavaScript online submissions for Symmetric Tree.

04. 二叉树的最大深度

题目

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var maxDepth = function(root) {
    if(root == null || root == undefined){
        return 0;
    }else{
        return Math.max(maxDepth(root.left),maxDepth(root.right)) + 1;
    }
};
//Runtime: 80 ms, faster than 96.88% of JavaScript online submissions for Maximum Depth of Binary Tree.

107. 二叉树的层次遍历 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) {
    let level = [];
    function roll(node, deep){
        if(!node) return ;
        if(!level[deep]) level[deep] = [];
        level[deep].push(node.val);
        roll(node.left, deep+1);
        roll(node.right, deep+1);
    }
    roll(root, 0);
    return level.reverse();
};
//Runtime: 76 ms, faster than 73.68% of JavaScript online submissions for Binary Tree Level Order Traversal II.

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

题目

/**
 * 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;   
    var mid = Math.floor((nums.length)/2);
    var root = new TreeNode(nums[mid]);
    root.left = sortedArrayToBST(nums.slice(0, mid));
    root.right = sortedArrayToBST(nums.slice(mid+1));
    return root; 
};
//Runtime: 88 ms, faster than 76.67% of JavaScript online submissions for Convert Sorted Array to Binary Search Tree.

110. 平衡二叉树

题目

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isBalanced = function(root) {
    let flag = true;
    const tree = (node) => {
        if(!flag) return;
        if(node){
            const left = tree(node.left);
            const right = tree(node.right);
            if(Math.abs(left - right) > 1){
                flag = false;
                return;
            }
            return Math.max(left, right) + 1;
        }
        return 0;
    }
    tree(root);
    return flag;
};
//Runtime: 88 ms, faster than 98.28% of JavaScript online submissions for Balanced Binary Tree.

111. 最小二叉树

题目

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var minDepth = function(root) {
    if(!root) return 0;
    let result;
    function minHeight(root, depth){
        if(!root.left && !root.right){
            result = Math.min(result || depth, depth);
            return ;
        }
        if(root.left) minHeight(root.left, depth + 1);
        if(root.right) minHeight(root.right, depth + 1);
    }
    minHeight(root, 1);
    return result;
};
//Runtime: 80 ms, faster than 100.00% of JavaScript online submissions for Minimum Depth of Binary Tree.

二分查找

69. x 的平方根

题目

/**
 * @param {number} x
 * @return {number}
 */
var mySqrt = function(x) {
    if(x == 0 || x == 1) return x;
    let left = 1;
    let right = Math.floor(x / 2) + 1;
    let mid;
    while(left <= right){
        mid = Math.floor((right + left) / 2);
        if(mid * mid == x){
            return mid;
        }else if(mid * mid > x){
            right = mid - 1;
        }else{
            left = mid + 1;
        }
    }
    return right;
};
//Runtime: 96 ms, faster than 80.92% of JavaScript online submissions for Sqrt(x).
//Memory Usage: 16.7 MB, less than 51.43% of JavaScript online submissions for Sqrt(x).

//牛顿迭代法
var mySqrt = function(x) {
    r = x;
    while (r*r > x)
        r = ((r + x/r) / 2) | 0;
    return r;
};
//Runtime: 92 ms, faster than 100.00% of JavaScript online submissions for Sqrt(x).
//Memory Usage: 16.9 MB, less than 30.00% of JavaScript online submissions for Sqrt(x).

trie树

208. 实现 Trie (前缀树)

题目

/**
 * Initialize your data structure here.
 */
var Trie = function() {
    this.root = new TriNode();
};
var TriNode = function () {
    this.next = new Array(26);
    this.word = null;
};
/**
 * Inserts a word into the trie. 
 * @param {string} word
 * @return {void}
 */
Trie.prototype.insert = function(word) {
    let curr = this.root;
    for (let i = 0; i < word.length; i++) {
        if (!curr.next[word[i].charCodeAt(0) - 97]) {
            curr.next[word[i].charCodeAt(0) - 97] = new TriNode();
        }
        curr = curr.next[word[i].charCodeAt(0) - 97];
    }
    curr.word = word;
};

/**
 * Returns if the word is in the trie. 
 * @param {string} word
 * @return {boolean}
 */
Trie.prototype.search = function(word) {
    let curr = this.root;
    for (let i = 0; i < word.length; i++) {
        if (!curr.next[word[i].charCodeAt(0) - 97]) return false;
        curr = curr.next[word[i].charCodeAt(0) - 97];
    }
    if (curr.word === word) return true;
    return false;
};

/**
 * Returns if there is any word in the trie that starts with the given prefix. 
 * @param {string} prefix
 * @return {boolean}
 */
Trie.prototype.startsWith = function(prefix) {
    let curr = this.root;
    for (let i = 0; i < prefix.length; i++) {
        if (!curr.next[prefix[i].charCodeAt(0) - 97]) return false;
        curr = curr.next[prefix[i].charCodeAt(0) - 97];
    }
    return true;
};

/** 
 * Your Trie object will be instantiated and called as such:
 * var obj = Object.create(Trie).createNew()
 * obj.insert(word)
 * var param_2 = obj.search(word)
 * var param_3 = obj.startsWith(prefix)
 */
 
//Runtime: 244 ms, faster than 52.73% of JavaScript online submissions for Implement Trie (Prefix Tree).
//Memory Usage: 61.2 MB, less than 20.00% of JavaScript online submissions for Implement Trie (Prefix Tree).

位运算

191. 位1的个数

题目

方法1: 不断对2求余
解题思路:
不断对2求余, 然后统计个数
代码:
/**
 * @param {number} n - a positive integer
 * @return {number}
 */
var hammingWeight = function(n) {
 let count = 0;
  while (n > 0) {
    if (n % 2) count++;
    n = parseInt(n / 2, 10);
  }
  return count;
};
//Runtime: 84 ms, faster than 88.89% of JavaScript online submissions for Number of 1 Bits.
//Memory Usage: 16 MB, less than 15.63% of JavaScript online submissions for Number of 1 Bits.
方法2: 使用&运算
解题思路:
将n的最后一个1消除的公式: n & (n - 1).
代码:
var hammingWeight = function(n) {
  let count = 0;
  while (n !== 0) {
    n = n & (n - 1);
    count++;
  }
  return count;
};
//Runtime: 84 ms, faster than 88.89% of JavaScript online submissions for Number of 1 Bits.
//Memory Usage: 15.3 MB, less than 84.38% of JavaScript online submissions for Number of 1 Bits.

动态规划

70. 爬楼梯

题目

/**
 * @param {number} n
 * @return {number}
 */
var climbStairs = function(n) {
    if (n <= 3) return n;
    return climbStairs(n-1) + climbStairs(n-2);
};
//Runtime: 12740 ms, faster than 0.86% of JavaScript online submissions for Climbing Stairs.
//Memory Usage: 15 MB, less than 0.88% of JavaScript online submissions for Climbing Stairs.
var climbStairs = function(n) {
    if (n <= 3) return n;
    let arr = [1,2,3];
    for (let i = 3; i < n; i++) {
        arr.push(arr[i-1] + arr[i-2]);
    }
    return arr.pop();
};
//Runtime: 72 ms, faster than 14.18% of JavaScript online submissions for Climbing Stairs.
//Memory Usage: 14.5 MB, less than 35.54% of JavaScript online submissions for Climbing Stairs.

脑筋急转弯

292. Nim游戏

题目
你和你的朋友,两个人一起玩 Nim游戏:桌子上有一堆石头,每次你们轮流拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。你作为先手。

你们是聪明人,每一步都是最优解。 编写一个函数,来判断你是否可以在给定石头数量的情况下赢得游戏。

//解决方案:如果堆中石头的数量 n 不能被 44 整除,那么你总是可以赢得 Nim 游戏的胜利。让我们考虑一些小例子。显而易见的是,如果石头堆中只有一块、两块、或是三块石头,那么在你的回合,你就可以把全部石子拿走,从而在游戏中取胜。而如果就像题目描述那样,堆中恰好有四块石头,你就会失败。因为在这种情况下不管你取走多少石头,总会为你的对手留下几块,使得他可以在游戏中打败你。因此,要想获胜,在你的回合中,必须避免石头堆中的石子数为 4 的情况。同样地,如果有五块、六块、或是七块石头,你可以控制自己拿取的石头数,总是恰好给你的对手留下四块石头,使他输掉这场比赛。但是如果石头堆里有八块石头,你就不可避免地会输掉,因为不管你从一堆石头中挑出一块、两块还是三块,你的对手都可以选择三块、两块或一块,以确保在再一次轮到你的时候,你会面对四块石头。
/**
 * @param {number} n
 * @return {boolean}
 */
var canWinNim = function(n) {
    return n % 4 !== 0;
};
//Runtime: 68 ms, faster than 35.22% of JavaScript online submissions for Nim Game.
//Memory Usage: 33.7 MB, less than 100.00% of JavaScript online submissions for Nim Game.

319. 灯泡开关

题目
首先观察题目给的例子,结合题意,很自然就能想到,一个开关i被拨动的次数就是i的约数的个数,比如第8个开关,它被拨动了4次,分别在轮数=1,2,4,8轮数=1,2,4,8时,而1,2,4,8就是8的约数。
所以题目就变成了求1-n中每个数ii的约数个数,统计约数个数是奇数的数目,因为如果约数个数是奇数,则开关是开的。
那么下一步就是求i(i≤n)i(i≤n)的约数个数,想到这里,要发现一点,约数是成对存在的,即2是8的约数,那么8÷2=48÷2=4也是8的约数,其中有一种特殊情况,就是i为完全平方数,比如9跟它的约数3,因此,
如果i是完全平方数,那么i的约数个数肯定是奇数,如果i不是完全平方数,由于约数成对出现,所以约数个数肯定是偶数。

/**
 * @param {number} n
 * @return {number}
 */
var bulbSwitch = function(n) {
    return Math.floor(Math.sqrt(n));
};
//Runtime: 68 ms, faster than 23.26% of JavaScript online submissions for Bulb Switcher.
//Memory Usage: 33.9 MB, less than 100.00% of JavaScript online submissions for Bulb Switcher.
var bulbSwitch = function(n) {
    let lo = 0;
    let hi = n;
    while(lo <= hi) {
         let mid = Math.floor((lo + hi) / 2);
         if (mid * mid > n) {
          hi = mid - 1;   
         }
         else {
           lo = mid + 1;  
         } 
    }
    return Math.floor(hi);
};

你可能感兴趣的:(数据结构)