1. 两数之和
分类:数组 | 哈希表
- 给定一个整数数组
nums和一个整数目标值target,请你在该数组中找出 和为目标值target的那 两个 整数,并返回它们的数组下标。 - 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
- 你可以按任意顺序返回答案。 示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
方法一:暴力枚举
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
* 因为forEach不支持提前返回,所以只能用for
*/
var twoSum = function (nums, target) {
for (let i=0; i<nums.length; i++) {
for (let j=i+1; j<nums.length; j++) {
if (nums[i] + nums[j] === target) {
return [i, j]
}
}
}
};
方法二:哈希表
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
* 因为forEach不支持提前返回,所以只能用for
*/
var twoSum = function (nums, target) {
let map = new Map()
for (let index = 0; index < nums.length; index++) {
if (map.has(target - nums[index])){
return [map.get(target - nums[index]), index]
} else {
map.set(nums[index], index)
}
}
return []
};
2. 两数相加
分类:链表
- 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
- 请你将两个数相加,并以相同形式返回一个表示和的链表。
- 你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
方法一:模拟
var addTwoNumbers = function(l1, l2) {
const dummyHead = new ListNode();
let temp = dummyHead;
let andOne = 0;
// 开始遍历l1、l2 结束的条件(l1和l2都遍历完了,还有一种情况是l1+l2 >= 10的情况,还需要添加一个)
while(l1 || l2 || andOne) {
const number1 = l1 ? l1.val : 0; //l1不为空返回l1当前节点的值
const number2 = l2 ? l2.val : 0;
const num = (number1 + number2 + andOne) % 10; // 逢10进1
andOne = number1 + number2 + andOne >= 10 ? 1 : 0; // 这里决定要不要进一(要把上一次进位的值加上)
const newNode = new ListNode(num); // 要插入的新节点
temp.next = newNode; // 将新节点挂在dummyHead节点上(temp是用来移动dummyHead节点的)
temp = temp.next; // 移动temp节点为下个节点;
l1 = l1 && l1.next; //如果 l1 是非空(即不是 null 或 undefined),那么 l1 && l1.next 将会继续执行,进入下一步。
l2 = l2 && l2.next;
}
return dummyHead.next; // 将dummyHead节点的next返回
}
解题思路: 链表。把两个链表看成是相同长度的(不存在的位置用0代替),逢十进一。
Tips: 做链表的题目一般来说会设置一个虚拟的头节点dummyHead,最后返回dummyHead.next;并且会用一个temp来作为中间节点来链接新的节点。使用预先指针的目的在于链表初始化时无可用节点值,而且链表构造过程需要指针移动,进而会导致头指针丢失,无法返回结果。
const: const 声明的变量是常量,一旦被赋值后就无法再修改其值。使用 const 声明的变量必须在声明时进行初始化,否则会引发错误。常量意味着它的值在声明后不能被重新赋值。然而对于对象(包括数组和函数)而言,const 并不代表其内容不可变,而是指向该对象的引用不能被改变。也就是说,可以修改对象的属性,但不能重新赋值整个对象。
const a = 10;
// a = 20; // 这行代码会引发错误,因为常量a的值不能再次赋值
const obj = { name: 'John' };
obj.name = 'Alice'; // 合法,修改了对象的属性值
// obj = { age: 30 }; // 这行代码会引发错误,因为不能重新分配const对象的引用
let: let 声明的变量是可变的(mutable),可以重新赋值。let 声明的变量可以在作用域内被更新和修改。
let x = 10;
x = 20; // 合法,let声明的变量可以被重新赋值
let y;
y = 30; // 合法,在稍后的任意时间点初始化let声明的变量
哪个更好取决于具体的使用情境。通常建议在需要声明不可变变量时使用 const,因为它可以提供更多的安全性和可读性。而在需要可变的变量时,使用 let。良好的编程实践是尽可能使用 const,只有在确实需要可变性时才使用 let。这样可以帮助代码更加清晰和易于维护。