算法思想:递归 回溯 分治 动态规划 2019-04-22

几种算法思想:

一、递归(保留往期第五天任务)

通过LeetCode上【70. 爬楼梯】学习
中文路径:https://leetcode-cn.com/problems/climbing-stairs/submissions/
思路1:将n=1~4的结果列出来,发现规律跟斐波那契数列很像,采用动态规划DP方式, int* sum=new int[n];将上两个情况的和作为新的值返回。代码如下:

class Solution {
    public:
    int climbStairs(int n) {
        if(n==0) return 0;
        if(n==1) return 1;
        
        int* sum=new int[n];
        
        sum[0]=1;
        sum[1]=2;
        for(int i=2;i<n;i++){
            sum[i]=sum[i-1]+sum[i-2];            
        }
        return sum[n-1];            
            
    }
};

思路2:用递归调用方式,调用自身的上两次计算结果 求和返回。
但是无法提交啊不知道为什么运行超时了。执行的时候是ok 的。
https://leetcode-cn.com/problems/climbing-stairs/submissions/

二、回溯
当问题是要求满足某种性质(约束条件)的所有解或最优解时,往往使用回溯法。实现方法有两种:递归和递推(也称迭代)
回溯思路:搜索时采用深度优先算法DFS,一个路径满足要求一搜到底,如果不符合条件则舍弃该子节点所有的路径回到平级的节点去重新搜--不符合就回去即为回溯。

  1. 利用回溯算法求解八皇后问题
    国际象棋8*8棋盘,皇后可以沿横竖斜线走任意步数。
    放置一个皇后占位,下一个皇后需要搜索在某行时是否与占位皇后在同一竖线斜线上,如果到尽头依然在,则回到行进行移动再重复后续步骤。
    中文路径:https://leetcode-cn.com/problems/n-queens/
class Solution {
public:
    vector<vector<string>> solveNQueens(int n) {
 
        if( n <= 0)
            return vector< vector< string> >();
        int col[n];
        vector< vector< string> > res;
        queens( col, 0, n, res);
        return res;
    }
    void queens( int * col, int row, int n, vector< vector< string> > &res){
        if( row == n){
            push(col, res, n);
            return;
        }
        for( int i = 0; i < n; ++i){
            col[row] = i;
            bool flag = true;
            for( int j = 0; j < row; ++j){
                if( col[row] == col[j] || col[row] - col[j] == row - j || col[row] - col[j] == j - row){
                    flag = false;
                    break;
                }
            }
            if(flag)
                queens( col, row+1, n, res);
        }
    }
    //把值压进数组
    void push( int * col, vector< vector< string> > &res, int n){
        vector< string> temp;//这里不能初始化,不然会有初始化值
        for( int i = 0; i < n; ++i){
            string str = "";
            for( int j = 0; j < n; ++j){
                if( col[i] == j)
                    str += 'Q';
                else
                    str += '.';
            }
            temp.push_back(str);
        }
        res.push_back(temp);
    }


};
  1. 利用回溯算法求解 0-1 背包问题

三、分治

  1. 利用分治算法求一组数据的逆序对个数
    求解逆序对个数采用分治法(Divide and Conquer)的一个非常典型的应用--归并排序(MERGE-SORT),是建立在归并操作上的一种有效的排序算法,时间复杂度为O(nlogn)。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路[归并]。

思路:逆序对是指在一个数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。先分后治:一个数组拆称两个对称部分(奇数数组怎么弄我还没研究),对左右数组分别再拆分,拆成一个元素一个数组之后,对最新的左右数组进行比较、排序、记录逆序对、合并成一个数组,如此重复最终和并成一个完整的有序列表。

四、动态规划

  1. 0-1 背包问题
    ※有编号分别为1,2,3,4,5的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?
    动态规划的核心过程有两部分,一个是找出问题的”子状态”,再一个就是建立“状态转移方程”(所谓的递推公式)动态规划解决问题的核心就在于填表,表填写完毕,最优解也就找到。
    由此可以得出递推关系式:Vi表示第 i 个物品的价值,Wi表示第 i 个物品的体积(重量)

1) j<w(i) V(i,j)=V(i-1,j)

2) j>=w(i) V(i,j)=max{ V(i-1,j),V(i-1,j-w(i))+v(i) }

  1. 最小路径和(详细可看 Minimum Path Sum)
    动态规划的过程可以看做是递归的逆过程,既然递归是从上往下求解,每个大的问题都要先去求解子问题,所以,动态规划是先求解小的子问题,依次往上,所以大问题需要的子问题已经提前求好了。

先生成一张二维dp表,然后按照递归相反的方向求解;
先把dp表的最右下角+最后一行+最后一列的位置填好;
然后找一个普通的位置依赖它下面的位置和左边的位置,所以我们依次从下到上,做右往左,填整张dp表,最后dp[0][0]就是答案。
参考:https://blog.csdn.net/zxzxzx0119/article/details/81227300

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
   
       int mm=grid.size();
        int nn=grid[0].size();
        vector<vector<int> > dis;
        vector<int> vec;
        vec.push_back(grid[0][0]);
        for (int i=1;i<nn;i++){
            vec.push_back(vec[i-1]+grid[0][i]);
        }
        dis.push_back(vec);
        for (int i=1;i<mm;i++){
            vec.clear();
            for (int j=0;j<nn;j++){
                if (j==0)   vec.push_back(dis[i-1][j]+grid[i][j]);
                else    vec.push_back(min(dis[i-1][j],vec[j-1])+grid[i][j]);
            }
            dis.push_back(vec);
        }
        return dis[mm-1][nn-1];


    }
};
  1. 编程实现莱文斯坦最短编辑距离
    word1经过多少步的操作变成(添加、删除、替换)word2:
    https://leetcode-cn.com/problems/edit-distance/submissions/

  2. 编程实现查找两个字符串的最长公共子序列

  3. 编程实现一个数据序列的最长递增子序列

