算法篇----递归回溯

1.递归

核心要点:构造一个函数来实现题目要实现的功能,不要去想这个函数怎么完成这个功能,就无条件相信它一定可以,之后写出递归出口,让函数自己调用自己,在做题时,不要格外关注这个递归函数的细节展开图(展开会很乱,容易把自己搞晕),无条件相信就好,就像要无条件相信自己的女朋友一样,具体步骤就是,找到相同的重复的子问题,设计函数头,随后只关注一个子问题是怎样解决的,根据此编写函数体,最后注意一下递归出口即可!!

例题:反转链表

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

题目要求:

参考代码:

代码原理就是结合技术要点进行理解!!

2.二叉树深搜

这个就是二叉树遍历的应用,对二叉树复习一下就好,不做额外说明,仅给出例题

例:布尔二叉树 https://leetcode.cn/problems/evaluate-boolean-binary-tree/

参考代码:

我们采用前序遍历

3.暴搜

这种题一般让你找出所有的可能路径或者子集之类的,所以就设置一个当前"路径"数组和最后的结果返回数组就好,其余的要通过话细节图来进行分析,抓一个局部的子问题进行分析,编写函数代码。

例题:全子集https://leetcode.cn/problems/subsets/

解题思路:利用排列组合知识画出分析图!我们发现所有节点就是要求的答案,因此在每次进入dfs函数之后,都要把这个"路径"加入到ret中!之后利用for 循环来确定遍历的开始位置

参考代码:

4.综合练习

这里我们做一道很常见的题型,一个二维数组,之后根据题目要求规划最优路径类型题目,解题方法就是,根据题目说的移动规则,设置出dx[]和dy[],用于控制移动,之后为了避免走回头路一直绕圈圈这种情况出现,我们可以设置一个二维的visit数组,来表示哪些位置已经走过了,随后结合题意编写代码即可~

例题:黄金矿工 https://leetcode.cn/problems/path-with-maximum-gold/

结合上述要点,应该不难写出代码!

复制代码
class Solution {
    bool visit[16][16];//防止走回头路
    int m,n;      //这里我是为了递归时少传一些参数才设置成全局变量的,大家根据自己的喜好调整即可
    int dx[4]={0,0,1,-1};
    int dy[4]={-1,1,0,0};
    int ret;
public:
    int getMaximumGold(vector<vector<int>>& g) {
        m=g.size(),n=g[0].size();
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(g[i][j]!=0)
                {
                    visit[i][j]=true;
                    dfs(g,i,j,g[i][j]);
                    visit[i][j]=false;  //回溯恢复现场
                }
            }
        }
        return ret;
    }

    void dfs(vector<vector<int>>& g,int i,int j,int path)
    {
        ret=max(ret,path);   //更新结果
        for(int k=0;k<4;k++)
        {
            int x=i+dx[k],y=j+dy[k];   //上下左右移动
            if(x>=0 && x<m && y>=0 && y<n && !visit[x][y] && g[x][y]!=0)
            {
                visit[x][y]=true;
                dfs(g,x,y,path+g[x][y]);
                visit[x][y]=false;
            }
        }
    }
};

5.floodfill算法

本质上不难,就是例题4的那种类型,找符合题干的连通区域,做法同上

例题:最大岛屿面积

https://leetcode.cn/problems/max-area-of-island/

代码:

复制代码
class Solution {
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    int m,n;
    int count=0;
    int ret=0;
    bool visit[51][51];
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        m=grid.size();
        n=grid[0].size();
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(visit[i][j]==false && grid[i][j]==1)       //没走过的陆地
                {
                    visit[i][j]=true;   //这里我走过了,不能走回头走了
                    count++;
                    dfs(grid,i,j);
                    count=0;
                }
            }
        }
        return ret;
    }
    void dfs(vector<vector<int>>& grid,int i,int j)
    {
        ret=max(count,ret);   //更新结果
        //进行上下移动探索陆地
        for(int k=0;k<4;k++)
        {
            int x=i+dx[k];
            int y=j+dy[k];
            if(x>=0&&x<m&&y>=0&&y<n&&visit[x][y]==false&&grid[x][y]==1)
            //先判断是否越界在看走没走过
            {
                count++;
                visit[x][y]=true;
                dfs(grid,x,y);
                visit[x][y]=false;
            }
        }
    }
};

6.记忆化搜索

不要害怕,就给理解成带有备忘录的递归就好,就是为了降低时间复杂度才搞出来的算法,备忘录可以通过数组,哈希表等一切方式来实现,能实现"记录"功能就可以,不管黑猫白猫,能抓耗子就是好猫!参考这个,有点类似于数学里的整体带入~如下图,我们就可以把这个d(3)加入备忘录,下次用的时候不用算了~

例题:路径问题

https://leetcode.cn/problems/unique-paths/

代码:

方法一:暴力搜索(会超时)

超时原因就是重复展开了很多相同的情况!!

方法二:记忆化搜索

复制代码
class Solution {   
public:
    int uniquePaths(int m, int n)
    {
        vector<vector<int>> memo(m+1,vector<int>(n+1));
        return dfs(m,n,memo);
        
    }
    int dfs(int i,int j,vector<vector<int>>& memo)
    {
        if(memo[i][j]!=0)
        {
            return memo[i][j];
        }
        if(i==0||j==0) return 0;
        if(i==1&&j==1) 
        {
            memo[1][1]=1;
            return 1;
        }
        memo[i][j]=dfs(i,j-1,memo)+dfs(i-1,j,memo);
        return memo[i][j];
    }
};

方法三:动态递归法(目前可以理解为把暴搜进行改造),思路差不多

相关推荐
Aevget4 小时前
MFC扩展库BCGControlBar Pro v37.2新版亮点:控件功能进一步升级
c++·mfc·界面控件
六义义4 小时前
java基础十二
java·数据结构·算法
四维碎片4 小时前
QSettings + INI 笔记
笔记·qt·算法
Tansmjs4 小时前
C++与GPU计算(CUDA)
开发语言·c++·算法
独自破碎E5 小时前
【优先级队列】主持人调度(二)
算法
weixin_445476685 小时前
leetCode每日一题——边反转的最小成本
算法·leetcode·职场和发展
打工的小王6 小时前
LeetCode Hot100(一)二分查找
算法·leetcode·职场和发展
Swift社区6 小时前
LeetCode 385 迷你语法分析器
算法·leetcode·职场和发展
sonadorje6 小时前
svd在图像处理中的应用
算法
挖矿大亨6 小时前
c++中的函数模版
java·c++·算法