LeetCode 203 移除链表元素
题目链接:移除链表元素
思路:之前处理数组的移除元素需要双指针对原数组内容进行覆盖,但链表的处理方式并不需要这么麻烦。相比之下,链表的移除元素关注点在于头结点的处理,链表结构的定义。
正确思路:下面给出的java代码给出了问题的正确答案,通过设置哑结点作为数值节点的虚拟头结点进行遍历,可以更好的处理头结点本身就是要找的目标值。此外,代码还给出了链表的构造情况。
package ListNode;
/**
* @author rpstart
* @create 2023-06-30 19:02
*/
public class removeElements203 {
public static void main(String[] args) {
ListNode head = new ListNode(1);
ListNode node1 = new ListNode(2);
ListNode node2 = new ListNode(6);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
ListNode node5 = new ListNode(5);
ListNode node6 = new ListNode(6);
head.next = node1;
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node6;
ListNode res = removeElements(head, 6);
System.out.println(res);
}
public static ListNode removeElements(ListNode head, int val) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode cur = dummy;
while (cur.next != null) {
if (cur.next.val == val) {
cur.next = cur.next.next;
}else {
cur = cur.next;
}
}
return dummy.next;
}
}
class ListNode {
int val;
ListNode next;
public ListNode() {
}
public ListNode(int val) {
this.val = val;
}
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
@Override
public String toString() {
return "ListNode{" +
"val=" + val +
", next=" + next +
'}';
}
}
易错点:特别注意在处理链表中的循环内部判断时,当找到目标值时,由于已经把目标节点的子节点传给当前节点,所以无需移动指针。只有找不到目标值时才需要移动指针。如果条件判断写错,会出现空指针异常,因为指针跳过了目标节点的子节点。
如下是错误代码,可进行debug查看错误情况。
package ListNode;
/**
* @author rpstart
* @create 2023-06-30 19:02
*/
public class removeElements203 {
public static void main(String[] args) {
ListNode head = new ListNode(1);
ListNode node1 = new ListNode(2);
ListNode node2 = new ListNode(6);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
ListNode node5 = new ListNode(5);
ListNode node6 = new ListNode(6);
head.next = node1;
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node6;
ListNode res = removeElements(head, 6);
System.out.println(res);
}
public static ListNode removeElements(ListNode head, int val) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode cur = dummy;
while (cur.next != null) {
if (cur.next.val == val) {
cur.next = cur.next.next;
}
cur = cur.next;
}
return dummy.next;
}
}
class ListNode {
int val;
ListNode next;
public ListNode() {
}
public ListNode(int val) {
this.val = val;
}
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
@Override
public String toString() {
return "ListNode{" +
"val=" + val +
", next=" + next +
'}';
}
}
LeetCode 707 设计链表
题目链接:设计链表
思路:本题目主要考察对链表的理解,实际上是链表结构的构造器及相应方法的具体实现。链表节点的构造在移除链表元素中已经说明,不再赘述,本题在链表节点结构上进行设计,实现的是链表的构造。
注意,该题在力扣中有些难以理解,因为题目本身的描述不太让初学者看懂,但练习习题者只要懂其中的思路即可。
因为本身题目的链表中,自带一个哑结点,哑结点的下标为0,但不算做数值节点,数值节点的第一个的下标为0,因此每个方法的下标都指的是数值节点。
package ListNode;
import com.sun.org.apache.bcel.internal.generic.NEW;
/**
* @author rpstart
* @create 2023-06-30 20:00
*/
public class MyLinkedList707 {
//链表元素的个数
int size;
//头结点
ListNode head;
public MyLinkedList707() {
size = 0;
//题目要求,节点下标从0开始
head = new ListNode(0);
}
public int get(int index) {
if (index < 0 || index >= size) {
return -1;
}
ListNode cur = head;
for (int i = 0; i <= index; i++) {
cur = cur.next;
}
return cur.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 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) {
if (index < 0 || index >= size) {
return;
}
size--;
if (index == 0) {
head = head.next;
return;
}
ListNode cur = head;
for (int i = 0; i < index; i++) {
cur = cur.next;
}
cur.next = cur.next.next;
}
}
LeetCode 206 翻转链表
题目链接:翻转链表
思路:翻转链表的思路其实很简单,而且有多种思路,我最常用的还是利用哑结点,因为本身容易理解。需要注意的是由于头插法会使用原链表的当前节点,一定注意不要被覆盖掉,如下代码第一种方式会重新生成节点,第二种方式更优一点。
package ListNode;
/**
* @author rpstart
* @create 2023-06-30 20:53
*/
public class reverseList206 {
public static void main(String[] args) {
ListNode head = new ListNode(1);
ListNode node1 = new ListNode(2);
ListNode node2 = new ListNode(3);
ListNode node3 = new ListNode(4);
ListNode node4 = new ListNode(5);
head.next = node1;
node1.next = node2;
node2.next = node3;
node3.next = node4;
ListNode res = reverseList(head);
System.out.println(res);
}
public static ListNode reverseList(ListNode head) {
ListNode dummy = new ListNode(-1);
ListNode cur = head;
while (cur != null) {
ListNode temp = new ListNode(cur.val);
temp.next = dummy.next;
dummy.next = temp;
cur = cur.next;
}
return dummy.next;
}
}
package ListNode;
/**
* @author rpstart
* @create 2023-06-30 20:53
*/
public class reverseList206 {
public static void main(String[] args) {
ListNode head = new ListNode(1);
ListNode node1 = new ListNode(2);
ListNode node2 = new ListNode(3);
ListNode node3 = new ListNode(4);
ListNode node4 = new ListNode(5);
head.next = node1;
node1.next = node2;
node2.next = node3;
node3.next = node4;
ListNode res = reverseList(head);
System.out.println(res);
}
public static ListNode reverseList(ListNode head) {
ListNode dummy = new ListNode(-1);
ListNode cur = head;
while (cur != null) {
ListNode temp = cur.next;
cur.next = dummy.next;
dummy.next = cur;
cur = temp;
}
return dummy.next;
}
}