LeetCode练习-动态规划算法(一)

来源:互联网 发布:手机保密软件 编辑:程序博客网 时间:2024/05/01 16:26


一、Maximum Subarray(最大连续子序列和)

描述:

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [−2,1,−3,4,−1,2,1,−5,4], the contiguous subarray [4,−1,2,1] has the largest sum = 6.

分析:


代码1:

#include<iostream>#include<string.h>using namespace std;/*最大连续子序列和*/int maxSubArray(int a[], int n);int main(){int a[] = {-2,1,-3,4,-1,2,1,-5,4};int n = sizeof(a)/4;cout << maxSubArray(a, n) << endl;return 0;}int maxSubArray(int a[], int n){int i;int f=0;int result=-99999;for(i=0; i<n; ++i){//f = (f+a[i]) > a[i] ? (f+a[i]) : a[i];//result = result > f ? result : f;if(f>0)f = f+a[i];elsef = a[i];result = result > f ? result : f;//新旧结果对比,因为a[i]可能小于0。若a[i]小于0,则用老结果。}return result;}

代码2:与代码1相比,可以返回子序列!!!

#include<iostream>#include<string.h>using namespace std;/*最大连续子序列和*/int maxSubArray(int a[], int n, int &l, int &r);// l、r分别为最大连续子序列的起始和终止点int main(){int a[] = {-2,1,-3,4,-1,2,1,-5,4};int n = sizeof(a)/4;int l=0, r=0;int out = maxSubArray(a, n, l, r);cout << out << endl;int i;for(i=l; i<=r; i++)cout << a[i] << ' ';cout << endl;return 0;}int maxSubArray(int a[], int n, int &l, int &r){int i;int f=0;int last_f=0;int result=-99999;int last_result=-99999;for(i=0; i<n; ++i){if(f>0)f = f+a[i];elsef = a[i];if(last_f<0 && f>0)//f由负跳到正的时候,记录子序列起始点l = i;last_f = f;if(result < f)//result增大时,记录子序列终止点{result = f;r = i;}}return result;}

二、Candy

题目描述
There are N children standing in a line. Each child is assigned a rating value.
You are giving candies to these children subjected to the following requirements:
    Each child must have at least one candy.
    Children with a higher rating get more candies than their neighbors.
What is the minimum candies you must give?

class Solution {public:    int candy(vector<int> &ratings){        int i;        if(ratings.size() == 0)//没有小孩儿            return 0;        else if(ratings.size() == 1)//有一个小孩儿            return 1;        else{            int num = ratings.size();//小孩儿的个数            vector<int> candies(num, 1);            for(i=1; i<num; ++i){//从左往右遍历                if(ratings[i]>ratings[i-1] && candies[i] <= candies[i-1])                    candies[i] = candies[i-1] + 1;            }            for(i=num-2; i>=0; --i){//从右往左遍历                if(ratings[i] > ratings[i+1] && candies[i] <= candies[i+1])                    candies[i] = candies[i+1] + 1;            }            int result=0;            for(i=0; i<num; ++i){//计算糖果数量                result += candies[i];            }            return result;        }    }};

三、triangle

题目描述
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
For example, given the following triangle
[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]

The minimum path sum from top to bottom is11(i.e., 2 + 3 + 5 + 1 = 11).
Note:
Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.

思路:

