一、两数之和

给定一个整数数组 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]

题解:

给定一个数组,首先想到的是两次for循环,第一次for循环时拿到第一个元素,第二次for循环时拿到后面的元素,进行判断第一个元素和后面的元素加起来是否是目标值,是则添加到新数组中。

var twoSum = function(nums, target) {
let num = [];
for (let i = 0; i<nums.length; i++){
for(let j = i+1;j<nums.length;j++){
if(nums[i] + nums[j] == target){
num.push(i,j);
}
}
}
return num;
};

二、字母异位词分组

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

示例1:

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

示例 2:

输入: strs = [""]
输出: [[""]]

示例 3:

输入: strs = ["a"]
输出: [["a"]]

题解:

计数方法

由于互为字母异位词的两个字符串包含的字母相同,因此两个字符串中的相同字母出现的次数一定是相同的,故可以将每个字母出现的次数使用字符串表示,作为哈希表的键。

由于字符串只包含小写字母,因此对于每个字符串,可以使用长度为 26 的数组记录每个字母出现的次数。

var groupAnagrams = function(strs) {
const map = new Object();
for (let s of strs) {
// 创建了一个长度为26的新数组 count ,并将每个元素初始化为0。
// 用于存储每个字符出现的次数,其中索引0对应字符'a',索引1对应字符'b',依此类推,直到索引25对应字符'z'
const count = new Array(26).fill(0);
for (let c of s) {
// 计算字符 c 的ASCII码值与字符'a'的ASCII码值之间的差
count[c.charCodeAt() - 'a'.charCodeAt()]++;
}
// 检查 map 对象中是否已经有一个以当前字符串的字符计数数组为键的数组
// 如果有,就将当前字符串添加到这个数组中;
// 如果没有,就创建一个新的数组,并将这个数组与当前字符串关联起来作为 map 对象的一个新键值对。
map[count] ? map[count].push(s) : map[count] = [s];
}
return Object.values(map);
};

三、最长连续序列

给定一个未排序的整数数组 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

题解:

将数组元素存入 set 中
遍历nums,如果 当前项 - 1 存在于 set ,说明当前项不是连续序列的起点,忽略,继续遍历
如果当前项没有“左邻居”,它就是连续序列的起点,循环查看当前项连续的右邻居有多少个
返回最长的连续次数

此方法的时间复杂度为O(n)

var longestConsecutive = function (nums) {
// 把题目中数组的数字全部放入set中,一来去重,二来方便快速查找
const set = new Set(nums);
let max = 0;
for (let [key,a] of set.entries()) {
// 没有左邻居,是序列的起点
if (!set.has(a - 1)) {
let count = 1;
let cur = a;
// 有右邻居,看连续的右邻居有多少个
while (set.has(cur + 1)) {
cur++;
count++;
}
// 存放最大的连续邻居的值
max = Math.max(max, count);
}
}
return max;
};

先将数组排序,设置计数器等于1,最长连续计数器等于1,如果数组的长度为0,则返回0,遍历数组,如果数组的第一个和他后面的一个值相同,就继续比较,类似 Set 方法,如果数组前一个值加一等于下一个的值,count就加一,否则重置计数器为1,每当遍历完一次回合都要更新一次 maxCount 计数器,将最长序列存储,遍历完成后,返回最长序列的长度

时间复杂度为O(nlogn)

var longestConsecutive = function(nums) {
if (nums.length === 0) return 0; // 如果数组为空,返回0
nums.sort((a, b) => a - b); // 对数组进行排序

let count = 1; // 初始化连续序列的计数器
let maxCount = 1; // 初始化最长连续序列的计数器

for (let i = 1; i < nums.length; i++) { // 从第二个元素开始遍历
if (nums[i] == nums[i - 1]) {
// 如果当前元素与前一个元素相同,则跳过
continue;
}
if (nums[i] == nums[i - 1] + 1) {
// 如果当前元素是连续的,增加计数器
count++;
} else {
// 如果当前元素不是连续的,重置计数器
count = 1;
}
maxCount = Math.max(maxCount, count); // 更新最长连续序列的长度
}

return maxCount; // 返回最长连续序列的长度
};