剑指 Offer II 021. 删除链表的倒数第 n 个结点(快慢指针)
给定一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode(0,head);
ListNode* fast = head;
ListNode* slow = dummy;
for(int i=0;i<n;i++){
fast = fast->next;
}
while(fast){
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
ListNode* ans = dummy->next;
delete dummy;
return ans;
}
};
剑指 Offer II 022. 链表中环的入口节点(哈希表)
给定一个链表,返回链表开始入环的第一个节点。 从链表的头节点开始沿着 next 指针进入环的第一个节点为环的入口节点。如果链表无环,则返回 null。
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
unordered_set<ListNode* > visit;
while(head){
if(visit.count(head))
return head;
visit.insert(head);
head = head->next;
}
return nullptr;
}
};
剑指 Offer II 023. 两个链表的第一个重合节点
给定两个单链表的头节点 headA 和 headB ,请找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
在指针 pA 移动了 a+c+b次、指针 pB 移动了 b+c+a 次之后,两个指针会同时到达两个链表相交的节点
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* n1 = headA;
ListNode* n2 = headB;
while(n1!=n2){
n1=n1 == nullptr ? headB : n1->next;
n2=n2 == nullptr ? headA : n2->next;
}
return n1;
}
};
剑指 Offer II 024. 反转链表
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* cur = head;
ListNode* pre = nullptr;
ListNode* next = nullptr;
while(cur){
next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
};
剑指 Offer II 027. 回文链表(先放到数组里再判断)
class Solution {
public:
bool isPalindrome(ListNode* head) {
vector<int> v;
int i=0;
while(head){
v.push_back(head->val);
head = head->next;
}
int n = v.size();
for(int i=0;i<n;i++){
if(v[i]!=v[n-1-i])
return false;
}
return true;
}
};
剑指 Offer II 025. 链表中的两数相加(反转链表+模拟)
class Solution {
public:
ListNode* reverseList(ListNode* head){
ListNode* ptr = nullptr;
ListNode* cur = head;
ListNode* next = nullptr;
while(cur){
next = cur->next;
cur->next = ptr;
ptr = cur;
cur = next;
}
return ptr;
}
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int jw=0;
ListNode* r1 = reverseList(l1);
ListNode* r2 = reverseList(l2);
int num1=0,num2=0;
ListNode* tmp = new ListNode(0);
ListNode* ptr = tmp;
while(r1!=nullptr||r2!=nullptr||jw){
if(r1!=nullptr){
num1 = r1->val;
r1=r1->next;
}
else num1 = 0;
if(r2!=nullptr){
num2 = r2->val;
r2 = r2->next;
}
else num2=0;
int num = num2+num1+jw;
jw = num/10;
num %=10;
ptr->next = new ListNode(num);//这个时候就不要动tmp了,把ptr当成tmp
ptr= ptr->next;
}
return reverseList(tmp->next);
}
};
剑指 Offer II 026. 重排链表(反转链表+找中点+融合链表)
给定一个单链表 L 的头节点 head ,单链表 L 表示为:
L0 → L1 → … → Ln-1 → Ln
请将其重新排列后变为:
L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
class Solution {
public:
void reorderList(ListNode* head) {
ListNode* mid = middleNode(head);
ListNode* l1 = head;
ListNode* l2 = mid->next;
mid->next = nullptr;
l2 = reverseList(l2);
mergeList(l1,l2);
}
ListNode* reverseList(ListNode* head){
ListNode* cur = head;
ListNode* nex = nullptr;
ListNode* ptr = nullptr;
while(cur!=nullptr){
nex = cur->next;
cur->next = ptr;
ptr = cur;
cur = nex;
}
return ptr;
}
ListNode* middleNode(ListNode* head){
ListNode* fast = head;
ListNode* slow = head;
while(fast->next!=nullptr && fast->next->next!=nullptr){
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
//分别从两个链表拿出一个来组成新链表
void mergeList(ListNode* l1, ListNode* l2){
ListNode* t1;//用来提示下一个位置
ListNode* t2;//
while(l1!=nullptr &&l2!=nullptr){
t1 = l1->next;
t2=l2->next;
l1->next = l2;
l1=t1;
l2->next = l1;
l2 = t2;
}
}
};