---
# System prepended metadata

title: Leetcode 707. Design Linked List 練習
tags: [java, Leetcode, Algorithm]

---

# Leetcode 707. Design Linked List 練習
> Difficulty : `Medium`
> `Java` `演算法Algorithm`

> 撰寫人[name=KVJK_2125] [time=Fri, Mar 29, 2024 22:07]

## 題目
### 說明 Description
Design your implementation of the linked list. You can choose to use a singly or doubly linked list.
A node in a singly linked list should have two attributes: `val` and `next`. `val` is the value of the current node, and `next` is a pointer/reference to the next node.
If you want to use the doubly linked list, you will need one more attribute `prev` to indicate the previous node in the linked list. Assume all nodes in the linked list are **0-indexed**.

Implement the `MyLinkedList` class:

- `MyLinkedList()` Initializes the `MyLinkedList` object.
- `int get(int index)` Get the value of the `index th` node in the linked list. If the index is invalid, return `-1`.
- `void addAtHead(int val)` Add a node of value `val` before the first element of the linked list. After the insertion, the new node will be the first node of the linked list.
- `void addAtTail(int val)` Append a node of value `val` as the last element of the linked list.
- `void addAtIndex(int index, int val)` Add a node of value `val` before the `index th` node in the linked list. If `index` equals the length of the linked list, the node will be appended to the end of the linked list. If `index` is greater than the length, the node **will not be inserted**.
- `void deleteAtIndex(int index)` Delete the `index th` node in the linked list, if the index is valid.

### 範例 Example
Example 1:
> Input
["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get"]
[[], [1], [3], [1, 2], [1], [1], [1]]
Output
[null, null, null, null, 2, null, 3]

>Explanation
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.addAtHead(1);
myLinkedList.addAtTail(3);
myLinkedList.addAtIndex(1, 2);    // linked list becomes 1->2->3
myLinkedList.get(1);              // return 2
myLinkedList.deleteAtIndex(1);    // now the linked list is 1->3
myLinkedList.get(1);              // return 3

### 限制條件 Constraints
- `0 <= index, val <= 1000`
- Please do not use the built-in LinkedList library.
- At most 2000 calls will be made to `get`, `addAtHead`, `addAtTail`, `addAtIndex` and `deleteAtIndex`.

## 解題
### 思路 Intuition/Approach
以Example 1做解釋：
- Step1.<br>先建立一個`class Node`，其中建立`val`存放值，`next`指向下一個node

- Step2.<br>在`MyLinkedList`中，建立一個空指標`Node head = null`，以及一個變數紀錄資料長度`int bruh = 0`

