1. word Ladder
Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that:
- Only one letter can be changed at a time
- Each intermediate word must exist in the dictionary
For example,
Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]
As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog"
,
return its length 5
.
Note:
- Return 0 if there is no such transformation sequence.
- All words have the same length.
- All words contain only lowercase alphabetic characters.
BFS,
<unordered_set> . A nice property of unordered_set is it can find an element in O(1) time.
The key here is: the search for all valid strings in the dictionary can be considered as we generate all the possible strings and see if they are in the dictionary. For each char in the string, we can change it to the 26 letters, one position at a time, check if the new string exists in the dictionary. What is the complexity of this step? O(m*26).
record all possible next element in the dict into the queue<string> path
then next loop, to check the element in the queue
int ladderLength(string start, string end, unordered_set<string> &dict) {
if(start.size() != end.size()) return 0;//should have same length
if(start.empty() || end.empty()) return 0;//should not empty
queue<string> path;
path.push(start);
int level = 1;//record distance
int count = 1;
dict.erase(start);//delete start in dict
while(dict.size()>0 && !path.empty()){
string curword = path.front();
path.pop();
count --;
for(int i=0; i<curword.size();i++){
string tmp = curword;
for(char j='a';j<='z';j++){//record next element in dict
if(tmp[i]==j) continue;
tmp[i] =j;
if(tmp == end) return level+1;
if(dict.find(tmp)!=dict.end()) path.push(tmp);
dict.erase(tmp);
}
}
if(count ==0){
count = path.size();
level++;
}
}
return 0;
}
2. Surrounded Region
Given a 2D board containing 'X'
and '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
Analysis:
Search is a good way to solve this problem!
First and easy thought might, scan all the element, if meets ‘O’, looking for a path to the boundary, if not exist, put it to ‘X’. To look for the path, if all the four directions all have no way out, this element has no way out. The DFS can be used. See code(small case) below. Actually, it only cannot pass the last big test case (where 250×250 matrix is provided).
However, it will not pass the big test, because the complexity is too high. One common thought is to use BFS instead of DFS, which use more space, but less time.
So how BFS is conducted, we can think from out to inside. Because the boundary ‘O’ are definitely “live” (have a path out) element, so, we BFS from each ‘O’ in the boundary, mark all its four directions (where is also ‘O’) as “live”. If you think here, you almost done, the standard BFS using a queue (here I use vector for simplicity) can solve the problem. Last step is to flip “O” to “X” because there is no way out, and flip “Y”(live) to “O”, because it has a path out. See code (big case) for details. All the test cases are passed
已经知道连通区域必须至少一个元素是在四边,那么一开始直接从四边开始扫描就好了,所以无法connect到得元素都是应该被清除的。所以,算法如下:
1. 从四条边上的O元素开始BFS,所有相连的O都赋个新值,比如‘Y’
2. 扫描整个数组,所有现存的O元素全部置为X,所有Y元素置为O
Java
public void solve(char[][] board) {
ArrayList<Integer> xIndex = new ArrayList<>();
ArrayList<Integer> yIndex = new ArrayList<>();
int row = board.length;
if(row == 0) return;
int col = board[0].length;
if(col ==0) return;
//record the element in the boundary that are o
for(int i=0;i<row;i++){
if(board[i][0]=='O'){
xIndex.add(i);
yIndex.add(0);
}
if(board[i][col-1]=='O'){
xIndex.add(i);
yIndex.add(col-1);
}
}
for(int j=1;j<col-1;j++){
if(board[0][j]=='O'){
xIndex.add(0);
yIndex.add(j);
}
if(board[row-1][j]=='O'){
xIndex.add(row-1);
yIndex.add(j);
}
}
int k=0;
while(k<xIndex.size()){//detect 'o' path form the edge
int x = xIndex.get(k);
int y = yIndex.get(k);
board[x][y] = 'Y';
if(x>0 && board[x-1][y]=='O'){//up
xIndex.add(x-1);
yIndex.add(y);
}
if(x<row-1 && board[x+1][y]=='O'){//down
xIndex.add(x+1);
yIndex.add(y);
}
if(y>0 && board[x][y-1]=='O'){//left
xIndex.add(x);
yIndex.add(y-1);
}
if(y<col-1 && board[x][y+1]=='O'){//right
xIndex.add(x);
yIndex.add(y+1);
}
k++;
}
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(board[i][j]=='O') board[i][j] = 'X';//should first change to X
if(board[i][j]=='Y') board[i][j] = 'O';
}
}
}
c++
void solve(vector<vector<char>> &board) {
vector<int> xIndex;
vector<int> yIndex;
int row = board.size();
if(row == 0) return;
int col = board[0].size();
if(col ==0) return;
//record the element in the bounary that are o
for(int i=0;i<row;i++){
if(board[i][0]=='O'){
xIndex.push_back(i);
yIndex.push_back(0);
}
if(board[i][col-1]=='O'){
xIndex.push_back(i);
yIndex.push_back(col-1);
}
}
for(int j=1;j<col-1;j++){
if(board[0][j]=='O'){
xIndex.push_back(0);
yIndex.push_back(j);
}
if(board[row-1][j]=='O'){
xIndex.push_back(row-1);
yIndex.push_back(j);
}
}
int k=0;
while(k<xIndex.size()){//detect 'o' path form the edge
int x = xIndex[k];
int y = yIndex[k];
board[x][y] = 'Y';
if(x>0 && board[x-1][y]=='O'){//up
xIndex.push_back(x-1);
yIndex.push_back(y);
}
if(x<row-1 && board[x+1][y]=='O'){//down
xIndex.push_back(x+1);
yIndex.push_back(y);
}
if(y>0 && board[x][y-1]=='O'){//left
xIndex.push_back(x);
yIndex.push_back(y-1);
}
if(y<col-1 && board[x][y+1]=='O'){//right
xIndex.push_back(x);
yIndex.push_back(y+1);
}
k++;
}
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(board[i][j]=='O') board[i][j] = 'X';//should first change to X
if(board[i][j]=='Y') board[i][j] = 'O';
}
}
}
Given a 2D board containing 'X'
and '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
Analysis:
Search is a good way to solve this problem!
First and easy thought might, scan all the element, if meets ‘O’, looking for a path to the boundary, if not exist, put it to ‘X’. To look for the path, if all the four directions all have no way out, this element has no way out. The DFS can be used. See code(small case) below. Actually, it only cannot pass the last big test case (where 250×250 matrix is provided).
However, it will not pass the big test, because the complexity is too high. One common thought is to use BFS instead of DFS, which use more space, but less time.
So how BFS is conducted, we can think from out to inside. Because the boundary ‘O’ are definitely “live” (have a path out) element, so, we BFS from each ‘O’ in the boundary, mark all its four directions (where is also ‘O’) as “live”. If you think here, you almost done, the standard BFS using a queue (here I use vector for simplicity) can solve the problem. Last step is to flip “O” to “X” because there is no way out, and flip “Y”(live) to “O”, because it has a path out. See code (big case) for details. All the test cases are passed
已经知道连通区域必须至少一个元素是在四边,那么一开始直接从四边开始扫描就好了,所以无法connect到得元素都是应该被清除的。所以,算法如下:
1. 从四条边上的O元素开始BFS,所有相连的O都赋个新值,比如‘Y’
2. 扫描整个数组,所有现存的O元素全部置为X,所有Y元素置为O
Java
public void solve(char[][] board) {
ArrayList<Integer> xIndex = new ArrayList<>();
ArrayList<Integer> yIndex = new ArrayList<>();
int row = board.length;
if(row == 0) return;
int col = board[0].length;
if(col ==0) return;
//record the element in the boundary that are o
for(int i=0;i<row;i++){
if(board[i][0]=='O'){
xIndex.add(i);
yIndex.add(0);
}
if(board[i][col-1]=='O'){
xIndex.add(i);
yIndex.add(col-1);
}
}
for(int j=1;j<col-1;j++){
if(board[0][j]=='O'){
xIndex.add(0);
yIndex.add(j);
}
if(board[row-1][j]=='O'){
xIndex.add(row-1);
yIndex.add(j);
}
}
int k=0;
while(k<xIndex.size()){//detect 'o' path form the edge
int x = xIndex.get(k);
int y = yIndex.get(k);
board[x][y] = 'Y';
if(x>0 && board[x-1][y]=='O'){//up
xIndex.add(x-1);
yIndex.add(y);
}
if(x<row-1 && board[x+1][y]=='O'){//down
xIndex.add(x+1);
yIndex.add(y);
}
if(y>0 && board[x][y-1]=='O'){//left
xIndex.add(x);
yIndex.add(y-1);
}
if(y<col-1 && board[x][y+1]=='O'){//right
xIndex.add(x);
yIndex.add(y+1);
}
k++;
}
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(board[i][j]=='O') board[i][j] = 'X';//should first change to X
if(board[i][j]=='Y') board[i][j] = 'O';
}
}
}
c++
void solve(vector<vector<char>> &board) {
vector<int> xIndex;
vector<int> yIndex;
int row = board.size();
if(row == 0) return;
int col = board[0].size();
if(col ==0) return;
//record the element in the bounary that are o
for(int i=0;i<row;i++){
if(board[i][0]=='O'){
xIndex.push_back(i);
yIndex.push_back(0);
}
if(board[i][col-1]=='O'){
xIndex.push_back(i);
yIndex.push_back(col-1);
}
}
for(int j=1;j<col-1;j++){
if(board[0][j]=='O'){
xIndex.push_back(0);
yIndex.push_back(j);
}
if(board[row-1][j]=='O'){
xIndex.push_back(row-1);
yIndex.push_back(j);
}
}
int k=0;
while(k<xIndex.size()){//detect 'o' path form the edge
int x = xIndex[k];
int y = yIndex[k];
board[x][y] = 'Y';
if(x>0 && board[x-1][y]=='O'){//up
xIndex.push_back(x-1);
yIndex.push_back(y);
}
if(x<row-1 && board[x+1][y]=='O'){//down
xIndex.push_back(x+1);
yIndex.push_back(y);
}
if(y>0 && board[x][y-1]=='O'){//left
xIndex.push_back(x);
yIndex.push_back(y-1);
}
if(y<col-1 && board[x][y+1]=='O'){//right
xIndex.push_back(x);
yIndex.push_back(y+1);
}
k++;
}
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(board[i][j]=='O') board[i][j] = 'X';//should first change to X
if(board[i][j]=='Y') board[i][j] = 'O';
}
}
}