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;
}
}