第三天| 203.移除链表元素 ,707.设计链表 ,206.反转链表
/**
* 2023/12/29 第三天 T1
* 203.移除链表元素
*/
public ListNode removeElements(ListNode head, int val) {
while (head != null && head.val == val){//删除开头等于val的节点
head = head.next;
}
if (head == null) return head; //坑!!这里一定要判断是否为空,不然p.next head.next 就是空指针异常!!
ListNode p = head;//用p去遍历链表,并删除val值的节点(head始终指向第一个节点)
while (p.next != null){
if (p.next.val == val){
p.next = p.next.next; //p的下一个节点的值等于val 删除即可
} else {
p = p.next; //p的下一个节点的值不等于val p就右移
}
}
return head;
}
-
写出来了,但是有个小坑。
-
没有判断head.next是否为null,导致空指针异常。
-
收获:复习了链表相关操作,1h。
/**
* 2023/12/29 第三天 T2
* 707.设计链表
*/
class ListNode {
int val;
ListNode next;
ListNode(){}
ListNode(int val) {
this.val=val;
}
}
class MyLinkedList {//单链表 默认节点下标从0开始(不包括头节点)!!!
int size;
ListNode head; //设置头节点是为了方便插入时的统一 使得在所有插入都采用头插法(包括尾部插入,此时需要插入的节点的前一个节点就是链表最后一个元素)
public MyLinkedList() {
size = 0;//初始化链表长度
head = new ListNode(0); //初始化头节点
}
public int get(int index) { //get
if (index < 0 || index >= size) return -1;
ListNode p = head;
for (int i =0; i <= index; i++){
p = p.next;
}
return p.val;
}
public void addAtHead(int val) {
addAtIndex(0,val);
}
public void addAtTail(int val) {
addAtIndex(size,val);
}
public void addAtIndex(int index, int val) { //add
if (index > size) return; //大于size默认插入失败
if(index < 0) index = 0; //小于0默认index为0 即在头部插入(插入到头节点之后)
size++; //链表长度+1
ListNode s = new ListNode(val);
ListNode p = head;
for (int i = 0; i < index; i++){//找到插入元素的前驱节点
p = p.next;
}
//头插法
s.next = p.next;
p.next = s;
}
public void deleteAtIndex(int index) { //delete
if (index < 0 || index >= size) return; //注意等于size的情况 会报空指针异常,因此要排除。
size--; //链表长度-1
ListNode p = head;
for (int i = 0; i < index; i++){ //找到删除元素的前驱节点
p = p.next;
}
p.next = p.next.next;
}
}
//双链表写法 (待补充...)
- 自己写还是很多小错误。
- 设置头节点head统一插入(类似使用头插法构建链表的方式)和删除的方式,设置size便于下标相关的增删查操作。
- 收获:复习了链表相关操作,1h。
/**
* 2023/12/29 第三天 T3
* 206.反转链表
*/
//双指针写法
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
ListNode tmp = null;
while (cur != null){ //注意循环条件cur != null
tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
//递归写法 (待补充...)
-
太久了忘记写法了。。
-
思路:
双指针法:注意使用到了 pre cur tmp 三个ListNode引用,其中cur用来遍历链表,pre用来保存前一个元素,tmp用来保存即将加入反转链表的旧链表的元素,为了防止旧链表断开后没有引用指向旧链表。
-
收获:反转链表双指针解法,1h。