阅读 223
Villay的Leetcode刷题记录

Villay的Leetcode刷题记录

单词长度得最大乘积

给定一个字符串数组 words,请计算当两个字符串 words[i] 和 words[j] 不包含相同字符时, 它们长度的乘积的最大值。假设字符串中只包含英语的小写字母。如果没有不包含相同字符的一对字符串,返回 0。

  1. 输入: words = ["abcw","baz","foo","bar","fxyz","abcdef"]

    输出: 16

    解释: 这两个单词为 "abcw", "fxyz"。它们不包含相同字符,且长度的乘积最大。

  2. 输入: words = ["a","ab","abc","d","cd","bcd","abcd"]

    输出: 4

    解释: 这两个单词为 "ab", "cd"。

  3. 输入: words = ["a","aa","aaa","aaaa"]

    输出: 0

    解释: 不存在这样的两个单词。

var maxProduct = function (words) {
    let len = words.length;
    let max = 0;
    let bits = new Array(len).fill(0);

    //构建每一个单词得二进制值
    for(let i = 0;i < len ;i ++) {
        let word = words[i];
        for(let j = 0;j < word.length;j++) {
           bits[i] |= 1 << (word[j].charCodeAt() - 97);
           // 将存在字母置于二进制得位值为1
        }
    }

    for(let i = 0;i < len ; i++) {
        for(let j = 0;j < i ; j++) {
            if((bits[i] & bits[j]) === 0) {
                // &运算如果没有相同得字母则计算最大长度
                max = Math.max(max,words[i].length * words[j].length)
            }
        }
    }
   return max;
}
复制代码

二叉树得最大深度

给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 说明: 叶子节点是指没有子节点的节点。

  1. 给定二叉树 [3,9,20,null,null,15,7] 返回它的最大深度 3 。
const maxDepth = (root) => {
  if(root == null) return 0
  const queue = [root]
  let depth = 1;
  while(queue.length) {
      //当前层的节点个数
      const levelSize = queue.length
      //逐个让当前层的节点出列
      for(let i = 0;i<levelSize;i++) {
          //当前出列的节点
          const cur = queue.shift()
          //左右子节点入列
          if(cur.left) queue.push(cur.left)
          if(cur.right) queue.push(cur.right)  
      }
      //当前层所有节点已经出列,如果队列不为空,说明有下一层节点,depth + 1
      if(queue.length) depth++
  }
  return depth
}
复制代码

二进制加法

给定两个 01 字符串 a 和 b,请计算它们的和,并以二进制字符串的形式输出。输入为 非空 字符串且只包含数字 1 和 0。

  1. 输入: a = "11", b = "10"
    输出: "101"
  2. 输入: a = "1010", b = "1011" 输出: "10101"

每个字符串仅由字符 '0' 或 '1' 组成。 1 <= a.length, b.length <= 10^4 字符串如果不是 "0" ,就都不含前导零。

var addBinary = function (a,b) {
    return (BigInt('0b' + a) + BigInt('0b' + b)).toString(2)
}
复制代码

回文数

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。

  • 输入:x = 121 输出:true
  • 输入:x = -121 输出:false
  • 解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
  • 输入:x = 10 输出:false
  • 解释:从右向左读, 为 01 。因此它不是一个回文数。
  • 输入:x = -101
  • 输出:false
/**
 * 
 * @param {*} x 
 * @returns 
 */ 
var isPalindrome = function(x) {
    return x === Number(x.toString().split('').reverse().join(''))
}
复制代码

两数相加

给定一个整数数组 nums 和一个整数目标值target, 请你在该数组中找出和为目标值target的那两个整数并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺序返回答案。

  • 输入:nums = [2,7,11,15], target = 9

  • 输出:[0,1]

  • 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

  • 输入:nums = [3,2,4], target = 6

  • 输出:[1,2]

  • 输入:nums = [3,3], target = 6

  • 输出:[0,1]

/**
 * 
 * @param {*} nums 
 * @param {*} target 
 * @returns 
 */
var twoSum = function (nums,target) {
    let len = nums.length;
    // 创建MAP
    const MAP = new Map();
    // 由于第一个元素在它之前一定没有元素与之匹配,所以先存入哈希表
    MAP.set(nums[0],0)
    for(let i = 1;i<len;i++) {
    //提取共用
    let other = target - nums[i]
    //判断是否符合条件,返回对应的下标
    if(MAP.get(other) !== undefined) return [MAP.get(other),i]
    //不符合的存入hash表
    MAP.set(nums[i],i)
    }
}

复制代码

拿硬币

桌上有 n 堆力扣币,每堆的数量保存在数组 coins 中。我们每次可以选择任意一堆, 拿走其中的一枚或者两枚,求拿完所有力扣币的最少次数。

  • 输入:[4,2,1]

  • 输出:4

  • 解释:第一堆力扣币最少需要拿 2 次,第二堆最少需要拿 1 次,第三堆最少需要拿 1 次,总共 4 次即可拿完。

  • 输入:[2,3,10]

  • 输出:8