对应的 LeetCode 练习题

实战递归:完成Leetcode上的Letter Combinations of a Phone Number(17)及permutations(46)

(保留往期第六天任务)

实战DP:完成0-1背包问题实现(自我实现)及Leetcode上Palindrome Partitioning II(132)

补充题目:leetcode198 House Robber

(保留往期第七天任务)

Regular Expression Matching(正则表达式匹配)

英文版:https://leetcode.com/problems/regular-expression-matching/

public:
    bool isMatch(string s, string p) {
        int m = s.size(), n = p.size();
          vector<vector<bool>> dp(m + 1, vector<bool>(n + 1, false));
         dp[0][0] = true;
         for (int i = 1; i <= n; ++i) {
              if (p[i - 1] == '.') dp[0][i] = dp[0][i - 1];
          }
         for (int i = 1; i <= m; ++i) {
             for (int j = 1; j <= n; ++j) {
                 if (p[j - 1] == '.') {                     
                     dp[i][j] = dp[i - 1][j] || dp[i][j - 1];
                 } else {
                     dp[i][j] = (s[i - 1] == p[j - 1] || p[j - 1] == '*') && dp[i - 1][j - 1];
                 }
             }
         }
         return dp[m][n];
    }
};

中文版:https://leetcode-cn.com/problems/regular-expression-matching/

Minimum Path Sum(最小路径和)

英文版:https://leetcode.com/problems/minimum-path-sum/

中文版:https://leetcode-cn.com/problems/minimum-path-sum/

见↑四动态规划2
https://leetcode-cn.com/problems/minimum-path-sum/

Coin Change (零钱兑换)

英文版:https://leetcode.com/problems/coin-change/

中文版:https://leetcode-cn.com/problems/coin-change/
递归+memo的DP

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int> memo(amount + 1, INT_MAX);
        memo[0] = 0;
        return coinChangeDFS(coins, amount, memo);
    }
    int coinChangeDFS(vector<int>& coins, int target, vector<int>& memo) {
        if (target < 0) return - 1;
        if (memo[target] != INT_MAX) return memo[target];
        for (int i = 0; i < coins.size(); ++i) {
            int tmp = coinChangeDFS(coins, target - coins[i], memo);
            if (tmp >= 0) memo[target] = min(memo[target], tmp + 1);
        }
        return memo[target] = (memo[target] == INT_MAX) ? -1 : memo[target];
    }
};

https://www.cnblogs.com/grandyang/p/5138186.html
Best Time to Buy and Sell Stock(买卖股票的最佳时机)

英文版:https://leetcode.com/problems/best-time-to-buy-and-sell-stock/

中文版:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if(prices.size()==0) return 0;
        int profit=0;
        int permin = prices[0];
        for(int i=0;i<prices.size();i++)
        {   
            if(prices[i]<permin) permin = prices[i];//找到买入最小金额
            profit = max(profit, prices[i]-permin); //找到卖出最大差价
            
        }
        return profit;
        
    }
};

Maximum Product Subarray(乘积最大子序列)

英文版:https://leetcode.com/problems/maximum-product-subarray/

中文版:https://leetcode-cn.com/problems/maximum-product-subarray/

class Solution {
public:
    int maxProduct(vector<int>& nums) {
     /*   if(nums.size()==0) return 0;
        if(nums.size()==1) return nums[0];
        int maxval=0;
       //没有通过上传:[-3,3,-8]返回了3,预期是72,我就纳闷了难道-3和8是连续子序列???
        for(int i=0;i<nums.size();i++) {   
            if(maxval<=nums[i]) maxval = nums[i];
            if((i+1)<nums.size()){
                if(maxval<(nums[i]*nums[i+1])) maxval = nums[i]*nums[i+1];//找到大于单元素子序列的双元素子序列    
        }
        else {}
            
        }
        return maxval;
      */
        int max_local = nums[0];
         int min_local = nums[0];
         int max_copy;
         int global = nums[0];
         
         for(int i = 1; i < nums.size(); i++){
              max_copy = max_local;
              max_local = max(max(max_local*nums[i], nums[i]), min_local*nums[i]);
              min_local = min(min(max_copy*nums[i], nums[i]), min_local*nums[i]);
              global = max(global,max_local);
         }
         
         return global;
    
    }
};

Triangle(三角形最小路径和)

英文版:https://leetcode.com/problems/triangle/

中文版:https://leetcode-cn.com/problems/triangle/

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
   /* for (int i = 1; i < triangle.size(); ++i) {
            for (int j = 0; j < triangle[i].size(); ++j) {
                if (j == 0) {
                    triangle[i][j] += triangle[i - 1][j];
                } else if (j == triangle[i].size() - 1) {
                    triangle[i][j] += triangle[i - 1][j - 1];
                } else {
                    triangle[i][j] += min(triangle[i - 1][j - 1], triangle[i - 1][j]);
                }
            }
        }
        return *min_element(triangle.back().begin(), triangle.back().end());*/
        vector<int> dp(triangle.back());
        for (int i = (int)triangle.size() - 2; i >= 0; --i) {
            for (int j = 0; j <= i; ++j) {
                dp[j] = min(dp[j], dp[j + 1]) + triangle[i][j];
            }
        }
        return dp[0];
    }
    
};
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容