LeetCode第 86 场双周赛

举报
长路 发表于 2022/11/22 23:47:24 2022/11/22
【摘要】 之后会参与leetcode周赛、双周赛,希望自己能够坚持下来,并以此来督促检验、提升自己的算法能力,加油!

@[toc]

前言

之后会参与leetcode周赛、双周赛,希望自己能够坚持下来,并以此来督促检验、提升自己的算法能力,加油!

第86场双周赛情况

地址:第86场双周赛

image-20220904194158821

战绩:

image-20220904000419803

第三题案例还差两个过了:

image-20220904000443425

最后的情况:真太菜了

image-20220904165558373

目前竞赛分数:

image-20220904194339895

题目复盘+题解

题1:6171. 和相等的子数组【easy】

题目链接:6171. 和相等的子数组

题目内容:

给你一个下标从 0 开始的整数数组 nums ,判断是否存在 两个 长度为 2 的子数组且它们的 和 相等。注意,这两个子数组起始位置的下标必须 不相同 。
如果这样的子数组存在,请返回 true,否则返回 false 。
子数组 是一个数组中一段连续非空的元素组成的序列。

示例 1:
输入:nums = [4,2,4]
输出:true
解释:元素为 [4,2][2,4] 的子数组有相同的和 6 。

示例 2:
输入:nums = [1,2,3,4,5]
输出:false
解释:没有长度为 2 的两个子数组和相等。

示例 3:
输入:nums = [0,0,0]
输出:true
解释:子数组 [nums[0],nums[1]][nums[1],nums[2]] 的和相等,都为 0 。
注意即使子数组的元素相同,这两个子数组也视为不相同的子数组,因为它们在原数组中的起始位置不同。

提示:
2 <= nums.length <= 1000
-109 <= nums[i] <= 109

复盘:当时题目没有读清楚,其实就是连续子数组两个 + 两数和相等不同情况,最终就是求方案数。我耗费了一大堆时间就是因为题目没有理解清楚。

思路:

1、利用哈希

复杂度分析:时间复杂度O(n);空间复杂度O(1)

class Solution {
    
    //连续的子数组
    public boolean findSubarrays(int[] nums) {
        Set<Integer> set = new HashSet<>();
        for (int i = 1; i < nums.length; i++) {
            int val = nums[i - 1] + nums[i];
            if (set.contains(val)) {
                return true;
            }
            set.add(val);
        }
        return false;
    }
}

image-20220904170008798

题2:6172. 严格回文的数字【medium】

题目链接:6172. 严格回文的数字

题目内容:

如果一个整数 n 在 b 进制下(b 为 2 到 n - 2 之间的所有整数)对应的字符串 全部 都是 回文的 ,那么我们称这个数 n 是 严格回文 的。
给你一个整数 n ,如果 n 是 严格回文 的,请返回 true ,否则返回 false 。
如果一个字符串从前往后读和从后往前读完全相同,那么这个字符串是 回文的 。

示例 1:
输入:n = 9
输出:false
解释:在 2 进制下:9 = 1001 ,是回文的。
在 3 进制下:9 = 100 ,不是回文的。
所以,9 不是严格回文数字,我们返回 false 。
注意在 4, 5, 67 进制下,n = 9 都不是回文的。

示例 2:
输入:n = 4
输出:false
解释:我们只考虑 2 进制:4 = 100 ,不是回文的。
所以我们返回 false 。
 
提示:
4 <= n <= 105

思路:

1、左右拆分

复杂度分析:时间复杂度O(n);空间复杂度O(1)

class Solution {
    
    //n表示[2, n - 2]进制,判断是否是回文
    public boolean isStrictlyPalindromic(int n) {
        //i表示几位进制数
        for (int i = 2; i < n - 1; i++) {
            if (n % i == 0) {
                return false;
            }
            //拆成左右两边
            int leftVal = n / 2;
            int rightVal = n - leftVal;
            if (leftVal % i == 0 || rightVal % i == 0) {
                return false;
            }
        }
        return true;
    }
}

2、数学证明(推荐)

参考:数学证明-灵茶山艾府

思路:

根据题目得知:2 <= b <= n-2,b表示的是进制数,而n表示的是某个数字,对应范围n给出了4 <= n <= 105
对于在任意进制b的情况下我们都可以使用一个公式来表示:n = q*b + r,并且其中的0 <= r < b
我们来列举一些案例:
n = 4
  b = 2   =>  100 (不成立)

n = 5
  b = 2   =>  101 (成立)
  b = 3   =>  12 (不成立)

n = 6
  b = 2   =>  110(不成立)
  b = 3   =>  20(不成立)
  b = 4   =>  12(不成立)

n = 7
  b = 2   =>  111(成立)
  b = 3   =>  21(不成立)
  b = 4   =>  13(不成立)
  b = 5   =>  12(不成立)

n = 8
  b = 2   =>  1000(不成立)
  b = 3   =>  22(不成立)
  b = 4   =>  20(不成立)
  b = 5   =>  13(不成立)
  b = 6   =>  12(不成立)
  
你发现了什么,当n>4的时候,当b进制为n-2时,每个数的b进制数都是12,那么可以得出结论
当n > 4时,b=n-2时结果值为12,不是回文数
当n = 4时,不是回文数

