程式碼隨想錄演算法訓練營,8月30日 | 203.移除連結串列元素, 707.設計連結串列, 206.反轉連結串列

漪欢酒發表於2024-08-30

連結串列理論基礎
1.單連結串列:資料域和指標域(指向下一個結點的位置)組成,頭結點,結尾為空指標;雙連結串列:多了一個指向前一個結點的指標;迴圈連結串列:結尾指向頭結點。
2.連結串列在記憶體中的儲存不是順序的,跟陣列不同,要找一個資料只能透過前一個資料來找,所有這就導致連結串列的查詢比陣列麻煩,但是插入刪除資料卻更方便(只用修改前面的資料的指標,以及將自己的指標指向下一個資料)。
3.Java裡定義一個連結串列:

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.移除連結串列元素
題目連結:203.移除連結串列元素
文件講解︰程式碼隨想錄(programmercarl.com)
影片講解︰移除連結串列元素
日期:2024-08-30

思路:1.移除連結串列的元素想到連結串列的結構,將要移除的元素的前一個元素的指標變成指向它的下一個元素的就行了,但還要考慮到頭結點沒有前一個元素,單獨提出來操作;
2.增加一個虛擬頭結點指向頭結點就可以免去單獨操作頭結點的操作。
Java程式碼如下:

//原陣列上操作
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        while(head != null && head.val == val){
            head = head.next;
        }
        ListNode cur = head;
        while(cur != null && cur.next != null){
            if(cur.next.val == val){
                cur.next = cur.next.next;
            }else{
                cur = cur.next;
            }
        }
        return head;
    }
}
//虛擬頭結點
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        ListNode dummyHead = new ListNode();
        dummyHead.next = head;
        ListNode cur = dummyHead;
        while(cur != null && cur.next != null){
            if(cur.next.val == val){
                cur.next = cur.next.next;
            }else{
                cur = cur.next;
            }
        }
        return dummyHead.next;//注意這個才是新的頭結點
    }
}

總結:連結串列很多時候都要考慮特殊的那個頭結點,加一個虛擬的頭結點就讓它不特殊了,可以像其他結點一樣操作

707.設計連結串列
題目連結:707.設計連結串列
文件講解︰程式碼隨想錄(programmercarl.com)
影片講解︰設計連結串列
日期:2024-08-30

思路:首先這道題要先知道Java中連結串列的結構是怎麼定義的,清楚了後再考慮是不是能用虛擬頭結點來避免很多有關頭結點的討論,還有一點就是既然有要求再index這個位置插入,那麼我必須知道index這個值到底在不在連結串列中,所有我們在定義MyLinkedList時還要考慮一個size這個值,並且後面增刪也要對應的改動。
Java程式碼如下:

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 {
    int size;
    ListNode dummyHead;
    public MyLinkedList() {
        dummyHead = new ListNode(0);//這是一個虛擬頭結點
        size = 0;
    }
    
    public int get(int index) {
        if(index < 0 || index > size - 1){
            return -1;
        }
        ListNode cur = dummyHead;
        for(int i = 0; i < index + 1; i++){//這裡的是index + 1
            cur = cur.next;
        }
        return cur.val;
    }
    
    public void addAtHead(int val) {
        ListNode node = new ListNode(val);
        node.next = dummyHead.next;
        dummyHead.next = node;
        size++;
    }
    
    public void addAtTail(int val) {
        ListNode node = new ListNode(val);
        ListNode cur = dummyHead;
        while(cur.next != null){
            cur = cur.next;
        }
        cur.next = node;
        size++;
    }
    
    public void addAtIndex(int index, int val) {
        if(index < 0 ){
            index = 0;
        }
        if(index > size){
            return;
        }
        ListNode node = new ListNode(val);
        ListNode cur = dummyHead;
        for(int i = 0; i < index; i++){
            cur = cur.next;
        }
        node.next = cur.next;
        cur.next = node;
        size++;
    }
    
    public void deleteAtIndex(int index) {
        if(index < 0 || index > size - 1){
            return;
        }
        ListNode cur = dummyHead;
        for(int i = 0; i < index; i++){
            cur = cur.next;
        }
        cur.next = cur.next.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);
 */

總結:清楚了連結串列的定義以及用了虛擬頭結點後就比較容易了,增刪也是些基本的操作。

206.反轉連結串列
題目連結:206.反轉連結串列
文件講解︰程式碼隨想錄(programmercarl.com)
影片講解︰反轉連結串列
日期:2024-08-30

思路:直接在連結串列原本上操作,改下指標的方向,從頭開始的話cur = head,cur要指向null(pre前一個結點),但這之前要保留下cur.next,反轉完了,pre變為cur,cur變為之前保留的那個後續的結點,直到cur.next為null。
Java程式碼如下:

/**
 * 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) {
        ListNode cur = head;
        ListNode pre = null;
        ListNode temp = null;
        while(cur != null){
            temp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }
}

總結:實際上手時while判定出錯了,while裡面已經將cur設定為了後一位,所有判定條件直接是cur != null就行,而不是cur.next;最後返回的值pre才是頭的位置,第一次想當然以為是cur。

相關文章