【KOKO-代码随想录算法训练营Day 3【链表】|203|707|206

KOKO-代码随想录算法训练营Day 3|203|707|206



一、203 移除链表元素

1.题目

https://leetcode.cn/problems/remove-linked-list-elements/

2.代码

 public ListNode removeElements(ListNode head, int val) {
        if(head==null){
            return null;
        }
        ListNode node=new ListNode(-1);
        node.next=head;
        ListNode res=node;
        while (head!=null){
            if(head.val==val){
                res.next=head.next;
            }else {
                res=res.next;
            }
            head=head.next;
        }
        return node.next;
    }

3.总结

1.移除链表,为了移除头节点,应创建一个虚拟头节点指向头节点,可以将移除操作统一化。令,题目给的val值都是>=0的,说明可以创建一个虚拟头节点的值小于0,即-1.
2.再对链表操作时,定义的带虚拟头节点如node,不做遍历操作,即(node=node.next,这种操作一般用临时指针去做。如cur=cur.next,cur指向虚拟头节点)定义的带虚拟头节点的链表作为返回值,临时指针遍历节点。
3.删除或插入都需要知道当前节点的前一个节点,可以用pre,或cur.next表示。移动前一个,移动后一个。

二、707 设计链表

1.题目

https://leetcode.cn/problems/design-linked-list/

2.代码

public class MyLinkedList {
    int val;
    MyLinkedList next;

    public MyLinkedList() {
       this.next=null;
       this.val=-1;
    }

    public int get(int index) {
        int res=-1;
        MyLinkedList node=this.next;
        while (node!=null){
            res=node.val;
            node=node.next;
            if(index==0){
                return res;
            }
            index--;
        }
        return -1;
    }

    public void addAtHead(int val) {
        MyLinkedList node=new MyLinkedList();
        node.val=val;
        if (this.next==null){
            this.next=node;
        }else {
            MyLinkedList nodes=this.next;
            node.next=nodes;
            this.next=node;
        }
    }

    public void addAtTail(int val) {
        MyLinkedList node=this.next;
        MyLinkedList nodes=new MyLinkedList();
        nodes.val=val;
        if(node==null){
            this.next=nodes;
        }else {
            while (node.next!=null){
                node=node.next;
            }
            node.next=nodes;
        }

    }

    public void addAtIndex(int index, int val) {
        MyLinkedList node=new MyLinkedList();
        node.val=val;
        MyLinkedList head=this.next;
        MyLinkedList res=this;
        while (head!=null&&index>0){
            head=head.next;
            res=res.next;
            index--;
        }
        if(index==0){
            node.next=head;
            res.next=node;
        }
    }

    public void deleteAtIndex(int index) {
        MyLinkedList head=this.next;
        MyLinkedList res=this;
        while (head!=null&&index>0){
            head=head.next;
            res=res.next;
            index--;
        }
        if(head!=null){
            res.next=head.next;
        }

    }
}

3.总结

1.我在写这个题时,直接将MyLinkedList 定义成了链表的数据结构,在初始化时定义了虚拟头节点,不够清晰,应当定义一个内部类,此外用size去维护链表的大小。
2.在头节点之前插入元素和在下标0前插入元素,尾部插入元素应当属于同一种方法,都是在下 标i处插入元素。
3.插入:
向第一个元素插入时,直接插即可。
new node();node.next=pre.next;
pre.next=node;
4.删除:
插入或删除都需要找出下标为index的元素,不同于插入,删除的下标为0时,直接让头节点指向下一个即可,否则会报空指针,因为pre.next=null;null.next.next会报空指针。
while(index–>0){
pre=pre.next}
pre为要操作元素的前一个下标。因为==0时不走while里的语句。
5.看完卡哥的题目详解后代码优化如下:

package com.suanfa.lianbiao;

class LinkedListNode{
    int val;
    LinkedListNode next;

    public LinkedListNode(int val) {
        this.val = val;
    }
}
public class MyLinkedList2 {
    int size;//维护链表大小

    LinkedListNode head;//虚拟头节点

    public MyLinkedList2(){
        size=0;
        head=new LinkedListNode(0);
    }

    public int get(int index){
        if(index<0||index>=size){
            return -1;
        }
        LinkedListNode cur=head.next;
        while (index-->0){
            cur=cur.next;
        }
        return cur.val;
    }

    public void addAtHead(int val){
        addAtIndex(0,val);

    }
    public void addAtTail(int val){
        addAtIndex(size,val); //用size,表示在末尾之后添加。
    }
    public void addAtIndex(int index, int val){
        LinkedListNode pre=head;
        if(index<0||index>size){
            return;
        }
        if(size<0 ){
            index=0;
        }
        while (index-->0){
            pre=pre.next;
        }
        LinkedListNode node = new LinkedListNode(val);
        node.next=pre.next; //head如果没有初始化,这里pre.next会报错。
        pre.next=node;
        size++;
    }
    public void deleteAtIndex(int index){
        if(index<0||index>=size){
            return;
        }
        size--;
        if(index==0){
            head=head.next;
            return;
        }
        LinkedListNode pre=head;
        while (index-->0){
            pre=pre.next;
        }
        pre.next=pre.next.next;
    }
}

三. 206.反转链表

1.题目:

https://leetcode.cn/problems/reverse-linked-list/

2.代码:

public static ListNode reverseList(ListNode head) {
        ListNode node=head.next;
        head.next=null;
        while (node!=null){
            ListNode temp=node;
            node=node.next;
            temp.next=head;
            head=temp;
        }
        return head;
    }

3.总结:

总结

1.定义两个指针,一个为head,一个指向头节点的下一个节点,用head记录翻转之后,temp保存临时节点。将每个节点和下一个节点分隔开。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值