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

链表理论基础

链表的定义:

链表是⼀种通过指针串联在⼀起的线性结构,每⼀个节点由两部分组成,⼀个是数据域⼀个是指针域 (存放指向下⼀个节点的指针),最后⼀个节点的指针域指向null (空指针的意思)。
链表的⼊⼝节点称为链表的头结点也就是 head

链表的常见类型:

单链表
单链表中的指针域只能指向节点的下⼀个节点。
双链表
每⼀个节点有两个指针域,⼀个指向下⼀个节点,⼀个指向上⼀个节点。
双链表 既可以向前查询也可以向后查询。
循环链表
链表⾸尾相连

链表的存储方式

数组是在内存中是连续分布的,但是链表在内存中可不是连续分布的。
链表是通过指针域的指针链接在内存中各个节点。所以来链表在内存中是散乱分布的

链表的定义

class listNode{
    int val;
    listNode next;

    public listNode(){
    }

    public listNode(int val) {
        this.val = val;
    }

    public listNode(int val, listNode next) {
        this.val = val;
        this.next = next;
    }
}

链表的操作

删除节点

因为链表中的节点不能直接删除,所以需要找到待删除节点的前一个节点,让其指向待删除节点的后一个节点,这样即可完成删除,该操作结束后,待删除节点被自动回收装置回收即完成删除

如果要删除头节点让头节点后移即可(head=head.next)

增加节点

找到需要添加位置,让其前一个节点的next指向新节点,然后新节点的next指向 前一个节点的next

203.移除链表元素 

题目链接

LeetCode_203

视频链接

手把手带你学会操作链表 | LeetCode:203.移除链表元素

思路:

简单的数组删除操作

代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeElements(ListNode head, int val) {
           while (head!=null&&head.val==val){//如果头节点的val==val那么删除头节点
              head=head.next;//头节点直接后移
          }
          ListNode temp=head;//设置一个temp 指针指向头节点用来遍历链表
          while (temp!=null&&temp.next!=null){
              if(temp.next.val==val) {//如果找到需要删除的节点,直接删除
                  temp.next = temp.next.next;
              }else {
                  temp=temp.next;//如果找到需要删除的节点,temp后移继续找
              }
          }
        return head;
    }
}

使用虚拟头节点对删除操作进行统一

/**
 * Definition for singly-linked list.
 * public class ListNode {
 * int val;
 * ListNode next;
 * ListNode() {}
 * ListNode(int val) { this.val = val; }
 * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeElements(ListNode head, int val) {
         listNode  dummyhead=new listNode();//使用虚拟头节点对节点的增加和删除操作进行统一
     dummyhead.next=head;
     listNode temp=dummyhead;//这里遍历指针需要指向虚拟头节点(删除节点你需要找到前一个节点)所以这里需要指向虚拟头节点
     while (temp.next!=null){
         if(temp.next.val==val){
             temp.next=temp.next.next;
         }else {
             temp=temp.next;
         }
     }
     return dummyhead.next;
    }
    }
}

  

707.设计链表

题目链接

LeetCode_707

视屏链接

手把手带你学会操作链表 | LeetCode:203.移除链表元素、、

代码:

class Node{//编写节点类
    int val;
    Node next;
    public Node(int val) {//节点构造函数
        this.val = val;
    }
}

class LinkedList{//创建链表类
    Node dummyhead;//虚拟头节点
    int size;//链表当前大小

    public void MyLinkedList() {//链表类的初始化
        dummyhead=new Node(0);
        size=0;
    }

    public int get(int index) {//获取指定节点的val
      if(index<0||index>size){
          return -1;
      }
      Node curnt=dummyhead;
        for (int i = 0; i <=index ; i++) {
            curnt=curnt.next;
        }
        return curnt.val;
    }

    public void addAtHead(int val) {//将一个值为 val 的节点插入到链表中第一个元素之前
        Node newnode = new Node(val);
        newnode.next=dummyhead.next;
        dummyhead.next=newnode;
        size++;
    }

    public void addAtTail(int val) {//将一个值为 val 的节点插入到链表中末端
        Node curnt=dummyhead;
        while (curnt.next!=null){
            curnt=curnt.next;
        }
        curnt.next=new Node(val);
        size++;
    }

    public void addAtIndex(int index, int val) {//在第n个元素前添加一个节点
        Node curnt=dummyhead;
       while (index-->0) {
           curnt = curnt.next;
       }
        Node newnode = new Node(val);
        newnode.next=curnt.next;
        curnt.next=newnode;
        size++;
    }

    public void deleteAtIndex(int index) {//如果下标有效,则删除链表中下标为 index 的节点
        Node curnt=dummyhead;
        while (index-->0) {
            curnt = curnt.next;
        }
        curnt.next=curnt.next.next;
        size--;
    }
}

206.反转链表

题目链接

LeetCode_206

视频链接

手把手带你学会操作链表 | LeetCode:203.移除链表元素

思路:

使用双指针,⾸先定义⼀个cur指针,指向头结点,再定义⼀个pre指针,初始化为null。 然后就要开始反转了,⾸先要把 cur->next 节点⽤tmp指针保存⼀下,也就是保存⼀下这个节点。 为什么要保存⼀下这个节点呢,因为接下来要改变 cur->next 的指向了,将cur->next 指向pre ,此时已经反转了 第⼀个节点了。 接下来,就是循环⾛如下代码逻辑了,继续移动precur指针。

代码:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
       ListNode pre=null;//pre指针指向头节点前一个
       ListNode cur=head;//cur指针指向头节点
       ListNode temp;//临时变量保存cur.next
       while (cur!=null){
           temp=cur.next;
           cur.next=pre;
           pre=cur;
           cur=temp;
       }
       return pre;
    }
}

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值