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

707.设计链表

我的错误代码

function ListNode(val,next=null){
        this.val=val;
        this.next=next;
    }

var MyLinkedList = function() {
    this.head=null
    this.tail = this.head
    this.size =0
    this.virtualHead = new ListNode(-1,this.head)  

};



/** 
 * @param {number} index
 * @return {number}

 */
MyLinkedList.prototype.get = function(index) {   //第index节点的val是?
    if (index < 0 || index >= this.size) return -1 //index不符合规定
    let label = -1    
    let cur = this.virtualHead  
    while (label !== index){  //不符合,向下找
        cur = cur.next
        label++
    }   //等于时,退出
    return cur.val;
};



/** 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtHead = function(val) {  //在前面加上一个节点
    let newHead = new ListNode(val,this.head)  //创建新节点,数据是val,next指向这条链表之前的head
    this.virtualHead.next = newHead   //链表的虚拟节点的next指向此节点的头
    this.head = newHead  //更新链表头节点
    if (!this.head){    //如果头节点不存在
        this.tail = newHead   //此节点设为尾结点
    }
    this.size++   //节点数量加一
};

/** 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtTail = function(val) { //后面加节点
    let newTail = new ListNode(val,null)  //新尾结点
    if (!this.tail){                      //没有尾结点的话(一个节点都没有)
        this.virtualHead.next = newTail   //虚拟节点指向尾结点
        this.head = newTail    //头节点指向新结点
        this.tail = newTail    //尾结点也指向新节点
    } else {       
        this.tail.next = newTail   //原尾结点后面加上此节点
        this.tail = newTail     //此节点为新的节点
    }
    this.size++       //数量++
};

/** 
 * @param {number} index 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtIndex = function(index, val) {  //在index出添加this.val=val的节点
    if (index > this.size) return    //判断是否越界
    if (index === this.size) {   //加尾
        this.addAtTail(val)
        return
    }
    if (index <= 0){   //加头
        this.addAtHead(val)
        return
    }

    let newNode = new ListNode(val)   //新节点1
    let label = 0   //头节点为
    let prev, cur = this.head    //把链表的头节点复制到两个新节点上
    while (label !== index){
        prev = cur       //prev就是index
        cur = cur.next   //cur快prev一步
        label++
    }
    prev.next = newNode   //index的next指向新节点
    newNode.next = cur  //新节点的next指向cur节点
    this.size++


};

/** 
 * @param {number} index
 * @return {void}
 */
MyLinkedList.prototype.deleteAtIndex = function(index) {
if (index < 0 || index >= this.size) return  //越界
    let prev, cur = this.virtualHead   //虚拟头节点复制到新节点上
    let label = -1   //从虚拟节点开始,为-1
    while (label !== index){
        prev = cur
        cur = cur.next
        label++
    }
    if (cur === this.tail) this.tail = prev  //tail为倒数第二个,完成了删除操作
    prev.next = cur.next  //1.不是尾部,跳过cur2.是尾部cur的next==0
    cur = null  //删除cur
    this.size--
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * var obj = new MyLinkedList()
 * var param_1 = obj.get(index)
 * obj.addAtHead(val)
 * obj.addAtTail(val)
 * obj.addAtIndex(index,val)
 * obj.deleteAtIndex(index)
 */

官方的正确代码


var MyLinkedList = function() {
    this.size = 0;
    this.head = new ListNode(0);
};

MyLinkedList.prototype.get = function(index) {
    if (index < 0 || index >= this.size) {
        return -1;
    }
    let cur = this.head;
    for (let i = 0; i <= index; i++) {
        cur = cur.next;
    }
    return cur.val;
};

MyLinkedList.prototype.addAtHead = function(val) {
    this.addAtIndex(0, val);
};

MyLinkedList.prototype.addAtTail = function(val) {
    this.addAtIndex(this.size, val);
};

MyLinkedList.prototype.addAtIndex = function(index, val) {
    if (index > this.size) {
        return;
    }
    index = Math.max(0, index);
    this.size++;
    let pred = this.head;
    for (let i = 0; i < index; i++) {
        pred = pred.next;
    }
    let toAdd = new ListNode(val);
    toAdd.next = pred.next;
    pred.next = toAdd;
};

MyLinkedList.prototype.deleteAtIndex = function(index) {
    if (index < 0 || index >= this.size) {
        return;
    }
    this.size--;
    let pred = this.head;
    for (let i = 0; i < index; i++) {
        pred = pred.next;
    }
    pred.next = pred.next.next;
};

function ListNode(val, next) {
    this.val = (val===undefined ? 0 : val)
    this.next = (next===undefined ? null : next)
}

第一想法

知道思想,不知道怎么写

困难

一点一点理解,代码还是不过

收获

  • TypeError: Cannot read properties of null (reading ‘XXX’)定义为空,找不到就会这样子
  • js的一些理解
  • 链表的理解

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) {
   
    while(head!=null && head.val==val){  //当头等于,去头
        head = head.next;
    }
    let curr = head; 
    while(curr!==null){     //cur不等于,且不为null
        while(curr.next!=null && curr.next.val == val){  //cur.nexr符合,删除
            curr.next = curr.next.next;  //删除
        }
        curr = curr.next;  //下一个,cur不为val
    }
    return head;


};

第一想法

知道思想,不知道怎么写

困难

过界

收获

  • TypeError: Cannot read properties of null (reading ‘XXX’)定义为空,找不到就会这样子

206.反转链表

/**
 * 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===null||head.next===null)  //若没有元素或只有一个元素,直接返回
        return head

    let newhead=new ListNode(0,null)    //新链表虚拟头节点
    while(head!==null){     
        let temp=new ListNode(head.val,newhead.next)  //建立一个node,val是head.val,next是虚拟头结点的next
        newhead.next=temp;   //temp设为头部
        head=head.next //下一个
    }
    return newhead.next;
};

//法二:双指针
var reverseList = function(head) {
    if(head===null||head.next===null)  //若没有元素或只有一个元素,直接返回
        return head
    let pre= head  
    let cur=head.next
    pre.next=null    //重点
    while(cur!==null){     
       let temp=cur.next  //记录cur的下一个
       cur.next=pre  //指针翻转
       pre=cur   //pre向前一步
       cur=temp  //cur跳转
    }
    return pre;
};

第一想法

法一

困难

法一:

  • while(head!==null)与while(head.next!==null)?

head.next是一个节点,若是后者,结果就是【4,3,2,1】,当head.val=5时,while不满足条件。
前者,head.val=5时,最后一行head.next===null不会错。
那TypeError: Cannot read properties of null (reading ‘XXX’)定义为空,到底是啥???


法二:

  • pre.next=null

没有的话,报错Error - Found cycle in the ListNode—>链表成为一个圈,一开始就cur和pre互相指。

为啥放while前,因为只断第一次pre的next

  • 定义

如果设虚拟节点且定义方法为,let pre=new ListNde(0,null)结果前面会多一个0,【0,5,4,3,2,1】
解决方式:let temp = null, pre = null, cur = head;

收获

  • 更熟练链表
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值