- Step3.整理函式內容<br>
-- <b>MyLinkedList()</b>：初始化。<br>
-- <b>get(index)</b>：<br>先判斷index是否有效（是否超出長度，或是否小於0）`index >= bruh || index < 0`，否則回傳`-1`。<br>有效則建立一個新節點`Node headtmp = head`，在執行`index`次內，指向`next`，在最後回傳值。<br>
-- <b>addAtHead(val)</b>：<br>建立一個新節點`Node veHead = new Node(val)`，將`veHead.next`指向`head`，再把`head`指向`vehead`，這樣就把新節點放入最前面了。<br>在最後長度記得加1`bruh++`。<br>
-- <b>addAtTail(val)</b>：<br>先判斷head是否為空（`head == null ?`）。<br>若為空的話，直接將`val`加入list即可（`head = new Node(val)`）；<br>若不為空，則建立一個指向`head`的新節點`Node headtmp = head`。直到`next`為空(`null`)之前，將新建的node指向`next`。<br>最後一個`next`指向`val`使其成為最後一個元素。<br>在最後長度記得加1`bruh++`。<br>
-- <b>addAtIndex(index, val)</b>：有點亂，我用寫的。<br>![SmartSelect_20240329_215428_Samsung Notes](https://hackmd.io/_uploads/ByZ6dS410.jpg =80%x)<br>
--<b>addAtDelete(index)</b>：<br>先判斷index是否有效（是否超出長度，或是否小於0）`index >= bruh || index < 0`，<br>有效的話，建立一個指向`head`的新節點`Node current = head`，在建立一個指向空`null`的新節點`Node previous = null`。<br>在執行index次內，指向`next`。<br>結束後，若`previous == null`，則將`head`指向`next`；若`previous!=null`，則略過`current`，讓`previous.next`指向`current.next`，即刪除`current`。<br>在最後長度記得減1`bruh--`。<br>

### 程式碼 Code（加註解）
```clink=java
class MyLinkedList {
    Node head = null;   //建立空指標
    int bruh = 0;   //這個用來記錄長度
    
    //初始化
    public MyLinkedList() {
    }
    
    //取得下標為index的node的值。無效則回傳-1。
    public int get(int index) {
        //判斷是否有效
        if(index < 0 || index >= bruh)
            return -1;
        //建立指向head的node
        Node headtmp = head;
        //在index次數內，指向next
        for(int i = 0;i<index;i++)
           headtmp = headtmp.next;
        //如果不是空值，就回傳值
        return headtmp != null ? headtmp.val : 0; 
    }
    
    //將一個值為val的node插入第一個元素之前(vefore the first element)，成為linked list第一個node
    public void addAtHead(int val) {
        Node vehead = new Node(val);    //建立新的node
        vehead.next = head; //新node的下一個指向head
        head = vehead;  //head指向新node，讓新node成為first element
        bruh++;
    }
    
    //將一個值為val的node追加到linkedlist，成為最後一個元素(as the last element)
    public void addAtTail(int val) {
        //判斷head是不是null
        if(head == null){
            head = new Node(val);   //是空指標的話，就追加val
        }else{
           Node headtmp = head; //建立新node指向head
           while(headtmp.next != null) //直到next為空指標(null)之前
             headtmp = headtmp.next;    //將新建的node指向next
            headtmp.next = new Node(val);   //並成為val
        }
        bruh++; //長度記得++
    }
    
    //將一個值為val的node插入到下標為index的node前
    //如果index等於linked list的長度，該node會被追加到linked list的末端。
    //如果index大於linked list的長度，該node不會被寫入(will not be inserted)。
    public void addAtIndex(int index, int val) {
        if(index == bruh){
            addAtTail(val); //追加到末端
        }else if(index > bruh){
            return; //不寫入
        }else{
            Node veNode = new Node(val);
            if(head == null ){
                //如果head為空
                head = veNode;  //head指向新node
            }else if(index == 0){
                //如果index為0
                veNode.next = head; //新node的next指向head
                head = veNode;   //head指向新node
            }else{
                //建立分別指向head和null的node
                Node current = head;
                Node previous = null;
                //在index次數內
                for(int i = 0;i<index;i++){
                    previous = current; 
                    current = current.next; //指向next
                }
                veNode.next = current;  //新node的next指向最後
                previous.next = veNode; //指向新節點
            }
            bruh++; //長度記得++
        }
    }
    
    //如果下標有效(if the index is valid)，刪除表中下標為index的node
    public void deleteAtIndex(int index) {
        //判斷是否有效
        if(index < 0 || index >= bruh )
            return;
        //建立分別指向head和null的node
        Node current = head;
        Node previous = null;
        //在index次數內
        for(int i = 0;i<index;i++){
            previous = current;
            current = current.next; //指向next
        }
        if(previous == null){
            //將head指向next
            head = head.next;
        }else {
            //略過current，刪除
            previous.next = current.next;
        }
        bruh--; //長度記得--
    }
}

class Node{
    //題目說要叫做val跟next
    int val;
    Node next = null;
    public Node(int val){
        this.val = val;
    }
    public Node(int val, Node next){
        this.val = val;
        this.next = next;
    }
}
```