Leetcode第123场双周赛

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
实时数仓Hologres,5000CU*H 100GB 3个月
简介: 在LeetCode的第123场双周赛中,参赛者需解决三个问题。第一题涉及根据给定数组构建三角形并判断其类型,如等边、等腰或不等边,代码实现通过排序简化条件判断。第二题要求找出满足差值为k的好子数组的最大和,解决方案利用前缀和与哈希表提高效率。第三题则需要计算点集中满足特定条件的点对数量,解题策略是对点按坐标排序并检查点对是否满足要求。

Leetcode第123场双周赛

本人水平有限,只做前三道

一、三角形类型

给你一个下标从 0 开始长度为 3 的整数数组 nums ,需要用它们来构造三角形。

如果一个三角形的所有边长度相等,那么这个三角形称为 equilateral 。
如果一个三角形恰好有两条边长度相等,那么这个三角形称为 isosceles 。
如果一个三角形三条边的长度互不相同,那么这个三角形称为 scalene 。
如果这个数组无法构成一个三角形,请你返回字符串 "none" ,否则返回一个字符串表示这个三角形的类型。

示例 1:

输入:nums = [3,3,3]
输出:"equilateral"
解释:由于三条边长度相等,所以可以构成一个等边三角形,返回 "equilateral" 。
示例 2:

输入:nums = [3,4,5]
输出:"scalene"
解释:
nums[0] + nums[1] = 3 + 4 = 7 ,大于 nums[2] = 5 。
nums[0] + nums[2] = 3 + 5 = 8 ,大于 nums[1] = 4 。
nums[1] + nums[2] = 4 + 5 = 9 ,大于 nums[0] = 3 。
由于任意两边纸盒都大于第三边,所以可以构成一个三角形。
因为三条边的长度互不相等,所以返回 "scalene" 。

解题思路

经典的条件逻辑题
先将数组排序能够简化条件逻辑

代码

class Solution {
   
    public String triangleType(int[] nums) {
   
        Arrays.sort(nums);
        int a = nums[0];
        int b = nums[1];
        int c = nums[2];
        if(a==c){
   
            return "equilateral";
        }
        if(a+b>c){
   
            if(a==b||b==c){
   
                return "isosceles";
            }
            return "scalene";
        }
        return "none";
    }
}

二、最大好子数组和

题目

给你一个长度为 n 的数组 nums 和一个 正 整数 k 。

如果 nums 的一个子数组中,第一个元素和最后一个元素 差的绝对值恰好 为 k ,我们称这个子数组为 好 的。换句话说,如果子数组 nums[i..j] 满足 |nums[i] - nums[j]| == k ,那么它是一个好子数组。

请你返回 nums 中 好 子数组的 最大 和,如果没有好子数组,返回 0 。

示例 1:

输入:nums = [1,2,3,4,5,6], k = 1
输出:11
解释:好子数组中第一个元素和最后一个元素的差的绝对值必须为 1 。好子数组有 [1,2] ,[2,3] ,[3,4] ,[4,5] 和 [5,6] 。最大子数组和为 11 ,对应的子数组为 [5,6] 。
示例 2:

输入:nums = [-1,3,2,4,5], k = 3
输出:11
解释:好子数组中第一个元素和最后一个元素的差的绝对值必须为 3 。好子数组有 [-1,3,2] 和 [2,4,5] 。最大子数组和为 11 ,对应的子数组为 [2,4,5] 。
示例 3:

输入:nums = [-1,-2,-3,-4], k = 2
输出:-6
解释:好子数组中第一个元素和最后一个元素的差的绝对值必须为 2 。好子数组有 [-1,-2,-3] 和 [-2,-3,-4] 。最大子数组和为 -6 ,对应的子数组为 [-1,-2,-3] 。

解题思路

前缀和+哈希表
如果不使用前缀和数组而构建求区间和的函数,很容易导致超时。
哈希表是为了记录数组值和其下标,便于找到与数组值的差的绝对值为k的下标。同时如果在数组中出现重复数字,则需要考虑更新数组

代码

class Solution {
   
