# 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; } } ```