203、移除链表元素
文章讲解:代码随想录
题目:
给你一个链表的头节点head和
一个整数val
,请你删除链表中所有满足Node.val == val
的节点,并返回新的头节点。
思路:
移除操作,就是让节点next指针直接指向下下一个节点。
移除头结点和移除其他节点的操作是不一样的,因为链表的其他节点都是通过前一个节点来移除当前节点,而头结点没有前一个节点。可以设置一个虚拟头结点,这样原链表的所有节点就都可以按照统一的方式进行移除了。
代码:
/**
* 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 dummpyNode = new ListNode(Integer.MAX_VALUE);
ListNode pre = dummpyNode;
while(head != null){
//节点值不为val时,将节点加到链表后面
if(head.val != val){
pre.next = head;
pre = pre.next;
}
//节点值为val时,跳过
head = head.next;
}
//防止最后一个节点需要移除时,也被加入链表中
//确保最后一次循环只往链表中加入了一个节点
pre.next = null;
return dummpyNode.next;
}
}
707.设计链表
文章讲解:代码随想录
题目:
你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性:val
和 next
。val
是当前节点的值,next
是指向下一个节点的指针/引用。
如果是双向链表,则还需要属性 prev
以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。
实现 MyLinkedList
类:
MyLinkedList()
初始化MyLinkedList
对象。int get(int index)
获取链表中下标为index
的节点的值。如果下标无效,则返回-1
。void addAtHead(int val)
将一个值为val
的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。void addAtTail(int val)
将一个值为val
的节点追加到链表中作为链表的最后一个元素。void addAtIndex(int index, int val)
将一个值为val
的节点插入到链表中下标为index
的节点之前。如果index
等于链表的长度,那么该节点会被追加到链表的末尾。如果index
比长度更大,该节点将不会插入到链表中。void deleteAtIndex(int index)
如果下标有效,则删除链表中下标为index
的节点。
思路:
首先创建一个节点类ListNode类,表示链表中的节点。
然后创建MyLinkedList类,实现对应的方法。
注意:构造方法的创建,初始化对象时创建了一个虚拟头节点。
代码:
/**
* 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);
*/
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;
}
}
class MyLinkedList {
int size;
ListNode head;
public MyLinkedList() {
this.size = 0;
head = new ListNode(0);
}
public int get(int index) {
if (index < 0 || index >= this.size) {
return -1;
}
ListNode h = head;
for (int i = 0; i <= index; i++) {
h = h.next;
}
return h.val;
}
public void addAtHead(int val) {
this.addAtIndex(0,val);
}
public void addAtTail(int val) {
this.addAtIndex(size, val);
}
public void deleteAtIndex(int index) {
if (index >= 0 && index < this.size) {
ListNode h = head;
for (int i = 0; i < index; i++) {
h = h.next;
}
h.next = h.next.next;
this.size--;
}
}
public void addAtIndex(int index, int val) {
if (index > this.size) {
return;
}
if(index<0){
index = 0;
}
ListNode h = head;
for (int i = 0; i < index; i++) {
h = h.next;
}
ListNode temp = h.next;
h.next = new ListNode(val);
h.next.next = temp;
this.size++;
}
}
206.反转链表
文章讲解:代码随想录
题目:
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
思路:
双指针法:首先定义一个cur指针,指向头结点,再定义一个prev指针,初始化为null。
每次循环从链表中取出一个节点,作为prev的头节点,curr则保存剩余节点。循环结束,prev即为反转后的链表。
代码:
/**
* 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) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
}