一、两数之和
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
//优化的常见思路是用空间换时间。
//我们暴力解法中,第二层循环的目的是找到和 i 匹配的元素,由于数组不是有序的,我们不得不一个个遍历。而借助外部内存,我们就可以把该过程缩减为 O(1) 复/杂度,那就是哈希表
//在上述解法中,依然要建一个完整的哈希表,空间占用一点没省下来,理想解法是边查边存
const twoSum = (nums, target) => {
const map = new Map();
for (let i = 0; i < nums.length; i++) {
let x = target - nums[i]
if (map.has(x)) {
return [map.get(x), i]
}
// 边读边存构建字典
map.set(nums[i], i)
}
}
二、两数相加
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
const addTwoNumbers = (l1, l2) => {
// 定义一个新链表
const l3 = new ListNode(0);
// 定义三个链表的指针
let [p1, p2, p3] = [l1, l2, l3];
// c表示进位数,一开始为0
let c = 0;
// 遍历两个链表,直到两个都为空为止
while (p1 || p2) {
// p1指针当前的值
const v1 = p1 ? p1.val : 0;
// p2指针当前的值
const v2 = p2 ? p2.val : 0;
// 将两个指针的值和进位相加
const val = v1 + v2 + c;
// 更新进位数
c = Math.floor(val / 10);
// 更新新链表下一位
p3.next = new ListNode(val % 10);
// 如果p1还有值,更新到下一位,p2同理
p1 = p1?.next;
p2 = p2?.next;
// p3更新到下一位
p3 = p3.next;
}
// 如果到最后还有进位,再新加一个节点,存储最后的进位
if (c) p3.next = new ListNode(c);
return l3.next;
};
三、无重复字符的最长子串
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
var lengthOfLongestSubstring = function (s) {
let arr = [];
let max = 0;
for (let i = 0; i < s.length; i++) {
//如果之前存在,就删除,知道没有为止
if (arr.indexOf(s[i]) !== -1) {
arr.splice(0, arr.indexOf(s[i]) + 1);
}
//加入当前元素
arr.push(s[i]);
//取最大
max = Math.max(max, arr.length);
}
return max;
};