LeetCode题目链接:https://leetcode.cn/problems/remove-linked-list-elements/
先看题目,因为要在链表中删去等于val值的元素,如果从head开始迭代会存在问题:如果head也需要被删去,那么需要对head进行特殊处理,以适应新的头结点,非常麻烦。
因此,首先初始化一个虚拟头结点来作为当前的头结点,不用担心头结点的特殊处理。之后进行迭代,如果指向的节点的下一个节点val符合要求,则将节点的next指向原先的next->next。 同时,要注意在判定cur.next是否为空之前,需要判定cur是否为空。
值得注意的是,当进行节点删除的操作后,不需要再将节点后移。以保证更新后的节点都可以被迭代到。否则相当于删去后跳过了一个节点。代码如下:
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummyHead = new ListNode(0,head);
ListNode cur = dummyHead;
while (cur != null && cur.next != null) {
if (cur.next.val == val) {
cur.next = cur.next.next;
}else {
cur = cur.next;
}
}
return dummyHead.next;
}
}
LeetCode题目链接:https://leetcode.cn/problems/design-linked-list/
观察可以得到,初始化时链表为空,为了给初始添加链表元素提供根据,在初始化阶段应当设置出一个虚拟头结点,以满足插入和删除元素的需要(不能直接放入node节点,来作为计算,因为会造成多了一个节点的错误)。同时,addAtIndex中存在索引参数,并且需要对索引参数进行判定,因此初始化中应当有方法对当前链表的长度进行统计。因此,还应该引入len变量来计入链表长度。
此后,addAtHead和addAtTail可以看成addAtIndex操作的一个特例。所以仅对增删和get进行重点书写。
注意事项:1、addAtIndex 方法中描述的“如果 index 等于链表的长度,则该节点将附加到链表的末尾” 这句话中 链表长度这里是指 size而不是size - 1,如果是size-1的话那就会和在最后一个元素前插入冲突了。2、这里的index是从0开始的。
具体代码如下:
class MyLinkedList {
private ListNode dummyHead;
private int len;
public MyLinkedList() {
dummyHead = new ListNode(0,null);
len = 0;
}
public int get(int index) {
if (index >= len) return -1;
ListNode curr = dummyHead.next;
while (index > 0) {
curr = curr.next;
index--;
}
return curr.val;
}
public void addAtHead(int val) {
addAtIndex(0, val);
}
public void addAtTail(int val) {
addAtIndex(len, val);
}
public void addAtIndex(int index, int val) {
if (index > len) return;
ListNode add = new ListNode(val,null);
ListNode curr = dummyHead;
ListNode temp = curr.next;
while (index > 0) {
curr = curr.next;
temp = curr.next;
index--;
}
curr.next = add;
add.next = temp;
len++;
}
public void deleteAtIndex(int index) {
if (get(index) == -1) return;
ListNode pre = dummyHead;
ListNode curr = pre.next;
while (index > 0) {
pre = curr;
curr = curr.next;
index--;
}
pre.next = curr.next;
len--;
}
}
LeetCode题目链接:https://leetcode.cn/problems/reverse-linked-list/
采用双指针迭代法,逐步对两两元素进行迭代。注意双指针初始值的选择,设为NULL可以满足链表末尾元素指向NULL的要求。
具体代码如下:
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode curr = head;
ListNode temp;
while (curr != null) {
temp = curr.next;
curr.next = pre;
pre = curr;
curr = temp;
}
return pre;
}
}
此外,也可以使用递归的方法来进行,在使用递归首先要确定终止条件,即当快指针的值为null时,说明已经到了最后一个元素。此时应该返回最后一个节点的值。其他和双指针法没有区别:
class Solution {
public ListNode reverseNode (ListNode pre, ListNode curr) {
if (curr == null) return pre;
ListNode temp = curr.next;
curr.next = pre;
return reverseNode(curr, temp);
}
public ListNode reverseList(ListNode head) {
return reverseNode(null, head);
}
}