限制:1 <= n <= 4 1 <= coins[i] <= 10

var minCount = function(coins) {
    let sum = 0;
    for(let i = 0;i < coins.length ;i ++) {
        if(coins[i] % 2 !== 0 ) {
            sum = sum + ((coins[i] + 1) / 2 )
        } else if (coins[i] % 2 == 0) {
            sum = sum + ((coins[i] / 2 ))
        }

    }
}

var minCount = function(coins) {
    coins[0] = Math.ceil(coins[0] / 2)
    return coins.reduce((p, c) => p + Math.ceil(c / 2))
};


var minCount = function (arr) {
    var num = 0;
    arr.forEach(element => {
      num += Math.ceil(element / 2)
    });
    return num;
  };
复制代码

排序数组中2个数组之和

给定一个已按照 升序排列  的整数数组 numbers , 请你从数组中找出两个数满足相加之和等于目标数 target 。 函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。 numbers 的下标 从 0 开始计数 , 所以答案数组应当满足 0 <= answer[0] < answer[1] < numbers.length 。 假设数组中存在且只存在一对符合条件的数字,同时一个数字不能使用两次。

  • 输入:numbers = [1,2,4,6,10], target = 8

  • 输出:[1,3]

  • 解释:2 与 6 之和等于目标数 8 。因此 index1 = 1, index2 = 3 。

  • 输入:numbers = [2,3,4], target = 6

  • 输出:[0,2]

  • 输入:numbers = [-1,0], target = -1

  • 输出:[0,1]

var twoSum = function (numbers,target) {
    let left = 0, right = numbers.length - 1;
    while (left < right ) {
        const sum = numbers[left] + numbers[right]
        if(sum == target) {
            return [left,right]
        } else if(sum < target) {
            left ++
        } else {
            right --
        }
    }
    return []
}
console.log(twoSum([1,2,4,6,10],11))
复制代码

前n个数字二进制中1的个数

给定一个非负整数 n ,请计算 0 到 n 之间的每个数字的二进制表示中 1 的个数,并输出一个数组。

  • 输入: n = 2

  • 输出: [0,1,1]

  • 解释:

  • 0 --> 0

  • 1 --> 1

  • 2 --> 10

  • 输入: n = 5

  • 输出: [0,1,1,2,1,2]

  • 解释:

  • 0 --> 0

  • 1 --> 1

  • 2 --> 10

  • 3 --> 11

  • 4 --> 100

  • 5 --> 101

var countBits = function (n) {
    let res = [] //用来存放每个数的1的个数
    for(let i = 0;i <= n;i++ ) {
        // 按循环一个一个来比对
        let num = i 
        let L = 0 //此变量用来计数1的个数
        while(num) {
            num = num & (num - 1) 
            L ++
        }
        res.push(L)
    }
    return res
}
console.log(countBits(6))
复制代码

硬币找零

题目描述:给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。 如果没有任何一种硬币组合能组成总金额,返回 -1

  • 示例1:

  • 输入: coins = [1, 2, 5], amount = 11

  • 输出: 3

  • 解释: 11 = 5 + 5 + 1

  • 示例2:

  • 输入: coins = [2], amount = 3

  • 输出: -1

const coinChange = function(coins,amout) {
    // 用于保存每个目标总额对应的最小硬币个数
    const f = [];
    // 提前定义已知情况
    f[0] = 0;
    // 遍历[1,amout]再这个区间的硬币总额
    for(let i = 1; i <= amout; i++) {
        // 求得是最小值,因此我们预设为无穷大,确保它一定会被更小得数更新
        f[i] = Infinity;
        // 循环遍历每个可用硬币得面额
        for(let j = 0;j < coins.length;j ++) {
            // 若硬币面额小于目标总额,则问题成立
            if(i - coins[j] >= 0) {
                // 状态转移方程
                f[i] = Math.min(f[i],f[i-coins[j]] + 1);
            }
        }
    }
    // 若目标总额对应得解为无穷大,则意味着没有一个符合条件得硬币总数来更新它,本题无解,返回-1
    if(f[amout] === Infinity) {
        return -1;
    }
    // 若有解,直接返回解得内容
    return f[amout];
}
console.log(coinChange([1,2,5],22))
复制代码

有效的回文

给定一个字符串 s ,验证 s 是否是 回文串 ,只考虑字母和数字字符,可以忽略字母的大小写。 本题中,将空字符串定义为有效的 回文串 。

  • 输入: s = "A man, a plan, a canal: Panama"

  • 输出: true

  • 解释:"amanaplanacanalpanama" 是回文串

  • 输入: s = "race a car"

  • 输出: false

  • 解释:"raceacar" 不是回文串

var isPalindrome = function(s) {
    s = s.toLowerCase()
    let arr = ''
    for(var key of s) {
        if(/[A-Za-z0-9]/.test(key)) {
            arr += key
        }
    }
    let left = 0
    let right = arr.length - 1
    while(left < right) {
        if(arr[left] !== arr[right]) {
            return false
        }
        left ++
        right --
    }
    return true
}
复制代码
文章分类
前端
文章标签