     [2],        ----------------> [2]
    [3,4],      --------------->[5,6]
   [6,5,7],   ------------->[11,10,13]         把当前行的第j个元素与former_res中第j与第j-1较小的值相加,
  [4,1,8,3]  ----------->[15,11,18,16]      第0个元素与former_res的第0个元素相加,最后一个元素同理。

代码:

class Solution {public:    int minimumTotal(vector<vector<int> > &triangle){        vector<int> former_res;//记录前边的结果        vector<int> result;//记录考虑当前行的结果        int i, j;        int temp;        former_res.push_back(triangle[0][0]);//把三角形的第一个元素给former_res        for(i=1; i<triangle.size(); ++i){//遍历三角形每一行            result.push_back(triangle[i][0] + former_res[0]);//每一个行的第一个元素直接与former_res的第一个元素相加,并保存            for(j=1; j<triangle[i].size()-1; ++j){//每一个行的第i个元素与former_res较小的值相加,并保存                temp = (former_res[j-1] < former_res[j] ? former_res[j-1] : former_res[j]);                result.push_back(temp+triangle[i][j]);            }            //每一个行的最后一个元素直接与former_res的最后一个元素相加,并保存            result.push_back(triangle[i][triangle[i].size()-1] + former_res[former_res.size()-1]);            former_res.clear();//清空former_res            former_res = result;//用result更新former_res            result.clear();//清空result        }        vector<int>::iterator biggest = min_element(former_res.begin(), former_res.end());//找到向量former_res中最小的元素        return *biggest;    }};
本地调试代码:

#include<iostream>#include<string>#include<vector>#include <algorithm>using namespace std;int minimumTotal(vector<vector<int> > &triangle);int main(){vector<vector<int> > triangle;int n;cout << "The rows of triangle: ";cin >> n;int num = n*(n+1)/2;cout << "num: " << num << endl;int count=0, COUNT=1;int a;vector<int> b;int i, j;for(i=0; i<num; ++i){cin >> a;b.push_back(a);++count;if(count == COUNT){triangle.push_back(b);b.clear();count=0;++COUNT;}}for(i=0; i<triangle.size(); ++i){for(j=0; j<triangle[i].size(); ++j)cout << triangle[i][j] << ' ';cout << endl;}cout << "result: " << minimumTotal(triangle) << endl;return 0;}
四、climbing-stairs
题目描述
You are climbing a stair case. It takes n steps to reach to the top.

Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

思路:

//climbStairs(n) = climbStairs(n-1) + climbStairs(n-2);
//与《王道》里边的铺砖问题一样!

代码:

class Solution {public:        int climbStairs(int n){        if(n<0)            return NULL;        else if(n<=2)            return n;        else{            vector<int> a;            a.push_back(0);            a.push_back(1);            a.push_back(2);            for(int i=3; i<=n; ++i){                int b = a[i-1]+a[i-2];                a.push_back(b);            }            return a[a.size()-1];        }    }};

五、minimum-path-sum

题目描述
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.
Note: You can only move either down or right at any point in time.

思路:在计算result时,result(i, j) = min( result(i-1, j), result(i, j-1) ) + grid(i, j)

class Solution {public:    int sum(vector<int> a){        int sum=0;        for(int i=0; i<a.size(); ++i)            sum += a[i];        return sum;    }    int sum2(vector<vector<int> > a){        int sum=0;        for(int i=0; i<a.size(); ++i)            sum += a[i][0];        return sum;    }    int minPathSum(vector<vector<int> > &grid){        if(grid.size() <= 0)            return NULL;        else if(grid.size() == 1)//只有一行            return sum(grid[0]);        else if(grid[0].size() == 1)//只有一列            return sum2(grid);        else{            int i, j;            vector<vector<int> > result;            vector<int> result_row;            //计算result的第一行            result_row.push_back(grid[0][0]);            result.push_back(result_row);            for(j=1; j<grid[0].size(); ++j)                result[0].push_back(result[0][j-1] + grid[0][j]);            //计算result的剩余行            for(i=1; i<grid.size(); ++i){                result_row.clear();                result_row.push_back(result[i-1][0] + grid[i][0]);                result.push_back(result_row);                for(j=1; j<grid[i].size(); ++j){                    result[i].push_back((result[i][j-1] < result[i-1][j] ? result[i][j-1] : result[i-1][j]) + grid[i][j]);                }            }            return result[--i][--j];        }    }};
本地调试代码:

int main(){vector<vector<int> > grid;int m, n;cin >> m >> n;for(int i=0; i<m; ++i){vector<int> temp;for(int j=0; j<n; ++j){int x;cin >> x;temp.push_back(x);}grid.push_back(temp);}cout << "minPathSum: " << minPathSum(grid) << endl;/*调试用for(i=0; i<m; ++i){for(int j=0; j<n; ++j)cout << grid[i][j] << ' ';cout << endl;}cout << endl;*/return 0;}

六、unique-paths

题目描述
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).
How many possible unique paths are there?


Above is a 3 x 7 grid. How many possible unique paths are there?
Note: m and n will be at most 100.

思路:与上一题minimum-path-sum很像

代码:

class Solution {public:    int uniquePaths(int m, int n){        int i, j;        if(m<1 || n<1)            return 0;        vector<vector<int> > result(m, vector<int>(n, 1));//初始化全1        for(i=1; i<m; ++i)            for(j=1; j<n; ++j)                result[i][j] = result[i-1][j] + result[i][j-1];        return result[m-1][n-1];    }};
七、unique-paths-ii
题目描述
Follow up for "Unique Paths":
Now consider if some obstacles are added to the grids. How many unique paths would there be?
An obstacle and empty space is marked as1and0respectively in the grid.
For example,
There is one obstacle in the middle of a 3x3 grid as illustrated below.
[
  [0,0,0],
  [0,1,0],
  [0,0,0]
]
The total number of unique paths is2.

Note: m and n will be at most 100.

思路:与上一题unique-paths很像,区别在于:当 当前位置为障碍物时,把对应的result置为0。此外,result的第一行与第一列的设置方式与unique-paths也稍有区别!

代码:

class Solution {public:    int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid){        int i, j;        int m = obstacleGrid.size();//行数        int n = obstacleGrid[0].size();//列数        vector<vector<int> > result(m, vector<int>(n, 0));//初始化用于存储结果的数组,全为0        if(obstacleGrid[0][0] == 0)//如果左上角元素不是障碍物            result[0][0] = 1;        else//否则返回0            return 0;        for(j=1; j<n; ++j)//result的第一行            if(obstacleGrid[0][j] == 1)//如果当前位置是障碍物,此处的result设为0                result[0][j] = 0;            else//若不是障碍物                result[0][j] = result[0][j-1];//则为左邻居的值        for(i=1; i<m; ++i)//result的第一列,与第一行同理            if(obstacleGrid[i][0] == 1)                result[i][0] = 0;            else                result[i][0] = result[i-1][0];        for(i=1; i<m; ++i){            for(j=1; j<n; ++j){                if(obstacleGrid[i][j] == 1)//与uniquePaths的区别之处,若当前位置为障碍物                    result[i][j] = 0;//则把resutl设为0                else//若不是障碍物                    result[i][j] = result[i-1][j] + result[i][j-1];//则把左边和上边的邻居值相加            }        }        return result[m-1][n-1];//返回结果    }};

本地测试代码:

int main(){vector<vector<int> > grid;int m, n;cin >> m >> n;for(int i=0; i<m; ++i){vector<int> temp;for(int j=0; j<n; ++j){int x;cin >> x;temp.push_back(x);}grid.push_back(temp);}cout << uniquePathsWithObstacles(grid) << endl;return 0;}



1 0