LeetCode今日刷题2021/06/03

49. 字母异位词分组

给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

示例:

输入: ["eat", "tea", "tan", "ate", "nat", "bat"]
输出:
[
  ["ate","eat","tea"],
  ["nat","tan"],
  ["bat"]
]

说明:

- 所有输入均为小写字母。
- 不考虑答案输出的顺序。
/**
 * @param {string[]} strs
 * @return {string[][]}
 */
var groupAnagrams = function(strs) {
  // 字符长度为0直接返回
  if(strs.length === 0)
    return [];
  // 用map记录每个code所对应的字符串数组,code表示每个字符串每个字母的编码值,是一个长度为26位的数组,每一位表示该字母出现的次数
  const map = new Map();
  // 遍历输入的字符串数组
  for(const str of strs) {
    // 初始化code数组为全0
    const characters = Array(26).fill(0);
    // 遍历每一个字符串的所有字母
    for(let i = 0; i < str.length; i++) {
      // 找到该字母对应的位置,将ascii值转换为从0-25的一个数,97为a的ASCII值
      const ascii = str.charCodeAt(i) - 97;
      // 该字母出现次数加一
      characters[ascii]++;
    }
    // 将code数组转为字符串,作为map的键
    const key = characters.join(".");
    // 如果map有对应的code,将字符串加入此code对应的数组中
    if(map.has(key)) {
      map.set(key, [...map.get(key), str]);
    }else{
      // 否则该字符组合未出现过,作为一个新的键值对加入map中
      map.set(key, [str]);
    }
  }
  const result = [];
  // 采用for of遍历map,迭代器每次为一个数组arr, 其中arr[0]为key, arr[1]为value
  for(const arr of map) {
    result.push(arr[1])
  }
  return result;
};

53. 最大子序和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例 2:

输入:nums = [1]
输出:1

示例 3:

输入:nums = [0]
输出:0

示例 4:

输入:nums = [-1]
输出:-1

示例 5:

输入:nums = [-100000]
输出:-100000

提示:

- 1 <= nums.length <= 3 * 104
- -105 <= nums[i] <= 105
/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function (nums) {
  // 记录每一个位置对应的最大子序和
  const memo = [];
  // 初始时只有一个元素
  memo[0] = nums[0];
  // max记录所有最大子序和的最大值,作为整个数组的最大子序和
  let max = nums[0];
  // 循环遍历数组的每一个元素
  for (let i = 1; i < nums.length; i++) {
    // 动态规划,计算当前的最大子序和: Max(从第一个元素到当前数字的序列和, 从当前数字起的序列和)
    memo[i] = Math.max(nums[i] + memo[i - 1], nums[i]);
    // 更新max
    max = Math.max(max, memo[i]);
  }
  return max;
};

54. 螺旋矩阵

给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
示例 1:

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

示例 2:

输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
/**
 * @param {number[][]} matrix
 * @return {number[]}
 */
var spiralOrder = function (matrix) {
  // 矩阵为空则返回空数组
  if (matrix.length === 0) {
    return [];
  }
  // 定义上下左右边界值
  let top = 0;
  let bottom = matrix.length - 1;
  let left = 0;
  let right = matrix[0].length - 1;
  // 定义当前方向,方向的变化顺序为right->down->left->up->right->...
  let direction = "right";
  let result = [];
  // 循环遍历矩阵,当右边界大于等于左边界,下边界大于等于上边界时执行循环
  while (left <= right && top <= bottom) {
    if (direction === "right") {
      for (let i = left; i <= right; i++) {
        result.push(matrix[top][i]);
      }
      top++;
      direction = "down";
    } else if (direction === "down") {
      for (let i = top; i <= bottom; i++) {
        result.push(matrix[i][right]);
      }
      right--;
      direction = "left";
    } else if (direction === "left") {
      for (let i = right; i >= left; i--) {
        result.push(matrix[bottom][i]);
      }
      bottom--;
      direction = "top";
    } else if (direction === "top") {
      for (let i = bottom; i >= top; i--) {
        result.push(matrix[i][left]);
      }
      left++;
      direction = "right";
    }
  }
  return result;
};

55. 跳跃游戏

给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标。

示例 1:

输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。

示例 2:

输入:nums = [3,2,1,0,4]
输出:false
解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。
/**
 * @param {number[]} nums
 * @return {boolean}
 */
var canJump = function(nums) {
  // 记录到达当前位置最少需要的步数
  let maxJump = nums.length - 1;
  // 贪心法,自底向上。从后往前遍历数组
  for(let i = nums.length - 2; i >=0; i--) { 
    // 如果当前位置(maxJump)的前一个元素能跳到当前位置,则更新maxJump
    if(i + nums[i] >= maxJump) {
      maxJump = i;
    }
  }
  // 如果能遍历完数组,则说明问题有解
  return maxJump === 0;
};

56. 合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。

示例 1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

示例 2:

输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。

提示:

1 <= intervals.length <= 104
intervals[i].length == 2
0 <= starti <= endi <= 104
/**
 * @param {number[][]} intervals
 * @return {number[][]}
 */
var merge = function(intervals) {
  // 数组为空或长度为一时直接返回
  if(intervals.length < 2) {
    return intervals;
  }
  // 将元素按照区间左端点排序
  intervals.sort((a, b) => a[0] - b[0]);
  // 用于记录当前合并的最大的数组
  let curr = intervals[0];
  let result = [];
  // 循环遍历区间数组
  for(let interval of intervals) {
    // 如果后一个区间的左端点小于等于当前区间的右端点,则合并这两个区间
    if(curr[1] >= interval[0]) {
      curr[1] = Math.max(curr[1], interval[1]);
    } else {
      // 否则将当前最大的区间加入结果集中,并更新位置
      result.push(curr);
      curr = interval;
    }
  }
  // 注意最后一个区间不存在下一个区间来比较,直接加入结果集
  result.push(curr);
  return result;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值