代码随想录算法训练营DAY 3 | 203. 移除链表元素、707. 设计链表、206. 反转链表

文章介绍了链表基础操作,包括移除具有特定值的节点、设计链表类实现添加、获取和删除功能,以及如何反转链表。解题策略涉及到使用虚拟头节点简化处理,注意边界条件和节点间的连接变换。

链表基础知识

203. 移除链表元素

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

示例 1 输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]
示例 2 输入:head = [], val = 1 输出:[]
示例 3 输入:head = [7,7,7,7], val = 7输出:[] 
/**
 * 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) {
    let data = new ListNode(0, head)
    let cur = data
    while(cur.next) {
        if (cur.next.val === val) {
            cur.next = cur.next.next
            continue
        }
        cur = cur.next
    }
    return data.next
};
解题:前端接触链表这个结构比较少,但理解后也比较简单,主要是要把握cur.next这个定位到了哪里,还有一个比较好的使用点就是使用虚拟头节点,正常的处理是把head部分单独处理,当设立了虚拟头节点后,可以把head节点也当作普通的链表中节点来处理,无需单独处理
707. 设计链表

你可以选择使用单链表或者双链表,设计并实现自己的链表。

单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。

示例:输入
["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get"]
[[], [1], [3], [1, 2], [1], [1], [1]]
输出 [null, null, null, null, 2, null, 3]

解释
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.addAtHead(1);
myLinkedList.addAtTail(3);
myLinkedList.addAtIndex(1, 2);    // 链表变为 1->2->3
myLinkedList.get(1);              // 返回 2
myLinkedList.deleteAtIndex(1);    // 现在,链表变为 1->3
myLinkedList.get(1);              // 返回 3

class LinkNode {
    constructor(val, next) {
        this.val = val
        this.next = next
    }
}
var MyLinkedList = function() {
    this.size = 0
    this.tail = null
    this.head = null
};

MyLinkedList.prototype.getNode = function(index) {
    if(index<0 || index > this.size) return -1
    let ret = new LinkNode(0, this.head)
    while(index-- >= 0) {
        ret = ret.next
    }
    return ret
}

/**
 * @param {number} index
 * @return {number}
 */
MyLinkedList.prototype.get = function(index) {
    if(index<0 || index >= this.size) return -1
    return this.getNode(index).val
};

/**
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtHead = function(val) {
    let cur = new LinkNode(val, this.head)
    this.head = cur
    this.size++
    if(!this.tail) {
        this.tail = cur
    }
};

/**
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtTail = function(val) {
    if(!this.tail) {
        this.addAtHead(val)
        return;
    }
    let cur = new LinkNode(val, null)
    let per = this.getNode(this.size-1)
    per.next = cur
    this.tail = cur
    this.size++
};

/**
 * @param {number} index
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtIndex = function(index, val) {
    if (index<0 || index >this.size) return;
    if (index === 0) {
        this.addAtHead(val)
        return;
    } else if (index === this.size) {
        this.addAtTail(val)
        return;
    }
    let per = this.getNode(index - 1)
    let cur = new LinkNode(val, per.next)
    per.next = cur
    this.size++
};

/**
 * @param {number} index
 * @return {void}
 */
MyLinkedList.prototype.deleteAtIndex = function(index) {
    if (index<0 || index >= this.size) return;
    if (index === 0) {
        let cur = new LinkNode(0, this.head)
        cur.next = cur.next.next
        this.head = cur.next
        if (this.size === 1) {
            this.tail = this.head
        }
        this.size--
        return;
    }
    let cur = this.getNode(index-1)
    cur.next = cur.next.next
    if (index === this.size-1) {
        this.tail = cur
    }
    this.size--
};

解题:这道题卡了比较长的时间,主要是一些边界条件的限制做的不好,需要自己慢慢调试,思路不难理解,要注意一些必要的剪枝操作。

另外在需要实现的函数基础上,标准答案多做了一个getNode 函数,根据index值返回对应的node,这对于需要寻找上一个节点的操作来讲很好用

206. 反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例: 输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]
/**
 * 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 reverseList = function(head) {
    if(!head || !head.next) {
        return head
    }
    let temp = null, cur = head, pre = null;
    while(cur) {
        temp = cur.next
        cur.next = pre
        pre = cur
        cur = temp
    }
    return pre
};

解题:这里的思路也不难理解,但是除了做判断头部的剪枝以外,还需要多创建三个变量来做单独存储,并在while里面转换,最后返回原来的尾部节点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值