首页 > 其他分享 >[Leetcode Weekly Contest]365

[Leetcode Weekly Contest]365

时间:2023-10-07 19:11:08浏览次数:64  
标签:下标 nums int res Contest 三元组 数组 365 Leetcode

链接:LeetCode

[Leetcode]2873. 有序三元组中的最大值 I

给你一个下标从 0 开始的整数数组 nums 。
请你从所有满足 i < j < k 的下标三元组 (i, j, k) 中,找出并返回下标三元组的最大值。如果所有满足条件的三元组的值都是负数,则返回 0 。
下标三元组 (i, j, k) 的值等于 (nums[i] - nums[j]) * nums[k] 。

暴力即可,\(O(N^3)\)

class Solution {
    public long maximumTripletValue(int[] nums) {
        int n = nums.length;
        long res = 0;
        for(int i=0;i<n;++i) {
            for(int j=i+1;j<n;++j) {
                for(int k=j+1;k<n;++k) {
                    res = Math.max(res, (nums[i]-nums[j]) * 1L * nums[k]);
                }
            }
        }
        return res;
    }
}

[Leetcode]2874. 有序三元组中的最大值 II

给你一个下标从 0 开始的整数数组 nums 。
请你从所有满足 i < j < k 的下标三元组 (i, j, k) 中,找出并返回下标三元组的最大值。如果所有满足条件的三元组的值都是负数,则返回 0 。
下标三元组 (i, j, k) 的值等于 (nums[i] - nums[j]) * nums[k] 。

贪心。
首先,输出的数值最小为 0,同时数组中每个元素均为正数,因此,我们要让 (nums[i] - nums[j]) * nums[k] 最大,只需要对于固定的 k 找到其前面 nums[i] - nums[j] 的最大值。
为了使得 nums[i] - nums[j] 尽可能大,我们需要对于固定的 j 找到其前面最大的 nums[i] 再将两者相减。因此我们只需要维护三个东西:到当前位置的最大值,到当前位置为止最大的 nums[i] - nums[j],到当前位置为止最大的 (nums[i] - nums[j]) * nums[k]. 而从上面的分析可以看出,这些都可以遍历过程中实现。
因此时间复杂度是\(\mathcal{O}(n)\) 的。

class Solution {
    public long maximumTripletValue(int[] nums) {
        Deque<Integer> stack = new ArrayDeque<>();
        long res = 0, maxDiff = 0;
        long max = nums[0], min = nums[0];
        for(int i=0;i<nums.length-1;++i) {
            if(nums[i] > max) {
                max = nums[i];
                min = nums[i];
            } else if(nums[i] < min) {
                min = nums[i];
            }
            maxDiff = Math.max(maxDiff, max-min);
            res = Math.max(res, maxDiff * nums[i+1]);
        }
        return res;
    }
}

[Leetcode]2875. 无限数组的最短子数组

给你一个下标从 0 开始的数组 nums 和一个整数 target 。
下标从 0 开始的数组 infinite_nums 是通过无限地将 nums 的元素追加到自己之后生成的。
请你从 infinite_nums 中找出满足 元素和 等于 target 的 最短 子数组,并返回该子数组的长度。如果不存在满足条件的子数组,返回 -1 。

因为是无限循环的,所以结果可能是 任意 k 个完整的数组加上循环数组中的一部分。
提前求出有几个完整的,然后用滑动窗口计算最小的窗口。

class Solution {
    public int minSizeSubarray(int[] nums, int target) {
        int sum = getSum(nums);
        int n = nums.length;
        int[] doubleNums = new int[2*n];
        for(int i=0;i<n;++i) doubleNums[i] = nums[i];
        for(int i=n;i<2*n;++i) doubleNums[i] = nums[i-n];
        int res = getMinSizeSubarray(doubleNums, target % sum);
        return res == Integer.MAX_VALUE ? -1 : res + target / sum * n;
    }

