【每日一题见微知著】模拟题——三合一(比赛次数、对角线历遍、生命游戏)

⭐️寒假新坑——代码之狐的每日做题笔记

1688. 比赛中的配对次数

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

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

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

class Solution {
    public int numberOfMatches(int n) {
        if(n==1){
            return 0;
        }
        int ans=0;
        while(n!=1){
            ans=ans+n/2;
            n=(n+1)/2;
        }
        return ans;
    }
}

//一共淘汰n-1支队伍,需要n-1场比赛
class Solution {
    public int numberOfMatches(int n) {
        return n - 1;
    }
}

498. 对角线遍历-Mid

题目描述:

给你一个大小为 m x n 的矩阵 mat ,请以对角线遍历的顺序,用一个数组返回这个矩阵中的所有元素。

【每日一题见微知著】模拟题——三合一(比赛次数、对角线历遍、生命游戏)_第1张图片

解题思路:

模拟历遍路径,注意越界回退和终点判断(具体见代码)

代码实现:
class Solution {
    public int[] findDiagonalOrder(int[][] mat) {
        int m=mat.length;
        int n=mat[0].length;
        
        int[] ans=new int[m*n];
        //填入位置
        int cur=0;
        //记录数组历遍的位置
        int x=0;
        int y=0;
        
        //重复操作
        while(true){
            //斜向上历遍,直到x越界或y越界,由于只有x--(行上升),y++(列右移)
            //历遍填入数组
            while(x>=0&&y<n){
                ans[cur++]=mat[x][y];
                x--;
                y++;
            }
            //x回退
            x++;
            //x==m表示最后一行,即完成历遍
            if(x==m){
                return ans;
            }
            //如果y越界回退,且将x再次下降一行
            //但凡y越界,需要回退x,y后再将行下降一行
            //若只有x越界,则x,y回退,再将列右移一列(即相当于不回退y)
            if(y>=n){
                x++;
                y--;
            }
            
			//斜向下操作大致相同
            while(x<m&&y>=0){
                ans[cur++]=mat[x][y];
                x++;
                y--;
            }
            y++;
            if(y==n){
                return ans;
            }
            if(x>=m){
                x--;
                y++;
            }
        }
    }
}

289. 生命游戏-Hard

题目描述:

根据 百度百科 ,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。

给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态:1 即为活细胞(live),或 0 即为死细胞(dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:

  1. 如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
  2. 如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
  3. 如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
  4. 如果死细胞周围正好有三个活细胞,则该位置死细胞复活;

下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。给你 m x n 网格面板 board 的当前状态,返回下一个状态。

解题思路:

基本思路:统计周围1的个数,根据题意有,3个1,必更新为1;2个1,不改变状态;其他必为0;

题解一:使用新数组保存更新状态(题目规定了原地修改,所以用不了)

题解二:更新时,如果修改了状态(0->1,1->0)时,记录但是不参与统计,再次历遍,记录写入

class Solution {
    public void gameOfLife(int[][] board) {
        int[] dx=new int[]{-1,0,1,-1,1,-1,0,1};
        int[] dy=new int[]{-1,-1,-1,0,0,1,1,1};
        
        int m=board.length;
        int n=board[0].length;

        for(int x=0;x<m;x++){
            for(int y=0;y<n;y++){
                int count=0;
                int index=8;
                while(index-->0){
                    if(x+dx[index]<0||x+dx[index]>=m||y+dy[index]<0||y+dy[index]>=n){
                        ;
                    }
                    else if(board[x+dx[index]][y+dy[index]]==1||board[x+dx[index]][y+dy[index]]==-1){
                        count++;
                    }
                }
                if(count==3){
                    if(board[x][y]!=1){
                        board[x][y]=-2;//-2表示 由0变成1
                    }
                }
                else if(count<2||count>3){
                    if(board[x][y]!=0)
                        board[x][y]=-1;//-1表示 由1变0
                }
            }
        }
        //历遍记录写入
        for(int x=0;x<m;x++){
            for(int y=0;y<n;y++){
                if(board[x][y]==-2){
                    board[x][y]=1;
                }
                if(board[x][y]==-1){
                    board[x][y]=0;
                }
            }
        }
    }
}

结尾

题目来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems

⭐️关注作者,带你刷题,从简单的算法题了解最常用的算法技能(寒假每日一题)
⭐️关注作者刷题——简单到进阶,让你不知不觉成为无情的刷题机器,有问题请私信

你可能感兴趣的:(算法与数据结构,leetcode,算法,小模拟)