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

203.移除链表元素

解法:代码随想录

链表题之前做过类似的所以,很快想到用虚拟节点。虚拟节点的next指向head,然后从虚拟节点开始扫。最后直接return 虚拟节点的next。这道题一开始没有考虑连续出现val == target的情况所以在大while里面只设置了一个if,应该再用一个while来持续扫。

class Solution {
    public ListNode removeElements(ListNode head, int val) {
        ListNode slide = new ListNode();
        slide.next = head;
        head = slide;
        while(slide != null) {
            while (slide.next != null && slide.next.val == val) {
                slide.next = slide.next.next;
            }
            slide = slide.next;
        }
        return head.next;
    }
}

看了解析此题还有别的解法:

1.不设置虚拟节点,在前面用一个while扫到一个val != traget的节点,然后从此节点开始操作。

2.同时可以设置一个节点来记录之前的一个节点(prev). 当有val == target的情况,prev.next = cur.next; 并且 cur = cur.next;

707.设计链表

一开始自己做的时候把head当作一个实际节点而不是虚拟节点,导致需要判定的东西很多,同时addAtTaile和addAtLast也分别需要独自的判定才能完成。最后又写成一坨,接着就开始看讲解。

第二遍写的时候有两点导致无法AC

1. addAtIndex的时候可以index等与size想当与添加到末尾。(我想当然写成 index >= size就return

2. 在add的时候如果index小于0直接将index设置成0,完全没有注意到这点。看了答案才知道。

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 MyLinkedList {

    ListNode head;
    int size;
    public MyLinkedList() {
        head = new ListNode();
        int size = 0;
    }
    
    public int get(int index) {
        if (index < 0 || index >= size) return -1;
        ListNode slide = head;
        while (index > 0) {
            index--;
            slide = slide.next;
        }
        return slide.next.val;  
    }
    
    public void addAtHead(int val) {
        addAtIndex(0, val);
    }
    
    public void addAtTail(int val) {
        //index 可以等于size, 再次注意
        addAtIndex(size, val);
    }
    
    public void addAtIndex(int index, int val) {
        //index可以等于size
        if (index > size) return;
        if (index < 0) index = 0;
        ListNode slide = head;
        while (index > 0) {
            index--;
            slide = slide.next;
        }
        slide.next = new ListNode(val, slide.next);
        size++;
    }
    
    public void deleteAtIndex(int index) {
        if (index < 0 || index >= size) return;
        ListNode slide = head;
        while (index > 0) {
            index--;
            slide = slide.next;
        }
        size--;
        slide.next = slide.next.next;
    }
}

double linked周末再看吧

206.反转链表

这道题上个月做过还有,所以还有印象。上次第一次自己做的时候,用的stack来实现的反转,第一遍遍历存储到stack里面,第二遍遍历在pop的同时翻转。

看别人的code,发现除了stack,此题可以设置一个节点来记录前一个节点(ListNode prev = null), 这样可以实现在遍历的同时实现翻转。所以这次重新写,就用了这个方法。

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        while (head != null) {
            ListNode tmp = head.next;
            head.next = prev;
            prev = head;
            head = tmp;
        }
        return prev;
    }
}

同时试了试递归的写法,绕了半天绕出来了,递归本质上逻辑一致,还是需要一个prev来记录之前的node。在扫到null的时候递归终止,直接return上一个prev,而在此之前的loop只需要记录这个最后一个node并且return,这个node就是新的head。

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

    public ListNode helper(ListNode node, ListNode prev) {
        if (node == null) return prev;
        ListNode tmp = node.next;
        node.next = prev;
        return helper(tmp, node);
    }
}

看了解析,差不多一样,发现还有一种从后往前递归,这个有缘再看。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值