做题总结 707. 设计链表

文章介绍了LeetCode中单链表节点的默认定义,讨论了Java中构造函数的应用,以及如何在MyLinkedList类中正确处理链表操作,如添加、获取和删除节点,包括使用虚拟头节点简化索引查找。

leetcode中单链表节点的默认定义

class ListNode {
    int val;
    ListNode next;
    //无参
    public ListNode() {
    }
    //有参:1
    public ListNode(int val) {
        this.val = val;
    }
    //有参:2
    public ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}

如果不定义构造函数使用默认构造函数的话,在初始化的时候就不能直接给变量赋值。

我的尝试

请注意这段代码是错的,请勿参考

错误分析:
① 题目 “你可以选择使用单链表或者双链表,设计并实现自己的链表。” 是使用力扣官方给的单链表和双链表,然后设计实现自己的链表MyLinkedList 。单链表为 ListNode。
② MyLinkedList 中使用 ListNode类。
③ 添加一个变量 size,记录 MyLinkedList 中节点的个数。
④ 【问题】java中 this 指针可以更改指向吗?
MyLinkedList myLinkedList; myLinkedList.addAtHead(1); 这样是没法调用的,会报错,《might not have been initialized》
⑥ 下文代码中的 this==null 也是多余的,IDEA上说《Condition ‘this == null’ is always ‘false’》。我分析是因为this是 java虚拟机给每个对象分配的,代表当前对象。而对象一定是需要在堆中new出来的。如果只是MyLinkedList myLinkedList; 其实这个变量只是在栈中定义,堆中并没有对象。
⑦ 虚拟头节点/哑节点/dummy head,是为了方便增删。
⑧ 力扣中定义的class是可以加属性的。

//代码是错的,请勿参考。
class MyLinkedList {
    int val;
    MyLinkedList next;

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

    public int get(int index) {
        if(index < 0) return -1;//下标无效
        //this有可能为空吗?
        int count=0;
        MyLinkedList h = this;
        while(h!=null) {
            if(count == index) {
                return h.val;
            }
            h = h.next;
            count++;
        }
        return -1;
    }

    public void addAtHead(int val) {
        MyLinkedList newhead = new MyLinkedList();
        newhead.val = val;
        newhead.next = this;
        this = newhead;
    }

    public void addAtTail(int val) {
        MyLinkedList newnode = new MyLinkedList();
        newnode.val = val;
        newnode.next = null;

        if(this == null) {
            this = newnode;
        } else {
            MyLinkedList temp = this;
            while(temp.next != null) {
                temp = temp.next;
            }
            temp.next = newnode;
        }
    }

    public void addAtIndex(int index, int val) {
        //链表为空:index再合法也没用
        //index不合法
        //index超过链表长度
        //加在中间
        //加在末尾

        if(this == null) return;
        if(index < 0) return;

        MyLinkedList newnode = new MyLinkedList();
        newnode.val = val;
        newnode.next = null;

        //哑节点
        MyLinkedList newh = new MyLinkedList();
        newh.next = this;
        //temp
        MyLinkedList temp = newh;

        //计数
        int count=0;

        while(temp.next!=null) {
            if(count == index) {
                newnode.next = temp.next.next;
                temp.next = newnode;
                return;
            }
            count++;
            temp = temp.next;
        }
        if(index == count) {
            temp.next = newnode;
        }

        return;//index超过链表长度
    }

    public void deleteAtIndex(int index) {

    }
}

正确运行的代码(java)

分析:
① get、addAtIndex、 deleteAtIndex中的 for循环查找 index 用的是同一套逻辑,for循环之后,temp所在的位置是 目标为index节点的前一个
② addAtHead、addAtTail 可以合并到addAtIndex中。
③ size这个变量很巧妙得同时考虑到了,链表为空和 index大于链表长度的情况。

class MyLinkedList {
    int size;
    ListNode head;//注意这里是单链表节点 ListNode
    //虚拟头节点

    public MyLinkedList() {
        this.size = 0;
        head = new ListNode(0);//注意这里是单链表节点 ListNode
    }
    
    public int get(int index) {
        if(index < 0 || index >=size) {
            return -1;
        }

        ListNode temp = this.head;
        for(int i=0; i<index; i++) {
            temp = temp.next;
        }
        return temp.next.val;//这里
    }
    
    public void addAtHead(int val) {
        addAtIndex(0,val);
    }
    
    public void addAtTail(int val) {
        addAtIndex(size,val);
    }
    
    public void addAtIndex(int index, int val) {
        if(index < 0 || index > size) {
            return;
        }
        //size避免了链表为空,index大于链表长度的情况

        ListNode node = new ListNode(val);
        ListNode temp = this.head;
        for(int i=0; i<index; i++) {
            temp = temp.next;
        }
        node.next = temp.next;
        temp.next = node;
        size++;
    }
    
    public void deleteAtIndex(int index) {
        if(index < 0 || index >= size) {
            return;
        }
        ListNode temp = this.head;
        for(int i=0; i<index; i++) {
            temp = temp.next;
        }
        temp.next = temp.next.next;
        size--;//这里
    }
}

class ListNode {
    int val;
    ListNode next;
    //无参
    public ListNode() {
    }
    //有参:1
    public ListNode(int val) {
        this.val = val;
    }
    //有参:2
    public ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}

在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值