思路
使用双向链表,不使用哨兵,并通过一个len
记录链表的长度,从而简化判断index
是否合法的操作。
需要特殊处理的情况有:
- 长度为0情况下的元素添加
- 长度为1情况下元素的删除和添加
代码如下:
public class MyLinkedList {
private Node head;
private Node tail;
private Integer len;
private static class Node {
public int val;
public Node prev;
public Node next;
public Node(){
}
public Node(int val){
this.val = val;
}
public Node(int val, Node prev, Node next) {
this.val = val;
this.prev = prev;
this.next = next;
}
}
public MyLinkedList() {
len = 0;
}
private Node getNode(int index){
//内部使用,保证index的值合法
Node node = head;
for (int i = 0; i < index; i++) {
node = node.next;
}
return node;
}
public int get(int index) {
if (index < 0 || index >= len){
return -1;
}
return getNode(index).val;
}
public void addAtHead(int val) {
Node node = new Node(val);
if (len == 0){
head = node;
tail = node;
len++;
return;
}
//连接两节点
node.next = head;
head.prev = node;
//更新头节点
head = node;
//长度+1
len++;
}
public void addAtTail(int val) {
Node node = new Node(val);
if (len == 0){
head = node;
tail = node;
len++;
return;
}
//连接两节点
node.prev = tail;
tail.next = node;
//更新头节点
tail = node;
//长度+1
len++;
}
//在index节点前添加,使得添加后val的下标为index
public void addAtIndex(int index, int val) {
if (index <= 0){
//都是加在头部
addAtHead(val);
return;
} else if (index == len) {
//加在尾部
addAtTail(val);
return;
} else if (index > len) {
return;
}
//此时链表长度至少为2
//加在node节点前
//三个节点的连接
Node node = getNode(index);
Node newNode = new Node(val, node.prev, node);
node.prev.next = newNode;
node.prev = newNode;
//长度+1
len++;
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= len){
//索引无效
return;
}
//特判长度为1的情况
if (len == 1){
head = tail = null;
len--;
return;
}
//长度至少为2的情况,头尾指针最多只需要修改一个
if (index == 0){
//删头
head = head.next;
//删除连接
head.prev.next = null;
head.prev = null;
} else if (index == len-1){
//删尾
tail = tail.prev;
//删除连接
tail.next.prev = null;
tail.next = null;
} else {
//删除中间节点
Node node = getNode(index);
//删除连接
node.prev.next = node.next;
node.next.prev = node.prev;
node.next = null;
node.prev = null;
}
//长度-1
len--;
}
}
/**
* 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);
*/