Algorithm-week6

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) or Nx1 (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
...X
In the above board there are 2 battleships.

Invalid Example:

...X
XXXX
...X
This 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...



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值