    private int getMinSizeSubarray(int[] nums, int target) {
        if(target == 0) return 0;
        int res = Integer.MAX_VALUE;
        int start = 0;
        int sum = 0;
        for(int i=0;i<nums.length;++i) {
            sum += nums[i];
            while(sum > target) {
                sum -= nums[start];
                start ++;
            }
            if(sum == target) res = Math.min(res, i-start+1);
        }
        return res;
    }

    private int getSum(int[] nums) {
        int res = 0;
        for(int num:nums) res += num;
        return res;
    }
}

[Leetcode]2876. 有向图访问计数

现有一个有向图,其中包含 n 个节点,节点编号从 0 到 n - 1 。此外,该图还包含了 n 条有向边。
给你一个下标从 0 开始的数组 edges ,其中 edges[i] 表示存在一条从节点 i 到节点 edges[i] 的边。
想象在图上发生以下过程:

  • 你从节点 x 开始,通过边访问其他节点,直到你在 此过程 中再次访问到之前已经访问过的节点。

返回数组 answer 作为答案,其中 answer[i] 表示如果从节点 i 开始执行该过程,你可以访问到的不同节点数。

这是一个经典的类型的图——基环树,每个点都只有一条出去的边。其有特点:所有的点要么在环上,要么有一条路径走向环。环上的点不会有往外的边(因为该点的边指向环中其他的点)。
先找到所有的环,环上所有点能到达的点都是环上的点。接下来从环上的点出发往外走,每个点能到达的新的点可以进行访问点数的更新。如果原节点能到达 k 个,则往外走一步的新节点能到达 k+1 个点。

找环我们可以使用拓扑排序来做,即不断找入度为 0 的点放入栈中,删去其出边,再放入新产生的入度为 0 的点,最后剩下的图只有环,最后环里的所有点可以通过 DFS 等方式得到。

时间复杂度为 \(\mathcal{O}(n)\).

class Solution {
    public int[] countVisitedNodes(List<Integer> edges) {
        int n = edges.size();
        List<List<Integer>> rev = new ArrayList<>();
        int[] indegree = new int[n];
        for(int i=0;i<n;++i) {
            rev.add(new ArrayList<>());
        }
        for(int i=0;i<n;++i) {
            int v = edges.get(i);
            indegree[v] += 1;
            rev.get(v).add(i);
        }

        // 拓扑排序
        Deque<Integer> stack = new ArrayDeque<>();
        for(int i=0;i<n;++i) {
            if(indegree[i] == 0) stack.push(i);
        }
        while(!stack.isEmpty()) {
            int u = stack.pop();
            int v = edges.get(u);
            indegree[v] --;
            if (indegree[v] == 0) {
                stack.push(v);
            }
        }

        // 找环里的点
        int[] res = new int[n];
        for(int i=0;i<n;++i) {
            if(indegree[i] > 0) {
                LinkedList<Integer> elements = new LinkedList<>(List.of(i));
                while(edges.get(elements.getLast()) != i) {
                    elements.add(edges.get(elements.getLast()));
                }
                for(int element:elements) {
                    res[element] = elements.size();
                    indegree[element] = 0;
                }
            }
        }

        // 更新环外的点
        for(int i=0;i<n;++i) {
            if(res[i] == 0) continue;
            Deque<Integer> temp = new ArrayDeque<>(List.of(i));
            while(!temp.isEmpty()) {
                int u = temp.pop();
                for(int v: rev.get(u)) {
                    if(res[v] == 0) {
                        res[v] = res[u] + 1;
                        temp.push(v);
                    }
                }
            }
        }
        return res;
    }
}

参考:LeetCode

标签:下标,nums,int,res,Contest,三元组,数组,365,Leetcode
From: https://www.cnblogs.com/hellojamest/p/17747241.html

