LeetCode第 123 场双周赛个人题解

目录

一、100222. 三角形类型 II

1、原题链接

2、题目描述

3、思路分析

4、代码详解

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

1、原题链接

2、题目描述

3、思路分析

4、代码详解

三、100183. 最大好子数组和

1、原题链接

2、题目描述

3、思路分析

4、代码详解

四、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、代码详解

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、代码详解

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[],开一个哈希表记录每个数字上一次最小前缀出现位置

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

然后就要维护nums[i]在哈希表中存储的下标了

如果哈希表中没有nums[i],直接插入

如果已经存在hash[nums[i]] = j,如果pre[i] < pre[j],我们就将j替换为i

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

4、代码详解

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、代码详解

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;
    }
};

相关推荐

  1. LeetCode 123 个人题解

    2024-02-04 09:46:02       29 阅读
  2. LeetCode 132个人题解

    2024-02-04 09:46:02       10 阅读
  3. Leetcode 127 题解

    2024-02-04 09:46:02       19 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-04 09:46:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-04 09:46:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-04 09:46:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-04 09:46:02       18 阅读

热门阅读

  1. oracle 触发器事前触发和事后触发区别

    2024-02-04 09:46:02       33 阅读
  2. 微信小程序如何实现动态显示和隐藏某个控件

    2024-02-04 09:46:02       26 阅读
  3. C#中检查空值的最佳实践

    2024-02-04 09:46:02       27 阅读
  4. Ubuntu22扩大分区

    2024-02-04 09:46:02       29 阅读
  5. 【大厂AI课学习笔记】1.4 算法的进步(5)关于GPU

    2024-02-04 09:46:02       29 阅读
  6. 如何发布NPM包

    2024-02-04 09:46:02       29 阅读
  7. 如何在 Mac 上重置网络设置

    2024-02-04 09:46:02       29 阅读
  8. 【力扣经典面试题】274. H 指数

    2024-02-04 09:46:02       32 阅读
  9. [AIGC] Spring Gateway与 nacos 简介

    2024-02-04 09:46:02       27 阅读
  10. 20240203作业

    2024-02-04 09:46:02       29 阅读