707. 设计链表
题目:
要求:
你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性:val
和 next
。val
是当前节点的值,next
是指向下一个节点的指针/引用。
如果是双向链表,则还需要属性 prev
以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。
实现 MyLinkedList
类:
MyLinkedList()
初始化MyLinkedList
对象。int get(int index)
获取链表中下标为index
的节点的值。如果下标无效,则返回1
。void addAtHead(int val)
将一个值为val
的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。void addAtTail(int val)
将一个值为val
的节点追加到链表中作为链表的最后一个元素。void addAtIndex(int index, int val)
将一个值为val
的节点插入到链表中下标为index
的节点之前。如果index
等于链表的长度,那么该节点会被追加到链表的末尾。如果index
比长度更大,该节点将 不会插入 到链表中。void deleteAtIndex(int index)
如果下标有效,则删除链表中下标为index
的节点。
答案:
我看题目的要求以为是要在 MyLinkedList 中包含 val
和 next
,所以思路有点跑偏,所以写出来的答案比较复杂,花费的时间也比较久,不过也不算毫无收获,在我写题解的过程中,我对链表虚拟节点的使用掌握的更加熟练;另外学到的就是如果在一个问题上花费了太久,要么是非常难,要么就需要转换思路了,很明显,这道题目不难,那就需要转换思路,答案如下:
public class MyLinkedList {
private int val;
private MyLinkedList next;
private int length;
public MyLinkedList() {
length = 0;
}
public MyLinkedList(int val, int length) {
this.val = val;
this.length = length;
}
public int get(int index) {
if (index < 0 || index >= length) {
return -1;
}
MyLinkedList virtual = virtualNode();
MyLinkedList header = virtual.next;
int ind = 0;
while (ind < index) {
ind++;
header = header.next;
}
return header.val;
}
public void addAtHead(int val) {
if (length != 0) {
MyLinkedList temp = new MyLinkedList(this.val, length);
temp.next = next;
next = temp;
}
length++;
this.val = val;
}
public void addAtTail(int val) {
if (length != 0) {
MyLinkedList temp = new MyLinkedList(val, 1);
temp.next = null;
MyLinkedList virtual = next;
if (virtual == null) {
next = temp;
} else {
while (virtual.next != null) {
virtual.length++;
virtual = virtual.next;
}
virtual.next = temp;
virtual.length++;
}
} else {
this.val = val;
}
length++;
}
public void addAtIndex(int index, int val) {
if (index < 0 || index > length) {
return;
}
if (index == 0) {
addAtHead(val);
} else if (index == length) {
addAtTail(val);
} else {
// 构造添加的节点
MyLinkedList temp = new MyLinkedList(val, 1);
// 构造虚拟节点,虚拟节点的 next 为当前节点
MyLinkedList virtual = virtualNode();
MyLinkedList virtualHeader = virtual.next;
int ind = 0;
// 到目标索引的前一位
while (ind < index - 1) {
ind++;
virtualHeader.length++;
virtualHeader = virtualHeader.next;
}
// 修正指针和长度
temp.next = virtualHeader.next;
virtualHeader.next = temp;
virtualHeader.length++;
temp.length = temp.next.length + 1;
// 修正当前节点
correctTheCurrentNode(virtual);
}
}
private void correctTheCurrentNode(MyLinkedList virtual) {
if (virtual.next == null) {
this.val = 0;
this.next = null;
this.length = 0;
} else {
this.val = virtual.next.val;
this.next = virtual.next.next;
this.length = virtual.next.length;
}
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= length) {
return;
}
MyLinkedList virtual = virtualNode();
MyLinkedList virtualTwo = virtual;
int ind = 0;
// 到目标索引的前一位
while (ind < index) {
ind++;
virtualTwo = virtualTwo.next;
virtualTwo.length--;
}
virtualTwo.next = virtualTwo.next.next;
correctTheCurrentNode(virtual);
}
private MyLinkedList virtualNode() {
MyLinkedList virtual = new MyLinkedList(0, 0);
MyLinkedList virtualHeader = new MyLinkedList(this.val, length);
virtualHeader.next = next;
virtual.next = virtualHeader;
return virtual;
}
public static void main(String[] args) {
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.addAtHead(1);
myLinkedList.addAtTail(3);
myLinkedList.addAtIndex(1,2);
myLinkedList.get(1);
myLinkedList.deleteAtIndex(1);
myLinkedList.get(1);
}
}
接下来是我大致瞄了一眼官方答案写出来的答案,利用 ListNode 来实现。
class MyLinkedList {
int size;
ListNode header;
public MyLinkedList() {
size = 0;
header = null;
}
public int get(int index) {
if (index < 0 || index >= size) {
return -1;
}
ListNode temp = header;
while (index > 0) {
index --;
temp = temp.next;
}
return temp.val;
}
public void addAtHead(int val) {
ListNode temp = header;
ListNode addHeaderNode = new ListNode(val, temp);
header = addHeaderNode;
size ++;
}
public void addAtTail(int val) {
if (size == 0) {
addAtHead(val);
} else {
ListNode addTailNode = new ListNode(val);
ListNode temp = header;
while (temp.next != null) {
temp = temp.next;
}
temp.next = addTailNode;
size ++;
}
}
public void addAtIndex(int index, int val) {
if (index < 0 || index > size) {
return;
}
ListNode addTailNode = new ListNode(val);
// 构造虚拟节点
ListNode virtual = new ListNode(0, header);
ListNode temp = virtual;
int ind = 0;
while (ind < index) {
ind ++;
temp = temp.next;
}
addTailNode.next = temp.next;
temp.next = addTailNode;
size ++;
header = virtual.next;
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) {
return;
}
size --;
// 构造虚拟节点
ListNode virtual = new ListNode(0, header);
ListNode temp = virtual;
int ind = 0;
while (ind < index) {
ind ++;
temp = temp.next;
}
if (temp.next == null) {
header = null;
return;
}
temp.next = temp.next.next;
header = virtual.next;
}
}
class ListNode {
int val;
ListNode next;
ListNode() {
}
ListNode(int val) {
this.val = val;
}
ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}