LeetCode第 123 场双周赛个人题解

目录

[一、100222. 三角形类型 II](#一、100222. 三角形类型 II)

1、原题链接

2、题目描述

3、思路分析

4、代码详解

[二、100194. 人员站位的方案数 I](#二、100194. 人员站位的方案数 I)

1、原题链接

2、题目描述

3、思路分析

4、代码详解

[三、100183. 最大好子数组和](#三、100183. 最大好子数组和)

1、原题链接

2、题目描述

3、思路分析

4、代码详解

[四、100193. 人员站位的方案数 II](#四、100193. 人员站位的方案数 II)

1、原题链接

2、题目描述

3、思路分析

4、代码详解


一、100222. 三角形类型 II

1、原题链接

三角形类型 II - 力扣 (LeetCode) 竞赛

2、题目描述

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

  • 如果一个三角形的所有边长度相等,那么这个三角形称为 equilateral
  • 如果一个三角形恰好有两条边长度相等,那么这个三角形称为 isosceles
  • 如果一个三角形三条边的长度互不相同,那么这个三角形称为 scalene

如果这个数组无法构成一个三角形,请你返回字符串 "none" ,否则返回一个字符串表示这个三角形的类型。

3、思路分析

签到题,没什么说的

复制的时候多了个空格,喜提WA

时间复杂度:O(1) 空间复杂度:O(1)

4、代码详解

python 复制代码
class Solution:
    def triangleType(self, nums: List[int]) -> str:
        a, b, c = nums[0], nums[1], nums[2]
        if a + b > c and a + c > b and b + c > a:
            if a == b == c:
                return "equilateral"
            if a == b or a == c or b == c:
                return "isosceles"
            return "scalene"
        else:
            return "none"

二、100194. 人员站位的方案数 I

1、原题链接

人员站位的方案数 I - 力扣 (LeetCode) 竞赛

2、题目描述

给你一个 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) ,小羊肖恩的位置不是在围栏的右下角。

3、思路分析

二维偏序问题

他这个坐标太烦人了,我把它转了一下

将坐标转换为以左上角为源点,x轴往下延伸,y轴往右延伸

这样有什么好处呢?我们按x坐标升序排序,x相同就按y升序排序

然后我们遍历坐标数组,每个元素右边的所有满足纵坐标大于自己的坐标都有机会配对,因为排序后x坐标已经满足了,只用看y坐标

那么对于那些可能的坐标如何进一步判断配对呢?只要二者围成的区域内没有别的点即可

这个时候我们坐标变换的好处就体现出来了,我们可以通过二维前缀和来判断区域内是否有别的点(不变换也能求前缀和,但是容易写错)

只要区域和为2(即只有配对的两个点),我们答案计数+1

时间复杂度:O(N^2) 空间复杂度:O(U^2),U为坐标最大值

4、代码详解

cpp 复制代码
class Solution
{
public:
    typedef vector<int> vi;
    int g[55][55];
    int numberOfPairs(vector<vector<int>> &p)
    {
        memset(g, 0, sizeof(g));
        int ret = 0, n = p.size();
        for (auto &x : p){
            int a = x[0] + 1, b = x[1] + 1;
            g[x[0] = 52 - b][x[1] = a] = 1;
        }
        sort(p.begin(), p.end(), [&](vi &x, vi &y)
             {
            if(x[0] != y[0])
                return x[0] < y[0];
            return x[1] < y[1]; });

        for (int i = 1; i <= 51; i++)
            for (int j = 1; j <= 51; j++)
                g[i][j] += g[i - 1][j] + g[i][j - 1] - g[i - 1][j - 1];
        for (int i = 0; i < n; i++)
        {
            int a = p[i][0], b = p[i][1];
            for (int j = i + 1; j < n; j++)
            {
                int x = p[j][0], y = p[j][1];
                if (y >= b && g[x][y] - g[x][b - 1] - g[a - 1][y] + g[a - 1][b - 1] == 2)
                    ret++;
            }
        }
        return ret;
    }
};

三、100183. 最大好子数组和

1、原题链接

最大好子数组和 - 力扣 (LeetCode) 竞赛

2、题目描述

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

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

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

3、思路分析

一眼哈希,我们预处理前缀和pre\[\],开一个哈希表记录每个数字上一次最小前缀出现位置

我们遍历数组,对于numsi,如果前面出现过numsi - k 或者numsi + k,那么我们就维护好子数组和最大值

然后就要维护numsi在哈希表中存储的下标了

如果哈希表中没有numsi,直接插入

如果已经存在hashnums\[i] = j,如果prei < prej,我们就将j替换为i

时间复杂度:O(N) 空间复杂度:O(N)

4、代码详解

cpp 复制代码
class Solution
{
public:
    long long maximumSubarraySum(vector<int> &nums, int k)
    {
        int n = nums.size();
        unordered_map<int, int> mp;
        vector<long long> pre(n + 1);
        for (int i = 1; i <= n; i++)
            pre[i] = pre[i - 1] + nums[i - 1];
        long long ret = -1e15;
        for (int i = 0; i < n; i++)
        {
            if (mp.count(nums[i] - k))
            {
                ret = max(ret, pre[i + 1] - pre[mp[nums[i] - k]]);
            }
            if (mp.count(k + nums[i]))
            {
                ret = max(ret, pre[i + 1] - pre[mp[k + nums[i]]]);
            }

            if (!mp.count(nums[i]))
                mp[nums[i]] = i;
            else if(pre[i] < pre[mp[nums[i]]]) mp[nums[i]] = i;
        }
        return ret == -1e15 ? 0 : ret;
    }
};

四、100193. 人员站位的方案数 II

1、原题链接

人员站位的方案数 II - 力扣 (LeetCode) 竞赛

2、题目描述

给你一个 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) ,小羊肖恩的位置不是在围栏的右下角。

3、思路分析

第二题我们的做法是O(N^2)的时间复杂度,本题1e3的数据量照样能过

但是由于这次坐标范围太大了,所以我们要对坐标进行离散化,其它操作一样

时间复杂度:O(N^2) 空间复杂度:O(U^2),U为坐标最大值

4、代码详解

cpp 复制代码
class Solution
{
public:
    typedef vector<int> vi;
    int g[1010][1010], ax[1010], ay[1010], nx, ny;
    int numberOfPairs(vector<vector<int>> &p)
    {
        memset(g, 0, sizeof(g));
        int ret = 0, n = p.size();
        for (int i = 0; i < n; i++)
            ax[i] = p[i][0], ay[i] = p[i][1];
        sort(ax, ax + n), sort(ay, ay + n);
        nx = unique(ax, ax + n) - ax, ny = unique(ay, ay + n) - ay;
        for (auto &x : p)
        {
            int a = lower_bound(ax, ax + nx, x[0]) - ax + 1, b = lower_bound(ay, ay + ny, x[1]) - ay + 1;
            g[x[0] = 1005 - b][x[1] = a] = 1;
        }
        sort(p.begin(), p.end(), [&](vi &x, vi &y)
             {
            if(x[0] != y[0])
                return x[0] < y[0];
            return x[1] < y[1]; });

        for (int i = 1; i <= 1005; i++)
            for (int j = 1; j <= 1005; j++)
                g[i][j] += g[i - 1][j] + g[i][j - 1] - g[i - 1][j - 1];
        for (int i = 0; i < n; i++)
        {
            int a = p[i][0], b = p[i][1];
            for (int j = i + 1; j < n; j++)
            {
                int x = p[j][0], y = p[j][1];
                if (y >= b && g[x][y] - g[x][b - 1] - g[a - 1][y] + g[a - 1][b - 1] == 2)
                    ret++;
            }
        }
        return ret;
    }
};
相关推荐
Purple Coder4 小时前
基于DGN的电工基础-8
职场和发展
QiLinkOS5 小时前
第三视觉理解徐玉生与他的商业活动(30)
大数据·c++·人工智能·算法·开源协议
mit6.8245 小时前
阅读的核心,是再读
c++
疯狂打码的少年5 小时前
【操作系统】页面置换算法(OPT/FIFO/LRU)
算法
Waay5 小时前
面试口述版:个人对 Prometheus 完整理解
运维·学习·云原生·面试·职场和发展·kubernetes·prometheus
小O的算法实验室6 小时前
2026年CIE,优化客货协同运输:综合地铁系统的列车容量动态分配
算法
Coder_Shenshen6 小时前
西门子S7CommPlus协议鉴权算法原理与流程详解
网络·后端·算法
硕风和炜7 小时前
【LeetCode: 2492. 两个城市间路径的最小分数 + DFS】
java·算法·leetcode·深度优先·dfs·bfs·并查集
upgrador7 小时前
基础知识:C++ STL构造函数的左闭右开惯例及其实现原理
开发语言·c++
我是一颗柠檬8 小时前
【Java项目技术亮点】加权轮询负载均衡算法
java·算法·负载均衡