代码随想录算法训练营第3天

今日任务

● 链表理论基础 ● 203.移除链表元素 ● 707.设计链表 ● 206.反转链表

链接:https://docs.qq.com/doc/DUGdqYWNYeGhlaVR6 (opens in a new tab)

链表理论基础

复习一下C++和Java怎么声明、创建单链表

struct ListNode {
    int val;  // 节点上存储的元素
    ListNode *next;  // 指向下一个节点的指针
    ListNode(int x) : val(x), next(NULL) {}  // 节点的构造函数
};
public class ListNode {
    int val;  // 结点的值
    ListNode next;  // 下一个结点
 
    public ListNode() {  // 节点的构造函数(无参)
    }
 
    public ListNode(int val) {  // 节点的构造函数(有一个参数)
        this.val = val;
    }
 
    public ListNode(int val, ListNode next) {  // 节点的构造函数(有两个参数)
        this.val = val;
        this.next = next;
    }
}

203.移除链表元素

设置一个虚拟头结点,这样原链表的所有节点就都可以按照统一的方式进行移除了。

自己想法

/**
 * 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 dummy = new ListNode(-1, head);
        ListNode cur = dummy.next;
        ListNode pre = dummy;
 
        while (cur != null) {
            if (cur.val == val) {
                // delete cur
                pre.next = cur.next;
            }
            else {
                pre = cur;
            }
            cur = cur.next;
        }
 
        return dummy.next;
    }
}

题解想法

困难

回顾

回顾虚拟头结点的思想。

707.设计链表

自己想法

class MyLinkedList {
    class ListNode {
        int val;
        ListNode next;
 
        public ListNode(int val, ListNode next) {
            this.val = val;
            this.next = next;
        }
    }
 
    ListNode head;
    ListNode dummy;
    int length;
 
    public MyLinkedList() {
        this.length = 0;
        this.head = null;
        this.dummy = new ListNode(-1, null);
    }
 
    public int get(int index) {
        ListNode cur = this.head;
        if (0 <= index && index <= this.length - 1) {
            for (int i = 0; i < index; i++) {
                cur = cur.next;
            }
            return cur.val;
        }
        else {
            return -1;
        }
    }
 
    public void addAtHead(int val) {
        ListNode tmp;
        if (this.length == 0) {
            tmp = new ListNode(val, null);
        }
        else {
            tmp = new ListNode(val, this.head);
        }
        this.head = tmp;
        this.length ++;
    }
 
    public void addAtTail(int val) {
        this.addAtIndex(this.length, val);
    }
 
    public void addAtIndex(int index, int val) {
        this.dummy.next = this.head;
        ListNode cur = this.dummy.next;
        ListNode pre = this.dummy;
        if (0 <= index && index <= this.length) {
            for (int i = 0; i < index; i++) {
                pre = cur;
                cur = cur.next;
            }
            ListNode tmp = new ListNode(val, cur);
            pre.next = tmp;
            this.length ++;
            this.head = this.dummy.next;
        }
    }
 
    public void deleteAtIndex(int index) {
        this.dummy.next = this.head;
        ListNode cur = this.dummy.next;
        ListNode pre = this.dummy;
        if (0 <= index && index < this.length) {
            for (int i = 0; i < index; i++) {
                pre = cur;
                cur = cur.next;
            }
            pre.next = cur.next;
            this.length --;
            this.head = this.dummy.next;
        }
    }
}

题解想法

困难

回顾

206.反转链表

自己想法

相当于新建一个链表,每次往头部插入一个节点。

/**
 * 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) {
            ListNode reverse_head = new ListNode(head.val, null);
            ListNode cur = head.next;
            while (cur != null) {
                ListNode tmp = new ListNode(cur.val, reverse_head);
                reverse_head = tmp;
                cur = cur.next;
            }
            return reverse_head;
        }
        else {
            return null;
        }
    }
}

题解想法

如果再定义一个新的链表,实现链表元素的反转,其实这是对内存空间的浪费。

其实只需要改变链表的next指针的指向,直接将链表反转 ,而不用重新定义一个新的链表。

一个 cur 一个 pre 指针就好。

困难

回顾