Week6
Program--Medium--419. Battleships in a Board
Given an 2D board, count how many battleships are in it. The battleships are represented with 'X'
s, empty slots are represented with '.'
s. You may assume the following rules:
- You receive a valid board, made of only battleships or empty slots.
- Battleships can only be placed horizontally or vertically. In other words, they can only be made of the shape
1xN
(1 row, N columns) orNx1
(N rows, 1 column), where N can be of any size. - At least one horizontal or vertical cell separates between two battleships - there are no adjacent battleships.
Example:
X..X ...X ...XIn the above board there are 2 battleships.
Invalid Example:
...X XXXX ...XThis is an invalid board that you will not receive - as battleships will always have a cell separating between them.
Follow up:
Could you do it in one-pass, using only O(1) extra memory and without modifying the value of the board?
题目解析:
这是一道类似与图的连通问题,在一张矩形的图中,只有相邻为X的点才是连通的,为"."的点则是不通的,问题就可以转化为有多少个连通集合,且连通的方向只有上下或者左右,为寻找同路提供了方便。在这里,我用一种消除的方法,从左到右,从上往下,在找到一个X后,水平或者垂直搜索,找与之连通的其他X,边找边把他们变为“.”,将这个连通集合消除变为“.”,表示这艘船以及被找过,同时count++。做到最后,消除所有X后,count的值就记录了我们消除的船的个数。
代码:
class Solution {
public:
int countBattleships(vector<vector<char>>& map) {
int count = 0;
for (int i = 0; i < map.size(); i++) {
for (int j = 0; j < map[i].size(); j++) {
if (map[i][j] == 'X') {
map[i][j] = '.';
if (j + 1 < map[i].size()) {
if (map[i][j + 1] == 'X') {
findShip(map, i, j + 1, "hor");
}
}
if (i + 1 < map.size()) {
if (map[i + 1][j] == 'X')
findShip(map, i + 1, j, "ver");
}
count++;
}
}
}
return count;
}
void findShip(vector<vector<char>> &map, int i, int j, string dir) {
if (dir == "ver") {
while(i < map.size() && map[i][j] == 'X') {
map[i][j] = '.';
i++;
}
} else {
while(j < map[i].size() && map[i][j] == 'X') {
map[i][j] = '.';
j++;
}
}
}
};
Program--Medium--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.
题目解析:
这个问题类似于图算法中的最小路径的寻找,那么,解决方法就很直观了,直接利用Dijkstra算法即可。不过细节还是值得注意的,这主要体现在各种变量的数据结构上。对于Dijkstra算法,我们需要维护从起点到点u的路径长dis[u],由于直接输出右下角的dis,所以我们不需要维护当前点的前一个点的记录变量prev,所以重点就只在dis和队列的数据结构上。
1.在这里我用vector<vector<int>>dis来存储距离信息,通过Dijkstra算法,遍历整个邻接矩阵,就可以得到右下角点的最短距离。
2.算法按最小值排序的需求我用优先队列来实现,我没有事先把所有点的值放入队列中进行排序,只有当下一个点满足判断要求才加入,这样就避免那些值为无穷大的被加进去,我们是不需要维护他们的大小关系的,因为他们永远位于队列之后。当一个点的距离有无限变成更小值时,它一定会被加入队列,避免有的点不会入队。
代码:
class Solution {
public:
struct node {
int i;
int j;
int val;
node(int r, int c, int v) {
i = r;
j = c;
val = v;
};
friend bool operator < (node a, node b) {
return a.val > b.val; //重载小于号使得小的先出队列
}
};
int minPathSum(vector<vector<int>>& grid) {
vector<vector<int>> dis(grid);
priority_queue<node> Queue;
for(int i = 0; i < grid.size(); i++) {
for (int j = 0; j < grid[i].size(); j++) {
int temp;
if (!i && !j) {
dis[i][j] = grid[0][0];
} else {
dis[i][j] = INT_MAX;
}
}
}
Queue.push(node(0,0,dis[0][0]));
while(Queue.size()) {
node temp = Queue.top();
Queue.pop();
int r = temp.i, c = temp.j;
if (r+1<grid.size()) {
if (dis[r+1][c] > dis[r][c] + grid[r+1][c]) {
dis[r+1][c] = dis[r][c] + grid[r+1][c];
Queue.push(node(r+1,c,dis[r+1][c]));
}
}
if (c+1<grid[0].size()) {
if (dis[r][c+1] > dis[r][c] + grid[r][c+1]) {
dis[r][c+1] = dis[r][c] + grid[r][c+1];
Queue.push(node(r,c+1,dis[r][c+1]));
}
}
}
return dis[grid.size()-1][grid[0].size()-1];
}
};
To be Continued...