203.移除链表元素(三种方法)
1.删除头节点时另做考虑
由于头节点没有前一个节点,所以需要单独判断头节点是否需要删除。然后通过遍历链表依次删除其他满足条件的节点。
public ListNode removeElements(ListNode head, int val) {
while (head != null && head.val == val) {
head = head.next;
}
ListNode current = head;
while (current != null && current.next != null) {
if (current.next.val == val) {
current.next = current.next.next;
} else {
current = current.next;
}
}
return head;
}
2.添加虚拟头节点
通过添加一个虚拟头节点,避免单独处理头节点的逻辑,统一处理链表中的所有节点。
public ListNode removeElements(ListNode head, int val) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode current = dummy;
while (current.next != null) {
if (current.next.val == val) {
current.next = current.next.next;
} else {
current = current.next;
}
}
return dummy.next;
}
3.递归
public ListNode removeElements(ListNode head, int val) {
if (head == null) {
return null;
}
head.next = removeElements(head.next, val);
return head.val == val ? head.next : head;
}
总结
删除头节点时另做考虑:代码清晰,但需要额外处理头节点的逻辑。
添加虚拟头节点:统一逻辑,无需额外处理头节点,是常用写法。
递归:代码简洁,但可能会因为递归深度导致栈溢出,尤其在节点数较多时。
707.设计链表
1.直接使用原链表进行操作
思路
- 获取值:
从头节点遍历到目标索引。 - 在头部插入:
创建新节点并指向当前头节点,将其作为新的头节点。 - 在尾部插入:
遍历到链表尾部并追加新节点。 - 在索引处插入:
对于索引为 0 的情况,调用addAtHead。
对其他索引,遍历到目标位置前的节点后插入。 - 删除节点:
对于删除头节点的情况,更新头节点。
遍历到目标位置前的节点并调整指针。
class MyLinkedList {
private class Node {
int val;
Node next;
Node(int val) {
this.val = val;
}
}
private Node head;
private int size;
public MyLinkedList() {
head = null;
size = 0;
}
public int get(int index) {
if (index < 0 || index >= size) {
return -1;
}
Node current = head;
for (int i = 0; i < index; i++) {
current = current.next;
}
return current.val;
}
public void addAtHead(int val) {
Node newNode = new Node(val);
newNode.next = head;
head = newNode;
size++;
}
public void addAtTail(int val) {
Node newNode = new Node(val);
if (head == null) {
head = newNode;
} else {
Node current = head;
while (current.next != null) {
current = current.next;
}
current.next = newNode;
}
size++;
}
public void addAtIndex(int index, int val) {
if (index > size) {
return;
}
if (index <= 0) {
addAtHead(val);
return;
}
Node newNode = new Node(val);
Node current = head;
for (int i = 0; i < index - 1; i++) {
current = current.next;
}
newNode.next = current.next;
current.next = newNode;
size++;
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) {
return;
}
if (index == 0) {
head = head.next;
} else {
Node current = head;
for (int i = 0; i < index - 1; i++) {
current = current.next;
}
current.next = current.next.next;
}
size--;
}
}
2.设置虚拟头节点
思路
- 虚拟头节点:
创建一个dummy节点,dummy.next指向实际链表头节点。 - 获取值:
从dummy.next遍历到目标索引。 - 在头部插入:
在dummy后插入新节点。 - 在尾部插入:
遍历到链表尾部并追加新节点。 - 在索引处插入:
遍历到目标位置前的节点并插入新节点。 - 删除节点:
遍历到目标位置前的节点并调整指针。
class MyLinkedList {
private class Node {
int val;
Node next;
Node(int val) {
this.val = val;
}
}
private Node dummy; // 虚拟头节点
private int size;
public MyLinkedList() {
dummy = new Node(0);
size = 0;
}
public int get(int index) {
if (index < 0 || index >= size) {
return -1;
}
Node current = dummy.next;
for (int i = 0; i < index; i++) {
current = current.next;
}
return current.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;
}
Node newNode = new Node(val);
Node current = dummy;
for (int i = 0; i < index; i++) {
current = current.next;
}
newNode.next = current.next;
current.next = newNode;
size++;
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) {
return;
}
Node current = dummy;
for (int i = 0; i < index; i++) {
current = current.next;
}
current.next = current.next.next;
size--;
}
}
无论如何请使用虚拟头节点法!
206.反转链表
1.迭代
public ListNode reverseListIterative(ListNode head) {
ListNode prev = null;
ListNode current = head;
while (current != null) {
ListNode nextNode = current.next;
current.next = prev;
prev = current;
current = nextNode;
}
return prev;
}
2.递归
public ListNode reverseListRecursive(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode reversedHead = reverseListRecursive(head.next);
head.next.next = head;
head.next = null;
return reversedHead;
}
比较简单
321

被折叠的 条评论
为什么被折叠?