    public long maximumSubarraySum(int[] nums, int k) {
   
        int n = nums.length;
        // 构建前缀和数组
        long[] pre = new long[n+1];
        for (int i = 0; i < n; i++) {
   
            pre[i+1] = pre[i] + nums[i];
        }
        // 答案
        long ans = Long.MIN_VALUE;
        // 记录nums[i] : i
        Map<Integer,Integer> index = new HashMap<>();
        for (int i = 0; i < n; i++) {
   
            int x = nums[i];
            int last1 = k + x;
            int last2 = x - k;
            if(index.containsKey(last1)){
   
                int idx = index.get(last1);
                // 更新答案
                ans = Math.max(pre[i+1]-pre[idx],ans);
            }
            if(index.containsKey(last2)){
   
                int idx = index.get(last2);
                ans = Math.max(pre[i+1]-pre[idx],ans);
            }

            // 如果nums[i]在之前出现过,那么用贪心的想法来更新
            if(index.containsKey(x)){
   
                int idx = index.get(x);
                long seg = pre[i] - pre[idx];
                if(seg <= 0){
   
                    index.put(x,i);
                }
            } else{
   
                index.put(x,i);
            }
        }
        return ans == Long.MIN_VALUE ? 0 : ans;
    }
}

三、人员站位的方案数I

给你一个 n x 2 的二维数组 points ,它表示二维平面上的一些点坐标,其中 points[i] = [xi, yi] 。

我们定义 x 轴的正方向为 右 (x 轴递增的方向),x 轴的负方向为 左 (x 轴递减的方向)。类似的,我们定义 y 轴的正方向为 上 (y 轴递增的方向),y 轴的负方向为 下 (y 轴递减的方向)。

你需要安排这 n 个人的站位,这 n 个人中包括 liupengsay 和小羊肖恩 。你需要确保每个点处 恰好 有 一个 人。同时,liupengsay 想跟小羊肖恩单独玩耍,所以 liupengsay 会以 liupengsay 的坐标为 左上角 ,小羊肖恩的坐标为 右下角 建立一个矩形的围栏(注意,围栏可能 不 包含任何区域,也就是说围栏可能是一条线段)。如果围栏的 内部 或者 边缘 上有任何其他人,liupengsay 都会难过。

请你在确保 liupengsay 不会 难过的前提下,返回 liupengsay 和小羊肖恩可以选择的 点对 数目。

注意,liupengsay 建立的围栏必须确保 liupengsay 的位置是矩形的左上角,小羊肖恩的位置是矩形的右下角。比方说,以 (1, 1) ,(1, 3) ,(3, 1) 和 (3, 3) 为矩形的四个角,给定下图的两个输入,liupengsay 都不能建立围栏,原因如下:

图一中,liupengsay 在 (3, 3) 且小羊肖恩在 (1, 1) ,liupengsay 的位置不是左上角且小羊肖恩的位置不是右下角。
图二中,liupengsay 在 (1, 3) 且小羊肖恩在 (1, 1) ,小羊肖恩的位置不是在围栏的右下角。

示例 1:

输入:points = [[1,1],[2,2],[3,3]]
输出:0
解释:没有办法可以让 liupengsay 的围栏以 liupengsay 的位置为左上角且小羊肖恩的位置为右下角。所以我们返回 0 。
示例 2:

输入:points = [[6,2],[4,4],[2,6]]
输出:2
解释:总共有 2 种方案安排 liupengsay 和小羊肖恩的位置,使得 liupengsay 不会难过:

  • liupengsay 站在 (4, 4) ,小羊肖恩站在 (6, 2) 。
  • liupengsay 站在 (2, 6) ,小羊肖恩站在 (4, 4) 。
    不能安排 liupengsay 站在 (2, 6) 且小羊肖恩站在 (6, 2) ,因为站在 (4, 4) 的人处于围栏内。
    示例 3:

