每日一点学习记录吧JS

51 阅读4分钟

关于两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺序返回答案。

function(arrs,num){ for(let i = 0;i<arrs.length;i++){ 
for(let j=i+1;j<arrs.length;j++){
if(arrs[i}+arrs[j]==num){
return [i,j]
}
}
}
return null;
}

上边的写法 一般且常规 但是 若存在 大批量的 数据 循环会很吃性能 非最优解

我们可以使用此类写法

A.哈希表 (可以减少时间的复杂度)

function func(arrs,num){
 const map = new Map();
 for(let i = 0;i<arrs.length;i++){
 const complement = num - arrs[i];
 //如果得到的差值 在map中 则 返回 差值所在位置和 减数的位置
 if(map.has(complement)){
 return [map.get(complement),i]
 }
 // 若不符合 上述的哦判定 则将对应的 下标和元素  set进 map中。但是若  set的值就是 arra[i] 已经存在 map中 后续 新的值 会覆盖掉 之前set的旧值
 map.set(arrs[i],i];
 }
 return null;
}

两数相加

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

如:给定 2→4→3 和 5→6→4 得到 7→0→8

function ListNode(val,node){
    this.val = val===undefined ? 0 : val
    this.next = nex===undefined ? 0 : next 
} //这个部分定义了一个 ListNode 构造函数,用于创建链表节点。每个节点有一个值 (val) 和一个指向下一个节点的指针 (next)。
function arrayToList(arr) {
    let dummyHead = new ListNode(0);
    let current = dummyHead;
    for (let i = 0; i < arr.length; i++) {
        current.next = new ListNode(arr[i]);
        current = current.next;
    }
    return dummyHead.next;
} //这一步 根据实际情况而定  我是以 输入的数据为 数组 举例  ,那么则需要 进行 数组转链表
const addTwoNumbers = function(l1, l2) {
    // 创建一个值为 0 的 dummyHead 节点,它是新链表的临时头节点,帮助我们更容易地返回新链表的头节点。
    let dummyHead = new ListNode(0);
    // 初始化三个指针 p, q, 和 current,以及一个名为 carry 的变量来存储进位。
    let p = l1, q = l2, current = dummyHead;
    let carry = 0;
    // 循环继续,直到两个链表都被遍历完。
    while (p !== null || q !== null) {
        // 如果链表 p 或 q 没有到达末尾,取其当前节点的值,否则取 0。
        let x = (p !== null) ? p.val : 0;
        let y = (q !== null) ? q.val : 0;
        // 计算当前位的和和新的进位值。
        let sum = carry + x + y;
        carry = Math.floor(sum / 10);
        // 创建一个新节点来存储当前位的结果,并将 current 指针移到新节点。
        current.next = new ListNode(sum % 10);
        current = current.next;
        // 移动 p 和 q 指针到下一个节点,如果存在的话。
        if (p !== null) p = p.next;
        if (q !== null) q = q.next;
    }
    // 如果在完成所有迭代后仍有一个进位,创建一个新节点来存储这个进位。
    if (carry > 0) {
        current.next = new ListNode(carry);
    }
    // 返回 dummyHead 的下一个节点,它是新链表的头节点。dummyHead 自身不是结果的一部分,它只是一个临时节点,帮助我们构建新链表
    return dummyHead.next;
};
console.log(addTwoNumbers(arrayToList([2,4,3]),arrayToList([5,6,4])))
console.log(arrayToList([2,4,3]),arrayToList([5,6,4]))

引申一下 链表的 相关知识点

1. 首先是结构 (长什么样)

{
    "val": 2,
    "next": {
        "val": 4,
        "next": {
            "val": 3,
            "next": null
        }
    }
} //以 单项为例

a. 链表的基本结构:

  • 节点 (Node) : 链表由节点组成,每个节点通常包含两个部分:值(或数据)和指向下一个节点的指针。
  • 头节点 (Head) : 链表的起始节点称为头节点。
  • 尾节点 (Tail) : 链表的最后一个节点称为尾节点,它的下一个节点指针指向nullnil

b. 链表的类型:

  • 单向链表 (Singly Linked List) : 每个节点只有一个指向下一个节点的指针。
  • 双向链表 (Doubly Linked List) : 每个节点有两个指针,一个指向下一个节点,另一个指向前一个节点。
  • 循环链表 (Circular Linked List) : 尾节点的下一个节点指针指向头节点,形成一个循环。

c. 链表的操作:

  • 插入 (Insertion) : 在链表的特定位置插入一个新节点。
  • 删除 (Deletion) : 删除链表中的一个节点。
  • 搜索 (Search) : 在链表中搜索一个特定的值或节点。
  • 遍历 (Traversal) : 遍历链表以访问每个节点。

d. 链表和数组的比较:

  • 动态大小: 链表的大小是动态的,而数组的大小是固定的。
  • 内存分配: 链表不需要连续的内存空间,而数组需要。
  • 插入和删除: 链表中的插入和删除操作通常更快,因为不需要移动其他元素。