相关文章

  • 2022 China Collegiate Programming Contest (CCPC) Mianyang Onsite
    2022ChinaCollegiateProgrammingContest(CCPC)MianyangOnsiteC.CatchYouCatchMe解题思路:站在距离出口最近的点等深度深的蝴蝶飞上来即可。时间复杂度:\(O(n)\)代码:#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;voidsolve(){ intn......
  • AtCoder Grand Contest 057 E RowCol/ColRow Sort
    洛谷传送门AtCoder传送门首先考虑一个经典的套路:转\(01\)。具体而言,我们考虑若值域是\([0,1]\)怎么做。发现可以很容易地判定一个\(A\)是否合法。设矩阵第\(i\)行的和为\(r_i\),第\(j\)列的和为\(c_j\),那么合法当且仅当\(A\)的\(\{r_i\}\)和\(\{c_j\}\)(可重集......
  • 2022 China Collegiate Programming Contest (CCPC) Weihai Site EAJGCI
    2022ChinaCollegiateProgrammingContest(CCPC)WeihaiSite目录2022ChinaCollegiateProgrammingContest(CCPC)WeihaiSiteVP概况E-PythonWillbeFasterthanC++A-DunaiJ-Eat,Sleep,RepeatG-Grade2C-GrassI-DragonBloodlineVP概况这场我一年......
  • 2023中大厂Android面试八股文合集,GitHub,牛客,leetcode已爆火!
    前言金九银十已过半,不知道大家现在都到哪个阶段了,有没有已经找到心仪的工作的朋友?有没有还没准备好面试在各大平台找资料临时抱佛脚的朋友?或是现在在准备,想要明年金三银四跳槽的朋友?不管你是现在急切找工作还是找资料备战,我都非常推荐你看看我花2个多月从GitHub,牛客,leetcode上为大......
  • Leetcode刷题模版总结
    1.双指针双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务。也可以延伸到多个数组的多个指针。1)滑动窗口若两个指针指向同一数组,遍历方向相同且不会相交,则也称为滑动窗口(两个指针包围的区域即为当前的窗口),经常用于区间搜索。 例题:classSolution{public:......
  • 2022-2023 ICPC Central Europe Regional Contest
    The1stUniversalCup.Stage8:SloveniaD.Deforestation这道题出题人比较谜语人,对于一个分叉点,只能选择若干个儿子和父亲组成一组,剩下的儿子之间不能相互组合。所以从叶子节点开始贪心处理就好。对于一个父亲他有若干个儿子,就贪心的选择剩下部分更小的儿子。#include<bits......
  • The 2021 ICPC Asia Macau Regional Contest
    A.SoI'llMaxOutMyConstructiveAlgorithmSkills首先一行正一行反的把所有的行拼到一起,然后判断一下正着走时候合法不合法就反过来走就好。#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongusingvi=vector<int>;voidsolve(){intn;......
  • The 2022 ICPC Asia Jinan Regional Contest
    A.Tower首先用了dp验证出把一个数字变成另一个数字的最优解一定是能除就先进行除法,然后再使用加一减一。这样我们就有\(O(\logn)\)的复杂度求出把一个数变成另一个数的最小代价。然后就是猜测最终的目标一定是某个数除了若干次二得到的。所以就枚举一下目标即可。#include......
  • Leetcode刷题83. 删除排序链表中的重复元素
    给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。示例1:输入:head=[1,1,2]输出:[1,2]示例2:输入:head=[1,1,2,3,3]输出:[1,2,3] 提示:链表中节点数目在范围 [0,300] 内-100<=Node.val<=100题目数......
  • LeetCode——95. 不同的二叉搜索树 II
    本次博客,我将记录leetcode95,不同的二叉搜索树95.不同的二叉搜索树II本题要求我们从1~n构造不同的二叉搜索树因为好久不碰数据结构了,导致对二叉搜索树的概念十分模糊以下是一些概念:二叉搜索树(BST,BinarySearchTree),也称二叉排序树或二叉查找树。性质如下:1.非空左子树的所......