输入:points = [[3,1],[1,3],[1,1]]
输出:2
解释:总共有 2 种方案安排 liupengsay 和小羊肖恩的位置,使得 liupengsay 不会难过:

  • liupengsay 站在 (1, 1) ,小羊肖恩站在 (3, 1) 。
  • liupengsay 站在 (1, 3) ,小羊肖恩站在 (1, 1) 。
    不能安排 liupengsay 站在 (1, 3) 且小羊肖恩站在 (3, 1) ,因为站在 (1, 1) 的人处于围栏内。
    注意围栏是可以不包含任何面积的,上图中第一和第二个围栏都是合法的。

    解题思路

    这个题目要求我们计算在给定的点集中,有多少种方式可以选择两个点作为矩形的左上角和右下角,满足以下条件:
  1. 矩形的左上角和右下角分别是两个特定的人,我们可以称之为A和B。
  2. A必须位于矩形的左上角,B必须位于矩形的右下角。
  3. 矩形的内部和边缘不能有任何其他点。

为了解决这个问题,我们需要遍历每一对点对,并判断一个点是否在另一个点的左上角,并且这两个点形成的矩形(包括边界)是否存在其他点?

  1. 对所有点按照x坐标进行排序,如果x坐标相同,则按照y坐标排序。这样可以确保我们在遍历点对时,总是从左向右,从上到下进行。
  2. 实际的点对并不是所有点的排布都遵循从左上到右下的规律,在循环内还要对点的纵坐标进行一次判断后才能计数。

    代码

    class Solution {
         
     public int numberOfPairs(int[][] points) {
         
         int pairs = 0;
         Arrays.sort(points,(a,b) -> {
         
             if(a[0] != b[0]){
         
                 return a[0]-b[0];
             } else{
         
                 return b[1]-a[1];
             }
         });
         int n = points.length;
         for (int i = 0; i < n; i++) {
         
             for (int j = i+1; j < n; j++) {
         
                 if(points[i][1] >= points[j][1] && isGood(points, i, j)){
         
                     pairs++;
                 }
             }
         }
         return pairs;
     }
     public boolean isGood(int[][] points,int index1,int index2){
         
         int n = points.length;
         for (int i = 0; i < n; i++) {
         
             if(i==index1||i==index2){
         
                 continue;
             }
             if(points[i][0]>=points[index1][0] && points[i][0]<=points[index2][0] && points[i][1] <= points[index1][1] && points[i][1] >= points[index2][1]){
         
                 return false;
             }
         }
         return true;
     }
    }
    
目录
相关文章
|
6月前
力扣双周赛 -- 117(容斥原理专场)
力扣双周赛 -- 117(容斥原理专场)
【Leetcode】- 第 29 场双周赛
【Leetcode】- 第 29 场双周赛
|
机器人
LeetCode 双周赛 106(2023/06/10)两道思维题
往期回顾:[LeetCode 单周赛第 348 场 · 数位 DP 模版学会了吗?](https://mp.weixin.qq.com/s/4aLHpyaLOUEHSaX2X8e5FQ)
87 0
LeetCode 双周赛 106(2023/06/10)两道思维题
|
算法 索引
LeetCode 双周赛 107(2023/06/24)滑动窗口与离散化
> **本文已收录到 [AndroidFamily](https://github.com/pengxurui/AndroidFamily),技术和职场问题,请关注公众号 \[彭旭锐] 和 \[BaguTree Pro] 知识星球提问。**
74 0
LeetCode 双周赛 107(2023/06/24)滑动窗口与离散化
|
边缘计算 缓存 算法
LeetCode 双周赛 102,模拟 / BFS / Dijkstra / Floyd
昨晚是 LeetCode 双周赛第 102 场,你参加了吗?这场比赛比较简单,拼的是板子手速,继上周掉大分后算是回了一口血 😁。
111 0
|
人工智能 算法 测试技术
LeetCode 双周赛 101,DP / 中位数贪心 / 裴蜀定理 / Dijkstra / 最小环
这周比较忙,上周末的双周赛题解现在才更新,虽迟但到哈。上周末这场是 LeetCode 第 101 场双周赛,整体有点难度,第 3 题似乎比第 4 题还难一些。
99 0
|
存储 数据安全/隐私保护
|
人工智能 算法 测试技术
LeetCode 双周赛 103(2023/04/29)区间求和的树状数组经典应用
这场周赛是 LeetCode 双周赛第 103 场,难得在五一假期第一天打周赛的人数也没有少太多。这场比赛前 3 题比较简单,我们把篇幅留给最后一题。
80 0