演算法與資料結構基礎 - 遞迴(Recursion)
遞迴基礎
遞迴(Recursion)是常見常用的演算法,是DFS、分治法、回溯、二叉樹遍歷等方法的基礎,典型的應用遞迴的問題有求階乘、漢諾塔、斐波那契數列等,視覺化過程。
應用遞迴演算法一般分三步,一是定義基礎條件(base case),二是改變狀態、向基礎條件轉移,三是遞迴地呼叫自身。例如 LeetCode題目 1137. N-th Tribonacci Number:
// 1137. N-th Tribonacci Number
private: vector<int> nums={0,1,1}; //基礎條件 int maxN=2; public: int tribonacci(int n) { if(n<=maxN) return nums[n%3];//改變狀態、遞迴地呼叫自身 nums[n%3]=tribonacci(n-3)+tribonacci(n-2)+tribonacci(n-1); maxN=n; return nums[n%3]; }
相關LeetCode題:
1137. N-th Tribonacci Number 題解
938. Range Sum of BST 題解
779. K-th Symbol in Grammar 題解
894. All Possible Full Binary Trees 題解
776. Split BST 題解
247. Strobogrammatic Number II 題解
248. Strobogrammatic Number III 題解
698. Partition to K Equal Sum Subsets 題解
761. Special Binary String 題解
有時候遞迴函式的返回值即是所求,有時候我們利用遞迴函式的返回值作為中間計算結果,例如 LeetCode題目 687. Longest Univalue Path:
// 687. Longest Univalue Path private: int helper(TreeNode* root,int& res){ int l=root->left?helper(root->left,res):0; int r=root->right?helper(root->right,res):0; int resl=root->left&&root->left->val==root->val?l+1:0; int resr=root->right&&root->right->val==root->val?r+1:0; res=max(res,resl+resr); return max(resl,resr); } public: int longestUnivaluePath(TreeNode* root) { int res=0; if(root) helper(root,res); return res; }
以上遞迴函式返回 “子樹最長唯一值節點長度” 這一中間結果,而最終所求由左子樹、右子樹、當前root節點決定。留意這裡與函式返回即為所求的差別。
相關LeetCode題:
687. Longest Univalue Path 題解
543. Diameter of Binary Tree 題解
783. Minimum Distance Between BST Nodes 題解
時間複雜度
如何計算遞迴演算法的時間複雜度,詳見:
Time complexity of recursive functions [Master theorem]
【演算法16】遞迴演算法的時間複雜度終結篇
&n