class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head == null){ //如果第一个节点不存在则返回第一个节点
retrun head;
}else{
while(head != null){ //如果第一个节点存在则开始判断
if(head.val == val){ //如果节点中元素和val相同则删除
head = null;
}else{ //如果不相同则保留并且判断下一个元素
head = head.next;
}
}
retrun head;
}
}
}
return 那里报错,不知为何。看解视频先。
如果删除的是第一个节点,怎么删,不是第一个节点又该怎么删,进行判断。用虚拟头结点可以统一删除规则,创建一个指针去遍历链表。
看完视频自己敲一波:
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode ln = new ListNode();
ln.next = head; //创建一个虚拟头结点并指向头结点
ListNode crr = new ListNode();
crr = head; //创建一个指针指向头结点开始遍历链表
while(crr.next != null){ //当指针的下一个节点不为空时进入循环
if(crr.val == val){ //如果元素相同则删除
crr.next = crr.next.next;
}else{
crr = crr.next; //如果不相同则将指针crr移到下一个元素进行循环判断
}
}
return ln.next; //无论下一个结点是否存在,都可以返回虚拟头结点的下一个结点。
}
}
可以运行,但是结果不对,看一下为啥:第一、第二行注释那里,不是将crr指向实际的头结点,而是指向虚拟的头结点ln,不然就不能执行同样的删除操作了,如果指向头结点,那么头结点的val和目标val相同的时候无法删除真正的头结点。第二、if判断里的应该是crr.next.val而不是crr.val,此错误是由于第一个错误所引起的连环错误。改正之后则运行成功。
---------------------------------------------------------------------------------------------------------------------------------
class Node {
int val;
Node next;
Node(){}
Node(int val){
this.val = val;
}
}
class MyLinkedList {
int size; //size存储链表元素的个数
Node head; //头结点
//初始化链表
public MyLinkedList() {
size = 0;
head = new Node(0);
}
public int get(int index) {
if(index < 0 || index >= size){
return -1;
}
Node cur = head; //搞个指针指向头结点
for(int i = 0;i <= index;i++){ //将指针移动到index的位置
cur = cur.next;
}
return cur.val;
}
public void addAtHead(int val) {
// Node newnode = new Node(val); //新建一个val的结点
// Node frontnode = new Node(); //新建一个虚拟结点指向头结点
// frontnode.next = head;
// newnode.next = frontnode.next; //这里是关键,先将链表后面的一连串被新建结点所指向才不会丢失
// frontnode.next = newnode;
// size += 1;
addAtIndex(0,val);
}
public void addAtTail(int val) {
// Node newnode = new Node(val); //新建一个值为val的点
// Node crr = new Node(); //新建一个指针指向头结点
// crr.next = head;
// for(int i = 0;i <= size;i++){
// crr.next = crr;
// }
// crr.next = newnode;
// size++;
addAtIndex(size,val);
}
public void addAtIndex(int index, int val) {
if(index > size){
return;
}
if(index < 0){
index = 0;
}
size++;
//新建一个指针指向head
Node front = head;
for(int i = 0;i < index;i++){
front.next = front;
}
Node newnode = new Node(val); //新建要插入的结点
newnode.next = front.next;
front.next = newnode;
}
public void deleteAtIndex(int index) {
if(index < 0 || index >= size){
return;
}
size--;
if(index == 0){
head = head.next;
return;
}
//设一个指针指向head
Node front = head;
for(int i = 0;i < index;i++){
front = front.next;
}
front.next = front.next.next;
}
}
注意删除和添加的关键步骤,步骤错了会导致链表丢失。代码来回看了几遍,找不出问题。
---------------------------------------------------------------------------------------------------------------------------------
先将指针移到末尾,再往回移动。 但是倒数的时候不好表示结点,于是想到还是正着循环,用cur来表示反转之前的最后一个元素以至于不会导致链表的丢失。那么怎么分别表示两个结点呢?想到用上下两个指针来做移动循环。
class Solution {
public ListNode reverseList(ListNode head) {
ListNode up = head; //搞一个上指针up并告诉head的位置
ListNode down = head.next; //搞一个下指针down并将head的下一个结点的位置告之
while(down.next != null){ //当down指针尾不为空的时候一直循环
down.next = up;
up = up.next;
}
return down;
}
}
大概操作感觉没问题,但是超出时间限制。看看讲解视频先。
我发现down指针好像没有移动,再改改。
public ListNode reverseList(ListNode head) {
ListNode up = head; //搞一个上指针up并告诉head的位置
ListNode down = head.next; //搞一个下指针down并将head的下一个结点的位置告之
while(down.next != null){ //当down指针尾不为空的时候一直循环
ListNode temp = new ListNode(); //新建一个临时结点存放up的值
temp = up;
down.next = up;
up = temp.next;
}
return down;
}
}
还是超时,再看看。
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null; //搞个pre指针为空,即head的前面一个
ListNode cur = head; //搞个cur指针指向head
ListNode temp = null; //搞个temp为空存临时结点
while(cur != null){ //当cur不是空时执行循环
temp = cur.next; //将cur下一个结点存入临时结点
cur.next = pre; //开始第一个结点和第二个结点的反转
pre = cur; //完成第一个反转后将pre移动到cur的位置
cur = temp; //将cur的下一个结点即存入temp的临时值给cur即将cur移动到下一个结点
}
return pre;
}
}
重新做一次。还有递归的代码,再试试。
class Solution {
public ListNode reverseList(ListNode head) {
return reverse(null,head);
}
private ListNode reverse(ListNode pre, ListNode cur){
if(cur == null){
return pre;
}
ListNode temp = null;
temp = cur.next;
cur.next = pre;
return reverse(cur,temp);
}
}
好好理解一下递归的方法。