前端JavaScript力扣HOT100刷题【1-50】

注:纯手打,如有错误欢迎评论区交流!
转载请注明出处:https://blog.youkuaiyun.com/testleaf/article/details/147258015
编写此文是为了更好地学习前端知识,如果损害了有关人的利益,请联系删除!
本文章将不定时更新,敬请期待!!!
欢迎点赞、收藏、转发、关注,多谢!!!
前端JavaScript力扣HOT100刷题【51-100】:
https://blog.youkuaiyun.com/testleaf/article/details/148953015

目录

一、哈希

1、【简单】两数之和

题目描述:
给定一个整数数组 nums 和一个整数目标值 target
请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。
你可以按任意顺序返回答案。

示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
   
   
    const changeMap = {
   
   };
    for (let i = 0; i < nums.length; i++) {
   
   
        const curNum = nums[i];
        const comNum = target - curNum;
        if (comNum in changeMap) {
   
   
            return [changeMap[comNum], i];
        } else {
   
   
            changeMap[curNum] = i;
        }
    }
};

2、【中等】字母异位词分组

题目描述:
给你一个字符串数组,请你将 字母异位词 组合在一起。
可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

示例 1:
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
示例 2:
输入: strs = [""]
输出: [[""]]
示例 3:
输入: strs = ["a"]
输出: [["a"]]

方法一:排序【推荐】

/**
 * @param {string[]} strs
 * @return {string[][]}
 */
var groupAnagrams = function(strs) {
   
   
  const changeMap = new Map();
  for (let i = 0; i < strs.length; i++) {
   
   
    const sortStrs = strs[i].split("").sort().join("");
    if (!changeMap.has(sortStrs)) {
   
   
      changeMap.set(sortStrs, [strs[i]]);
    } else {
   
   
      changeMap.get(sortStrs).push(strs[i]);
    }
  }
  return Array.from(changeMap.values());
};

方法二:计数

/**
 * @param {string[]} strs
 * @return {string[][]}
 */
var groupAnagrams = function(strs) {
   
   
  const changeMap = new Map();
  for (let s of strs) {
   
   
      const count = new Array(26).fill(0);
      for (let c of s) {
   
   
          count[c.charCodeAt() - 'a'.charCodeAt()]++;
      }
      changeMap[count] ? changeMap[count].push(s) : changeMap[count] = [s];
  }
  return Object.values(changeMap);
};

3、【中等】最长连续序列

题目描述:
给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4
示例 2:
输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9
示例 3:
输入:nums = [1,0,1,2]
输出:3

/**
 * @param {number[]} nums
 * @return {number}
 */
var longestConsecutive = function(nums) {
   
   
  const betterSet = new Set(nums);
  let longCon = 0;
  betterSet.forEach(num=>{
   
   
    if(!betterSet.has(num-1)){
   
   
      let curNum = num;
      let curCon = 1;
      while(betterSet.has(curNum+1)){
   
   
        curNum+=1;
        curCon+=1;
      }
      longCon = longCon>curCon?longCon:curCon;
    }
  })
  return longCon;
};

二、双指针

4、【简单】移动零

题目描述:
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
示例 2:
输入: nums = [0]
输出: [0]

方法一:把 nums 当作栈【推荐】

/**
 * @param {number[]} nums
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var moveZeroes = function(nums) {
   
   
  let stackSize = 0;
  nums.forEach(x=>{
   
   
    if (x !== 0) {
   
   
      nums[stackSize++] = x;
  }
  })
  nums.fill(0, stackSize);
};

方法二:双指针

/**
 * @param {number[]} nums
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var moveZeroes = function(nums) {
   
   
  let j = 0;
  for (let i = 0; i < nums.length; i++) {
   
   
      if (nums[i] !== 0) {
   
   
          [nums[i], nums[j]] = [nums[j], nums[i]];
          j++;
      }
  }
};

5、【中等】盛最多水的容器

题目描述:
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0)(i, height[i])
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。

示例 1:

输入:height = [1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49
示例 2:
输入:height = [1,1]
输出:1

/**
 * @param {number[]} height
 * @return {number}
 */
var maxArea = function(height) {
   
   
    let i=0,j=height.length-1;
    let maxRes=0;
    while(i<j){
   
   
      maxRes=Math.max(maxRes,(j-i)*Math.min(height[i],height[j]));
      if(height[i]<height[j]){
   
   
          i++;
      }else{
   
   
          j--;
      }
    }
    return maxRes;
};

6、【中等】三数之和

题目描述:
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != k
同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0
不同的三元组是 [-1,0,1][-1,-1,2]
注意,输出的顺序和三元组的顺序并不重要。
示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0
示例 3:
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
   
   
    const n = nums.length;
    nums.sort((a, b) => a - b);
    let ans = [];
    for (let first = 0; first < n; first++) {
   
   
      if (first > 0 && nums[first] == nums[first-1]) continue; 
      let third = n - 1;
      let target = -nums[first];
      for (let second = first + 1; second < n; second++) {
   
   
        if (second > first + 1 && nums[second] == nums[second-1]) continue;
        while (second < third && nums[second] + nums[third] > target) {
   
   
          third--;
        }
        if (second == third) break;
        if (nums[second] + nums[third] == target) {
   
   
          ans.push([nums[first], nums[second], nums[third]]);
        }
      }
    }
    return ans;
};

三、滑动窗口

8、【中等】无重复字符的最长子串

题目描述:
给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。

