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

一、链表理论基础

定义

链表是一种通过指针串联再一起的线性结构,每个节点由两部分组成,一个是数据域,一个是指针域(指向下一个节点的指针),最后一个节点的指针域指向null(空指针)

如图所示

img

链表的类型

  • 单链表
  • 双链表
  • 循环链表
单链表

img

双链表

img

特点
  1. 两个指针域,一个指向下一个节点,一个指向上一个节点
  2. 既可以向前查询也可以向后查询
循环链表

img

特点

首位相连。可以解决约瑟夫环的问题。

链表的存储方式

  • 链表在内存中不是连续分布的,散乱分布在内存中的某个地址上,分配机制取决于操作系统的内存管理
  • 链表通过指针域链接在内存中的各个节点

链表的定义

lass ListNode {
  val;
  next = null;
  constructor(value) {
    this.val = value;
    this.next = null;
  }
}

链表的操作

  • 删除节点

img

  • 添加节点

img

二、203.移除链表元素

链接:203.移除链表元素

方法一:直接使用与啊来的链表来进行删除操作

var removeElements = function(head, val) {
    //非虚拟头节点 确定头节点
    while(head!=null&&head.val===val){
        head=head.next
    }
    var cur=head
    //找下一个指针|操作下一个指针的值
    while(cur!=null&&cur.next!=null){
        if(cur.next.val===val){
            cur.next=cur.next.next
        }else{
            cur=cur.next
        }
    }
    return head
}

方法二:设置一个虚拟头结点在进行删除操作

var removeElements = function(head, val) {
  //虚拟头节点
  //错误 否没有向下继续
  // while(cur.next!=null&&cur.next.val==val){
  //     cur.next=cur.next.next
  // }
  const ret = new ListNode(0, head);
  let cur = ret;
  while(cur.next) {
      if(cur.next.val === val) {
          cur.next =  cur.next.next;
          continue;
      }
      cur = cur.next;
  }
  return ret.next;
};

三、707.设计链表

class LinkNode {
    constructor(val, next) {
        this.val = val;
        this.next = next;
    }
}

/**
 * Initialize your data structure here.
 * 单链表 储存头尾节点 和 节点数量
 */
var MyLinkedList = function() {
    this._size = 0;
    this._tail = null;
    this._head = null;
};

/**
 * Get the value of the index-th node in the linked list. If the index is invalid, return -1. 
 * @param {number} index
 * @return {number}
 */
MyLinkedList.prototype.getNode = function(index) {
    if(index < 0 || index >= this._size) return null;
    // 创建虚拟头节点
    let cur = new LinkNode(0, this._head);
    // 0 -> head
    while(index-- >= 0) {
        cur = cur.next;
    }
    return cur;
};
MyLinkedList.prototype.get = function(index) {
    if(index < 0 || index >= this._size) return -1;
    // 获取当前节点
    return this.getNode(index).val;
};

/**
 * Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtHead = function(val) {
    const node = new LinkNode(val, this._head);
    this._head = node;
    this._size++;
    if(!this._tail) {
        this._tail = node;
    }
};

/**
 * Append a node of value val to the last element of the linked list. 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtTail = function(val) {
    const node = new LinkNode(val, null);
    this._size++;
    if(this._tail) {
        this._tail.next = node;
        this._tail = node;
        return;
    }
    this._tail = node;
    this._head = node;
};

/**
 * Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. 
 * @param {number} index 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtIndex = function(index, val) {
    if(index > this._size) return;
    if(index <= 0) {
        this.addAtHead(val);
        return;
    }
    if(index === this._size) {
        this.addAtTail(val);
        return;
    }
    // 获取目标节点的上一个的节点
    const node = this.getNode(index - 1);
    node.next = new LinkNode(val, node.next);
    this._size++;
};

/**
 * Delete the index-th node in the linked list, if the index is valid. 
 * @param {number} index
 * @return {void}
 */
MyLinkedList.prototype.deleteAtIndex = function(index) {
    if(index < 0 || index >= this._size) return;
    if(index === 0) {
        this._head = this._head.next;
        // 如果删除的这个节点同时是尾节点,要处理尾节点
        if(index === this._size - 1){
            this._tail = this._head
        }
        this._size--;
        return;
    }
    // 获取目标节点的上一个的节点
    const node = this.getNode(index - 1);    
    node.next = node.next.next;
    // 处理尾节点
    if(index === this._size - 1) {
        this._tail = node;
    }
    this._size--;
};

// MyLinkedList.prototype.out = function() {
//     let cur = this._head;
//     const res = [];
//     while(cur) {
//         res.push(cur.val);
//         cur = cur.next;
//     }
// };
/**
 * 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)
 */

四、206.反转链表

// 双指针:
var reverseList = function(head) {
  if(!head||!head.next) return head
    let pre=null,cur=head,temp=null;
    while(cur){
      temp=head->next
      cur.next=pre
      pre=cur
      cur=temp
    }
  return pre
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值