算法学习-动态规划-实战一
2015-04-20 11:17
337 查看
1 二维数组路径最小和(leetcode 64):
1.1 问题描述:
一个m行n列的二维数组,每个元素是一个非负数,从左上角走到右下角,每次只能朝右或者下走,不能走出矩阵,使得总和最小。1.2 算法思想:
1.3 代码:
class Solution { public: int minPathSum(vector<vector<int> > &grid) { int M = grid.size(); int N = grid[0].size(); vector<int> paycost(N); for(int i=0; i<M; i++){ for(int j=0; j<N; j++){ if(i == 0){ if(j == 0){ paycost[j] = grid[i][j]; }else{ paycost[j] = paycost[j-1] + grid[i][j]; } }else if(j == 0){ paycost[j] = paycost[j] + grid[i][j]; }else{ paycost[j] = min(paycost[j],paycost[j-1]) + grid[i][j]; } } } return paycost[N-1]; } };
2 最大子数组求和(leetcode53):
2.1 问题描述:
一个整数数组,一个非空的子数组(连续一段数),使得它的和最大 (Leetcode 53)2.1 算法思想:
1.2 代码:
a.分治(我的代码超时了,不知道为什么):int divideAndCOnquermaxSubArray(vector<int>& nums,int start,int end){ if(end < start) return 0; if(end == start) return 1; int t = (end - start + 1)>>1; int mid = start+((end - start + 1)>>1); int sum = max(divideAndCOnquermaxSubArray(nums,start,mid-1), divideAndCOnquermaxSubArray(nums,mid+1,end)); int leftSum = 0; int leftMax = 0; for(int i=mid; i>=0; i--){ leftSum += nums[i]; leftMax = leftMax>leftSum ? leftMax : leftSum; } int rightSum = 0; int rightMax = 0; for(int i=mid; i<=end; i++){ rightSum += nums[i]; rightMax = rightMax>rightSum ? rightMax : rightSum; } return max(sum,leftMax+rightMax-nums[mid]); }
这个是我看的视频公开课的代码:
b.动态规划:
int DynamicProgramingMaxSubArray(vector<int>& nums){ int size = nums.size(); vector<int> p(size); for(int i=0; i<size; i++){ if(i == 0){ p[i] = nums[i]; }else{ p[i] = max(nums[i], nums[i]+p[i-1]); } } int max; for(int i=0; i<size; i++){ if(i==0) max = p[0]; else if(max < p[i]){ max = p[i]; } } return max; } //动态规划 优化空间 int DynamicProgramingMaxSubArrayGood(vector<int>& nums){ int size = nums.size(); int endHere; int maxAnd; for(int i=0; i<size; i++){ if(i == 0){ endHere = nums[i]; maxAnd = endHere; }else{ endHere = max(nums[i],endHere+nums[i]); maxAnd = max(maxAnd,endHere); } } return maxAnd; }c.线性枚举;
class Solution { public: int maxSubArray(vector<int>& nums) { int size = nums.size(); int minSum,sum; int maxAnd; for(int i=0; i<size; i++){ if(i == 0){ sum = maxAnd = nums[i]; minSum = min(0,nums[i]); }else{ sum += nums[i]; maxAnd = max(maxAnd,sum - minSum); minSum = min(minSum,sum); } } return maxAnd; } };
1.3 需要注意的问题:
a.在分治中,必须考虑还中点,和边界,由于我的中点开始时没有加start,一直没看出来,浪费了很多时间。b.在线性枚举的时候也是对边界(i==0时),对minSum的处理考虑不足。
3.编辑距离(leetcode 72):
3.1 问题描述:
给定两个字符串S和T,求把S变成T所需要的最少操作次数。操作包括:在任意位置增加一个字符、减少任意一个字符以及修改任意一个字符。(Leetcode 72)
3.2 算法思想:
3.3 代码:
int minDistance(string word1, string word2) { int WL1 = word1.length(); int WL2 = word2.length(); vector<vector<int> > paycost(WL1+1,vector<int>(WL2+1)); for(int i=0; i<=WL1; i++){ for(int j=0; j<=WL2; j++){ if(i == 0) paycost[i][j] = j; else if(j == 0) paycost[i][j] = i; else{ int cost0 = paycost[i-1][j-1] + (word1[i-1]==word2[j-1] ? 0 : 1); int cost1 = paycost[i-1][j] + 1; int cost2 = paycost[i][j-1] + 1; paycost[i][j] = min(cost0,min(cost1,cost2)); } // cout<< paycost[i][j] <<" "; } // cout<<endl; } return paycost[WL1][WL2]; }
空间优化:
class Solution { public: int minDistance(string word1, string word2) { int WL1 = word1.length(); int WL2 = word2.length(); vector<int> paycost(WL2+1); int payPrePre = 0; for(int i=0; i<=WL1; i++){ for(int j=0; j<=WL2; j++){ if(i == 0) paycost[j] = j; else if(j == 0){ payPrePre = paycost[j]; paycost[j] = i; } else{ int cost0 = payPrePre + (word1[i-1]==word2[j-1] ? 0 : 1); int cost1 = paycost[j] + 1; int cost2 = paycost[j-1] + 1; payPrePre = paycost[j]; paycost[j] = min(cost0,min(cost1,cost2)); } } } return paycost[WL2]; } };
3.4 需要注意的问题:
a.这个问题中,对问题的转换的的思想很重要,不容易想到。在coding中,对于下图情况A一般容易想到。对于B和C,由于在第一个时就要考虑前一个的情况,所以对于存储数组的大小要加一,以处理这一特殊情况。否则就要考虑很多边界情况。b.对于空间优化:在处理(i,j)点时需要考虑三个点(i-1,j-1)、(i-1,j)、(i,j-1)。此时(i,j)点还未更新。故(i-1,j)、(i,j-1)可以用以为数组(j-1)、(j)两个点表示。对于(i-1,j-1)。考虑N点,对于N点的左上正好是在处理(i,j)点时更新前的(j),所以用一个变量存起来即可。但是在边界点F时要单独处理。否则处理F后一点就会出错。
4 总结:
本文主要参考视频公开课视频公开课上实战进行练习。对于动态规划,最重要的就是a、递推式
b、初值
c、空间优化
在coding的过程中,一般容易出问题的就是初值和边界条件,写代码前最好现在纸上写,出了问题不要马上随便改一个地方继续试。这样会出行case by case的循环中。最好分析清楚再写,这样反而可以节约时间。
后续练习:
Leetcode (leetcode.com)题号 85, 91, 97, 120,131, 132, 139, 140, 152
5 参考资料:
http://www.julyedu.com/video/play/id/19
相关文章推荐
- 算法学习-动态规划-实战二(leetcode 85)
- 机器学习实战——使用K-近邻算法进行约会配对
- 机器学习实战-第2章(k-近邻算法)
- 机器学习实战 - K-近邻算法
- 机器学习实战:k-临近算法(一)
- 机器学习实战_初识朴素贝叶斯算法_理解其python代码(二)
- 机器学习实战学习笔记 一 k-近邻算法
- 机器学习实战-基本算法总结2
- 程序员面试学习宝典(算法设计、系统设计、数据科学、职业发展、实战项目)
- 机器学习实战之k-近邻算法(4)--- 如何归一化数据
- 【算法导论学习-29】动态规划经典问题02:最长公共子序列问题(Longest common subsequence,LCS)
- 机器学习实战笔记(1)——k-近邻算法
- 算法学习--动态规划
- 机器学习实战笔记(1)——kNN(k Nearest Neighbor)算法
- 【算法学习】最优二叉查找树(动态规划)
- 机器学习笔记--KNN算法2-实战部分
- 机器学习实战-KNN算法实现及遇到的问题总结
- 算法学习 - 01背包问题(动态规划C++)
- 算法学习——动态规划
- 【算法导论学习-27】动态规划经典问题01:钢条切割的最大收益