由此,我们最后无需进行进制运算,最后直接返回false即可。

复杂度分析:时间复杂度O(1);空间复杂度O(1)

class Solution {
    public boolean isStrictlyPalindromic(int n) {
        return false;
    }
}

image-20220904171545376

题3:6173. 被列覆盖的最多行数【medium】

题目链接:6173. 被列覆盖的最多行数

题目内容:

给你一个下标从 0 开始的 m x n 二进制矩阵 mat 和一个整数 cols ,表示你需要选出的列数。
如果一行中,所有的 1 都被你选中的列所覆盖,那么我们称这一行 被覆盖 了。
请你返回在选择 cols 列的情况下,被覆盖 的行数 最大 为多少。

复盘:在调试过程中,我为了过一个例子,竟然加了一个校验条件,导致我最后两个案例没过,其实最后的全排列函数中我的代码是没有问题的,之后再进行调试时不能乱加一些无意义的校验代码,说多了都是累啊,本来第三题也能过的!

image-20220904180104622

思路:

1、全排列+哈希表+回溯

复杂度分析:时间复杂度O(n!*m*n),空间复杂度O(n!)

class Solution {
    
    public int maximumRows(int[][] mat, int cols) {
        if (mat.length == cols) {
            return cols;
        }
        quanpailie(mat, cols, 0, new HashSet<>());
        return max;
    }
    
    private int max = -1;
    
    //res存储的是对应的列方案
    public void quanpailie(int[][] mat, int cols, int col, Set<Integer> res) {
if (res.size() == cols) {
            int num = 0;
            //实际来进行处理操作
            for (int i = 0; i < mat.length; i++) {
                boolean flag = true;
                for (int j = 0; j < mat[0].length; j++) {
                    if (!res.contains(j) && mat[i][j] == 1) {
                        flag = false;
                        break;
                    }
                }
                if (flag) num++;
            }
            if (num > max) max = num;
            return;
        }
        for (int i = col; i < mat[0].length; i++) {
            res.add(i);
            quanpailie(mat, cols, i + 1, res);
            res.remove(i);
        }
    }
}

image-20220904181046544

题4:预算内的最多机器人数目【hard】

题目链接:6143. 预算内的最多机器人数目

题目内容:

你有 n 个机器人,给你两个下标从 0 开始的整数数组 chargeTimes 和 runningCosts ,两者长度都为 n 。第 i 个机器人充电时间为 chargeTimes[i] 单位时间,花费 runningCosts[i] 单位时间运行。再给你一个整数 budget 。
运行 k 个机器人 总开销 是 max(chargeTimes) + k * sum(runningCosts) ,其中 max(chargeTimes) 是这 k 个机器人中最大充电时间,sum(runningCosts) 是这 k 个机器人的运行时间之和。
请你返回在 不超过 budget 的前提下,你 最多 可以 连续 运行的机器人数目为多少。

示例 1:
输入:chargeTimes = [3,6,1,3,4], runningCosts = [2,1,3,4,5], budget = 25
输出:3
解释:
可以在 budget 以内运行所有单个机器人或者连续运行 2 个机器人。
选择前 3 个机器人,可以得到答案最大值 3 。总开销是 max(3,6,1) + 3 * sum(2,1,3) = 6 + 3 * 6 = 24 ,小于 25 。
可以看出无法在 budget 以内连续运行超过 3 个机器人,所以我们返回 3 。

示例 2:
输入:chargeTimes = [11,12,19], runningCosts = [10,8,7], budget = 19
输出:0
解释:即使运行任何一个单个机器人,还是会超出 budget,所以我们返回 0 。

提示:
chargeTimes.length == runningCosts.length == n
1 <= n <= 5 * 104
1 <= chargeTimes[i], runningCosts[i] <= 105
1 <= budget <= 1015

思路:

1、大顶堆+双指针

复杂度分析:时间复杂度O(n);空间复杂度O(n)

class Solution {

    //chargeTimes  充电时间
    //runningCosts 运行时间
    //开销  max(chargeTimes) + k * sum(runningCosts)
    //budget 运算
    //考虑问题:连续n个数中的最大值(优先队列,大顶堆) +  双指针
    public int maximumRobots(int[] chargeTimes, int[] runningCosts, long budget) {
        int ans = 0;
        long cost = 0, sum = 0;
        int n = chargeTimes.length;
        PriorityQueue<Integer> maxHeap = new PriorityQueue<>((o1, o2)->o2 - o1);
        for (int l = 0, r = 0; r < n; r++) {
            while (cost > budget) {
                //减去当前的
                sum -= runningCosts[l];
                maxHeap.remove(chargeTimes[l]);
                l++;
                if (!maxHeap.isEmpty()) {
                    cost = maxHeap.peek() + sum * (r - l + 1);
                }else {
                    cost = 0;
                }
            }
            //重新计算新的值
            sum += runningCosts[r];
            maxHeap.add(chargeTimes[r]);
            cost = maxHeap.peek() + sum * (r - l + 1);
            if (cost <= budget) {
                ans = Math.max(ans, r - l + 1);
            }
        }
        return ans;
    }
}

image-20220904192631460

参考资料

[1]. 【力扣双周赛 86】位运算黑科技 | 单调队列 | LeetCode 算法刷题

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。