链表的基本操作实现
https://leetcode-cn.com/problems/design-linked-list/
上代码
class MyLinkedList {
int size;
ListNode head;
public MyLinkedList() {
size = 0;
head = new ListNode(0);
}
//特别注意index >= size,为什么要加上=,因为index = 1,取的是链表的第三个元素了,index从0开始,链表又有一个哑节点head。
//因此,当size = 1,链表上有0 -> t,两个元素,index = 0 取的是t,index = 1 就越界了所以return -1.
public int get(int index) {
if(index < 0 || index >= size){
return -1;
}
ListNode currentNode = head;
for(int i = 0; i <= index;i++){
currentNode = currentNode.next;
}
return currentNode.val;
}
public void addAtHead(int val) {
addAtIndex(0,val);
}
public void addAtTail(int val) {
addAtIndex(size,val);
}
public void addAtIndex(int index, int val) {
ListNode addNode = head;
ListNode temp = new ListNode(val);
if(index < 0) index = 0;
if(index > size) return;
//这里把index = size的情况保留,相当于加入的链表末尾
//for循环停止时,addNode从head开始向前推移了index个单位,如果index = 1, addNode实际代表链表的第二个节点,在它后面插入节点。
for(int i = 0; i < index; i++){
addNode = addNode.next;
}
temp.next = addNode.next;
addNode.next = temp;
size++;
}
public void deleteAtIndex(int index) {
if(index < 0 || index >= size) return;
ListNode deleteNode = head;
//deleteNode也是一样,如果index = size - 1,deleteNode就会停留在链表的倒数第二个节点。
for(int i = 0; i < index; i++){
deleteNode = deleteNode.next;
}
System.out.println(deleteNode.val);
deleteNode.next = deleteNode.next.next;
size--;
}
}
/**
* 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);
*/
最关键的是搞懂那个index在实际链表中对应的位置,搞清楚边界情况,调试调了好久好久,人麻了。
顺便看人家的代码,照着写了个双链表结构
class MyLinkedList {
class ListNode {
int val;
ListNode next,prev;
ListNode(int x) {val = x;}
}
int size;
ListNode head,tail;
public MyLinkedList() {
size = 0;
head = new ListNode(0);
tail = new ListNode(0);
head.next = tail;
tail.prev = head;
}
public int get(int index) {
if(index < 0 || index >= size){
return -1;
}
ListNode cur = head;
if(index < (size - 1) / 2){
for(int i = 0; i <= index;i++){
cur = cur.next;
}
return cur.val;
}else{
cur = tail;
for(int i = 0; i <= size - index - 1; i++){
cur = cur.prev;
}
return cur.val;
}
}
public void addAtHead(int val) {
ListNode cur = head;
ListNode newNode = new ListNode(val);
newNode.next = cur.next;
cur.next.prev = newNode;
cur.next = newNode;
newNode.prev = cur;
size++;
}
public void addAtTail(int val) {
ListNode cur = tail;
ListNode newNode = new ListNode(val);
cur.prev.next = newNode;
newNode.prev = cur.prev;
newNode.next = tail;
cur.prev = newNode;
size++;
}
public void addAtIndex(int index, int val) {
if(index < 0) index = 0;
if(index > size) return;
ListNode cur = head;
ListNode temp = new ListNode(val);
for(int i = 0; i < index; i++){
cur = cur.next;
}
temp.next = cur.next;
temp.prev = cur;
cur.next.prev = temp;
cur.next = temp;
size++;
}
public void deleteAtIndex(int index) {
if(index < 0 || index >= size) return;
ListNode cur = head;
//deleteNode也是一样,如果index = size - 1,deleteNode就会停留在链表的倒数第二个节点。
for(int i = 0; i < index; i++){
cur = cur.next;
}
cur.next.next.prev = cur;
cur.next = cur.next.next;
size--;
}
}
/**
* 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);
*/
关键还是插入时候,prev和next的赋值顺序不能覆盖了,不然脑子里想的和实现出来的效果完全两码事