力扣 2025 年周赛题
2025-08
第462场周赛(20250810)
3643. 垂直翻转子矩阵
Details
给你一个 m x n
的整数矩阵 grid
,以及三个整数 x
、y
和 k
。
整数 x
和 y
表示一个 正方形子矩阵 的左上角下标,整数 k
表示该正方形子矩阵的边长。
你的任务是垂直翻转子矩阵的行顺序。
返回更新后的矩阵。
示例 1:
输入: grid = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]], x = 1, y = 0, k = 3
输出: [[1,2,3,4],[13,14,15,8],[9,10,11,12],[5,6,7,16]]
解释:
上图展示了矩阵在变换前后的样子。
示例 2:
输入: grid = [[3,4,2,3],[2,3,4,2]], x = 0, y = 2, k = 2
输出: [[3,4,4,2],[2,3,2,3]]
解释:
上图展示了矩阵在变换前后的样子。
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 50
1 <= grid[i][j] <= 100
0 <= x < m
0 <= y < n
1 <= k <= min(m - x, n - y)
根据题意,交换的行是[x, x+k-1],交换的列是[y, y+k-1]。
循环列,使用双指针交换左指针和右指针。
初始化左指针left = x,right = x+k-1,循环知道left >= right.
(现在写代码有很多的坑,自己没有想明白,就开始写,很多地方要用右指针,结果写的是k,导致错误。)
class Solution {
public int[][] reverseSubmatrix(int[][] grid, int x, int y, int k) {
// 交换对应的数就要用双指针
// 先循环列
for (int j = y; j < y + k; j++) {
// 双指针交换
int left = x, right = x + k - 1;
while (left < right) {
int t = grid[left][j];
grid[left][j] = grid[right][j];
grid[right][j] = t;
left++;
right--;
}
}
return grid;
}
}
3644. 排序排列
Details
给你一个长度为 n
的整数数组 nums
,其中 nums
是范围 [0..n - 1]
内所有数字的一个 排列 。
你可以在满足条件 nums[i] AND nums[j] == k
的情况下交换下标 i
和 j
的元素,其中 AND
表示按位与操作,k
是一个非负整数。
返回可以使数组按 非递减 顺序排序的最大值 k
(允许进行任意次这样的交换)。如果 nums
已经是有序的,返回 0。
排列 是数组所有元素的一种重新排列。
示例 1:
**输入:**nums = [0,3,2,1]
**输出:**1
解释:
选择 k = 1
。交换 nums[1] = 3
和 nums[3] = 1
,因为 nums[1] AND nums[3] == 1
,从而得到一个排序后的排列:[0, 1, 2, 3]
。
示例 2:
**输入:**nums = [0,1,3,2]
**输出:**2
解释:
选择 k = 2
。交换 nums[2] = 3
和 nums[3] = 2
,因为 nums[2] AND nums[3] == 2
,从而得到一个排序后的排列:[0, 1, 2, 3]
。
示例 3:
**输入:**nums = [3,2,1,0]
**输出:**0
解释:
只有当 k = 0
时,才能进行排序,因为没有更大的 k
能够满足 nums[i] AND nums[j] == k
的交换条件。
提示:
1 <= n == nums.length <= 105
0 <= nums[i] <= n - 1
nums
是从0
到n - 1
的一个排列。
说实话,这道题目还是很好理解的,但是现在我连题解都看不懂。
就是求能满足 nums[i] AND nums[j] = k的最大k值。
解题时需要注意的点:
- 元素是从0到n-1,所以说,之后的有序数组满足nums[i] = i
- 是否一定有解,k = 0 ?
class Solution {
public int sortPermutation(int[] nums) {
int ans = -1;
for(int i =0;i<nums.length;i++){
int x = nums[i];
if(i!=x){
ans &= x;
}
}
return Math.max(ans, 0);
}
}
2025-04
第 444 场周赛(20250406)
3507. 移除最小数对使数组有序 I
Details
给你一个数组 nums
,你可以执行以下操作任意次数:
- 选择 相邻 元素对中 和最小 的一对。如果存在多个这样的对,选择最左边的一个。
- 用它们的和替换这对元素。
返回将数组变为 非递减 所需的 最小操作次数 。
如果一个数组中每个元素都大于或等于它前一个元素(如果存在的话),则称该数组为非递减。
示例 1:
输入: nums = [5,2,3,1]
输出: 2
解释:
- 元素对
(3,1)
的和最小,为 4。替换后nums = [5,2,4]
。 - 元素对
(2,4)
的和为 6。替换后nums = [5,6]
。
数组 nums
在两次操作后变为非递减。
示例 2:
输入: nums = [1,2,2]
输出: 0
解释:
数组 nums
已经是非递减的。
提示:
1 <= nums.length <= 50
-1000 <= nums[i] <= 1000
面临的问题:
如何将计算出来的值在赋值到原数组上,比如nums=[5,2,3,1],如何将3+1=4的值放入数组?
- 通过使用List的api, remove(lit, index)来实现
如何找到最小的靠左的数对?比如nums=[5,2,3,1],如何确定3+1是最小的?
- 每次循环,将最小的数对记录下来。
class Solution {
public int minimumPairRemoval(int[] nums) {
List<Integer> newnums = new ArrayList<>();
for (int x : nums) {
newnums.add(x);
}
int ans = 0;
// 循环判断
while (!hasSort(newnums)) {
int index = ansIdx(newnums);
int sum = newnums.get(index) + newnums.get(index + 1);
newnums.remove(index + 1);
newnums.set(index, sum);
ans++;
}
return ans;
}
// 判断数组是否有序
boolean hasSort(List<Integer> nums) {
if (nums.size() == 1) {
return true;
}
for (int i = 0; i < nums.size() - 1; i++) {
if (nums.get(i) > nums.get(i + 1)) {
return false;
}
}
return true;
}
// 返回最小数对的下标
int ansIdx(List<Integer> nums) {
int minvalue = nums.get(0) + nums.get(1);
int minindex = 0;
for (int i = 1; i < nums.size() - 1; i++) {
int tmp = nums.get(i) + nums.get(i + 1);
if (tmp < minvalue) {
minvalue = tmp;
minindex = i;
}
}
return minindex;
}
}
3510. 移除最小数对使数组有序 II
Changelog
4c155
-on