1765.地图中的最高点&1688.比赛中的配对次数

161 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

1765.地图中的最高点

题目大意

给你一个大小为 m x n 的整数矩阵 isWater ,它代表了一个由 陆地水域 单元格组成的地图。

  • 如果 isWater[i][j] == 0 ,格子 (i, j) 是一个 陆地 格子。
  • 如果 isWater[i][j] == 1 ,格子 (i, j) 是一个 水域 格子。

你需要按照如下规则给每个单元格安排高度:

  • 每个格子的高度都必须是非负的。
  • 如果一个格子是是 水域 ,那么它的高度必须为 0
  • 任意相邻的格子高度差 至多1 。当两个格子在正东、南、西、北方向上相互紧挨着,就称它们为相邻的格子。(也就是说它们有一条公共边)

找到一种安排高度的方案,使得矩阵中的最高高度值 最大

请你返回一个大小为 m x n 的整数矩阵 height ,其中 height[i][j] 是格子 (i, j) 的高度。如果有多种解法,请返回 任意一个

样例

image-20220129134446438

数据规模

image-20220129134516725

思路

考虑到 水域 格子的高度肯定是00,那么周围的格子一定是由最近的 水域 格子来决定,所以可以考虑使用多源BFS来实现。所有的h[i][j]h[i][j]初始化为无穷大,对于所有的 水域 格子,它们的h[i][j]=0h[i][j]=0,并且加入队列中,然后进行bfsbfs。对于队列中的每一个节点,考虑它的四周,如果h[i][j]h[i][j]仍然无穷大,说明该点没有访问过,那么该点h[nex][ney]=h[x][y]+1h[nex][ney]=h[x][y]+1。最后所有的点都访问过之后,最优方案也就确定了,最后将答案储存到ansans中。

代码

class Solution {
public:
    int h[1000+50][1000+50];
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    vector<vector<int>> highestPeak(vector<vector<int>>& isWater) {
        int n=isWater.size(),m=isWater[0].size();
        memset(h,0x3f3f3f3f,sizeof(h));
        queue<pair<int,int>>q;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(isWater[i][j]==1){
                    h[i][j]=0;
                    q.push(make_pair(i,j));
                }
            }
        }
        vector<vector<int>> ans;
        while(!q.empty()){
            pair<int,int> x=q.front();q.pop();
            for(int i=0;i<4;i++){
                int nex=x.first+dx[i],ney=x.second+dy[i];
                if(nex>=0&&nex<n&&ney>=0&&ney<m){
                    if(h[nex][ney]!=0x3f3f3f3f)continue;
                    h[nex][ney]=h[x.first][x.second]+1;
                    q.push(make_pair(nex,ney)); 
                }
            }
        }
        for(int i=0;i<n;i++){
            vector<int>a;
            for(int j=0;j<m;j++){
                a.push_back(h[i][j]);
            }
            ans.push_back(a);
        }
        return ans;
    }
};

题目

1688.比赛中的配对次数

题目大意

给你一个整数 n ,表示比赛中的队伍数。比赛遵循一种独特的赛制:

  • 如果当前队伍数是 偶数 ,那么每支队伍都会与另一支队伍配对。总共进行 n / 2 场比赛,且产生 n / 2 支队伍进入下一轮。
  • 如果当前队伍数为 奇数 ,那么将会随机轮空并晋级一支队伍,其余的队伍配对。总共进行 (n - 1) / 2 场比赛,且产生 (n - 1) / 2 + 1 支队伍进入下一轮。

返回在比赛中进行的配对次数,直到决出获胜队伍为止。

样例

image-20220125193756179

数据规模

image-20220125193807282

思路

一开始读题目,以为这需要一个数学公式来加速完成,但是看到了1<=n<=2001<=n<=200,那就直接模拟过程就好了。

一直循环,直到n=1n=1停止。如果nn是奇数,那么贡献就是(n1)/2(n-1)/2;如果n是偶数,那么贡献就是n/2n/2,然后更新n的值。最后返回贡献sum即可。

代码

class Solution {
public:
    int numberOfMatches(int n) {
        int sum=0;
        while(n!=1){
            if(n&1)sum+=(n-1)/2,n=(n-1)/2+1;
            else sum+=n/2,n=n/2;
        }
        return sum;
    }
};

思路2

其实我看到样例我就在猜测答案会不会就是n1n-1,于是在用上面的代码AC之后,我直接提交了return n-1,果然它AC了。其实可以很感性的理解:有nn支队伍,其中n1n-1支队伍无法晋级,就需要n1n-1场比赛淘汰它们。

代码2

class Solution {
public:
    int numberOfMatches(int n) {
        return n-1;
    }
};