130. Surrounded Regions
Given a 2D board containing 'X'
and 'O'
(the letter O),
capture all regions surrounded by 'X'
.
A region is captured by flipping all 'O'
s
into 'X'
s in that surrounded region.
For example,
X X X X X O O X X X O X X O X X
After running your function, the board should be:
X X X X X X X X X X X X X O X X
Solution: 广度优先搜索(BFS),最外面一圈的O是一定保留的,然后跟它们相连的O也能被保留下来。
Code:
class Solution {
public:
void solve(vector<vector<char>>& board) {
if(board.size()==0 || board[0].size()==0) return;
queue<pair<int, int>> q;
//unordered_map<int, bool> visited; 这样做标记太浪费空间了,直接记录在board里面
//第一行
for(int i=0; i<board[0].size(); i++){
if(board[0][i] == 'O'){
q.push(make_pair(0, i));
board[0][i] = '+';//即能标记又能去重
}
if(board.back()[i] == 'O'){
q.push(make_pair(board.size()-1, i));
board[board.size()-1][i] = '+';
}
}
for(int i=0; i<board.size(); i++){
if(board[i][0] == 'O'){
q.push(make_pair(i, 0));
board[i][0] = '+';
}
if(board[i].back() == 'O'){
q.push(make_pair(i, board[0].size()-1));
board[i][board[0].size()-1] = '+';
}
}
while(!q.empty()){
int x = q.front().first;
int y = q.front().second;
if(x>0 && board[x-1][y]=='O'){
q.push(make_pair(x-1,y));
board[x-1][y] = '+';
}
if(y>0 && board[x][y-1]=='O'){
q.push(make_pair(x,y-1));
board[x][y-1] = '+';
}
if(x<board.size()-1 && board[x+1][y]=='O'){
q.push(make_pair(x+1,y));
board[x+1][y] = '+';
}
if(y<board[0].size()-1 && board[x][y+1]=='O'){
q.push(make_pair(x,y+1));
board[x][y+1] = '+';
}
q.pop();
}
for(int i=0; i<board.size(); i++){
for(int t=0; t<board[i].size(); t++){
if(board[i][t]=='O')
board[i][t]='X';
else if(board[i][t]=='+')
board[i][t]='O';
}
}
}
};
131. Palindrome Partitioning
Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.
For example, given s = "aab"
,
Return
[ ["aa","b"], ["a","a","b"] ]
Solution(1):深搜,每一步都将string分成两部分,一部分为一定包第一个字母的字符串,对剩下的字母构成的字符串继续递归,时间复杂度O(n^2),空间复杂度O(n)。
Code:
class Solution {
public:
vector<vector<string>> partition(string s) {
vector<vector<string>> ans;
vector<string> path;
dfs(0, s.size(), s, path, ans);
return ans;
}
private:
bool isPalindrome(string& s){
for(int i=0, j=s.size()-1; i<j; i++,j--){
if(s[i]!=s[j]) return false;
}
return true;
}
void dfs(int first, int end, string& s, vector<string>& path, vector<vector<string>>& ans){
if(first == end){
ans.push_back(path);
return;
}
for(int i=1; i<=end-first; i++){
string sub = s.substr(first, i);
if(isPalindrome(sub)){
path.push_back(sub);
dfs(first+i, end, s, path, ans);
path.pop_back();
}
}
}
};
Solution(2): 动态规划。
Code:
class Solution {
public:
vector<vector<string>> partition(string s) {
int n = s.size();
if(n==0){
vector<vector<string>> ans;
ans.push_back(vector<string>());
return ans;
}
//预处理,也是动规思想
bool Palindrome[n][n];//Palindrome[x][y],x-y之间的子串是否为回文
fill_n(&Palindrome[0][0], n*n, false);//Palindrome[x][y]要求x<=y,因此实际上真正有用的空间只有一半
for(int i=0; i<n; i++){
for(int t=i; t>=0; t--)
if(t<i-2 && i>0)
Palindrome[t][i] = s[i]==s[t] && Palindrome[t+1][i-1];
else
Palindrome[t][i] = s[i]==s[t];
}
//动规
vector<vector<string>> partition[n];//记录前n个字符partition的解集
for(int i=0; i<n; i++){//加入一个新字符
for(int t=i; t>0; t--){//遍历新字符作为最后一个能构成的所有子串
string sub = s.substr(t,i-t+1);
if(isPalindrome(sub)){
//如果子串是回文,则将不包含子串在内的前t个字符的解集逐一加上这个回文加入当前寻找的解集
for(vector<string> v:partition[t-1]){
v.push_back(sub);
partition[i].push_back(v);
}
}
}
//t=0的情况
string sub = s.substr(0,i+1);
if(isPalindrome(sub)) partition[i].push_back(vector<string>{sub});
}
return partition[n-1];
}
private:
bool isPalindrome(string& s){
for(int i=0, j=s.size()-1; i<j; i++,j--){
if(s[i]!=s[j]) return false;
}
return true;
}
};
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?
Above is a 3 x 7 grid. How many possible unique paths are there?
Note: m and n will be at most 100.
Solution(1): 深搜,直接深搜会超时,使用数组记录已经算过的值(备忘录法)。
Code:
class Solution {
public:
int uniquePaths(int m, int n) {
//this->f = vector<vector<int> >(m + 1, vector<int>(n + 1, 0));
//会报runtime erro,free()的时候无法成功,为什么?
for(int i=0; i<=m; i++){
up.push_back(vector<int>());
for(int t=0; t<=n; t++){
up.back().push_back(0);
}
}
return dfs(m, n);
}
private:
vector<vector<int>> up;
int dfs(int m, int n) {
if(m<=0 || n<=0) return 0;
if(m==1 || n==1) return 1;
if(up[m-1][n]==0) up[m-1][n] = dfs(m-1, n);
if(up[m][n-1]==0) up[m][n-1] = dfs(m, n-1);
return up[m-1][n]+up[m][n-1];
}
};
Solution(2): 动规,设状态为up[i][j],表示从起点(1; 1) 到达(i; j) 的路线条数,则状态转移方程为:up[i][j]=up[i-1][j]+up[i][j-1]
Code:
class Solution {
public:
int uniquePaths(int m, int n) {
int up[m][n];
for(int i=0; i<n; i++) up[m-1][i] = 1;
for(int i=0; i<m; i++) up[i][n-1] = 1;
for(int i=m-2; i>=0; i--){
for(int t=n-2; t>=0; t--){
up[i][t] = up[i+1][t]+up[i][t+1];
}
}
return up[0][0];
}
};
Solution(3): 数学方法,机器人一共需要走m+n-2步,其中有m-1步是向下走,问一共有多少种走法,即m+n-2步中选择m-1步向下一共有多少种组合方式,即C(m+n-2,m-1)。
Code:
class Solution {
public:
int uniquePaths(int m, int n) {
//C(m+n-2,m-1)
int k = min(m,n);//防止溢出
long long ans = 1;//防止溢出
for(int i=0,j=m+n-2; i<k-1; i++,j--)
ans *= j;
for(int i=1; i<=k-1; i++)
ans /= i;
return ans;
}
};