【LeetCode】 JavaScript实现 链表删除节点(重复、指定等情况) 题型汇总

面试题 02.01. 移除重复节点

原题链接:面试题 02.01. 移除重复节点
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var removeDuplicateNodes = function(head) {
  
};

解题思路:

①哈希表法

  • 利用哈希表依次存储结点
  • 用set.has()方法判断是否重复,如果重复通过指向进行删除,并后移
  • 不重复则通过set.add()存储,并后移
var removeDuplicateNodes = function(head) {
    //利用哈希
    if(head==null){
        return head;
    }
    var set=new Set();
    set.add(head.val);

    var prev=head;      //head赋给prev
    var curr=head.next; //head.next赋给curr

    while(curr!=null){
        if(set.has(curr.val)){ //如果当前结点重复
            prev.next=curr.next; //让prev的next指向curr的next 进行删除
            curr=curr.next; //curr后移
        }else{
            set.add(curr.val); //第一次出现 ,存储到set里
            prev=prev.next;    //prev和curr均后移
            curr=curr.next;
        }
    }
    return head;
};

②利用双指针法

  • 声明p、q指针,分别指向head和p
  • 将p指针的位置先固定,不断移动q指针进行扫描与p的值比较,相同则删除 ,否则q指向后移
  • 一轮循环完后,让p向后移,判断下一个结点
  • 时间复杂度较高,执行效率慢
var removeDuplicateNodes = function(head) {
    //双指针
    var p=head;
    while(p!=null){
        var q=p; //将p指针赋给q
        while(q.next!=null){
            if(q.next.val==p.val){ //如果后面的q有和固定的p有重复
                q.next=q.next.next; //删除重复
            }else{
                q=q.next;
            }
        }
        p=p.next; //让p向后移,判断下一个结点
    }
    return head;
};

83. 删除排序链表中的重复元素

原题链接:83. 删除排序链表中的重复元素
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var  deleteDuplicates = function (head) {
 
};

解题思路:

注意: 与上题的不同点在于,该链表已经按升序排列,所以重复元素一定相邻,比无序排列的链表删除重复元素简单

  • 让p指针指向head 并且判断p的val和p.next.val是否相等
  • 如果相等则为重复并删除 , 否则,p指针指向下一个元素
var  deleteDuplicates = function (head) {
    //链表为空
    if (head == null) {
        return head;
    }
    //链表不为空
    var p =head;
    while (p.next != null) {
        if (p.val == p.next.val) {
            p.next = p.next.next;  //删除重复元素
        } else {
            p = p.next; //指针指向后移
        }
    }
    return head;
};

82. 删除排序链表中的重复元素 II

82. 删除排序链表中的重复元素 II
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var deleteDuplicates = function(head) {

}

与上题不一样的地方是 :返回的链表只保留原始链表没有出现重复的数字,需要将重复的数字包括自己在内也要删掉

因此判断时就需要在提前一位进行比较,方便删除。需要比较curr.next.val和curr.next.next.val,而上题相当于比较 curr.val和curr.next.val

方法一:迭代法

var deleteDuplicates = function(head) {
    //可能会删除头节点 因此引入了哑结点
    const dummyHead=new ListNode(0);
    dummyHead.next=head;
    let curr=dummyHead;
    while(curr.next&&curr.next.next){
        if(curr.next.val===curr.next.next.val){
            let num=curr.next.val; //记下curr.next的值
            while(curr.next&&curr.next.val===num){ //将等于curr.next的值的所有节点全删除
                curr.next=curr.next.next;
            }
        }else{
            curr=curr.next;
        }
    }
    return dummyHead.next;
}

方法二:set方法

var deleteDuplicates = function(head) {
    const dummyHead=new ListNode(0);
    dummyHead.next=head;
    let curr=dummyHead;
    let set=new Set();
    while(curr.next&&curr.next.next){
        if(curr.next.val===curr.next.next.val){
            set.add(curr.next.val); //用set记录重复元素
            curr.next=curr.next.next;
        }else{
            curr=curr.next;
        }
    }
    curr=dummyHead;
    while(curr.next&&curr.next){
        if(set.has(curr.next.val)){
            curr.next=curr.next.next;
        }else{
            curr=curr.next;
        }
    }
    return dummyHead.next
};

203. 移除链表元素

原题链接:203. 移除链表元素
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} val
 * @return {ListNode}
 */
var removeElements = function(head, val) {

};

方法一:迭代法
需要判断头结点是否为删除的结点