示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function(s) {
   
   
  const curSet = new Set();
  let j = 0, ans = 0;
  for (let i = 0; i < s.length; i++) {
   
   
      if (i != 0) {
   
   
        curSet.delete(s.charAt(i - 1));
      }
      while (j < s.length && !curSet.has(s.charAt(j))) {
   
   
        curSet.add(s.charAt(j));
        j++;
      }
      ans = Math.max(ans, j - i);
  }
  return ans;
};

9、【中等】找到字符串中所有字母异位词

题目描述:
给定两个字符串 sp,找到 s 中所有 p异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

示例 1:
输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
示例 2:
输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。

/**
 * @param {string} s
 * @param {string} p
 * @return {number[]}
 */
var findAnagrams = function(s, p) {
   
   
    const sLen = s.length, pLen = p.length;
    if (sLen < pLen) {
   
   
        return [];
    }
    const ans = [];
    const count = Array(26).fill(0);
    for (let i = 0; i < pLen; ++i) {
   
   
        ++count[s[i].charCodeAt() - 'a'.charCodeAt()];
        --count[p[i].charCodeAt() - 'a'.charCodeAt()];
    }
    let differ = 0;
    for (let j = 0; j < 26; ++j) {
   
   
        if (count[j] !== 0) {
   
   
            ++differ;
        }
    }
    if (differ === 0) {
   
   
        ans.push(0);
    }
    for (let i = 0; i < sLen - pLen; ++i) {
   
   
        if (count[s[i].charCodeAt() - 'a'.charCodeAt()] === 1) {
   
     // 窗口中字母 s[i] 的数量与字符串 p 中的数量从不同变得相同
            --differ;
        } else if (count[s[i].charCodeAt() - 'a'.charCodeAt()] === 0) {
   
     // 窗口中字母 s[i] 的数量与字符串 p 中的数量从相同变得不同
            ++differ;
        }
        --count[s[i].charCodeAt() - 'a'.charCodeAt()];

        if (count[s[i + pLen].charCodeAt() - 'a'.charCodeAt()] === -1) {
   
     // 窗口中字母 s[i+pLen] 的数量与字符串 p 中的数量从不同变得相同
            --differ;
        } else if (count[s[i + pLen].charCodeAt() - 'a'.charCodeAt()] === 0) {
   
     // 窗口中字母 s[i+pLen] 的数量与字符串 p 中的数量从相同变得不同
            ++differ;
        }
        ++count[s[i + pLen].charCodeAt() - 'a'.charCodeAt()];
        if (differ === 0) {
   
   
            ans.push(i + 1);
        }
    }
    return ans;
};

四、子串

10、【中等】和为 K 的子数组

题目描述:
给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。
子数组是数组中元素的连续非空序列。

示例 1:
输入:nums = [1,1,1], k = 2
输出:2
示例 2:
输入:nums = [1,2,3], k = 3
输出:2

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var subarraySum = function(nums, k) {
   
   
    const mp = new Map();
    mp.set(
### Java LeetCode HOT100 顺序与推荐 在准备通过 LeetCodeHOT100 目提升算法能力时,建议按照一定的逻辑顺序逐步深入。以下是基于常见知识点分类以及难度递增的原则设计的学习路径: #### 一、基础目 这些目主要涉及基本的数据结构操作和简单的算法实现。 - **数组与字符串** - Two Sum[^1] - Reverse Integer[^1] - Palindrome Number[^1] - **链表** - Remove Nth Node From End of List[^1] - Merge Two Sorted Lists - **栈与队列** - Valid Parentheses - Implement Stack using Queues[^1] #### 二、中级目 此阶段的目通常需要掌握常见的排序算法及其应用,并能灵活运用多种数据结构解决问- **排序与搜索** - Search Insert Position[^2] - Find First and Last Position of Element in Sorted Array[^2] - **动态规划入门** - Climbing Stairs[^1] - House Robber[^1] - **树结构** - Same Tree[^1] - Invert Binary Tree[^1] #### 三、高级目 这一层次的目往往综合考察多个方面的技能,可能涉及到复杂的递归调用或者多层嵌套循环处理。 - **图论初步** - Clone Graph - **回溯法** - Subsets[^1] - Permutations - **深度优先/广度优先遍历** - Surrounded Regions - Word Search[^1] 对于具体的每道目,在解过程中可以参考如下资源来加深理解: - Bilibili 上有众多优质博主分享他们的经验,比如灵茶山艾府、遥儿_VUV 等都提供了详尽的 Python 版本讲解[^3] 。虽然他们是针对 Python 编程语言制作的内容,但是其中所蕴含的思想同样适用于其他编程语言如 Java。 下面给出一段用于解决 “Find First and Last Position of Element in Sorted Array” 这类问的标准模板代码作为示范: ```java class Solution { public int[] searchRange(int[] nums, int target) { int[] result = {-1, -1}; if(nums == null || nums.length == 0){ return result; } int leftIndex = findLeftBound(nums,target); if(leftIndex == -1){ return result; } int rightIndex = findRightBound(nums,target); result[0]=leftIndex; result[1]=rightIndex; return result; } private int findLeftBound(int[] nums,int target){ int low=0; int high=nums.length-1; while(low<=high){ int mid=(low+high)/2; if(nums[mid]==target &&(mid==0||nums[mid-1]<target)){ return mid; }else if(target>nums[mid]){ low=mid+1; }else{ high=mid-1; } } return -1; } private int findRightBound(int[] nums,int target){ int low=findLeftBound(nums,target); if(low==-1){ return -1; } int high=nums.length-1; while(low<=high){ int mid=(low+high)/2; if(nums[mid]==target&&(mid==nums.length-1||nums[mid+1]>target)){ return mid; }else if(target<nums[mid]){ high=mid-1; }else{ low=mid+1; } } return -1; } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

testleaf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值