Leetcode--2021.6.12周赛

emmm今天的我还是很菜,只能做前两道题,第三道之前没见过,没有任何头绪来解题,尝试了几种方法也不行,第四个根本不知道怎么处理。。。
原本前两道题都可以一次AC的,但是因为自己的粗心,导致第二个题逻辑出现错误,因为没注意错误案例,只好又提交了一次看案例(白送一次。。。)

前两个题还是非常基础的,后两个题的解法明天要好好学习一下。

第一题

在这里插入图片描述

思路

简单来说就是[left,right]是否在ranges数组内所有区间组成的大区间内,所以可以把题目简化为:

  1. 依次遍历[left,right]中的每一个元素,检查其是否在ranges的某个区间内,如果存在,则遍历下一个元素,如果不存在,直接返回false;

时间复杂度O( (right-left+1) * (ranges.length) )也就是[left,right]的元素数 × ranges数组的长度

代码

public boolean isCovered(int[][] ranges, int left, int right) {
        int row = ranges.length;
        int col = ranges[0].length;

        int sign = 0;
        for (int i=left;i<=right;i++)
        {
            sign = 0;
            for (int j=0;j<row;j++)
            {
                if (i>=ranges[j][0] && i<= ranges[j][1])
                {
                    sign = 1;
                    break;
                }
            }
//            System.out.println(i);
            if (sign == 0)
                return false;
        }
        return true;
    }

第二题

在这里插入图片描述
在这里插入图片描述

思路

因为涉及到循环,所以先判断是否需要循环?
需要循环的话,需要循环多少次?
然后使用k减去循环所需要的数量,再对chalk数组依次遍历即可。

需要注意的是,因为chalk的长度最大值chalk[i]的最大值均为 1 0 5 10^5 105,所以chalk的元素和最大值 1 0 10 10^{10} 1010超出int的范围了,可以通过在循环中实时检查是否大于k来避免溢出(一旦sum超过k,那么sum的值就没用了,不超过的话也就不会溢出)
算法步骤:

  1. 计算chalk数组的元素和,并实时检查sum是否大于k,大于k的话直接break;
  2. 计算循环的次数,然后k减去循环所需要的数量;
  3. 顺序遍历chalk数组,需要注意的是,题目中提到要严格小于才是当前学生,所以只使用<

代码

public int chalkReplacer(int[] chalk, int k) {
        int len = chalk.length;
		
		//计算元素和
        int sum = 0;
        for (int i: chalk){
            sum += i;
            if (sum > k)//实时判断大小
               break;
        }
        //计算循环次数
        int c = k / sum;
        k = k-c*sum;
        
        for (int i=0;i<len;i++)
        {
            if (k<chalk[i])//要严格小于
                return i;
            else
                k -= chalk[i];
        }

        return 0;
    }

第三题

在这里插入图片描述
在这里插入图片描述

思路

没啥头绪,明天学习一下这类题的解法
—2021.6.13更新----
昨天做这个题除了暴力求解外,没有任何头绪,但是暴力求解又超时,只能放弃了。
今天看了一下大佬们的解法,发现使用前缀和+暴力java可以双100%
在这里插入图片描述
所以贴出来学习、记录一下。原文地址

算法步骤:

  1. 首先计算行前缀和列前缀和,方便后面直接调用,减少重复计算;
  2. 获取可能的最大尺寸,然后开始暴力遍历
  3. 对于每个可能满足条件的尺寸,从给定的矩阵左上角开始遍历(注意边界范围),如果此时圈定的幻方满足条件(每行、每列、两条对角线的值均相等),则直接返回此时的k值,否在开始遍历下一个k值;
  4. 因为k=1时绝对满足条件,所以默认返回值为1

详细步骤详见代码注释。

代码

class Solution {
    int[][] row;
    int[][] col;
    public int largestMagicSquare(int[][] grid) {
        int r = grid.length;
        int c = grid[0].length;

        row = new int[r][c];
        col = new int[r][c];
        //首先计算前缀和,简化计算
        //行前缀和
        for (int i=0;i<r;i++)
        {
            row[i][0] = grid[i][0];
            for (int j=1;j<c;j++)
            {
                row[i][j] = row[i][j-1] + grid[i][j];
            }
        }
		
		//列前缀和
        for (int j = 0; j < c; j++) {
            col[0][j] = grid[0][j];
            for (int i = 1; i < r; i++) {
                col[i][j] = col[i-1][j] + grid[i][j];
            }
        }
        
        //从可能的最大方形矩阵开始逐个暴力遍历,然后尺寸逐渐缩小
        int n = Math.min(r,c);//因为数组可能不是正方形的,所以幻方的最大变成为数组边长的较小值
        
		//从最大可能边长开始遍历,最小为2,因为长度为1时一定成立
        for(int k=n;k>=2;k--)
        {
            for (int i=0;i<=r-k;i++)//注意边界范围,i最大为r-k,j最大为c-k
            {
                for (int j=0;j<=c-k;j++)
                {
                    if (checkCount(i,j,k,grid))//如果每行、每列、两条对角线的值均相等,返回此时幻方的长度
                        return k;
                }
            }
        }

        return 1;//默认返回值,在合法输入下,1都满足条件
    }
    public boolean checkCount(int r, int c, int k, int[][] grid)
    {
        //检查行
        //得到当前幻方第一行的和,以此为基准进行对比
        int cur = row[r][c+k-1] - row[r][c] + grid[r][c];
        for (int i=r+1;i<r+k;i++)
            if (cur != (row[i][c+k-1] - row[i][c] + grid[i][c]))
                return false;
        
        //检查列
        for (int j=c;j<c+k;j++)
            if (cur != col[r+k-1][j] - col[r][j] + grid[r][j])
                return false;
      
        //检查对角线
        int cur2 = 0;
        
		//左上到右下
        for (int i=r,j=c;i<r+k;i++,j++)
            cur2 += grid[i][j];
            
        if (cur2 != cur)
            return false;
            
        //左下到右上
        cur2 = 0;
        for (int i=r,j=c+k-1;i<r+k;i++,j--)
            cur2 += grid[i][j];

        return cur == cur2;
    }
}

第四题

在这里插入图片描述
在这里插入图片描述

思路

没啥头绪,明天学习一下

代码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值