挑战LeetCode热题100(TS版本)
打卡第一天
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]
思路:暴力破解、二分查找、hash
暴力破解:
function twoSum(nums: number[], target: number): number[] {
for(let i=0;i<nums.length;i++) {
for(let j=i;j<nums.length;j++) {
if(nums[i] + nums[j] === target) {
return [i,j]
}
}
}
return [0,0]
}
- 时间复杂度:O
- 空间复杂度:O(1)
二分查找:
function twoSum(nums: number[], target: number): number[] {
if(nums.length === 2 && nums[0] + nums[1] === target) {
return [0,1]
}
const sortedArr = [...nums].sort((a, b) => a - b); // 对数组进行排序
let left = 0;
let right = sortedArr.length - 1;
while (left < right) {
const sum = sortedArr[left] + sortedArr[right];
if (sum === target) {
// 找到两个数的和,获取它们在原始数组中的位置
const index1 = nums.indexOf(sortedArr[left]);
const index2 = nums.indexOf(sortedArr[right]);
return [index1, index2];
} else if (sum < target) {
left++; // 和小于目标值,左指针右移
} else {
right--; // 和大于目标值,右指针左移
}
}
return []; // 没有找到两个数的和,返回空数组
}
- 时间复杂度:O
- 空间复杂度:O(n)
Hash:
function twoSum(nums: number[], target: number): number[] {
const map = new Map()
for(let i=0;i<nums.length;i++) {
const component = target - nums[i]
if(map.has(component)) {
return [map.get(component), i]
}
map.set(nums[i], i)
}
return []
}
- 时间复杂度:O
- 空间复杂度:O(1)
2、字母异位词分组
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
示例 1:
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
示例 2:
输入: strs = [""]
输出: [[""]]
示例 3:
输入: strs = ["a"]
输出: [["a"]]
思路:暴力破解、Hash
暴力破解:
function groupAnagrams(strs: string[]): string[][] {
const result = []
for(let i=0;i<strs.length;i++) {
const a = [strs[i]]
const bool = result.findIndex(item => item.includes(strs[i]))
if(bool !== -1) {
continue
}
for(let j=i+1; j<strs.length;j++) {
if(strs[i].split('').sort().join() === strs[j].split('').sort().join()) {
a.push(strs[j])
}
}
result.push(a)
}
return result
};
- 时间复杂度:O
- 空间复杂度:O(n*m)
Hash:
function groupAnagrams(strs: string[]): string[][] {
const map = new Map()
for(const str of strs) {
const sortChar = str.sort()
if(map.has(sortChar)) {
map.get(sortChar).push(str)
} else {
map.set(sortChar, [str])
}
}
return Array.from(map.values())
};
- 时间复杂度:O
- 空间复杂度:O(1)
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
**思路: Hash1(排序、对比今后记录在Hash中) 、Hash2(寻找到最小的值,从最小值开始对比) **
Hash1:
function longestConsecutive(nums: number[]): number {
const sortArr = nums.sort((a,b) => a - b)
const map = new Map()
let maxLength = 0
for(let i=0;i< sortArr.length;i++) {
map.set(sortArr[i], 1)
}
for(let i=0;i< sortArr.length;i++) {
if(sortArr[i] + 1 === sortArr[i+1]) {
const mp_pre = map.get(sortArr[i])
const mp_next = map.get(sortArr[i+1])
map.set(sortArr[i+1], mp_pre + mp_next)
} else {
continue
}
}
for(let [key, value] of map) {
if(value > maxLength) {
maxLength = value
}
}
return maxLength
};
- 时间复杂度:O
- 空间复杂度:O(n)
Hash2:
function longestConsecutive(nums: number[]): number {
const set = new Set()
const maxLength = 0
for(const n of nums) {
set.add(n)
}
for(const s of set) {
if(!set.has(s-1)) {
let currentNum = s
let currentLength = 1
while(set.has(currentNum + 1)) {
currentNum=s+1
currentLength+=1
}
maxLength = Math.max(currentLength, maxLength)
}
}
return maxLength
};
- 时间复杂度:O
- 空间复杂度:O(n)
总结一下: 上面三道题推荐用Hash解法。如有更好的解法欢迎评论,如有问题欢迎指正!