day 3|| 203.移除链表元素、707.设计链表、206.反转链表

203. 移除链表元素

class Solution {
    public ListNode removeElements(ListNode head, int val) {
        if(head == null){    //如果第一个节点不存在则返回第一个节点
            retrun head;
        }else{                      
            while(head != null){        //如果第一个节点存在则开始判断
                if(head.val == val){             //如果节点中元素和val相同则删除
                    head = null;
                }else{                      //如果不相同则保留并且判断下一个元素
                    head = head.next;
                }
            }
            retrun head;
        }
    }
}

return 那里报错,不知为何。看解视频先。

如果删除的是第一个节点,怎么删,不是第一个节点又该怎么删,进行判断。用虚拟头结点可以统一删除规则,创建一个指针去遍历链表。

看完视频自己敲一波:

class Solution {
    public ListNode removeElements(ListNode head, int val) {
        ListNode ln = new ListNode();   
        ln.next = head;             //创建一个虚拟头结点并指向头结点
        ListNode crr = new ListNode();    
        crr = head;                 //创建一个指针指向头结点开始遍历链表
        while(crr.next != null){    //当指针的下一个节点不为空时进入循环
            if(crr.val == val){      //如果元素相同则删除
                crr.next = crr.next.next;
            }else{
                crr = crr.next;         //如果不相同则将指针crr移到下一个元素进行循环判断
            }         
        }
            return ln.next;             //无论下一个结点是否存在,都可以返回虚拟头结点的下一个结点。
    }
}

可以运行,但是结果不对,看一下为啥:第一、第二行注释那里,不是将crr指向实际的头结点,而是指向虚拟的头结点ln,不然就不能执行同样的删除操作了,如果指向头结点,那么头结点的val和目标val相同的时候无法删除真正的头结点。第二、if判断里的应该是crr.next.val而不是crr.val,此错误是由于第一个错误所引起的连环错误。改正之后则运行成功。

---------------------------------------------------------------------------------------------------------------------------------

707. 设计链表

class Node {
    int val;
    Node next;
    Node(){}
    Node(int val){
        this.val = val;
    }
}



class MyLinkedList {
    int size;       //size存储链表元素的个数

    Node head;      //头结点

    //初始化链表
    public MyLinkedList() {
        size = 0;
        head = new Node(0);

    }
    
    public int get(int index) {
        if(index < 0 || index >= size){
            return -1;
        }
        Node cur = head;    //搞个指针指向头结点
        for(int i = 0;i <= index;i++){  //将指针移动到index的位置
            cur = cur.next;
        }
        return cur.val;


    }
    
    public void addAtHead(int val) {
        // Node newnode = new Node(val);   //新建一个val的结点
        // Node frontnode = new Node();        //新建一个虚拟结点指向头结点
        // frontnode.next = head;
        // newnode.next = frontnode.next;      //这里是关键,先将链表后面的一连串被新建结点所指向才不会丢失
        // frontnode.next = newnode;
        // size += 1;
        addAtIndex(0,val);

    }
    
    public void addAtTail(int val) {
        // Node newnode = new Node(val);   //新建一个值为val的点
        // Node crr = new Node();      //新建一个指针指向头结点
        // crr.next = head;
        // for(int i = 0;i <= size;i++){
        //         crr.next = crr;
        // }
        //     crr.next = newnode;
        //     size++;
        addAtIndex(size,val);

    }
    
    public void addAtIndex(int index, int val) {
        if(index > size){
            return;
        }
        if(index < 0){
            index = 0;
        }
        size++;
        //新建一个指针指向head
        Node front = head;
        for(int i = 0;i < index;i++){
                front.next = front;
        }
        Node newnode = new Node(val);   //新建要插入的结点
        newnode.next = front.next;
        front.next = newnode;

    }
    
    public void deleteAtIndex(int index) {
        if(index < 0 || index >= size){
            return;
        }
        size--;
        if(index == 0){
            head = head.next;
            return;
        }
        //设一个指针指向head
        Node front = head;
        for(int i = 0;i < index;i++){
            front = front.next;
        }
        front.next = front.next.next;

    }
}

注意删除和添加的关键步骤,步骤错了会导致链表丢失。代码来回看了几遍,找不出问题。 

---------------------------------------------------------------------------------------------------------------------------------

206. 反转链表

先将指针移到末尾,再往回移动。 但是倒数的时候不好表示结点,于是想到还是正着循环,用cur来表示反转之前的最后一个元素以至于不会导致链表的丢失。那么怎么分别表示两个结点呢?想到用上下两个指针来做移动循环。

class Solution {
    
    public ListNode reverseList(ListNode head) {
        ListNode up = head;     //搞一个上指针up并告诉head的位置
        ListNode down = head.next;  //搞一个下指针down并将head的下一个结点的位置告之
        while(down.next != null){       //当down指针尾不为空的时候一直循环
            down.next = up;
            up = up.next;
        }
        return down;
        
    }
}

大概操作感觉没问题,但是超出时间限制。看看讲解视频先。

我发现down指针好像没有移动,再改改。

    public ListNode reverseList(ListNode head) {
        ListNode up = head;     //搞一个上指针up并告诉head的位置
        ListNode down = head.next;  //搞一个下指针down并将head的下一个结点的位置告之
        while(down.next != null){       //当down指针尾不为空的时候一直循环
            ListNode temp = new ListNode(); //新建一个临时结点存放up的值
            temp = up;
            down.next = up;
            up = temp.next;
        }
        return down;
        
    }
}

还是超时,再看看。

class Solution {
    
    public ListNode reverseList(ListNode head) {
        ListNode pre = null;    //搞个pre指针为空,即head的前面一个
        ListNode cur = head;    //搞个cur指针指向head
        ListNode temp = null;   //搞个temp为空存临时结点
        while(cur != null){     //当cur不是空时执行循环
            temp = cur.next;    //将cur下一个结点存入临时结点
            cur.next = pre;     //开始第一个结点和第二个结点的反转
            pre = cur;          //完成第一个反转后将pre移动到cur的位置
            cur = temp;         //将cur的下一个结点即存入temp的临时值给cur即将cur移动到下一个结点
        }
        return pre;
    }
}

 重新做一次。还有递归的代码,再试试。

class Solution {
    public ListNode reverseList(ListNode head) {
        return reverse(null,head);
    }

    private ListNode reverse(ListNode pre, ListNode cur){
        if(cur == null){
            return pre;
        }
        ListNode temp = null;
        temp = cur.next;
        cur.next = pre;
        return reverse(cur,temp);
    }
}

 好好理解一下递归的方法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值