看清合法与不合法的要求!!!!
单向链表(别忘了节点类)
//创建链表的节点
public class ListNode {
int val;
ListNode next;
ListNode(int val){
this.val=val;
}
}
//链表的尺寸和“假”头结点
class MyLinkedList {
int size;
ListNode head;
public MyLinkedList() {
size = 0;
head = new ListNode(0);//这是个假头
}
/** 按照序号查找节点的值,没有序号就直接返回-1*/
public int get(int index) {
// 无效序号(有效序号还是类似数组的序号,从0开始,到size-1结束)
if (index < 0 || index >= size){
return -1;
}
ListNode curr = head;//注意这是个假头
//i < index + 1必须这样,为了越过这个假头
for(int i = 0; i < index + 1; ++i){
curr = curr.next;
}
return curr.val;
}
/** 增加一个头结点,注意仍然位于那个假头的后面 */
public void addAtHead(int val) {
addAtIndex(0, val);
}
/** 增加一个尾结点 */
public void addAtTail(int val) {
addAtIndex(size, val);
}
/** 在对应的任意合法位置加入一个节点*/
public void addAtIndex(int index, int val) {
//节点的序号超过链表的尺寸就不会添加(原来的链表的有效序号是0--size-1,新加的节点最大序号是size)
if (index > size) return;
// [so weird] If index is negative,
// the node will be inserted at the head of the list.
if (index < 0) index = 0;
++size;//调节尺寸
// 寻找要加入位置节点的前一个节点,(如果输入序号就是0,直接加到假头节点的后面)
ListNode pred = head;
for(int i = 0; i < index; ++i){
pred = pred.next;
}
// 将要加入的节点的下一个==前一个节点的下一个节点(原来这个位置的节点依次顺延往后)
//前一个节点的下一个节点的下一个节点==带加入的节点
ListNode toAdd = new ListNode(val);
toAdd.next = pred.next;
pred.next = toAdd;
}
/** 删除对应位置的节点 */
public void deleteAtIndex(int index) {
// if the index is invalid, do nothing
if (index < 0 || index >= size) return;
size--;
// 找到待删除节点的前一个节点
ListNode pred = head;
for(int i = 0; i < index; ++i) pred = pred.next;
// 前一个节点的下一个节点指向待删除节点的下一个节点
pred.next = pred.next.next;
}
}
/**
* 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);
*/
双向链表(假头和假尾)
public class ListNode {
int val;
ListNode next;
ListNode prev;
ListNode(int x) { val = x; }
}
class MyLinkedList {
int size;
ListNode head, tail; // 设置一个假头和一个假尾
public MyLinkedList() {
size = 0;//这个size指的是有效节点的个数
head = new ListNode(0);
tail = new ListNode(0);
head.next = tail;//初始化时,假头和假尾互指
tail.prev = head;
}
public int get(int index) {
// if index is invalid
if (index < 0 || index >= size) return -1;
// 注意假头和假尾,以及如何快速寻找序号位置(离头近还是离尾近)
//index+1和(size-1)-index+1==size-index相互比较--分别需要移动的步数
//待寻找节点
ListNode curr = head;
if (index + 1 < size - index){
for(int i = 0; i < index + 1; ++i){
curr = curr.next;
}
}else {
curr = tail;
for(int i = 0; i < size - index; ++i){
curr = curr.prev;
}
}
return curr.val;
}
public void addAtHead(int val) {
//待插入节点的前后两个节点
ListNode pred = head, succ = head.next;
++size;
//拼接两头的节点
ListNode toAdd = new ListNode(val);
toAdd.prev = pred;
toAdd.next = succ;
pred.next = toAdd;
succ.prev = toAdd;
}
public void addAtTail(int val) {
//待插入节点的前后两个节点
ListNode succ = tail, pred = tail.prev;
++size;
ListNode toAdd = new ListNode(val);
toAdd.prev = pred;
toAdd.next = succ;
pred.next = toAdd;
succ.prev = toAdd;
}
public void addAtIndex(int index, int val) {
if (index > size) return;
// [so weird] If index is negative,
// the node will be inserted at the head of the list.
if (index < 0) index = 0;
//寻找待插入节点的前一个节点和后一个节点(哪头可以快速寻找)
ListNode pred, succ;
if (index < size - index) {//寻找前一个节点(index-1位置)
pred = head;
for(int i = 0; i < index; ++i){
pred = pred.next;
}
succ = pred.next;
}else {//注意:寻找到原来这个位置(index位置)的节点是要作为新的这个节点的后一个节点的
succ = tail;
for (int i = 0; i < size - index; ++i){
succ = succ.prev;
}
pred = succ.prev;
}
// 拼接三段
++size;
ListNode toAdd = new ListNode(val);
toAdd.prev = pred;
toAdd.next = succ;
pred.next = toAdd;
succ.prev = toAdd;
}
public void deleteAtIndex(int index) {
// if the index is invalid, do nothing
if (index < 0 || index >= size) return;
// 寻找待删除节点的前一个节点和后一个节点(哪头可以快速寻找)
ListNode pred, succ;
if (index < size - index) {//寻找前一个节点(index-1位置)
pred = head;
for(int i = 0; i < index; ++i) {
pred = pred.next;
}
succ = pred.next.next;
} else {//寻找后一个节点(index+1位置)
succ = tail;
for (int i = 0; i < size - index - 1; ++i){
succ = succ.prev;
}
pred = succ.prev.prev;
}
// 待删除节点的前一个节点与后一个节点互指
--size;
pred.next = succ;
succ.prev = pred;
}
}
/**
* 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);
*/