力扣379场周赛

Q1、对角线最长的矩形的面积

给你一个下标从 0 开始的二维整数数组 dimensions

对于所有下标 i0 <= i < dimensions.length),dimensions[i][0] 表示矩形 i 的长度,而 dimensions[i][1] 表示矩形 i 的宽度。

返回对角线最 的矩形的 面积 。如果存在多个对角线长度相同的矩形,返回面积最 的矩形的面积。

示例 1:

输入:dimensions = [[9,3],[8,6]]
输出:48
解释:
下标 = 0,长度 = 9,宽度 = 3。对角线长度 = sqrt(9 * 9 + 3 * 3) = sqrt(90) ≈ 9.487。
下标 = 1,长度 = 8,宽度 = 6。对角线长度 = sqrt(8 * 8 + 6 * 6) = sqrt(100) = 10。
因此,下标为 1 的矩形对角线更长,所以返回面积 = 8 * 6 = 48。

示例 2:

输入:dimensions = [[3,4],[4,3]]
输出:12
解释:两个矩形的对角线长度相同,为 5,所以最大面积 = 12。

提示:

  • 1 <= dimensions.length <= 100
  • dimensions[i].length == 2
  • 1 <= dimensions[i][0], dimensions[i][1] <= 100

解析:第一题也没什么难度,直接暴力枚举每个矩形的对角线长度,然后求最长对角线矩形对应的面积即可。

    int areaOfMaxDiagonal(vector<vector<int>>& dimensions) {
        unordered_map<double, int> areas;
        double max_diag_length = 0;
        int max_area = 0;

        for (int i = 0; i < dimensions.size(); i++) {
            int length = dimensions[i][0];
            int width = dimensions[i][1];
            double diag_length = sqrt(pow(length, 2) + pow(width, 2));
            int area = length * width;

            if (areas.find(diag_length) != areas.end()) {
                if (area > areas[diag_length]) {
                    areas[diag_length] = area;
                }
            } else {
                areas[diag_length] = area;
            }

            if (diag_length > max_diag_length) {
                max_diag_length = diag_length;
            }
        }

        max_area = areas[max_diag_length];

        return max_area;
    }

Q2、捕获黑皇后需要的最少移动次数

现有一个下标从 0 开始的 8 x 8 棋盘,上面有 3 枚棋子。

给你 6 个整数 abcdef ,其中:

  • (a, b) 表示白色车的位置。
  • (c, d) 表示白色象的位置。
  • (e, f) 表示黑皇后的位置。

假定你只能移动白色棋子,返回捕获黑皇后所需的最少移动次数。

请注意

  • 车可以向垂直或水平方向移动任意数量的格子,但不能跳过其他棋子。
  • 象可以沿对角线方向移动任意数量的格子,但不能跳过其他棋子。
  • 如果车或象能移向皇后所在的格子,则认为它们可以捕获皇后。
  • 皇后不能移动。

示例 1:

img

输入:a = 1, b = 1, c = 8, d = 8, e = 2, f = 3
输出:2
解释:将白色车先移动到 (1, 3) ,然后移动到 (2, 3) 来捕获黑皇后,共需移动 2 次。
由于起始时没有任何棋子正在攻击黑皇后,要想捕获黑皇后,移动次数不可能少于 2 次。

示例 2:

img

输入:a = 5, b = 3, c = 3, d = 4, e = 5, f = 2
输出:1
解释:可以通过以下任一方式移动 1 次捕获黑皇后:
- 将白色车移动到 (5, 2) 。
- 将白色象移动到 (5, 2) 。

提示:

  • 1 <= a, b, c, d, e, f <= 8
  • 两枚棋子不会同时出现在同一个格子上。

解析

​ 这题本质就是一个分类讨论的题,需要分析清楚各种情况,写好细节即可。分析如下

1.白车可以直接攻击到黑后 -> 返回1

2.白象可以直接攻击到黑后 ->返回1

3.中间有障碍:白车被白象阻挡,那么移走白象,白车可以直接攻击到黑后 ->返回2

4.中间有障碍:白象被白车阻挡,那么移走白车,白象可以直接攻击到黑后 ->返回2

5.其他情况:移动白车,总有一个方向不会被挡住

我们先分析车,当车和后在同一直线时,只需再满足象不在此直线或者象在此直线但不在车与后之间即可一步攻击到后,因此我们写一个函数判断中间是否有障碍

车情况一:

image-20240108124633173

车情况二:

