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