力扣题目链接
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
class Solution_LC203 {
public 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;
}
}
力扣题目链接
你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性: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
的节点。输入
["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get"]
[[], [1], [3], [1, 2], [1], [1], [1]]
输出
[null, null, null, null, 2, null, 3]
解释
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.addAtHead(1);
myLinkedList.addAtTail(3);
myLinkedList.addAtIndex(1, 2); // 链表变为 1->2->3
myLinkedList.get(1); // 返回 2
myLinkedList.deleteAtIndex(1); // 现在,链表变为 1->3
myLinkedList.get(1); // 返回 3
单链表
class MyLinkedList {
int size;
ListNode dummy;
public MyLinkedList() {
size = 0;
dummy = new ListNode(-1);
}
public int get(int index) {
//如果index非法,返回-1
if (index < 0 || index >= size) {
return -1;
}
ListNode cur = dummy;
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 pre = dummy;
for (int i = 0; i < index; i++) {
pre = pre.next;
}
ListNode addNode = new ListNode(val);
addNode.next = pre.next;
pre.next = addNode;
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) {
return;
}
size--;
if (index == 0) {
dummy = dummy.next;
return;
}
ListNode pre = dummy;
for (int i = 0; i < index; i++) {
pre = pre.next;
}
pre.next = pre.next.next;
}
class ListNode {
public int val;
public ListNode next = null;
public ListNode(int val) {
this.val = val;
}
public ListNode() {
}
}
}
双链表
class MyLinkedList {
//记录链表中元素的数量
int size;
//记录链表的虚拟头结点和尾结点
DListNode head, tail;
public MyLinkedList() {
head = new DListNode(-1);
tail = new DListNode(-1);
size = 0;
head.next = tail;
tail.prev = head;
}
public int get(int index) {
if (index < 0 || index >= size) {
return -1;
}
DListNode cur = head;
if (index >= size / 2) {
cur = tail;
for (int i = 0; i < size - index; i++) {
cur = cur.prev;
}
} else {
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) {
//index大于链表长度
if (index > size) {
return;
}
//index小于0
if (index < 0) {
index = 0;
}
size++;
DListNode pre = head;
for (int i = 0; i < index; i++) {
pre = pre.next;
}
DListNode next = pre.next;
DListNode newNode = new DListNode(val);
pre.next = newNode;
newNode.next = next;
newNode.prev = pre;
next.prev = newNode;
}
public void deleteAtIndex(int index) {
//判断索引是否有效
if (index < 0 || index >= size) {
return;
}
size--;
DListNode cur = this.head;
for (int i = 0; i <= index; i++) {
cur = cur.next;
}
DListNode prev= cur.prev;
DListNode next= cur.next;
prev.next = next;
next.prev = prev;
}
//双链表
class DListNode {
int val;
DListNode next, prev;
DListNode() {
}
DListNode(int val) {
this.val = val;
}
}
}
/**
* 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);
*/
力扣题目链接
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while (cur != null) {
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}
力扣题目链接
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
输入:head = [1,2,3,4]
输出:[2,1,4,3]
class Solution_LC24 {
public ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode cur = dummy;
while (cur.next != null && cur.next.next != null) {
ListNode node1 = cur.next;
ListNode node2 = cur.next.next;
ListNode next = node2.next;
cur.next = node2;
node2.next = node1;
node1.next = next;
cur = node1;
}
return dummy.next;
}
}
力扣题目链接
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
class Solution_LC19 {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode slow = dummy;
ListNode fast = dummy;
for (int i = 0; i < n; i++) {
fast = fast.next;
}
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummy.next;
}
}
力扣题目链接
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null
。
lenA+lenB
个节点后,如果存在相交的节点,那么肯定能找到交点。public class Solution_LC160 {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
return null;
}
ListNode pA = headA;
ListNode pB = headB;
while (pA != pB) {
pA = pA == null ? headB : pA.next;
pB = pB == null ? headA : pB.next;
}
return pA;
}
}
力扣题目链接
给你一个链表的头节点 head
,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos
不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true
。 否则,返回 false
。
public class Solution {
public boolean hasCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
return true;
}
}
return false;
}
}
力扣题目链接
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
ListNode index1 = fast;
ListNode index2 = head;
// 两个指针,从头结点和相遇结点,各走一步,直到相遇,相遇点即为环入口
while (index1 != index2) {
index1 = index1.next;
index2 = index2.next;
}
return index1;
}
}
return null;
}
}