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

203.移除链表元素

  • 刷题icon-default.png?t=N7T8https://leetcode.cn/problems/remove-linked-list-elements/description/
  • 文章讲解icon-default.png?t=N7T8https://programmercarl.com/0203.%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8%E5%85%83%E7%B4%A0.html
  • 视频讲解icon-default.png?t=N7T8https://www.bilibili.com/video/BV18B4y1s7R9/?vd_source=af4853e80f89e28094a5fe1e220d9062
  • 题解1(带虚拟头结点实现):
/**
 * 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 dummyNode = new ListNode();
        dummyNode.next = head;
        ListNode current = dummyNode;
        while(current.next != null){
            if(current.next.val == val){
                current.next = current.next.next;
            }else{
                current = current.next;
            }
        }
        // 返回新链表的头结点(虚拟头结点指向的新的head,原head可能已被删除)
        return dummyNode.next;
    }
}
  •  题解2(不带头结点链表实现):
/**
 * 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 current = head;
        // 若传入空链表,直接返回
        if(head == null){
            return head;
        }
        // 处理链表头结点等于val状态
        while(head != null && head.val == val){
            head = head.next;
        }
        // 处理正常状态
        while(current.next != null){
            if(current.next.val == val){
                current.next = current.next.next;
            }else{
                current = current.next;
            }
        }
        // 返回处理后的链表
        return head;
    }
}

 707.设计链表

  • 刷题icon-default.png?t=N7T8https://leetcode.cn/problems/design-linked-list/description/
  • 文章讲解icon-default.png?t=N7T8https://programmercarl.com/0707.%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8.html
  • 视频讲解icon-default.png?t=N7T8https://www.bilibili.com/video/BV1FU4y1X7WD/?spm_id_from=333.788&vd_source=af4853e80f89e28094a5fe1e220d9062
  • 题解(不使用JavaApi偷懒的版本):
// 表结点类
class LinkNode{
    //下一个结点
    LinkNode next;
    //当前结点的值 
    int val;    
    // 构造函数
    public LinkNode(){}
    public LinkNode(int val){
        this.val = val;
    }
}
// 链表类
class MyLinkedList {
    // 初始化链表长度
    int size;
    // 初始化链表头结点
    LinkNode head;
    // 使用虚拟头结点
    LinkNode dummyNode = new LinkNode();
    //MyLinkedList() 初始化 MyLinkedList 对象。
    public MyLinkedList() {
        size = 0;
        // debug:head只是一个头指针,初始化的时候不能为其分配结点空间。
                //初始结点空间分配在虚拟头结点dummyNode身上。
        // head = new LinkNode();
        dummyNode.next = head;
    }
    // int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。
    public int get(int index) {
        // 检查输入index的合法性
        if(index < 0 || index > size-1){
            return -1;
        }
        LinkNode current = dummyNode;
        while(index != 0){
            current = current.next;
            index--;
        }
        return current.next.val;
    }
    // void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。
    // 在插入完成后,新节点会成为链表的第一个节点。
    public void addAtHead(int val) {
        LinkNode newNode = new LinkNode(val);
        newNode.next = dummyNode.next;
        dummyNode.next = newNode;
        head = dummyNode.next;
        size++;
    }
    // void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。
    public void addAtTail(int val) {
        LinkNode newNode = new LinkNode(val);
        LinkNode current = dummyNode;
        while(current.next != null){
            current = current.next;
        }
        current.next = newNode;
        size++;
    }
    // void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。
    // 如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将不会插入到链表中。
    public void addAtIndex(int index, int val) {
        if(index < 0 || index > size){
            return;
        }
        LinkNode newNode = new LinkNode(val);
        LinkNode current = dummyNode;
        while(index != 0){
            current = current.next;
            index--;
        }
        newNode.next = current.next;
        current.next = newNode;
        head = dummyNode.next;
        size++;
    }
    // void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。
    public void deleteAtIndex(int index) {
        if(index < 0 || index > size - 1){
            return;
        }
        LinkNode current = dummyNode;
        while(index != 0){
            current = current.next;
            index--;
        }
        current.next = current.next.next;
        head = dummyNode.next;
        size--;
    }
}



/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList obj = new MyLinkedList();
 * int param_1 = obj.get(index);
 * obj.addAtHead(val);
 * obj.addAtTail(val);
 * obj.addAtIndex(index,val);
 * obj.deleteAtIndex(index);
 */
debug记录:
  1. 看了一晚上没发现问题,第二天发现问题:写顺手了head指针初始化的时候分配了实际空间。
  2. dummy虚拟头结点承担了初始化时的初始空间分配,head只是一个辅助指针,初始化时不能空间分配,否则会莫名其妙多一个结点。 
  3. 并且,若链表结构发生变化,记得链表实际头结点为dummy.next,因为变化有可能使原链表head发生变动。
  4. 当然也可以使用JavaApi偷懒,但是我不想。

206.反转链表

  • 刷题
  • 文章讲解
  • 视频讲解
  • 题解1(双指针解法):
/**
 * 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) {
        // 若传入链表为空
        if(head == null){
            return head;
        }
        ListNode current = head,pre = null,temp = current.next;
        while(current != null){
            temp = current.next;
            current.next = pre;
            pre = current;
            current = temp;
        }
        return pre;
    }
}
  • 题解2(递归解法): 
/**
 * 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 reverse(ListNode current,ListNode pre){
        // 递归边界条件
        if(current == null){
            return pre;
        }
        ListNode temp = current.next;
        current.next = pre;
        return reverse(temp,current);
    }
    public ListNode reverseList(ListNode head) {
        return reverse(head,null);
    }
}

 

你可能感兴趣的:(代码随想录训练营一刷,算法,链表,数据结构)