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

[Leetcode Weekly Contest]333

时间:2023-02-23 20:13:51浏览次数:51  
标签:lcp Contest int mask 333 id result 数组 Leetcode

链接:LeetCode

[Leetcode]2570. 合并两个二维数组 - 求和法

给你两个 二维 整数数组 nums1 和 nums2.
nums1[i] = [idi, vali] 表示编号为 idi 的数字对应的值等于 vali 。
nums2[i] = [idi, vali] 表示编号为 idi 的数字对应的值等于 vali 。
每个数组都包含 互不相同 的 id ,并按 id 以 递增 顺序排列。
请你将两个数组合并为一个按 id 以递增顺序排列的数组,并符合下述条件:

  • 只有在两个数组中至少出现过一次的 id 才能包含在结果数组内。
  • 每个 id 在结果数组中 只能出现一次 ,并且其对应的值等于两个数组中该 id 所对应的值求和。如果某个数组中不存在该 id ,则认为其对应的值等于 0 。
    返回结果数组。返回的数组需要按 id 以递增顺序排列。

遍历即可。

class KeyValuePair{
    public int key;
    public int value;

    public KeyValuePair(int key, int val) {
        this.key = key;
        this.value = val;
    }

}

class Solution {
    public int[][] mergeArrays(int[][] nums1, int[][] nums2) {
        ArrayList<KeyValuePair> result = new ArrayList<>();
        int i=0, j=0;
        while(i<nums1.length || j<nums2.length) {
            int ind = 0, val = 0;
            if(i == nums1.length) {
                ind = nums2[j][0];
                val = nums2[j][1];
                ++j;
            }
            else if(j == nums2.length) {
                ind = nums1[i][0];
                val = nums1[i][1];
                ++i;
            }
            else if(nums2[j][0] < nums1[i][0]) {
                ind = nums2[j][0];
                val = nums2[j][1];
                ++j;
            }
            else if(nums1[i][0] < nums2[j][0]) {
                ind = nums1[i][0];
                val = nums1[i][1];
                ++i;
            }
            else {
                ind = nums1[i][0];
                val = nums1[i][1] + nums2[j][1];
                i++;
                j++;
            }
            if(result.size() == 0 || ind > result.get(result.size()-1).key) result.add(new KeyValuePair(ind, val));
            else result.get(result.size()-1).value += val;
        }
        int[][] res = new int[result.size()][2];
        int ind = 0;
        for(var pair: result) {
            res[ind][0] = pair.key;
            res[ind][1] = pair.value;
            ind++;
        }
        return res;
    }
}

[Leetcode]2571. 将整数减少到零需要的最少操作数

给你一个正整数 n ,你可以执行下述操作 任意 次:

  • n 加上或减去 2 的某个 幂
  • 返回使 n 等于 0 需要执行的 最少 操作数。
    如果 \(x == 2^i\) 且其中 i >= 0 ,则数字 x 是 2 的幂。

把 n 看成二进制数,那么更高位的比特1 是会受到更低位的比特 1 的加减影响的,但是,最小的比特 1 没有这个约束。
那么考虑优先消除最小的比特 1,设它对应的数字为 lowbit。
消除方法只能是加上lowbit,或者减去 lowbit。
注意,求lowbit可以通过n & -n来得到

class Solution {
    public int minOperations(int n) {
        if(n == 0) return 0;
        int lb = n & -n;
        return 1 + Math.min(minOperations(n+lb), minOperations(n-lb));
    }
}

[Leetcode]2572. 无平方子集计数

给你一个正整数数组 nums 。
如果数组 nums 的子集中的元素乘积是一个 无平方因子数 ,则认为该子集是一个 无平方 子集。
无平方因子数 是无法被除 1 之外任何平方数整除的数字。
返回数组 nums 中 无平方 且 非空 的子集数目。因为答案可能很大,返回对 \(10^9 + 7\) 取余的结果。
nums 的 非空子集 是可以由删除 nums 中一些元素(可以不删除,但不能全部删除)得到的一个数组。如果构成两个子集时选择删除的下标不同,则认为这两个子集不同。

子集状压 DP。可以枚举 mask 的补集 other 的子集 j,按照「选或不选」的思想,有如下转移:

\[f[j∣mask]+=f[j]⋅cnt[x] \]

其中 x 是 mask 对应的 NSQ,cnt[x] 为 x 在 nums 中的出现次数。

