707.设计链表
https://leetcode.cn/problems/design-linked-list/description/
单链表实现
单链表的创建需要一个头节点,它不存储值但指向第一个元素,便于后续的增删改查操作的实现
注意:
- 复用 addAtIndex 函数实现添加头尾节点的功能
class ListNode{int val;ListNode next;public ListNode(int val){this.val = val;this.next = null;}
}public class MyLinkedList {ListNode head;int size;public MyLinkedList(){size = 0;head = new ListNode(0);}public int get(int index) {if(index < 0 || index >= size) return -1;ListNode curNode = head;for(int count = 0; count <= index; ++count){curNode = curNode.next;}return curNode.val;}public void addAtHead(int val) {addAtIndex(0, val);}public void addAtTail(int val) {addAtIndex(size, val);}public void addAtIndex(int index, int val) {if(index < 0 || index > size) return;ListNode curNode = head;// 注意这里 count 没有 <= index,所以取的是index前一个节点for(int count = 0; count < index; ++ count){curNode = curNode.next;}ListNode addNode = new ListNode(val);++size;addNode.next = curNode.next;curNode.next = addNode;}public void deleteAtIndex(int index) {if(index < 0 || index >= size) return;ListNode curNode = head;for(int count = 0; count < index; ++ count){curNode = curNode.next;}curNode.next = curNode.next.next;--size;}
}
双链表实现
双链表的实现,需要头,尾节点
注意:
- 双链表则可以将头或尾节点作为起始点进行查找
- 将链表分为两半,判断当前需要查找的节点距离哪一端更近,可以遍历更少的节点
class ListNode{int val;ListNode next;ListNode prev;public ListNode(int val){this.val = val;this.next = null;this.prev = null;}
}class MyLinkedList {private ListNode head;private ListNode tail;private int size;public MyLinkedList() {head = new ListNode(0);tail = new ListNode(0);head.next = tail;tail.prev = head;size = 0;}public int get(int index) {if(index < 0 || index >= size) return -1;ListNode curNode;if(index + 1 < size - index){ // 在前半部分curNode = head;for(int i = 0; i <= index; ++i){curNode = curNode.next;}}else{ // 从后半部分遍历curNode = tail;for(int i = 0; i < size - index; ++i){curNode = curNode.prev;}}return curNode.val;}public void addAtHead(int val) {addAtIndex(0, val);}public void addAtTail(int val) {addAtIndex(size, val);}public void addAtIndex(int index, int val) {if(index < 0 || index > size) return;ListNode curNode, prevNode;if(index + 1 < size - index){curNode = head;for(int count = 0; count <= index; ++ count){curNode = curNode.next;}prevNode = curNode.prev;}else{curNode = tail;for(int i = 0; i < size - index; ++i){curNode = curNode.prev;}prevNode = curNode.prev;}ListNode addNode = new ListNode(val);addNode.prev = prevNode;addNode.next = curNode;prevNode.next = addNode;curNode.prev = addNode;++size;}public void deleteAtIndex(int index) {if(index < 0 || index >= size) return;ListNode curNode;if(index + 1 < size - index){curNode = head;for(int i = 0; i <= index; ++i){curNode = curNode.next;}}else{curNode = tail;for(int i = 0; i < size - index; ++i){curNode = curNode.prev;}}--size;curNode.prev.next = curNode.next;curNode.next.prev = curNode.prev;}
}
我的实现
没有注意双链表的特性,依然用单方向的遍历实现
class ListNode{int val;ListNode next;ListNode prev;public ListNode(int val){this.val = val;this.next = null;this.prev = null;}
}class MyLinkedList {private ListNode head;private ListNode tail;private int size;public MyLinkedList() {head = new ListNode(0);tail = new ListNode(0);head.next = tail;tail.prev = head;size = 0;}public int get(int index) {if(index < 0 || index >= size) return -1;ListNode curNode = head;for(int count = 0; count <= index; ++ count){curNode = curNode.next;}return curNode.val;}public void addAtHead(int val) {addAtIndex(0, val);}public void addAtTail(int val) {addAtIndex(size, val);}public void addAtIndex(int index, int val) {if(index < 0 || index > size) return;ListNode curNode = head;for(int count = 0; count <= index; ++ count){curNode = curNode.next;}ListNode prevNode = curNode.prev;ListNode addNode = new ListNode(val);addNode.prev = prevNode;addNode.next = curNode;prevNode.next = addNode;curNode.prev = addNode;++size;}public void deleteAtIndex(int index) {if(index < 0 || index >= size) return;ListNode curNode = head;for(int count = 0; count <= index; ++ count){curNode = curNode.next;}--size;curNode.prev.next = curNode.next;curNode.next.prev = curNode.prev;}
}