KOKO-代码随想录算法训练营Day 3|203|707|206
文章目录
一、203 移除链表元素
1.题目
https://leetcode.cn/problems/remove-linked-list-elements/
2.代码
public ListNode removeElements(ListNode head, int val) {
if(head==null){
return null;
}
ListNode node=new ListNode(-1);
node.next=head;
ListNode res=node;
while (head!=null){
if(head.val==val){
res.next=head.next;
}else {
res=res.next;
}
head=head.next;
}
return node.next;
}
3.总结
1.移除链表,为了移除头节点,应创建一个虚拟头节点指向头节点,可以将移除操作统一化。令,题目给的val值都是>=0的,说明可以创建一个虚拟头节点的值小于0,即-1.
2.再对链表操作时,定义的带虚拟头节点如node,不做遍历操作,即(node=node.next,这种操作一般用临时指针去做。如cur=cur.next,cur指向虚拟头节点)定义的带虚拟头节点的链表作为返回值,临时指针遍历节点。
3.删除或插入都需要知道当前节点的前一个节点,可以用pre,或cur.next表示。移动前一个,移动后一个。
二、707 设计链表
1.题目
https://leetcode.cn/problems/design-linked-list/
2.代码
public class MyLinkedList {
int val;
MyLinkedList next;
public MyLinkedList() {
this.next=null;
this.val=-1;
}
public int get(int index) {
int res=-1;
MyLinkedList node=this.next;
while (node!=null){
res=node.val;
node=node.next;
if(index==0){
return res;
}
index--;
}
return -1;
}
public void addAtHead(int val) {
MyLinkedList node=new MyLinkedList();
node.val=val;
if (this.next==null){
this.next=node;
}else {
MyLinkedList nodes=this.next;
node.next=nodes;
this.next=node;
}
}
public void addAtTail(int val) {
MyLinkedList node=this.next;
MyLinkedList nodes=new MyLinkedList();
nodes.val=val;
if(node==null){
this.next=nodes;
}else {
while (node.next!=null){
node=node.next;
}
node.next=nodes;
}
}
public void addAtIndex(int index, int val) {
MyLinkedList node=new MyLinkedList();
node.val=val;
MyLinkedList head=this.next;
MyLinkedList res=this;
while (head!=null&&index>0){
head=head.next;
res=res.next;
index--;
}
if(index==0){
node.next=head;
res.next=node;
}
}
public void deleteAtIndex(int index) {
MyLinkedList head=this.next;
MyLinkedList res=this;
while (head!=null&&index>0){
head=head.next;
res=res.next;
index--;
}
if(head!=null){
res.next=head.next;
}
}
}
3.总结
1.我在写这个题时,直接将MyLinkedList 定义成了链表的数据结构,在初始化时定义了虚拟头节点,不够清晰,应当定义一个内部类,此外用size去维护链表的大小。
2.在头节点之前插入元素和在下标0前插入元素,尾部插入元素应当属于同一种方法,都是在下 标i处插入元素。
3.插入:
向第一个元素插入时,直接插即可。
new node();node.next=pre.next;
pre.next=node;
4.删除:
插入或删除都需要找出下标为index的元素,不同于插入,删除的下标为0时,直接让头节点指向下一个即可,否则会报空指针,因为pre.next=null;null.next.next会报空指针。
while(index–>0){
pre=pre.next}
pre为要操作元素的前一个下标。因为==0时不走while里的语句。
5.看完卡哥的题目详解后代码优化如下:
package com.suanfa.lianbiao;
class LinkedListNode{
int val;
LinkedListNode next;
public LinkedListNode(int val) {
this.val = val;
}
}
public class MyLinkedList2 {
int size;//维护链表大小
LinkedListNode head;//虚拟头节点
public MyLinkedList2(){
size=0;
head=new LinkedListNode(0);
}
public int get(int index){
if(index<0||index>=size){
return -1;
}
LinkedListNode cur=head.next;
while (index-->0){
cur=cur.next;
}
return cur.val;
}
public void addAtHead(int val){
addAtIndex(0,val);
}
public void addAtTail(int val){
addAtIndex(size,val); //用size,表示在末尾之后添加。
}
public void addAtIndex(int index, int val){
LinkedListNode pre=head;
if(index<0||index>size){
return;
}
if(size<0 ){
index=0;
}
while (index-->0){
pre=pre.next;
}
LinkedListNode node = new LinkedListNode(val);
node.next=pre.next; //head如果没有初始化,这里pre.next会报错。
pre.next=node;
size++;
}
public void deleteAtIndex(int index){
if(index<0||index>=size){
return;
}
size--;
if(index==0){
head=head.next;
return;
}
LinkedListNode pre=head;
while (index-->0){
pre=pre.next;
}
pre.next=pre.next.next;
}
}
三. 206.反转链表
1.题目:
https://leetcode.cn/problems/reverse-linked-list/
2.代码:
public static ListNode reverseList(ListNode head) {
ListNode node=head.next;
head.next=null;
while (node!=null){
ListNode temp=node;
node=node.next;
temp.next=head;
head=temp;
}
return head;
}
3.总结:
总结
1.定义两个指针,一个为head,一个指向头节点的下一个节点,用head记录翻转之后,temp保存临时节点。将每个节点和下一个节点分隔开。