leetcode200场周赛
三题选手这周差点翻车,还剩最后10min的时候第三题过了(贪心题是真的难)。
T1:统计好三元组
给你一个整数数组 arr
,以及 a
、b
、c
三个整数。请你统计其中好三元组的数量。
如果三元组 (arr[i], arr[j], arr[k])
满足下列全部条件,则认为它是一个 好三元组 。
0 <= i < j < k < arr.length
|arr[i] - arr[j]| <= a
|arr[j] - arr[k]| <= b
|arr[i] - arr[k]| <= c
其中 |x|
表示 x
的绝对值。
返回 好三元组的数量 。
示例 1:
输入:arr = [3,0,1,1,9,7], a = 7, b = 2, c = 3
输出:4
解释:一共有 4 个好三元组:[(3,0,1), (3,0,1), (3,1,1), (0,1,1)] 。
示例 2:
输入:arr = [1,1,2,2,3], a = 0, b = 0, c = 1
输出:0
解释:不存在满足所有条件的三元组。
提示:
3 <= arr.length <= 100
0 <= arr[i] <= 1000
0 <= a, b, c <= 1000
数据只有1e2,直接O(n^3)求解即可。
代码如下:
class Solution {
public int countGoodTriplets(int[] arr, int a, int b, int c) {
int ans = 0;
for(int i = 0; i < arr.length - 2; i++){
for(int j = i + 1; j < arr.length - 1; j++){
for(int k = j + 1; k < arr.length; k++){
if(Math.abs(arr[i] - arr[j]) <= a &&Math.abs(arr[j] - arr[k]) <= b && Math.abs(arr[i] - arr[k]) <= c){
ans++;
}
}
}
}
return ans;
}
}
T2:找出数组游戏的赢家
给你一个由 不同 整数组成的整数数组 arr
和一个整数 k
。
每回合游戏都在数组的前两个元素(即 arr[0]
和 arr[1]
)之间进行。比较 arr[0]
与 arr[1]
的大小,较大的整数将会取得这一回合的胜利并保留在位置 0
,较小的整数移至数组的末尾。当一个整数赢得 k
个连续回合时,游戏结束,该整数就是比赛的 赢家 。
返回赢得比赛的整数。
题目数据 保证 游戏存在赢家。
示例 1:
输入:arr = [2,1,3,5,4,6,7], k = 2
输出:5
解释:一起看一下本场游戏每回合的情况:
回合 数组 获胜整数 连胜回合
1 [2,1,3,5,4,6,7] 2 1
2 [2,3,5,4,6,7,1] 3 1
3 [3,5,4,6,7,1,2] 5 1
4 [5,4,6,7,1,2,3] 5 2
因此将进行 4 回合比赛,其中 5 是赢家,因为它连胜 2 回合。
示例 2:
输入:arr = [3,2,1], k = 10
输出:3
解释:3 将会在前 10 个回合中连续获胜。
示例 3:
输入:arr = [1,9,8,2,3,7,6,4,5], k = 7
输出:9
示例 4:
输入:arr = [1,11,22,33,44,55,66,77,88,99], k = 1000000000
输出:99
提示:
2 <= arr.length <= 10^5
1 <= arr[i] <= 10^6
arr 所含的整数 各不相同 。
1 <= k <= 10^9
解决方案:
该问题是模拟题,只需按照题目要求模拟每一回合的游戏过程,由于存在数组元素的问题,底层使用linkedList容器存储。不过需要注意的是k可能是1e9,这种数字O(N)都跑不完,我们发现当开头元素是最大值时(若之前的元素没有获胜),直接返回最大值即可,由于后面的值不可能比他大了,如此玩下去他必然会获胜。如此将时间复杂度降为O(M),其中M为数组长度,1e5随便过。
代码如下:
class Solution {
public int getWinner(int[] arr, int k) {
Map<Integer,Integer> map = new HashMap<>();
List<Integer> list = new LinkedList<>();
int max = 0;
for(int num : arr){
list.add(num);
max = Math.max(num, max);
}
// 之前获胜的结点
int pre = - 1;
//连胜的次数
int num = 0;
for(int i = 0;; i++){
if(list.get(0) < list.get(1)){
int temp = list.get(0);
list.set(0, list.get(1));
list.set(1, temp);
}
list.add(list.remove(1));
if(list.get(0) == pre){
num++;
}else{
pre = list.get(0);
num = 1;
}
if(num == k){
break;
}
if(pre == max){
break;
}
}
return pre;
}
}
T3:排布二进制网格的最少交换次数
给你一个 n x n
的二进制网格 grid
,每一次操作中,你可以选择网格的 相邻两行 进行交换。
一个符合要求的网格需要满足主对角线以上的格子全部都是 0 。
请你返回使网格满足要求的最少操作次数,如果无法使网格符合要求,请你返回 -1 。
主对角线指的是从 (1, 1)
到 (n, n)
的这些格子。
示例1:
输入:grid = [[0,0,1],[1,1,0],[1,0,0]]
输出:3
示例2:
输入:grid = [[0,1,1,0],[0,1,1,0],[0,1,1,0],[0,1,1,0]]
输出:-1
解释:所有行都是一样的,交换相邻行无法使网格符合要求。
n == grid.length
n == grid[i].length
1 <= n <= 200
grid[i][j] 要么是 0 要么是 1 。
解决方案:
这题的贪心思路真的不太好想。
首先将二维问题转化为1维问题,统计每一行右边连零串的长度记做counts。之后只需交换counts数组中的元素即可。
此外我们发现要想变成全零上三角型,第i行右边连0的长度必须不小于N - 1 - i,即需要保证
一种贪心思路如下:
遍历counts数组,依次满足每一位,具体过程为从当前位置开始往后查找,找到其之后第一个可以满足当前位置的元素,然后依次两两交换,把找到的值交换到当前位置。如此即可完成上三角形的转化。
以示例1为例
counts = [0, 1, 2]
当前i = 0,N - 1 - 0= 2 从0开始找到第一个大于等于2的值,发现i= 2时其值等于2,先交换counts[2] counts[1],在交换counts[1] counts[0]
其交换后的结果为 counts[2, 0, 1]
细心的朋友可能已经发现了,从后往前两两交换的结果相当于从当前位置到0到目标位置2的一个循环右移。
代码如下:
class Solution {
public int minSwaps(int[][] grid) {
int n = grid.length;
int[] counts = new int[n];
for(int i = 0; i < n; i++){
for(int j = n - 1; j >= 0; j--){
if(grid[i][j] == 0){
counts[i]++;
}else{
break;
}
}
}
int ans = 0;
for(int i = 0; i < n - 1; i++){
if(counts[i] >= n - 1 - i){
continue;
}
int next = i + 1;
while(next < n){
if(counts[next] >= n - 1 - i){
break;
}else{
next++;
}
}
// 遍历到最后一个元素还没找到可以满足当前元素的值
if(next == n){
return -1;
}
ans += next - i;
int t = counts[next];
for(int j = next; j > i; j--){
counts[j] = counts[j - 1];
}
counts[i] = t;
}
return ans;
}
}
时间复杂度为O(N^2)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python遍历字典
- R语言随机森林模型中具有相关特征的变量重要性
- WPF 使用 Direct Manipulation 的方法
- R语言分析负利率下金融市场:负利率和年金价值的变化
- python字典-增、删、改
- C# dotnet 使用判断文件夹存在的方法判断一个文件路径会怎样
- 怎样给wordpress网站模板,添加最新文章、随机文章、热评文章?
- [医疗信息化][DICOM教程]1.使用Java的DICOM基础-理解DICOM文件-DICOM Basics using Java - Making Sense of the DICOM File
- python自动播放网课
- Istio实战——流量管理
- WordPress移除head头部js、css、feed等多余加载项
- python控制鼠标键盘,解放你的双手~
- 用腾讯云批量计算(batch-compute)调度GPU分布式机器学习
- R语言模拟保险模型中分类器的ROC曲线不良表现
- Linux xargs grep zgrep命令