115.Unique Path II
"不同的路徑" 的跟進問題:
現在考慮網格中有障礙物,那樣將會有多少條不同的路徑?
網格中的障礙和空位置分別用 1 和 0 來表示。
提示:注意初始化與前面不同,只能初始化第一個點。遍歷f[m][n],一旦有障礙就設置爲0,有左面或前面就+=。
答案:
class Solution {
public:
/**
* @param obstacleGrid: A list of lists of integers
* @return: An integer
*/
int uniquePathsWithObstacles(vector<vector<int>> &obstacleGrid) {
// write your code here
int m = obstacleGrid.size();
if(m == 0){
return 0;
}
int n = obstacleGrid[0].size();
if(n == 0){
return 0;
}
vector<vector<int>> f(m,vector<int>(n));
int i,j;
for(i = 0; i < m; ++i){
for(j = 0; j < n; ++j){
if(obstacleGrid[i][j] == 1){
f[i][j] = 0;
}
else{
if(i == 0 && j == 0){
f[i][j] = 1;
}
else{
f[i][j] = 0;
if(i - 1 >= 0){
f[i][j] += f[i-1][j];
}
if(j - 1 >= 0){
f[i][j] += f[i][j - 1];
}
}
}
}
}
return f[m - 1][n - 1];
}
};
397. Longest Increasing Continuous Subsequence
給定一個整數數組(下標從 0 到 n-1, n 表示整個數組的規模),請找出該數組中的最長上升連續子序列。(最長上升連續子序列可以定義爲從右到左或從左到右的序列。)
提示:如果當前位置的數字比前一個大,那麼臨時最大值+1,一旦不比前一個數字大,那麼臨時最大值與最大值做比較,把臨時最大值設置爲1。此題目示例單調遞減也算。此題目可以壓縮空間到f[2]。
答案:
class Solution {
public:
/**
* @param A an array of Integer
* @return an integer
*/
int longestIncreasingContinuousSubsequence(vector<int>& A) {
// Write your code here
int max = 1, s = 1, l = 1;
int len = A.size();
if (len == 0)
return 0;
for (int i = 1; i < len; ++i) {
if (A[i] > A[i-1])
s += 1;
else {
if (s > max) max = s;
s = 1;
}
if (A[i] < A[i-1])
l += 1;
else {
if (l > max) max = l;
l = 1;
}
}
if (s > max) max = s;
if (l > max) max = l;
return max;
}
};
110. Minimum Path Sum
給定一個只含非負整數的m*n網格,找到一條從左上角到右下角的可以使數字和最小的路徑。
提示:Dp[i][j] 存儲從(0, 0) 到(i, j)的最短路徑。
Dp[i][j] = min(Dp[i-1][j]), Dp[i][j-1]) + grid[i][j];
答案:
class Solution {
public:
/**
* @param grid: a list of lists of integers.
* @return: An integer, minimizes the sum of all numbers along its path
*/
int minPathSum(vector<vector<int> > &grid) {
// write your code here
int f[1000][1000];
if (grid.size() == 0 || grid[0].size() == 0)
return 0;
f[0][0] = grid[0][0];
for(int i = 1; i < grid.size(); i++)
f[i][0] = f[i-1][0] + grid[i][0];
for(int i = 1; i < grid[0].size(); i++)
f[0][i] = f[0][i-1] + grid[0][i];
for(int i = 1; i < grid.size(); i++)
for(int j = 1; j < grid[0].size(); j++)
f[i][j] = min(f[i-1][j], f[i][j-1]) + grid[i][j];
return f[grid.size()-1][grid[0].size()-1];
}
};
553. Bomb Enemy
給定一個二維矩陣, 每一個格子可能是一堵牆 W
,或者 一個敵人 E
或者空 0
(數字 '0'), 返回你可以用一個炸彈殺死的最大敵人數. 炸彈會殺死所有在同一行和同一列沒有牆阻隔的敵人。 由於牆比較堅固,所以牆不會被摧毀.
提示:分爲四個方向,分別計算每個點在指定方向能炸到的敵人數量,有敵人初始爲1+前一個點但不進入最大值計算,有牆直接 爲0。 一定要注意,行與列前後別搞反了!!!
答案:
class Solution {
public:
/**
* @param grid: Given a 2D grid, each cell is either 'W', 'E' or '0'
* @return: an integer, the maximum enemies you can kill using one bomb
*/
int maxKilledEnemies(vector<vector<char>> &grid) {
// write your code here
if(grid.size() == 0 || grid[0].size() == 0){
return 0;
}
int m = grid.size();
int n = grid[0].size();
int left[m][n], right[m][n], up[m][n], down[m][n];
// memset(left, 0, sizeof(left));
// memset(right, 0, sizeof(right));
// memset(up, 0, sizeof(up));
//memset(down, 0, sizeof(down));
int i, j, t;
for(i = 0; i < m; ++i){
for(j = 0; j < n; ++j){
up[i][j] = 0;
if(grid[i][j] != 'W'){
if(grid[i][j] == 'E'){
up[i][j] = 1;
}
if(i - 1 >= 0){
up[i][j] += up[i-1][j];
}
}
}
}
for(i = m - 1; i >= 0; --i){
for(j = 0; j < n; ++j){
down[i][j] = 0;
if(grid[i][j] != 'W'){
if(grid[i][j] == 'E'){
down[i][j] = 1;
}
if(i + 1 < m){
down[i][j] += down[i+1][j];
}
}
}
}
for(i = 0; i < m; ++i){
for(j = 0; j < n; ++j){
left[i][j] = 0;
if(grid[i][j] != 'W'){
if(grid[i][j] == 'E'){
left[i][j] = 1;
}
if(j - 1 >= 0){
left[i][j] += left[i][j-1];
}
}
}
}
for(i = 0; i < m; ++i){
for(j = n - 1; j >= 0; --j){
right[i][j] = 0;
if(grid[i][j] != 'W'){
if(grid[i][j] == 'E'){
right[i][j] = 1;
}
if(j + 1 < n){
right[i][j] += right[i][j+1];
}
}
}
}
int res = 0;
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j) {
if (grid[i][j] == '0') {
t = up[i][j] + down[i][j] + left[i][j] + right[i][j];
if (t > res) {
res = t;
}
}
}
}
return res;
}
};