0
点赞
收藏
分享

微信扫一扫

【002】每日算法学习——day2链表

yundejia 2022-08-13 阅读 35

单链表

Question No.1

反转链表

​​https://leetcode.cn/problems/reverse-linked-list/​​


第一种写法:

class Solution {
public:
ListNode* reverseList(ListNode* head) {
// 如果是空链表或者只有一个结点就直接返回
if(!head || !head->next) return head;

auto p = head,q = p->next;

while(q){
auto o = q->next;
q->next = p;
p = q,q =o;
}

// 此时原第一个结点为最后一个结点,让其next指向NULL
head->next = NULL;

return p;
}
};


第二种写法:

class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* last = nullptr;
while(head){
ListNode* next = head->next;
head->next = last;
last = head;
head = next;
}
return last;
}
};



Question No.2

K 个一组翻转链表

​​https://leetcode.cn/problems/reverse-nodes-in-k-group/​​


对我这个初学者还是比较难的,废了两个小时才理清楚。

class Solution {
public:
// 翻转一个子链表,并且返回新的头与尾
pair<ListNode*,ListNode*> myReverse(ListNode * head,ListNode *tail){
ListNode* prev = tail->next;
ListNode* p = head;
while(prev != tail){
ListNode* nex = p->next;
// 交换
p->next = prev;
prev = p;

p = nex;
}
return {tail,head};
}

ListNode* reverseKGroup(ListNode* head, int k) {
// 设置个头节点,保护
ListNode* hair = new ListNode(0);
hair->next = head;

ListNode* pre = hair;

// 分组遍历
while(head){
ListNode* tail = pre;

// 查看剩余长度是否大于k个,如果不足k个,直接返回这一组的第一个节点
for(int i = 0; i < k; i++){
tail = tail->next;
if(!tail){
return hair->next;
}
}

// 下一组的第一个结点
ListNode* nex = tail->next;

tie(head,tail) = myReverse(head,tail);

// pre指向翻转后子链表的头节点
pre->next = head;

pre = tail;
// 这里也可以写成head = nex;
head = tail->next;

}
return hair->next;
}
};



双链表

Question No.1

邻值查找

​​https://www.acwing.com/problem/content/description/138/​​

 还没有啃出来,啃出来后补








Question No.2

环形链表

​​https://leetcode.cn/problems/linked-list-cycle/​​

做法:快慢指针

思路,一个快指针,每次走两个位置;一个慢指针,每次走一个位置;如果有环,必相遇。如果快指针走到链表尾,则必然无环。

class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode* fast = head;
while(fast && fast->next){
fast = fast->next->next;
head = head->next;
if(fast == head) return true;
}
return false;
}
};



Question No.3

做法:快慢指针

思路:使用两个指针,​​fast​​​ 与 ​​slow​​​。它们起始都位于链表的头部。随后,​​slow​​​ 指针每次向后移动一个位置,而 ​​fast​​​ 指针向后移动两个位置。如果链表中存在环,则​​fas​​​t 指针最终将再次与 ​​slow​​​ 指针在环中相遇。(这里和上面第二题思路相同。)此时,让另一指针 ​​ptr​​​ 从链表头开始每次移动一个位置,让 ​​slow​​ 指针每次移动一个位置,两指针相遇的地方就是环点。

具体思路请参考:​​https://leetcode.cn/problems/linked-list-cycle-ii/solution/huan-xing-lian-biao-ii-by-leetcode-solution/​​

class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *slow = head;
ListNode *fast = head;
while(fast && fast->next){
fast = fast->next->next;
slow = slow->next;
if(fast == slow){
ListNode *ptr = head;
while(ptr != slow){
slow = slow->next;
ptr = ptr->next;
}
return ptr;
}
}
return nullptr;
}
};




课下作业

Question No.1

合并两个有序链表

​​https://leetcode.cn/problems/merge-two-sorted-lists/​​

做法:递归

思路:如果​​l1​​​为空,说明​​l1​​​是空表,就直接返回​​l2​​​;如果​​l2​​​为空,说明​​l2​​​是空表,就直接返回​​l1​​​;然后判断 ​​l1​​​ 和 ​​l2​​ 哪一个链表的头节点的值更小,然后递归地决定下一个添加到结果里的节点。如果两个链表有一个为空,递归结束。

class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1 == nullptr) return l2;
else if(l2 == nullptr) return l1;
else if(l1->val < l2->val){
l1->next = mergeTwoLists(l1->next,l2);
return l1;
}else{
l2->next = mergeTwoLists(l1,l2->next);
return l2;
}
}
};



Question No.2

加一

​​https://leetcode.cn/problems/plus-one/​​

思路:从后往前遍历,只需要关注末尾有几个9。有三种情况:

如果 ​​digits​​ 的末尾没有 9,例如 [1, 2, 3],那么我们直接将末尾的数加一,得到 [1, 2, 4] 并返回;

如果 ​​digits​​ 的末尾有若干个 9,例如 [1, 2, 3, 9, 9],那么我们只需要找出从末尾开始的第一个不为 9 的元素,即 3,将该元素加一,得到 [1, 2, 4, 9, 9]。随后将末尾的 9 全部置零,得到 [1, 2, 4, 0, 0]并返回。

如果 ​​digits​​ 的所有元素都是 9,例如 [9, 9, 9, 9, 9],那么答案为 [1, 0, 0, 0, 0, 0]。我们只需要构造一个长度比 digits 多 1 的新数组,将首元素置为 1,其余元素置为 0 即可。

class Solution {
public:
vector<int> plusOne(vector<int>& digits) {
int n = digits.size();
for(int i = n - 1; i >= 0; i--){
if(digits[i] != 9){
++digits[i];
return digits;
}else{
digits[i] = 0;
}
}

// 如果所有元素都是9,就构造一个比digits大1的新数组
vector<int> ans(n+1);
// 将第一个元素赋值为1
ans[0] = 1;
return ans;
}
};





举报

相关推荐

0 条评论