一、203 移除链表元素
- 定义一个虚拟节点指向头节点的前一位;
- 循环条件为虚拟节点和虚拟节点的下一位都不为null;
- 若虚拟节点的下一位(也就是head)为val,则将虚拟节点下一位的指向它的next;否则虚拟节点指向它的下一位。
- 返回虚拟节点的下一位。(但为什么不能反回head)
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummyhead = new ListNode(0);
dummyhead.next = head;
ListNode newhead = dummyhead;
while(newhead != null && newhead.next != null){
if(newhead.next.val == val){
newhead.next = newhead.next.next;
}
else{
newhead = newhead.next;
}
}
return dummyhead.next;
}
}
二、707设计链表
主要是找到index的位置进行添加或者删除。
for循环找到index的位置,添加时要注意先将加入的节点的下一个指向curr.next,然后再将curr指向加入的节点,顺序反了的话会导致curr.next值不见。删除节点也是for循环找到index节点的位置,删掉index节点,只需要将curr.next指向curr.next.next即可。
class ListNode{
int val;
ListNode next;
ListNode(){};
ListNode(int val){
this.val = val;
}
}
class MyLinkedList {
int size;
ListNode head;
public MyLinkedList() {
size = 0;
head = new ListNode(0);
}
public int get(int index) {
if(index < 0 || index >= size){
return -1;
}
ListNode curr = head;
for(int i=0; i<=index; i++){
curr = curr.next;
}
return curr.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++;
ListNode curr = head;
for(int i=0; i<index; i++){
curr = curr.next;
}
ListNode newadd = new ListNode(val);
newadd.next = curr.next;
curr.next = newadd;
}
public void deleteAtIndex(int index) {
if(size < 0 || index >= size){
return;
}
size--;
if(index == 0){
head = head.next;
return;
}
ListNode curr = head;
for(int i=0; i<index; i++){
curr = curr.next;
}
curr.next = curr.next.next;
}
}
三、206反转链表
双指针方法:定义指向头节点的curr和头节点之前的pre用于改变指向的方向。
- 循环条件为curr不为空节点;
- 在反转之间要讲curr的下一位先保存,不保存的话反转过后就会丢失curr.next的值;
- 将curr的下一位指向pre;
- 首先移动pre的指向,否则curr会变;
- 返回pre即可。
class Solution {
public ListNode reverseList(ListNode head) {
ListNode curr = head;
ListNode pre = null;
while(curr != null){
ListNode temp = curr.next;
curr.next = pre;
pre = curr;
curr = temp;
}
return pre;
}
}
递归方法:与双指针的思路一样, 都是使用到三个指针,然后反转指向的方向。
- 定义一个反转的功能函数,用到以上的双指针的两个节点pre和curr;
- 如果curr为空节点的话,则返回pre,否则继续递归;
- 定义一个临时节点来保存curr的下一位;
- 返回到功能函数进行递归。
class Solution {//递归
public ListNode reverseList(ListNode head) {
return reverse(null,head);
}
public ListNode reverse(ListNode pre , ListNode curr){
if(curr == null){
return pre;
}
ListNode temp = curr.next;
curr.next = pre;
return reverse(curr,temp);
}
}