标签:
338. Counting Bits
Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1‘s in their binary representation and return them as an array.
Example:
For num = 5
you should return [0,1,1,2,1,2]
.
vector<int> countBits(int num) { vector<int> ret(num + 1, 0); for(int i = 1; i <= num; ++i) ret[i] = ret[i>>1] + i % 2; return ret; }
343. Integer Break
Given a positive integer n, break it into the sum of at least two positive integers and maximize the product of those integers. Return the maximum product you can get.
For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 + 3 + 4).
Note: You may assume that n is not less than 2 and not larger than 58.
Hint:
int integerBreak(int n) { if (n == 2 || n == 3) return n - 1; int res = 1; while (n > 4) { res *= 3; n -= 3; } return res * n; }
96.
Unique Binary Search Trees
Given n, how many structurally unique BST‘s (binary search trees) that store values 1...n?
For example,
Given n = 3, there are a total of 5 unique BST‘s.
1 3 3 2 1 \ / / / \ 3 2 1 1 3 2 / / \ 2 1 2 3本题使用一维线性规划解决。
如果n == 0时,结果为0;
如果n == 1时,只有一个节点,结果为1;
如果n == 2时,根节点有两种选择,结果为2;
如果n >= 3时,n个点中每个点都可以作为root,当 i 作为root时,小于 i 的点都只能放在其左子树中,大于 i 的点只能放在右子树中,此时只需求出左、右子树各有多少种,二者相乘即为以 i 作为root时BST的总数。
class Solution { public: int numTrees(int n) { if(n <= 2) return n; vector<int> dp(n + 1, 0); dp[0] = 1; dp[1] = 1; dp[2] = 2; for(int i = 3; i <= n; ++i) { int tmp = 0; for(int j = 0; j < i; ++j) { tmp += dp[j] * dp[ i - j - 1]; } dp[i] = tmp; } return dp[n]; } };62. 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?
一、题目描述:
给定一个m*n的矩阵,让机器人从左上方走到右下方,只能往下和往右走,一共多少种走法。
二、解题方法:
//动态规划: //设状态为f[i][j],表示从起点(1;1)到达(i; j)的路线条数,则状态转移方程为: //f[i][j] = f[i-1][j] + f[i][j-1] class Solution { public: int uniquePaths(int m, int n) { vector<vector<int> > f(m, vector<int>(n, 1)); for (int i = 1; i < m; i++) for (int j = 1; j < n; j++) f[i][j] = f[i - 1][j] + f[i][j - 1]; return f[m - 1][n - 1]; } };上面方法的空间复杂度较大为O(m*n),然而通过观察可以发现,我们每次更新f[i][j]只需要f[i-1][j](同一列)和f[i][j-1](左一列),所以只要保存当前列和左一列就行,而不是整个m*n矩阵,下面的代码可以将空间复杂度优化到O(min(m,n))
class Solution { int uniquePaths(int m, int n) { if (m > n) return uniquePaths(n, m); vector<int> pre(m, 1); vector<int> cur(m, 1); for (int j = 1; j < n; j++) { for (int i = 1; i < m; i++) cur[i] = cur[i - 1] + pre[i]; swap(pre, cur); } return pre[m - 1]; } };通过进一步的观察,我们还可以发现,上面程序中的pre[i]就是更新前的cur[i],所以可以进一步优化为:
class Solution { int uniquePaths(int m, int n) { if (m > n) return uniquePaths(n, m); vector<int> cur(m, 1); for (int j = 1; j < n; j++) for (int i = 1; i < m; i++) cur[i] += cur[i - 1]; return cur[m - 1]; } };最终优化空间程序为:(其实先遍历m还是先遍历n都无所谓的。关键是要注意 vector的长度 与 内层for循环的长度 是一样的~!)
class Solution{ public: int uniquePaths(int m, int n) { if (m == 0 && n == 0) return 0; vector<int> dp(n, 1); for (int i = 1; i < m; i++) for (int j = 1; j < n; j++) dp[j] = dp[j - 1] + dp[j]; return dp[n - 1]; } };63. 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 as 1
and 0
respectively
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 is 2
.
Note: m and n will be at most 100.
这道题跟 Unique Paths 差不多,只是这道题给机器人加了障碍,不是每次都有两个选择(向右,向下)了。class Solution { public: int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) { int m = obstacleGrid.size(); int n = obstacleGrid[0].size(); if(m == 0 || n ==0) return 0; vector<int> dp(n); dp[0] = 1; for(int i = 0; i < m; ++i) { for(int j = 0; j < n; ++j) { if(obstacleGrid[i][j] == 1) dp[j] = 0; else if(j > 0) dp[j] += dp[j - 1]; } } return dp[n - 1]; } };64. 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.
这是动态规划的问题,由于每次只能向下或者向右移动,因此[i, j]位置时的最小路径的和等于[i, j-1] 与 [i-1, j]中较小的加上[i, j]位置的数值。
因此递推公式是grid[i][j] += min(grid[i][j-1], grid[i-1][j])。
时间复杂度:O(mn)
class Solution { public: int minPathSum(vector<vector<int>>& grid) { int m = grid.size(); int n = grid[0].size(); if(m == 0 && n == 0) return 0; vector<vector<int> > dp (m, vector<int>(n, 0)); dp[0][0] = grid[0][0]; for(int i = 1; i < m; ++i) dp[i][0] += grid[i][0] + dp[i - 1][0]; for(int i = 1; i < n; ++i) dp[0][i] += grid[0][i] + dp[0][i - 1]; for(int i = 1; i < m; ++i) { for(int j = 1; j < n; ++j) { dp[i][j] += grid[i][j] + min(dp[i - 1][j], dp[i][j - 1]); } } return dp[m - 1][n - 1]; } };
Given a positive integer n, find the least number of perfect square numbers (for example, 1,
4, 9, 16, ...
) which sum to n.
For example, given n = 12
, return 3
because 12
= 4 + 4 + 4
; given n = 13
, return 2
because 13
= 4 + 9
.
用动态规划Dynamic Programming来做,我们建立一个长度为n+1的一维dp数组,将第一个值初始化为0,其余值都初始化为INT_MAX.i从0循环到n,j从1循环到i+j*j <= n的位置,然后每次更新dp[i+j*j]的值,动态更新dp数组,其中dp[i]表示正整数i能少能由多个完全平方数组成,那么我们求n,就是返回dp[n]即可,也就是dp数组的最后一个数字,参见代码如下:
class Solution { public: int numSquares(int n) { vector<int> dp(n + 1, 0x7fffffff); for(int i = 0; i * i <= n; ++i) dp[i * i] = 1; for(int i = 1; i <= n; ++i) { for(int j = 1; i + j * j <= n; ++j) { dp[i + j * j] = min(dp[i] + 1, dp[i + j * j]); } } return dp[n]; } };
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 is 11
(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.
求一个三角形二维数组从顶到低端的最小路径和。每次只能挪一个位置。
我们从低端向顶端计算。设状态为 S[i][j]表示从从位置 ( i, j ) 出发,到最低端路径的最小和
状态转移方程:S[i][j] = min(S[i+1][j] + S[i+1][j+1]) +S[i][j]
S[0][0]就是要求解的答案。
时间复杂度 O(n^2) ,空间复杂度 O(1)
class Solution { public: int minimumTotal(vector<vector<int> > &triangle) { int size = triangle.size(); // down-to-top // 第i层 for(int i = size - 2;i >= 0;--i){ // 第i层的第j个元素 for(int j = 0;j <= i;++j){ triangle[i][j] += min(triangle[i+1][j], triangle[i+1][j+1]); } } return triangle[0][0]; } };
从上面思路的状态转移方程中看出:S[i][j] = min(S[i+1][j] + S[i+1][j+1]) +S[i][j]
S[i][j]只与下一行的第j个元素和第j+1个元素相关,i的关系是固定的,因此我们可以省去这一维。
开辟O(N)的数组,然后规划的时候使用S[j] = min(S[j+1], S[j) +Triangle[i][j]就可以了。
class Solution { public: int minimumTotal(vector<vector<int> > &triangle) { int n = triangle.size(); vector<int> dp(triangle.back());//dp初值设为triangle的最后一行 // down-to-top // 第i层 for(int i = n - 2;i >= 0;--i){ // 第i层的第j个元素 for(int j = 0;j <= i;++j){ dp[j] = min(dp[j], dp[j+1]) + triangle[i][j]; } } return dp[0]; } };
标签:
原文地址:http://blog.csdn.net/dr_unknown/article/details/51939833