class Solution {
    private static final int[] PRIMES = new int[]{2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
    private static final int MOD = (int) 1e9 + 7, MX = 30, N_PRIMES = PRIMES.length, M = 1 << N_PRIMES;
    private static final int[] NSQ_TO_MASK = new int[MX + 1]; // NSQ_TO_MASK[i] 为 i 对应的质数集合(用二进制表示)

    static {
        for (int i = 2; i <= MX; ++i)
            for (int j = 0; j < N_PRIMES; ++j) {
                int p = PRIMES[j];
                if (i % p == 0) {
                    if (i % (p * p) == 0) { // 有平方因子
                        NSQ_TO_MASK[i] = -1;
                        break;
                    }
                    NSQ_TO_MASK[i] |= 1 << j; // 把 j 加到集合中
                }
            }
    }

    public int squareFreeSubsets(int[] nums) {
        var f = new int[M]; // f[j] 表示恰好组成集合 j 的方案数
        f[0] = 1; // 空集的方案数为 1
        for (int x : nums) {
            int mask = NSQ_TO_MASK[x];
            if (mask >= 0) // x 是 NSQ
                for (int j = M - 1; j >= mask; --j)
                    if ((j | mask) == j)  // mask 是 j 的子集
                        f[j] = (f[j] + f[j ^ mask]) % MOD; // 不选 mask + 选 mask
        }
        var ans = 0L;
        for (int v : f) ans += v;
        return (int) ((ans - 1) % MOD); // -1 去掉空集
    }
}

[Leetcode]2573. 找出对应 LCP 矩阵的字符串

对任一由 n 个小写英文字母组成的字符串 word ,我们可以定义一个 n x n 的矩阵,并满足:
lcp[i][j] 等于子字符串 word[i,...,n-1] 和 word[j,...,n-1] 之间的最长公共前缀的长度。
给你一个 n x n 的矩阵 lcp 。返回与 lcp 对应的、按字典序最小的字符串 word 。如果不存在这样的字符串,则返回空字符串。
对于长度相同的两个字符串 a 和 b ,如果在 a 和 b 不同的第一个位置,字符串 a 的字母在字母表中出现的顺序先于 b 中的对应字母,则认为字符串 a 按字典序比字符串 b 小。例如,"aabd" 在字典上小于 "aaca" ,因为二者不同的第一位置是第三个字母,而 'b' 先于 'c' 出现。

因为要求字典序最小,我们尝试从前往后构造字符串,这样每次填入字典序尽可能小的字符,就能得到字典序最小的答案。

class Solution {
    public String findTheString(int[][] lcp) {
        int i = 0, n = lcp.length;
        var s = new char[n];
        for (char c = 'a'; c <= 'z'; ++c) {
            while (i < n && s[i] > 0) ++i;
            if (i == n) break; // 构造完毕
            for (int j = i; j < n; ++j)
                if (lcp[i][j] > 0) s[j] = c;
        }
        while (i < n) if (s[i++] == 0) return ""; // 没有构造完

        // 直接在原数组上验证
        for (i = n - 1; i >= 0; --i)
            for (int j = n - 1; j >= 0; --j) {
                int actualLCP = s[i] != s[j] ? 0 : i == n - 1 || j == n - 1 ? 1 : lcp[i + 1][j + 1] + 1;
                if (lcp[i][j] != actualLCP) return "";
            }
        return new String(s);
    }
}

参考:LeetCode

标签:lcp,Contest,int,mask,333,id,result,数组,Leetcode
From: https://www.cnblogs.com/hellojamest/p/17149219.html

相关文章

  • AtCoder Beginner Contest 139
    AtCoderBeginnerContest139https://atcoder.jp/contests/abc1395/6:今天前4题都很水,e还可以但是比较基础,f是计算几何的一个结论,挺没意思的,还是昨天的f比较好玩A-Ten......
  • 【LeetCode】1238. 循环码排列
    【LeetCode】1238.循环码排列题目链接格雷码(循环码)格雷码是一种二进制编码,两个相邻数字的格雷码只有一位二进制位的数码不同。自然码转格雷码数的自然码右移一位和......
  • [Leetcode Weekly Contest]332
    链接:LeetCode[Leetcode]2562.找出数组的串联值给你一个下标从0开始的整数数组 nums。现定义两个数字的串联 是由这两个数值串联起来形成的新数字。例如,15 和 ......
  • 【LeetCode二叉树#04】判断对称二叉树
    对称二叉树力扣题目链接(opensnewwindow)给定一个二叉树,检查它是否是镜像对称的。思路本题中,不能单纯去比较左右子节点的是否对称(都有值且不为空)因为如果按上面那......
  • #yyds干货盘点# LeetCode面试题: 括号生成
    1.简述:数字n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且有效的括号组合。 示例1:输入:n=3输出:["((()))","(()())","(())()","()(())","()()()"]......
  • #yyds干货盘点# LeetCode程序员面试金典:交点
    题目:给定两条线段(表示为起点start={X1,Y1}和终点end={X2,Y2}),如果它们有交点,请计算其交点,没有交点则返回空值。要求浮点型误差不超过10^-6。若有多个交点(线段重叠)则返......
  • 【算法训练营day60】LeetCode84. 柱状图中的最大的矩形
    LeetCode84.柱状图中的最大的矩形题目链接:84.柱状图中的最大的矩形独上高楼,望尽天涯路感觉和接雨水很像。慕然回首,灯火阑珊处思路如下。我们可以遍历每根柱子,以当......
  • 【算法训练营day59】LeetCode503. 下一个更大元素II LeetCode42. 接雨水
    LeetCode503.下一个更大元素II题目链接:503.下一个更大元素II独上高楼,望尽天涯路和昨天的那道题大部分是一个思路,对于循环数组,只需要遍历nums两遍即可。classSolutio......
  • 【算法训练营day58】LeetCode739. 每日温度 LeetCode496. 下一个更大元素
    LeetCode739.每日温度题目链接:739.每日温度独上高楼,望尽天涯路直接看题解。慕然回首,灯火阑珊处单调栈一般用来解决一维数组,任意一个元素的右边或者左边第一个比自己......
  • CF873E - Awards For Contestants
    题意:对于\(n\)个人,每个人有一个分数,现在要把所有人分成四等,使得:前三类都有人前三类中,任意类的人数不大于其他类的人数的两倍不能有\(i\)的分数比\(j\)高但......