代码随想录刷题之链表

164 阅读3分钟

代码随想录刷题记录

链表

基本知识

节点是对象,里面有两个属性,一个是val,一个是next,next存的是地址。

cur=cur.next;表示将cur下一个节点的地址/引传递给了cur,那么cur就理解为下一个节点。

let node = head;表示将head这个节点的引传递给了node,那么node就是头节点

let node = new ListNode(0,head),表示创建了一个指向head的虚拟头节点

题目

删除链表元素题目:给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

重点:创建虚拟节点,以前一个节点pre为参考,pre的下一个节点pre.next来实际操作

var removeElements = function(head, val) {
    // 创建虚拟头节点
    let node = new ListNode(0, head);
    let cur = node;
    // 循环条件是只要判断cur.next是否为空
    while(cur.next){
        // 第一次循环,cur.next是实际头节点
        if(cur.next.val == val){
            cur.next = cur.next.next;
            continue;
        }
        cur = cur.next;

    }
    // 返回值是返回头节点的地址
    return node.next;
};

反转链表题目

var reverseList = function(head) {
    //雷区:不要忘记判断链表为空或者只有一个元素
    if(!head || !head.next){ return head}
    let pre = null;
    let node = new ListNode(0,head);
    let cur = node.next;//头节点
    while(cur){
   //这里要先将下一个节点保存
        let next = cur.next;
        cur.next = pre;
        pre = cur;
        cur = next;
   }
   return pre;
}

题目删除倒数第n项的元素

var removeNthFromEnd = function(head, n) {
    let fast = slow = temp = new ListNode(0,head);
    while(n-- >=0){
        //此时fast指向index值为n的位置
        fast = fast.next;
    }
    while(fast){
        slow = slow.next;
        fast = fast.next;
    }
    // while结束,此时slow走到倒数第n项的前一项
    slow.next = slow.next.next;
    return temp.next;
};

创建虚拟头节点,让s和f同时指向这个虚拟头节点。

while(n-- >=0){
        //此时fast指向index值为n的位置
        fast = fast.next;
   }

此时fast从虚拟节点出发,while循环结束fast来到index=n的位置,如果fast从头节点触发,就让判断条件为>0。

 while(fast){
        slow = slow.next;
        fast = fast.next;
    }

此时fast和slow同时移动,直到fast到null的位置,slow到了删除节点的前一个节点。

为什么这样可行呢?因为这样保证了在fast到null时,slow走到第k-n个元素(假设总共k个元素),索引是k-n-1。

小小的证明:假设链表元素个数为k,要删除倒数第n个元素,那么fast从下标为n的元素走到null,需要走:k-1-n + 1=k-n步,+1是从最后一个走到null的。

此时slow就从虚拟头节点也走k-n步,就走到了第k-n个元素,也就是index=k-n-1的位置,即要删除元素的前一项。

题目:找到两个链表相交的位置

var getIntersectionNode = function(headA, headB) {
    // step1:将两个链表末尾对齐
    let lenA = listLength(headA);
    let lenB = listLength(headB);
    let curA = headA;
    let curB = headB;
    // 让A最为长的链表
    if(lenA<lenB){
        [lenA, lenB] = [lenB, lenA];
        [curA, curB] = [curB, curA];
    }
    let n = lenA - lenB;
    while(n-->0){
        curA = curA.next;
    }
    // 此时curA指向了两个链表尾部对齐时短的链表的头部
    while(curA !== curB && curA){
        curA = curA.next;
        curB = curB.next;
    }
    return curA;
};
// 定义一个读取链表长度的函数
function listLength(head){
    let len = 0, cur = head;
    while(cur) {
       len++;
       cur = cur.next;
    }
    return len;
}