1
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
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;
}
}
-
创建一个虚拟节点,其值为
0
。操作链表的常用技术,简化边缘情况,特别是当头节点可能被删除时。 -
dummy.next设置为head,实质上将虚拟节点放置
next
在原始列表的头部之前。 -
指针
current
在节点处初始化dummy
。 -
然后该方法进入一个
while
循环,只要next
ofcurrent
不是 ,该循环就会继续null
。A。如果
val
的next
节点 的current
等于目标val
,则next
更新current
的 来跳过该next
节点(即current.next = current.next.next
)。这有效地next
从列表中删除该节点,因为它现在没有被任何其他节点引用。b. 如果
val
的next
节点current
不等于目标val
,current
则移动到该next
节点。 -
循环继续,直到检查完所有节点并
val
删除所有值等于的节点。 -
该方法最终返回
dummy.next
,它是新列表的头部。
2
class MyLinkedList {
// 定义节点类
class Node{
int val; // 节点的值
Node next; // 指向下一个节点的指针/引用
Node(int val){
// 构造函数 创建节点时赋予它值
this.val = val;
}
}
private Node head; // 链表的头节点
private int size; // 链表的大小 即节点的数量
public MyLinkedList() {
head = null; // 初始化链表时 头节点为空
size = 0; // 初始化链表时 链表大小为0
}
public int get(int index) {
if(index < 0 || index >= size) {
// 如果索引无效 返回-1
return -1;
}
Node cur = head; // 从头节点开始
for(int i = 0; i< index; i++){
cur = cur.next;
}
return cur.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(size == 0){
// 如果链表为空
head = newNode; // 新节点为头节点
} else{
Node tail = getTail(); // 找到尾节点
tail.next = newNode; // 新节点添加到尾节点之后
}
size++; //链表大小加1
}
public void addAtIndex(int index, int val) {
if(index > size){
// 如果索引大于链表大小 不做任何操作
return;
}
if(index <= 0){
// 如果索引小于等于0 直接在头部添加新节点
addAtHead(val);
return;
}
if(index == size){
// 如果索引等于链表大小 直接在尾部添加新节点
addAtTail(val);
return;
}
// 找到指定索引前一个节点
Node prevNode = head;
for(int i = 0; i < index -1; i++){
prevNode = prevNode.next;
}
Node newNode = new Node(val); //创建新节点
newNode.next = prevNode.next; // 新节点的下一个节点为前一个节点的下一个节点
prevNode.next = newNode; // 前一个节点的下一个节点更新为新节点
size++; // 链表大小加1
}
public void deleteAtIndex(int index) {
if(index < 0 || index >= size){
// 如果索引无效 不做任何操作
return;
}
if(index == 0){
// 如果索引为0 删除头节点
head = head.next;
} else{
// 找到指定索引前一个节点
Node prevNode = head;
for(int i = 0; i< index -1; i++){
prevNode = prevNode.next;
}
// 前一个节点的下一个节点更新为当前节点的下一个节点 即删除当前节点
prevNode.next = prevNode.next.next;
}
size--; // 链表大小减1
}
private Node getTail(){
// 获取尾节点
Node cur = head;
while(cur.next != null){
// 当当前节点的下一个节点不为空, 即当前节点不是尾节点时, 继续往后
cur = cur.next;
}
return cur;
}
}
/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList obj = new MyLinkedList();
* int param_1 = obj.get(index);
* obj.addAtHead(val);
* obj.addAtTail(val);
* obj.addAtIndex(index,val);
* obj.deleteAtIndex(index);
*/
3
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode p = null;
ListNode q = head;
while(q != null){
ListNode temp = q.next;
q.next = p;
p = q;
q =temp;
}
return p;
}
}
-
如果输入
head
为null
或 的next
节点head
为null
,则它仅返回,head
因为空列表或只有一个节点的列表被视为已反转。 -
两个指针
p
和q
被初始化。p
被设置为null
(成为反转列表的新尾部)并被q
设置为head
(指向当前节点)。 -
然后它进入一个
while
循环,只要q
不是 ,该循环就会继续null
。循环内部:A。
temp
创建一个临时变量来存储对next
的节点的引用q
。b.
next
然后的节点被q
设置为p
,有效地改变当前节点的方向。C。
p
移动到 的位置q
并q
移动到temp
(这是 的原始next
节点q
)。重复此过程,始终沿着原始列表移动一步,但反转next
指针,直到q
变为null
。 -
一旦
q
isnull
,p
将指向原始链表的最后一个节点,该节点现在是反转链表的头节点。因此,它返回p
.
此方法就地修改链表,这意味着它不会创建新列表,而是更改next现有节点的指针。时间复杂度为 O(n),空间复杂度为 O(1),其中 n 是列表中的节点数。