基于力扣两道题,分析递归的方法

在这篇文章里,我们将基于力扣两道题目,分析递归的方法,并最后给出一个递归写法的模板

目录

括号生成

电话号码的字母组合

递归写法模板



括号生成

第一道题目是括号生成

我们需要生成给定对数的合法括号排列,且我们需要给出所有合法形式

此处递归的写法是:

        如果需要我们生成n对括号,

        那么我们采用递归的形式生成所有2n长度的括号排列,

        并从这里面选取所有合法的括号排列

对应代码如下:

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        def generate(l: list):
            if(len(l) == 2*n):
                if(valid(l)):
                    ans.append(''.join(l))
            else:
                l.append('(')
                generate(l)
                l.pop()
                l.append(')')
                generate(l)
                l.pop()
        
        def valid(l: list):
            cnt = 0
            for s in l:
                if(s == '('):
                    cnt = cnt + 1
                else:
                    cnt = cnt - 1
                    if(cnt < 0):
                        return False
            
            return cnt == 0 
                    
        ans = []
        generate([])

        return ans

电话号码的字母组合

第二道题目是 电话号码的字母组合

每一个号码都对应一串字符串,

那么我们连续输入几个号码,输出数字长度的所有字符排列

对应代码如下:

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        d_str_map = {
            '2': 'abc',
            '3': 'def',
            '4': 'ghi',
            '5': 'jkl',
            '6': 'mno',
            '7': 'pqrs',
            '8': 'tuv',
            '9': 'wxyz'
        }

        def generate(index):
            if(len(combination) == len(digits)):
                combinations.append(''.join(combination))
            else:
                digit = digits[index]
                d_str = d_str_map[digit]

                for s in d_str:
                    combination.append(s)
                    generate(index+1)
                    combination.pop()

        index = 0
        combination = []
        combinations = []
        if(not digits):
            return combinations
        generate(index)

        return combinations

递归写法模板

我们分析上面两道题目,发现递归写法的生成方式对应一棵树:

递归的写法,是对树的深搜写法。

        例如对于“括号生成”题目:

 

 生成所有长度为4的序列,以深度优先的方式,生成所有序列

但其实,我们在这4层树,对应一个长度为4的栈,它会压入括号,再弹出括号

        在代码中,就对应generate函数中的l列表

那么我们可以归纳出递归写法的模板:

        对于每一次生成的子节点,子节点的个数都多少个,

        同一层次,具体的递归算法就要调用多少次(注意他们是同一层的)

                不考虑这个递归算法再往深调用的递归算法

模板如下:

        digui(){

                if(len(combination) == 要生成的长度): //每一个分支的结束,已经完成了一个分支的叶子节点的生成

                        combinations.append(combination)   //combinations为结果集,一个分支结束,若符合要求,则保存下来

                else:   //如果一个分支还没有生成结束,则继续生成             

                        for i in llist:  //llist指每一层要生成的子节点列表  

                                combination.append(i) //combination即提到那个栈,也是我们要的一个结果

                                digui()  //往深一层调用递归算法

                                combination.pop()  //栈弹出一个元素,(循环的这一次结束,将在栈的这同一位置压入要循环的下一个元素) 

        }

        

### 经典递归与分治算法及解法 #### 斐波那契数列 斐波那契数列是一个经典的递归问。其定义如下: \[ F(n) = \begin{cases} 0 & n=0 \\ 1 & n=1 \\ F(n-1)+F(n-2) & n>1 \end{cases} \] ##### 递归实现 递归方法简单直观,但效率较低,因为存在大量重复计算。 ```python def fibonacci_recursive(n): if n == 0: return 0 elif n == 1: return 1 else: return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2) ``` ##### 迭代实现 迭代方式通过循环逐步求解,避免了递归中的冗余计算,时间复杂度为 \(O(n)\)[^2]。 ```python def fibonacci_iterative(n): a, b = 0, 1 for _ in range(n): a, b = b, a + b return a ``` --- #### 归并排序(Merge Sort) 归并排序是一种典型的分治算法应用案例。它将数组分成两半分别排序后再合并。 ##### 实现代码 ```python def merge_sort(arr): if len(arr) <= 1: return arr mid = len(arr) // 2 left_half = merge_sort(arr[:mid]) # 左侧子数组递归排序 right_half = merge_sort(arr[mid:]) # 右侧子数组递归排序 return merge(left_half, right_half) def merge(left, right): result = [] while left and right: if left[0] < right[0]: result.append(left.pop(0)) else: result.append(right.pop(0)) result.extend(left or right) return result ``` 上述代码展示了如何利用分治的思想解决问[^3]。 --- #### 快速排序(Quick Sort) 快速排序也是一种基于分治思想的经典排序算法。它的核心在于选取一个基准值,将数组分为小于基准值的部分和大于基准值的部分,然后再对这两部分递归处理。 ##### 实现代码 ```python def quick_sort(arr): if len(arr) <= 1: return arr pivot = arr[len(arr) // 2] left = [x for x in arr if x < pivot] middle = [x for x in arr if x == pivot] right = [x for x in arr if x > pivot] return quick_sort(left) + middle + quick_sort(right) ``` --- #### 最近点对问 最近点对问是另一个常见的分治算法应用场景。给定平面上的一组点,找到距离最短的两个点。 ##### 解决思路 1. 将所有点按横坐标排序; 2. 对于每一步,递归地寻找左侧和右侧区域内的最小距离; 3. 合并阶段考虑跨越中间线的情况。 --- #### 汉诺塔问 汉诺塔问也是一个经典的递归例子。目标是从一根柱子上移动一系列盘子到另一根柱子,遵循以下规则: 1. 每次只能移动一个盘子; 2. 较大的盘子不能放在较小的盘子上面。 ##### 实现代码 ```python def hanoi_tower(n, source, target, auxiliary): if n == 1: print(f"Move disk 1 from {source} to {target}") return hanoi_tower(n - 1, source, auxiliary, target) print(f"Move disk {n} from {source} to {target}") hanoi_tower(n - 1, auxiliary, target, source) ``` --- #### 力扣经典目推荐 以下是力扣上的几道涉及递归与分治的经典目: 1. **LeetCode 53. Maximum Subarray** 使用分治策略可以高效解决最大子数组和问[^4]。 2. **LeetCode 973. K Closest Points to Origin** 应用分治思想优化查找最近点的过程。 3. **LeetCode 240. Search a 2D Matrix II** 基于矩阵特性设计高效的分治搜索方案。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值