题目1:给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
示例1
输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]
错误:
1.链表node新节点要像列表一样定义出来,除非直接赋值为一个node
2.虚拟头节点可以不用定义val
3.cur节点要素直接等于则不用像列表一样定义出来(直接赋node了)
4..next .val都不是方法不用();
5.注意要是==val的位于链表尾部,则不应该再=cur.next所以cur遍历和删除节点是if else的关系
修正:
核心: 虚拟头节点+.next转换+.next!=null
答案:
class Solution {
public ListNode removeElements(ListNode head, int val) {
//1.遍历链表 虚拟头节点
//2.更改.next
ListNode fNode=new ListNode();
fNode.next=head;
ListNode cur= fNode;
while(cur.next !=null){
if(cur.next.val==val){
cur.next=cur.next.next;
}else{
cur=cur.next;
}
}
return fNode.next;
}
}
题目2:
你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性: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
的节点。
自己问题:
1.定义链表第一步-定义Listnode javabean
next
和 prev
都定义为 ListNode
类型,使得每个节点都能存储对其邻居节点的引用。这种结构允许双向遍历链表,便于在一些操作(如删除节点、插入节点等)中直接访问前后节点。
2.双向链表对象定义
常量有size
初始化的时候需要构建head和tail节点(虚拟节点val都为0/-1,避免空指针异常)并且相互指向
3.定义get方法=双向链表要判断哪一边遍历更短
4.add 方法:
this
关键字用于引用当前对象的实例。它通常在类的实例方法或构造函数中使用。通过使用 关键字,你可以访问当前对象的属性和方法
4.在头节点和尾节点添加可以等价于 add方法0和size处添加
5.删除node和addnode记得操作size--和size++;
修正:
javabean 用class name{} 方法用public name(){}
使用 来结束方法的执行,并从方法中返回。return
使用 来跳出当前的循环或 语句。break 只会结束当前而不会整个方法
核心:
答案:
class MyListNode {
// 1.常量
int val;
MyListNode next;
MyListNode prev;
// 2.构造方法,空+有值方法
MyListNode() {
};
MyListNode(int val) {
this.val = val;
}
}
class MyLinkedList {
// 1.常量
MyListNode head, tail;
int size;
// 2.构造方法
public MyLinkedList() {
this.size = 0;
this.head = new MyListNode(0);
this.tail = new MyListNode(0); 这一步非常关键,否则在加入头结点的操作中会出现null.next的错误!!
head.next = tail;
tail.prev = head;
}// 初始化操作
// 3.构造其他方法
public int get(int index) {
if (index<0||index > size) {
return -1;
}
MyListNode cur;
// 判断哪一边遍历时间更短
if (index >= size / 2) {
cur = tail;
for(int i=0;i<size-index;i++){
cur=cur.prev;
}
} else {
cur = head;
for(int i=0;i<=index;i++){
cur = cur.next;
}
}
return cur.val;
}
public void addAtHead(int val) {
// 等价于在第0个元素前添加
addAtIndex(0, val);
}
public void addAtTail(int val) {
// 等价于在最后一个元素null前添加
addAtIndex(size, val);
}
public void addAtIndex(int index, int val) {
if(index>size||index<0){
return;
}
size++;
MyListNode addNode = new MyListNode(val);
MyListNode cur=head;
for(int i=0;i<index;i++){
cur = cur.next;
}
MyListNode temp=cur.next;
cur.next=addNode;
addNode.prev=cur;
addNode.next= temp;
addNode.next.prev= addNode;
}
public void deleteAtIndex(int index) {
if (index >=size || index < 0) {
return;
}
size--;
MyListNode cur = head;
for(int i=0;i<=index;i++){
cur = cur.next;
}
MyListNode temp = cur.next;
if(temp!=null){//考虑删掉的是尾巴节点,则有可能cur.next是null!!!!
cur.next = temp.next;
if(temp.next!=null){
cur.next.prev=cur;
}
}
}
}