什么是递归? 函数自己调用自己的情况
为什么会用到递归? 本质:在解决主问题的时候衍生出一个相同处理过程的子问题,子问题再继续衍生子问题…
如何理解递归?
第一层次的理解:递归展开的细节图
第二层次的理解:二叉树题目练习
第三层次的理解:宏观看待递归过程
a. 不要再在意递归的细节展开图
b. 把递归的函数当成一个黑盒
c. 相信这个黑盒一定能完成既定任务
如何写好一个递归?
a. 先找到主问题和子问题的相同处理过程!!!-> 可以用于处理函数头的设计
b. 只关心某一个子问题是如何解决的 -> 可以用于处理函数体的书写
c. 注意一下递归函数的出口即可\
汉诺塔问题
找到主问题和子问题的相同处理过程 -> 用于处理函数头的设计:
n个盘子,从A柱子,借助B柱子,移动到C柱子 -> void dfs(int n, vector<int>& A, vector<int>& B, vector<int>& C)
void dfs ( int n, vector< int > & A, vector< int > & B, vector< int > & C)
{
if ( n == 1 )
{
C. push_back ( A. back ( ) ) ;
A. pop_back ( ) ;
return ;
}
dfs ( n- 1 , A, C, B) ;
C. push_back ( A. back ( ) ) ;
A. pop_back ( ) ;
dfs ( n- 1 , B, A, C) ;
}
void hanota ( vector< int > & A, vector< int > & B, vector< int > & C)
{
dfs ( A. size ( ) , A, B, C) ;
}
合并两个有序链表
找到主问题和子问题的相同处理过程 -> 用于处理函数头的设计:
合并两个有序链表 -> ListNode* dfs(list1, list2);
ListNode* mergeTwoLists ( ListNode* list1, ListNode* list2)
{
if ( list1 == nullptr ) return list2;
else 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;
}
}
反转链表
找到主问题和子问题的相同处理过程 -> 用于处理函数头的设计:
反转一个链表 -> ListNode* dfs(list1);
ListNode* reverseList ( ListNode* head)
{
if ( head == nullptr || head-> next == nullptr ) return head;
ListNode* newHead = reverseList ( head-> next) ;
head-> next-> next = head;
head-> next = nullptr ;
return newHead;
}
两两交换链表中的节点
找到主问题和子问题的相同处理过程 -> 用于处理函数头的设计:
两两交换链表中的节点 -> ListNode* dfs(ListNode* list1)
ListNode* swapPairs ( ListNode* head)
{
if ( head == nullptr || head-> next == nullptr ) return head;
ListNode* newHead = head-> next;
head-> next = newHead-> next;
newHead-> next = head;
head-> next = swapPairs ( head-> next) ;
return newHead;
}
Pow(x, n)
找到主问题和子问题的相同处理过程 -> 用于处理函数头的设计:
求 x 的 n 次幂 -> int dfs(int x, int n);
double dfs ( double x, int n)
{
if ( n == 0 ) return 1 ;
double tmp = dfs ( x, n / 2 ) ;
return n % 2 ? tmp * tmp * x : tmp * tmp;
}
double myPow ( double x, int n)
{
if ( n > 0 ) return dfs ( x, n) ;
else return 1 / dfs ( x, n) ;
}
计算布尔二叉树的值
找到主问题和子问题的相同处理过程 -> 用于处理函数头的设计:
返回一棵完整二叉树的布尔值 -> bool dfs(TreeNode* root);
bool evaluateTree ( TreeNode* root)
{
if ( root-> val == 0 ) return false ;
else if ( root-> val == 1 ) return true ;
if ( root-> val == 2 ) return evaluateTree ( root-> left) || evaluateTree ( root-> right) ;
else return evaluateTree ( root-> left) && evaluateTree ( root-> right) ;
}
求根节点到叶节点数字之和
int dfs ( TreeNode* root, int val)
{
val = val * 10 + root-> val;
if ( root-> left == nullptr && root-> right == nullptr ) return val;
int left = 0 , right = 0 ;
if ( root-> left) left = dfs ( root-> left, val) ;
if ( root-> right) right = dfs ( root-> right, val) ;
return left + right;
}
int sumNumbers ( TreeNode* root)
{
return dfs ( root, 0 ) ;
}
二叉树剪枝
TreeNode* pruneTree ( TreeNode* root)
{
if ( root == nullptr ) return nullptr ;
root-> left = pruneTree ( root-> left) ;
root-> right = pruneTree ( root-> right) ;
if ( root-> left == nullptr && root-> right == nullptr && root-> val == 0 )
return nullptr ;
return root;
}
验证二叉搜索树
二叉搜索树的中序遍历是有序的
long long prev = LLONG_MIN;
bool isValidBST ( TreeNode* root)
{
if ( root == nullptr ) return true ;
if ( isValidBST ( root-> left) == false ) return false ;
if ( prev < ( root-> val) ) prev = root-> val;
else return false ;
return isValidBST ( root-> right) ;
}
二叉搜索树中第K小的元素
int value = - 1 ;
int count = 0 ;
void dfs ( TreeNode* root)
{
if ( root == nullptr ) return ;
dfs ( root-> left) ;
if ( count == 0 ) return ;
if ( value < root-> val)
{
value = root-> val;
-- count;
}
dfs ( root-> right) ;
}
int kthSmallest ( TreeNode* root, int k)
{
count = k;
dfs ( root) ;
return value;
}
二叉树的所有路径
vector< string> v;
void dfs ( TreeNode* root, string s)
{
if ( root-> left == nullptr && root-> right == nullptr )
{
s += to_string ( root-> val) ;
v. push_back ( s) ;
return ;
}
s += to_string ( root-> val) ;
s += "->" ;
if ( root-> left) dfs ( root-> left, s) ;
if ( root-> right) dfs ( root-> right, s) ;
}
vector< string> binaryTreePaths ( TreeNode* root)
{
dfs ( root, "" ) ;
return v;
}