LeetCode Hot 100 前端解法 (1)

93 阅读4分钟

1. 两数之和

分类:数组 | 哈希表

1. 两数之和 - 力扣(LeetCode)

  • 给定一个整数数组 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. 两数相加

分类:链表

2. 两数相加 - 力扣(LeetCode)

  • 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
  • 请你将两个数相加,并以相同形式返回一个表示和的链表。
  • 你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1:

image.png

    输入: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。这样可以帮助代码更加清晰和易于维护。