203.移除链表元素
思路
链表中删除元素时,需要将指向被删除元素的指针指向被删除元素的下一位。如果是c语言,还需要手动释放这个节点内存,但是Java语言有垃圾回收器,当一个对象没有被任何引用指向时,它就成为了垃圾,垃圾回收器会在适当的时候将其回收并释放内存。
单独判断头结点
由于删除链表节点需要在遍历指针指向前一个节点时就改变节点的指针指向,所以头结点就需要单独处理(因为没有节点指向头结点),当头结点不为null且头结点的值等于要删除元素的值,那么就将头结点指向的下一个节点作为头结点,当头结点为空时,直接返回头结点,也就是null;
class Solution {
public ListNode removeElements(ListNode head, int val) {
while(head != null && head.val == val){
head = head.next;
}
if(head == null){
return head;
}
ListNode preNode = head;
while(preNode.next != null){
if(preNode.next.val == val){
preNode.next = preNode.next.next;
}else{
preNode = preNode.next;
}
}
return head;
}
}
设置虚拟头节点
对于头结点的另一种处理方法,是设置一个虚拟头节点dummyNode指向头结点,这样遍历链表的指针就可以直接从虚拟头结点开始,并且不需要单独处理头结点。
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummyNode = new ListNode(val - 1); //这里是为了防止虚拟头结点的值也等于val
dummyNode.next = head;
ListNode prev = dummyNode; //注意,dummyNode是虚拟头结点,不能直接拿它开始遍历,而是要再定义一个prev作为遍历指针
while(prev.next != null){
if(prev.next.val == val){
prev.next = prev.next.next;
}else{
prev = prev.next;
}
}
return dummyNode.next; //返回虚拟头结点的下一个节点,也就是头结点
}
}
递归
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head==null){
return null;
}
head.next=removeElements(head.next,val);
if(head.val==val){
return head.next;
}else{
return head;
}
}
}
总结
链表中删除元素非常简单,假设有a->b->c的链表,要删除b,直接把b的指向改为c,然后释放b的空间就可以了。但是因为头结点没有前驱节点,所以得考虑头结点的处理方式:一种就是把头结点拎出来单独处理,另外一种比较巧妙,设置一个虚拟头结点,指向头结点,这样头结点就可以才用和后面节点相同的处理方式,最后返回虚拟头结点的next,也就是头结点了。
707.设计链表
思路
考察链表综合运用的一道题,直接上代码
class ListNode {
int val;
ListNode next;
ListNode(){};
ListNode(int val){
this.val = val;
}
}
class MyLinkedList {
int size; //存放LinkedList中存放的元素个数
ListNode head; //链表头结点
public MyLinkedList() { //初始化链表
size = 0;
head = new ListNode(0);
}
public int get(int index) {
if (index < 0 || index >= size) {
return -1;
}
ListNode node = head;
for(int i = 0; i <= index; i++){
node = node.next;
}
return node.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;
}
index = Math.max(0, index);
size++;
ListNode pred = head;
for (int i = 0; i < index; i++) {
pred = pred.next;
}
ListNode toAdd = new ListNode(val);
toAdd.next = pred.next;
pred.next = toAdd;
}
public void deleteAtIndex(int index) {
ListNode dummyNode = new ListNode();
dummyNode.next = head;
ListNode prev = dummyNode;
if(index >= 0 && index < size){
while(index >= 0){
prev = prev.next;
index--;
}
prev.next = prev.next.next;
size--;
}
}
}
206.反转链表
待补充