image-20240108124803092

再来分析象,相似的,当象和后再同一斜线上时,只需再满足车不在同一斜线或者车在同一斜线上但是不在象与后之间

象情况一:

image-20240108124953087

象情况二:

image-20240108125011878

而其他情况我们直接返回2即可,无论这样车都可以两步攻击到后。

代码如下:

    bool ok(int left,int mid,int right)
    {
        return !((min(left, right) < mid) && (mid < max(left, right)));
    }

    int minMovesToCaptureTheQueen(int a, int b, int c, int d, int e, int f) {

    //车和后在一条横线  象和后不在一条横线    象不在车和后之间         
        if (a == e && (c != e || ok(b, d, f)) ||
            b == f && (d != f || ok(a, c, e))) {
            return 1;
        }

    //象和后在同一左斜线    车不在同一斜线      车不在象和后之间
    //减是右斜线
        if(c+d == e+f && (a+b != e+f || ok(c,a,e)) ||
           c-d == e-f && (a-b != e-f || ok(c,a,e)))
        {
            return 1;
        }

        return 2;
    }

Q3、移除后集合的最多元素数

给你两个下标从 0 开始的整数数组 nums1nums2 ,它们的长度都是偶数 n

你必须从 nums1 中移除 n / 2 个元素,同时从 nums2 中也移除 n / 2 个元素。移除之后,你将 nums1nums2 中剩下的元素插入到集合 s 中。

返回集合 s可能的 最多 包含多少元素。

示例 1:

输入:nums1 = [1,2,1,2], nums2 = [1,1,1,1]
输出:2
解释:从 nums1 和 nums2 中移除两个 1 。移除后,数组变为 nums1 = [2,2] 和 nums2 = [1,1] 。因此,s = {1,2} 。
可以证明,在移除之后,集合 s 最多可以包含 2 个元素。

示例 2:

输入:nums1 = [1,2,3,4,5,6], nums2 = [2,3,2,3,2,3]
输出:5
解释:从 nums1 中移除 2、3 和 6 ,同时从 nums2 中移除两个 3 和一个 2 。移除后,数组变为 nums1 = [1,4,5] 和 nums2 = [2,3,2] 。因此,s = {1,2,3,4,5} 。
可以证明,在移除之后,集合 s 最多可以包含 5 个元素。 

示例 3:

输入:nums1 = [1,1,2,2,3,3], nums2 = [4,4,5,5,6,6]
输出:6
解释:从 nums1 中移除 1、2 和 3 ,同时从 nums2 中移除 4、5 和 6 。移除后,数组变为 nums1 = [1,2,3] 和 nums2 = [4,5,6] 。因此,s = {1,2,3,4,5,6} 。
可以证明,在移除之后,集合 s 最多可以包含 6 个元素。 

提示:

  • n == nums1.length == nums2.length
  • 1 <= n <= 2 * 104
  • n是偶数。
  • 1 <= nums1[i], nums2[i] <= 109

对于这题呢思路是很清晰的,但是如何将其实现出来还是挺困难的。

解析:

​ 我们不妨逆向思维思考,从添加的角度来看此题,设nums1中有n1个不同的元素,nums2有n2个,他们的交集有common个元素:

​ 对于nums1优选不在交集中的元素,可以选n1-common哥,但不能超过n/2个,所以最多选c1=min(n1−common,n/2) ;

​ 同理c2=min(n2−common,n/2);

​ 如果c1+c2<n,那么还要选n-c1-c2个元素,这些元素只能从交集中选,所以不能超过common个

所以还能选min(nc1−c2,common) 个;

​ 最终答案c1+c2+min(nc1−c2,common) = min(n,c1+c2+common)

    int maximumSetSize(vector<int> &nums1, vector<int> &nums2) {
        unordered_set<int> set1(nums1.begin(), nums1.end());
        unordered_set<int> set2(nums2.begin(), nums2.end());
        int common = 0;
        
       	//求交集
        for (int x : set1) {
            common += set2.count(x);
        }

        int n = nums1.size();
        
        int c1 = min((int) set1.size() - common, n / 2);
        int c2 = min((int) set2.size() - common, n / 2);
        //这样写容易理解
        //return c1+c2+min(n-c1-c2, common);
        return min(n, c1 + c2 + common);
    }

最后,还得多跟灵神,多刷1300-1400的题。

posted @ 2024-01-08 13:11  桂洛克船长  阅读(3)  评论(0编辑  收藏  举报