244周赛(2021-06-06)

1886. 判断矩阵经轮转后是否一致

题目

给你两个大小为 n x n 的二进制矩阵 mat 和 target 。现 以 90 度顺时针轮转 矩阵 mat 中的元素 若干次 ,如果能够使 mat 与 target 一致,返回 true ;否则,返回 false 。

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

解1

暴力求解
将矩阵旋转四次看能否满足条件即可
时间复杂度 o(n^2)
旋转操作需要双重for循环

class Solution {
    public boolean findRotation(int[][] mat, int[][] target) {
    	//如果当前已经满足要求,返回结果即可
        if(isEqual(mat,target)){
            return true;
        }
        //三次循环可以判断所有情况
        for(int k = 0;k < 3;k++){
        	//定义旋转后的数组
            int[][] arr = new int[mat.length][mat[0].length];
            for(int i = 0;i < mat.length;i++){
                for(int j = 0;j < mat[0].length;j++){   
                	//旋转 
                    arr[i][j]=mat[mat[i].length-j-1][i];
                }
            }
            //旋转后将mat变为旋转后的数组
            mat = arr;
            //判断是否满足要求
            if(isEqual(target,arr)){
                return true;
            }
        }
        return false;
    }
    //判断两个矩阵是否相等的方法
    public boolean isEqual(int[][] target,int[][] arr){
        for(int i = 0;i < arr.length;i++){
            for(int j = 0;j < arr[0].length;j++){
                if(target[i][j] != arr[i][j]){
                    return false;
                }
            }
        }
        return true;
    }
}

1887. 使数组元素相等的减少操作次数

题目

给你一个整数数组 nums ,你的目标是令 nums 中的所有元素相等。完成
一次减少操作需要遵照下面的几个步骤:

  • 找出 nums 中的 最大值。记这个值为 largest 并取其下标 i (下标从 0 开始计数)。如果有多个元素都是最大值,则取最小的 i 。
  • 找出 nums 中的 下一个最大 值,这个值 严格小于 largest ,记为 nextLargest 。
  • 将 nums[i] 减少到 nextLargest 。
  • 返回使 nums 中的所有元素相等的操作次数。

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

解1

先排序,然后多维护一个数组arr,arr[i]代表与最小值间隔为i的数有几个
最后通过遍历取得res即可
时间复杂度o(nlogn)

class Solution {
    public int reductionOperations(int[] nums) {
        int[] arr = new int[nums.length];
        int index = 0;
        Arrays.sort(nums);
        for(int i = 1;i < nums.length;i++){
            if(nums[i] == nums[i - 1]){
                arr[index]++;
            }else{
                arr[++index]++;
            }
        }
        int res = 0;
        for(int i = 0;i < nums.length;i++){
            res += i * arr[i];
        }
        return res;
    }
}

解2

解1中的代码可以再简洁一点,不需要维护一个新的数组也可以

class Solution {
    public int reductionOperations(int[] nums) {
        int l = nums.length;
        Arrays.sort(nums);
        int res = 0;
        int count = 0;
        for(int i = 1;i < l;i++){
            if(nums[i] != nums[i - 1]){
                count++;
            }
            res += count;
        }
        return res;
    }
}

解3

找最大值即可
o(n)

class Solution {
    public int reductionOperations(int[] nums) {
        int max = 0;
        int l = nums.length;
        for(int num : nums){
            max = Math.max(num,max);
        }
        int[] arr = new int[max + 1];
        for(int num : nums){
            arr[num]++;
        }
        int res = 0;
        int count = 0;
        for(int val : arr){
            if(val != 0){
                res += count * val;
                count++; 
            }
        }
        return res;
    }
}

1888. 使二进制字符串字符交替的最少反转次数

题目

  • 给你一个二进制字符串 s 。你可以按任意顺序执行以下两种操作任意次:
    • 类型 1 :删除 字符串 s 的第一个字符并将它 添加 到字符串结尾。
    • 类型 2 :选择 字符串 s 中任意一个字符并将该字符 反转 ,也就是如果值为 >‘0’ ,则反转得到 ‘1’ ,反之亦然。
  • 请你返回使 s 变成 交替 字符串的前提下, 类型 2 的 最少 操作次数 。
  • 我们称一个字符串是 交替 的,需要满足任意相邻字符都不同。
    • 比方说,字符串 “010” 和 “1010” 都是交替的,但是字符串 “0100” 不是。

在这里插入图片描述

解1

通过 s + s 和滑动窗口枚举所有情况一所能获得的字符串的最小操作数
时间复杂度o(n)

class Solution {
    public int minFlips(String s) {
    	//此处用s的length,若用t的length,会因为数组奇偶性出错
        int l = s.length();
        //复制字符串
        String t = s + s;
        char[] arrA = new char[2 * l];
        char[] arrB = new char[2 * l];
        //因为010101  101010 交替字符串仅有两种可能 枚举两种即可
        for(int i = 0;i < 2 * l;i++){
            if(i % 2 == 0){
                arrA[i] = '1';
                arrB[i] = '0';
            }else{
                arrA[i] = '0';
                arrB[i] = '1';
            }
        }
        int res = l;
        int cA = 0;
        int cB = 0;
        char[] c = t.toCharArray();
        for(int i = 0;i < 2 * l;i++){
        	//不符合,则需要置换,操作数加一
            if(c[i] != arrA[i]){
                cA++;
            }
            if(c[i] != arrB[i]){
                cB++;
            }
            //滑动窗口,在i等于l时,需判断0是否与A,B两数组在此位置的值不同,如果不同,则原本需要改变值的操作取消,count--
            if(i >= l){
                if(c[i - l] != arrA[i - l]){
                    cA--;
                }
                if(c[i - l] != arrB[i - l]){
                    cB--;
                }
            }
            //每一种枚举的情况有不同的操作数,每次都需要记录
            if(i >= l - 1){
                res = Math.min(res,Math.min(cA,cB));
            }
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值