203.移除链表元素代码随想录
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
//虚拟头结点的方法
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dh = head , p = dh;//dh初始化时没有接上链表
while(p != null){//出现空指针异常,说明操作了某些空指针,要么越界要么对同一对象使用了多个指针
if(p.next.val == val){
p.next = p.next.next;
}else{
p = p.next;
}
}
return dh.next;
}
}
//修改后代码
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dh = new ListNode();
dh.next = head;
ListNode p = dh;
while(p.next != null){
if(p.next.val == val){
p.next = p.next.next;
}else{
p = p.next;
}
}
return dh.next;
}
}
707.设计链表代码随想录
一、想一下目标位置是由哪一个位置变化而来,假如目标位置是最后一个节点,由倒数第二个节点前进得来,那么这个过程就应当是最后一次循环的语句,其执行条件即是最后一次执行条件,其下一个过程的执行条件即是终止条件,一般取终止条件的否定,感觉这些条件判断要多见识积累。
二、应用于get节点和增删节点寻找其前一个节点的过程
出错程序一:
class Node {
int val;
Node next;
Node(){}
Node(int val) {
this.val=val;
}
}
class MyLinkedList {
int size;
Node head;
public MyLinkedList() {
size = 0;
head = new Node(0);
}
public int get(int index) {
if(index < 0 || index >= size){
return -1;
}
Node p = head;
while(index != 0){
p = p.next;
index--;
}
return p.val;
}
public void addAtHead(int val) {
// Node dummy = new Node();
// Node x = new Node(val);
// x.next = dummy.next;
// dummy.next = x;
addAtIndex(0,val);
}
public void addAtTail(int val) {
// Node x = new Node(val);
// Node p = head;
// while(p.next != null){
// p = p.next;
// }
// p.next = x;
addAtIndex(size,val);
}
// public void addAtIndex(int index, int val) {
// if(index > size){
// return;
// }
// if(index == 0){
// index = 0;
// }
// Node dummy = new Node();
// dummy.next = head;
// Node p = dummy;
// //while(index != 0)
// for(int i = 0; i < index; i++){
// p = p.next;
// }
// Node x = new Node(val);
// x.next = p.next;
// p.next = x;
// size++;
// }
public void addAtIndex(int index, int val) {
if (index > size) {
return;
}
if (index < 0) {
index = 0;
}
size++;
//找到要插入节点的前驱
Node dummy = new Node();
dummy.next = head;
Node pred = dummy;
for (int i = 0; i < index; i++) {
pred = pred.next;
}
Node toAdd = new Node(val);
toAdd.next = pred.next;
pred.next = toAdd;
}
public void deleteAtIndex(int index) {
if(index < 0 || index >= size){
return;
}
Node dummy = new Node();
dummy.next = head;
Node p = dummy;
while(index != 0){
p = p.next;
index--;
}
p.next = p.next.next;
}
// public int getsize(){
// Node p = head;
// int count = 0;
// while(p != null){
// count++;
// p = p.next;
// }
// return count;
// }
// public boolean isIndexValid(index){
// int size = getsize();
// if(index >= 0 && index < size - 1){
// return true;
// }else{
// return true;
// }
// }
}
/**
* 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);
*/
出错程序二:
class Node {
int val;
Node next;
Node(){}
Node(int val) {
this.val=val;
}
}
class MyLinkedList {
int size;
Node head;
public MyLinkedList() {
size = 0;
}
public int get(int index) {
if(index < 0 || index >= size){
return -1;
}
Node p = head;
while(index != 0){
p = p.next;
index--;
}
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) {
if(index > size){
return;
}
if(index < 0){
index = 0;
}
Node dummy = new Node();
dummy.next = head;
Node p = dummy;
while(index != 0){
p = p.next;
index--;
}
Node x = new Node(val);
x.next = p.next;
p.next = x;
size++;
}
public void deleteAtIndex(int index) {
if(index < 0 || index >= size){
return;
}
Node dummy = new Node();
dummy.next = head;
Node p = dummy;
while(index != 0){
p = p.next;
index--;
}
p.next = p.next.next;
}
}
没出错
class Node {
int val;
Node next;
Node(){}
Node(int val) {
this.val=val;
}
}
class MyLinkedList {
int size;
Node dummyhead;
public MyLinkedList() {
size = 0;
dummyhead = new Node(0);
}
public int get(int index) {
if(index < 0 || index >= size){
return -1;
}
Node p = dummyhead;
while((index+1) != 0){
p = p.next;
index--;
}
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) {
if(index > size){
return;
}
if(index < 0){
index = 0;
}
size++;
Node p = dummyhead;
for(int i = 0; i<index;i++){
p = p.next;
}
Node x = new Node(val);
x.next = p.next;
p.next = x;
}
public void deleteAtIndex(int index) {
if(index < 0 || index >= size){
return;
}
Node p = dummyhead;
while(index != 0){
p = p.next;
index--;
}
p.next = p.next.next;
size--;
}
}
出错程序三:
class Node {
int val;
Node next;
Node(){}
Node(int val) {
this.val=val;
}
}
class MyLinkedList {
int size;
Node dummyhead;
public MyLinkedList() {
size = 0;
dummyhead = new Node(0);
}
public int get(int index) {
if(index < 0 || index >= size){
return -1;
}
Node p = dummyhead;
while((index+1) != 0){
p = p.next;
index--;
}
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) {
if(index > size){
return;
}
if(index < 0){
index = 0;
}
size++;
Node p = dummyhead;
for(int i = 0; i<index;i++){
p = p.next;
}
Node x = new Node(val);
x.next = p.next;
p.next = x;
}
public void deleteAtIndex(int index) {
if(index < 0 || index >= size){
return;
}
Node p = dummyhead;
while(index != 0){
p = p.next;
index--;
}
p.next = p.next.next;
size--;
}
}
没出错
class Node {
int val;
Node next;
Node(){}
Node(int val) {
this.val=val;
}
}
class MyLinkedList {
int size;
Node dummyhead;
public MyLinkedList() {
size = 0;
dummyhead = new Node(0);
}
public int get(int index) {
if(index < 0 || index >= size){
return -1;
}
Node p = dummyhead;
while((index+1) != 0){
p = p.next;
index--;
}
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) {
if(index > size){
return;
}
if(index < 0){
index = 0;
}
size++;
Node p = dummyhead;
for(int i = 0; i<index;i++){
p = p.next;
}
Node x = new Node(val);
x.next = p.next;
p.next = x;
}
public void deleteAtIndex(int index) {
if(index < 0 || index >= size){
return;
}
Node p = dummyhead;
while(index != 0){
p = p.next;
index--;
}
p.next = p.next.next;
size--;
}
}
/**
* 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);
*/
我很执着于用head放入链表,在函数中添加dummy再操作,力扣判题时是直接在dummyhead后加新元素
head不算是第0个节点wc。head本身就是虚拟头结点,哨兵节点
size更新非常重要,会决定index约不越界,若删除了节点没更新size--,下一次删除index即使越界自己的判定语句也不会抛异常,而是执行while循环导致p越界去操作空指针。
总结,之前很多次提交没过
原因一:0号节点是从head.next开始的,
原因二:size没更新,导致index异常时还会走while循环,导致p越界操作了空指针。
检查时,重心都放在p有没有走到正确的位置上的代码逻辑有误问题,这个过程自己默认传入while的index值是合法的,实际上size的没更新,造成了越界,耗费了很多时间。一开始我的p从head前一个dummy开始走,理论上,到达的位置更靠前,也出现了p越界,现在想来原因大概还是出现在没有size--,以致index越界没被检测出来进入了while。
最后修改版本:
class Node {
int val;
Node next;
Node(){}
Node(int val) {
this.val=val;
}
}
class MyLinkedList {
int size;
Node head;
public MyLinkedList() {
size = 0;
head = new Node(0);
}
public int get(int index) {
if(index < 0 || index >= size){
return -1;
}
Node p = head.next;
while(index != 0){
p = p.next;
index--;
}
return p.val;
}
public void addAtHead(int val) {
Node x = new Node(val);
x.next = head.next;
head.next = x;
size++;
//addAtIndex(0,val);
}
public void addAtTail(int val) {
Node x = new Node(val);
Node p = head;
while(p.next != null){
p = p.next;
}
p.next = x;
size++;
//addAtIndex(size,val);
}
public void addAtIndex(int index, int val) {
if(index > size){
return;
}
if(index < 0){
index = 0;
}
Node p = head;
while(index != 0){
p = p.next;
index--;//漏了,死循环,p越界空指针了,重心都放在走了多少步,却忘了更新index
}
Node x = new Node(val);
x.next = p.next;
p.next = x;
size++;
}
public void deleteAtIndex(int index) {
if(index < 0 || index >= size){
return;
}
Node p = head;
while(index != 0){
p = p.next;
index--;
}
p.next = p.next.next;
size--;//漏了,导致第二次删节点时即使index越界了也能进入循环使p操作了空指针
}
}
206.反转链表代码随想录
双指针:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode p = head , p0 = null;
while(p != null){
ListNode temp = new ListNode();
temp = p.next;
p.next = p0;
p0 = p;
p = temp;//对应关系: p每一次前进都对应一次反转操作,最后一次情形:p在tail处反转tail后并前进到null,终止状态是p == tail时执行,p == null不执行
}
return p0;//直接把反转后的第一个节点当成头节点就好,虽然其有值,但题目要求就是单纯反转操作,不能在原链表上再接一个无值的head
}
}
递归:
递归太抽象了,脑子转不过来,有空再看,
感觉跟循环有对应的地方,有正着迭代下去的操作,一层一层套进去,这题的循环也是正着迭代下去的,暂且先掌握双指针做法。
双指针还能画个链表图比划比划较快地写出来,递归先留着。