var removeElements = function(head, val) {
    //头结点为空
    if (head == null) return head;
    //头结点为要删除的结点 或者新的头结点也要被删除
    while (head != null && head.val == val) {
        head = head.next;
    }
    var curr = head;
    //确保当前结点不为空,并且当前结点后还有结点
    while (curr != null && curr.next != null) {
        if (curr.next.val == val) {
            curr.next = curr.next.next;
        } else {
            curr = curr.next;
        }
    }
    return head;
};

方法二 :(与一类似)
添加一个虚拟头结点

var removeElements = function(head, val) {
    //头结点为空
    if (head == null) return head;
    //创建一个结点null,指向head结点 确保此时的head结点不是头结点
    //目的是为了确保head结点不是要删除的结点
    var list = new ListNode(null, head);
    var curr = list;
    while (curr.next != null) {
        if (curr.next.val == val) {
            curr.next = curr.next.next;
        } else {
            curr = curr.next;
        }
    }
    return list.next;
};

方法三:递归
终止条件是head为空。 head不为空时递归进行操作

var removeElements = function(head, val) {   
    if(head==null) return head;
    head.next=removeElements(head.next,val);
    if(head.val==val){
        return head=head.next;
    }else{
        return head;
    }
};

具体动画详解参考:动画演示 迭代法 #203 移除链表元素

剑指 Offer 18. 删除链表的节点

原题链接:剑指 Offer 18. 删除链表的节点
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} val
 * @return {ListNode}
*/
var deleteNode = function (head, val) {

};

先判断头结点是否为要删除,然后定义currNode指向头结点,并判断currNode.next的val值

var deleteNode = function (head, val) {
    if (head.val === val) //在链表头部删除
        return head.next;
    var currNode=head;
    while (currNode.next.val !== val && currNode !== null) {
        currNode = currNode.next;
    }
    currNode.next = currNode.next.next;
    return head;
};

237. 删除链表中的节点 / 面试题 02.03. 删除中间节点

原题链接:删除链表中的节点
在这里插入图片描述
原题链接:面试题 02.03. 删除中间节点
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} node
 * @return {void} Do not return anything, modify node in-place instead.
 */
var deleteNode = function(node) {

};

题目的坑!!!注意看题!

参数没有头结点 ,所以不能遍历链表找待删除的结点

要删除的结点是链表的一部分而不是结点的val值

var deleteNode = function(node) {
    //直接删除当前结点的值,并让下一结点的值取代
    node.val=node.next.val
    node.next=node.next.next
};

19. 删除链表的倒数第 N 个结点 / 剑指 Offer II 021. 删除链表的倒数第 n 个结点

原题链接: 19. 删除链表的倒数第 N 个结点

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} n
 * @return {ListNode}
 */
var removeNthFromEnd = function(head, n) {
	
};

方法一:定义快慢指针

让快指针先移动n步 ,同时移动快慢指针

当快指针到尾部时 ,慢指针为第倒数第n个结点

var removeNthFromEnd = function(head, n) {
    var pre=new ListNode(); 
    pre.next=head; //设预先指针下一个结点指向head 
    var start=pre,end=pre;
    while(n!=0){
        start=start.next;
        n--;
    }
    while(start.next!=null){
        start=start.next;  //快慢指针同时向前移动
        end=end.next;
    }
    end.next=end.next.next;
    return pre.next //不返回head 因为head有可能是被删除的结点
};

方法二:将倒数思路转换为正数思路

删除倒数第n个结点可以转换为删除第m个结点

var removeNthFromEnd = function(head, n) {
    var p=head;
    var count=0;
    //先计算长度
    while(p){
        count++;
        p=p.next;
    }
    if(count==n){ //倒数第n个等于长度 即删除的是正数第一个结点
        return head.next;
    }
    p=head;
    var m=count-n+1; //m为要正数删除的结点
    for(var i=1;i<m-1;i++){ //确保找到第m个结点的前一个结点
        p=p.next;
    }
    p.next=p.next.next;
    return head;
}

剑指 Offer 22. 链表中倒数第k个节点

原题链接: 剑指 Offer 22. 链表中倒数第k个节点
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var getKthFromEnd = function(head, k) {

}

解题方法:双指针

var getKthFromEnd = function(head, k) {
    //双指针 即快慢指针 均指向头部
    var fast=head;
    var slow=head;
    //让快指针先走k步
    for(var i=0;i<k;i++){
        //如果给的k值和链表长度不合理 返回null
        if(fast==null){
            return null;
        }
        //每次循环向前一步
        fast=fast.next;
    }
    while(fast!=null){
        // 让快指针和慢指针每次向前走一步,直到快指针走到头 此时慢指针恰好达到所需要的位置
        fast=fast.next;
        slow=slow.next;
    }
    return slow;
}
  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值