19. 删除链表的倒数第N个节点
难度中等833
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode dummy(-1);
dummy.next = head;
ListNode* fast = &dummy;
ListNode* slow = &dummy;
int k = n;
while(k--){
fast = fast->next;
}
while(fast->next){
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
return dummy.next;
}
};
237. 删除链表中的节点
难度简单686
请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。
现有一个链表 – head = [4,5,1,9],它可以表示为:
示例 1:
输入: head = [4,5,1,9], node = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
示例 2:
输入: head = [4,5,1,9], node = 1
输出: [4,5,9]
解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.
说明:
- 链表至少包含两个节点。
- 链表中所有节点的值都是唯一的。
- 给定的节点为非末尾节点并且一定是链表中的一个有效节点。
- 不要从你的函数中返回任何结果。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void deleteNode(ListNode* node) {
// node->val = node->next->val;
// node->next = node->next->next;
*node = *(node->next);
}
};
83. 删除排序链表中的重复元素
难度简单316
给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
示例 1:
输入: 1->1->2
输出: 1->2
示例 2:
输入: 1->1->2->3->3
输出: 1->2->3
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(head == nullptr || head->next == nullptr) return head;
auto cur = head;
while(cur->next){
if(cur->next->val == cur->val) cur->next = cur->next->next;
else cur = cur->next;
}
return head;
}
};
61. 旋转链表
难度中等264
给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL
示例 2:
输入: 0->1->2->NULL, k = 4
输出: 2->0->1->NULL
解释:
向右旋转 1 步: 2->0->1->NULL
向右旋转 2 步: 1->2->0->NULL
向右旋转 3 步: 0->1->2->NULL
向右旋转 4 步: 2->0->1->NULL
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if(!head) return head;
int n = 0;
for(auto p = head; p; p = p->next) n++;
k %= n;
// 寻找断裂点的位置
auto fast = head, slow = head;
while(k--){
fast = fast->next;
}
while(fast->next){
fast = fast->next;
slow = slow->next;
}
fast->next = head;
head = slow->next;
slow->next = nullptr;
return head;
}
};
24. 两两交换链表中的节点
难度中等506
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例:
给定 1->2->3->4, 你应该返回 2->1->4->3.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode dummy(-1);
dummy.next = head;
for(ListNode* pre = &dummy; pre->next && pre->next->next; ){
auto cur = pre->next, nxt = cur->next;
pre->next = nxt;
cur->next = nxt->next;
nxt->next = cur;
pre = cur;
}
return dummy.next;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(!head || !head->next) return head;
auto after = head->next;
head->next = swapPairs(after->next);
after->next = head;
return after;
}
};
206. 反转链表
难度简单986
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(!head || !head->next) return head;
ListNode* dummy = new ListNode(-1);
dummy->next = head;
auto cur = dummy->next->next;
dummy->next->next = nullptr;
while(cur){
auto nxt = cur->next;
cur->next = dummy->next;
dummy->next = cur;
cur = nxt;
}
return dummy->next;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(!head || !head->next) return head;
else{
auto newhead = reverseList(head->next);
head->next->next = head;
head->next = nullptr;
return newhead;
}
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(!head || !head->next) return head;
auto pre = head, cur = head->next;
while(cur){
auto nxt = cur->next;
cur->next = pre;
pre = cur;
cur = nxt;
}
head->next = nullptr;
return pre;
}
};
92. 反转链表 II
难度中等375
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
if(m == n) return head;
ListNode* dummy = new ListNode(-1);
dummy->next = head;
auto a = dummy, c = dummy;
for(int i = 0; i < m-1; i++) a = a->next;
for(int i = 0; i < n; i++) c = c->next;
auto b = a->next, d = c->next;
for(auto pre = b, cur = pre->next; cur != d; ){
auto nxt = cur->next;
cur->next = pre;
pre = cur;
cur = nxt;
}
b->next = d;
a->next = c;
return dummy->next;
}
};
148. 排序链表
难度中等565
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
int n = 0;
for(auto p = head; p; p=p->next) n++;
auto dummy = new ListNode(-1);
dummy->next = head;
for(int i = 1; i < n; i *= 2){
auto cur = dummy;
for(int j = 0; j + i < n; j += i * 2){
auto left = cur->next, right = cur->next;
for(int k = 0; k < i; k++) right = right->next;
int l = 0, r = 0;
while(l < i && r < i && right){
if(left->val <= right->val){
cur->next = left;
cur = left;
left = left->next;
l++;
}else {
cur->next = right;
cur = right;
right = right->next;
r++;
}
}
while(l < i){
cur->next = left;
cur = left;
left = left->next;
l++;
}
while(r < i && right){
cur->next = right;
cur = right;
right = right->next;
r++;
}
cur->next = right;
}
}
return dummy->next;
}
};
O,orz