leetcode200场周赛

时间:2022-07-22
本文章向大家介绍leetcode200场周赛,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

三题选手这周差点翻车,还剩最后10min的时候第三题过了(贪心题是真的难)。

T1:统计好三元组

给你一个整数数组 arr ,以及 abc 三个整数。请你统计其中好三元组的数量。

如果三元组 (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[i] >= N - 1 - i qquad forall iin [0,N - 1]

一种贪心思路如下:

遍历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)