✨✨✨学习的道路很枯燥,希望我们能并肩走下来!
目录
前言
一 深入理解递归
二 迭代VS递归
三 递归算法题目解析
3.1 汉诺塔问题
3.2 合并两个有序链表
3.3 反转链表
3.4 两两交换链表中的节点
3.5 Pow(x,n)(快速幂)
四 总结
总结
前言
作为递归、搜索与回溯算法系列的第一篇,本篇详细介绍了递归算法的使用,让使用者了解递归运算,而不是仅仅停留在表面, 文章可能出现错误,如有请在评论区指正,让我们一起交流,共同进步!
一 深入理解递归
二 迭代VS递归
三 递归算法题目解析
3.1 汉诺塔问题
面试题 08.06. 汉诺塔问题 - 力扣(LeetCode)
我们简单取1到4个圆盘进行移动,我们从宏观角度发现这是一个重复子问题
class Solution {
public:void move(vector<int>& A, vector<int>& B, vector<int>& C,int n){if(n == 1){C.push_back(A.back());A.pop_back();return;}move(A,C,B,n-1);C.push_back(A.back());A.pop_back();move(B,A,C,n-1);}void hanota(vector<int>& A, vector<int>& B, vector<int>& C) {int n = A.size();move(A,B,C,n);}
};
如果我们在笔试中遇到的,只需要保证能通过就行
不讲武德版:
class Solution {
public:void hanota(vector<int>& A, vector<int>& B, vector<int>& C) {C = A;}
};
3.2 合并两个有序链表
21. 合并两个有序链表 - 力扣(LeetCode)
我们之前是使用迭代(循环)来做的
迭代:
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{ListNode* l1 = list1;ListNode* l2 = list2;ListNode* newHead = NULL;ListNode* newTail = NULL;newHead = newTail = (ListNode*)malloc(sizeof(ListNode));if(l1==NULL){return l2;}if(l2==NULL){return l1;}while(l1&&l2){if(l1->val<l2->val){newTail->next=l1;newTail=newTail->next;l1=l1->next;}else{newTail->next=l2;newTail=newTail->next;l2=l2->next;}}if(l1){newTail->next=l1;}else{newTail->next=l2;}ListNode* ret = newHead->next;free(newHead);return ret;
}
递归:
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {if(list1 == nullptr) return list2;if(list2 == nullptr) return list1;if(list1->val <= list2->val){list1->next = mergeTwoLists(list1->next,list2);return list1;}else{list2->next = mergeTwoLists(list1,list2->next);return list2;}}
};
3.3 反转链表
206. 反转链表 - 力扣(LeetCode)
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* reverseList(ListNode* head) {if(head == nullptr ||head->next == nullptr) return head;ListNode* newNode = reverseList(head->next);head->next->next = head;head->next = nullptr;return newNode;}
};
3.4 两两交换链表中的节点
24. 两两交换链表中的节点 - 力扣(LeetCode)
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* swapPairs(ListNode* head) {if(head == nullptr || head->next == nullptr) return head;auto newNode = swapPairs(head->next->next);auto ret = head->next;head->next->next = head;head->next = newNode;return ret;}
};
3.5 Pow(x,n)(快速幂)
50. Pow(x, n) - 力扣(LeetCode)
class Solution {
public:double myPow(double x, int n) {return n<0 ? 1.0/Pow(x,-(long long)n) : Pow(x,n);}double Pow(double x, long long n) {if(n == 0) return 1.0;double tmp = Pow(x,n/2);return n%2 == 0 ? tmp*tmp : tmp*tmp*x;}
};
用long long避免int无法存n为2的-31次方
四 总结
1. 从题目发掘出重复的子问题
2. 只针对某一子问题考虑解决方法
3. 注意递归出口
总结
✨✨✨各位读友,本篇分享到内容是否更好的让你理解递归算法,如果对你有帮助给个👍赞鼓励一下吧!!
🎉🎉🎉世上没有绝望的处境,只有对处境绝望的人。
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!