专业建设网站制作,公司注册app流程下载,西安高端网站建设,洛阳小程序开发公司7-周赛333总结
还是只过了前两题#xff0c;第三题又写了好久好久#xff0c;然后也不知道错在了哪里#xff0c;只过了部分题解#xff0c;也许是思考不全面吧。下次也许先做第四题更好…第四题今天花了点时间 做出来了个大概 开心 :happy:
合并两个二维数组 - 求和法【…7-周赛333总结
还是只过了前两题第三题又写了好久好久然后也不知道错在了哪里只过了部分题解也许是思考不全面吧。下次也许先做第四题更好…第四题今天花了点时间 做出来了个大概 开心 :happy:
合并两个二维数组 - 求和法【LC2570】 给你两个 二维 整数数组 nums1 和 nums2. nums1[i] [idi, vali] 表示编号为 idi 的数字对应的值等于 vali 。nums2[i] [idi, vali] 表示编号为 idi 的数字对应的值等于 vali 。 每个数组都包含 互不相同 的 id 并按 id 以 递增 顺序排列。 请你将两个数组合并为一个按 id 以递增顺序排列的数组并符合下述条件 只有在两个数组中至少出现过一次的 id 才能包含在结果数组内。每个 id 在结果数组中 只能出现一次 并且其对应的值等于两个数组中该 id 所对应的值求和。如果某个数组中不存在该 id 则认为其对应的值等于 0 。 返回结果数组。返回的数组需要按 id 以递增顺序排列。 思路双指针、归并排序 使用双指针指向数组nums1和nums2中的元素优先取id较小的指针对应的二元组如果两个指针指向的id相同那么二元组的值为两个指针对应的值之和 实现 由于不确定有多少元素重复因此可以先将结果存储在动态数组中最后在将结果赋值至int数组中 class Solution {public int[][] mergeArrays(int[][] nums1, int[][] nums2) {int n nums1.length, m nums2.length;Listint[] list new ArrayList();int i 0, j 0;while (i n || j m){int[] add new int[2];if (j m || (i n nums1[i][0] nums2[j][0])){add[0] nums1[i][0];add[1] nums1[i][1];i;}else if(i n || (j m nums1[i][0] nums2[j][0])){add[0] nums2[j][0];add[1] nums2[j][1];j;}else{add[0] nums1[i][0];add[1] nums1[i][1] nums2[j][1]; i;j;}list.add(add);}int[][] res new int[list.size()][2];for (int k 0; k list.size(); k){res[k] list.get(k);}return res;}
}复杂度 时间复杂度O(nm)O(nm)O(nm)空间复杂度O(nm)O(nm)O(nm)动态数组的额外空间
将整数减少到零需要的最少操作数【LC2571】 给你一个正整数 n 你可以执行下述操作 任意 次 n 加上或减去 2 的某个 幂 返回使 n 等于 0 需要执行的 最少 操作数。 如果 x 2i 且其中 i 0 则数字 x 是 2 的幂。 思路贪心 由于操作只能加上或减去 2 的某个 幂因此采用位运算的方式解决此题求取n的二进制形式所有1变为0时所需要的操作数。 从最低位开始找到每个值为1的位假定为第iii位而第一个为0的位为第jjj位当连续1的个数等于1时采用减幂消除1当连续1的个数大于1时采用加幂进位的方式消除1 当连续1的个数等于1时减去该位对应的幂将该位变为0所需要的操作数为1次; 而当连续1的个数大于1时可以通过加2的最低1位对应的幂进位此时所有的连续1变为0然后产生了进位第jjj位变为1所需要的操作数也为1次【使用减幂方式所需要的操作数为j−ij-ij−i而使用进位的方式所需要的操作数为2次并且消除进位产生的1的同时可能会消除更多的1因此连续1的个数大于1时采用进位的方式消除1时最优的】 局部最优和全局最优 局部最优将连续的所有1变为0的次数最少全局最优将n变为0的操作数最少 实现 class Solution {public int minOperations(int n) {// 如果遇到连续1个数大于1时进位 操作数加1// 连续1个数等于1直接减操作int res 0;int i 0;while (n ! 0){// 找到从左到右第一个1while (((n i) 1) 0){i;}int j i;// 找到从左到右第一个0while (((n j) 1) 1){j;}if (j - i 1){n Math.pow(2, i);res;}else{n - Math.pow(2, i);res;}i j;}return res;}
}复杂度 时间复杂度O(logn)O(logn)O(logn)空间复杂度O(1)O(1)O(1) 优化 使用位运算获取最低位 lb n -n然后使用n (lb 1)) 0判断是否有连续1 class Solution {public int minOperations(int n) {int ans 1;while ((n (n - 1)) 0) { // n 不是 2 的幂次int lb n -n;if ((n (lb 1)) 0) n lb; // 多个连续 1else n - lb; // 单个 1ans;}return ans;}
}作者灵茶山艾府
链接https://leetcode.cn/problems/minimum-operations-to-reduce-an-integer-to-0/solutions/2120204/ji-yi-hua-sou-suo-by-endlesscheng-cm6l/
来源力扣LeetCode
著作权归作者所有。商业转载请联系作者获得授权非商业转载请注明出处。class Solution {public int minOperations(int n) {int ans 0;while (n ! 0) { int lb n -n;if ((n (lb 1)) 0) n lb; // 多个连续 1else n - lb; // 单个 1ans;}return ans;}
}
*无平方子集计数【LC2572】 给你一个正整数数组 nums 。 如果数组 nums 的子集中的元素乘积是一个 无平方因子数 则认为该子集是一个 无平方 子集。 无平方因子数 是无法被除 1 之外任何平方数整除的数字。 返回数组 nums 中 无平方 且 非空 的子集数目。因为答案可能很大返回对 109 7 取余的结果。 nums 的 非空子集 是可以由删除 nums 中一些元素可以不删除但不能全部删除得到的一个数组。如果构成两个子集时选择删除的下标不同则认为这两个子集不同。 思路 如果两个无平方因子数的最大公因数为1那么它们可以存在一个子集当中。 由于本题中nums的数值大小小于等于30因此可以对该范围的数进行预处理判断每个数是否是无平方因子数如果是无平方因子数则求出每个数对应质因数的集合并使用状态压缩法表示当mask的第iii位为1是第iii个质数在集合中如果不是无平方因子数那么mask设为-1。 题意可转化为「选一些不相交的质数集合它们的并集恰好为集合 jjj的方案数」。【01背包问题】 物品即为每个数字分解的质因数集合背包容量为背包可以容纳的质因数对应的状态码当物品对应质因数集合是背包容量的子集时则可以向该背包放入该物品 二维动态规划 确定dp数组dp table以及下标的含义 dp[i][j]表示 从前i个元素中取若干元素质因数出现的情况为j的方案数。 确定递推公式 不放元素idp[i][j]dp[i−1][j]dp[i][j] dp[i-1][j]dp[i][j]dp[i−1][j] 放元素i当nums[i]对应的状态码为mask前一个状态与mask不能相交因此前一个状态码为mask^j dp[i][j]dp[i−1][j⊕mask]dp[i][j] dp[i-1][j\oplus mask]dp[i][j]dp[i−1][j⊕mask] 动态规划公式为 dp[i][j]dp[i−1][j]dp[i−1][j⊕mask]dp[i][j] dp[i-1][j] dp[i-1][j \oplus mask] dp[i][j]dp[i−1][j]dp[i−1][j⊕mask] dp数组如何初始化 dp[0][0] 1;确定遍历顺序 二维dp遍历顺序不影响结果 先遍历物品再遍历背包重量确定物品i能否放进背包j中 举例推导dp数组 最后结果即为∑dp[n−1][j]\sum dp[n-1][j]∑dp[n−1][j] 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) {int n nums.length;int[][] dp new int[n 1][M]; // f[i][j] 表示恰好组成集合 j 的方案数 // Arrays.fill(dp[0], 1);// 空集的方案数为 1dp[0][0] 1;for (int i 0; i n; i) {for (int j 0; j M; j) dp[i 1][j] dp[i][j];// 不选 maskint mask NSQ_TO_MASK[nums[i]];if (mask 0) // x 是 NSQfor (int j mask; j M - 1; j){if ((j | mask) j) // mask 是 j 的子集dp[i 1][j] (dp[i 1][j] dp[i][j ^ mask]) % MOD; // 选 mask}}int ans 0;for (int j 0; j M; j){ans (ans dp[n][j]) % MOD;}return ans - 1;}
}复杂度 时间复杂度O(nM)O(nM)O(nM),n为数组长度M为状态压缩后包含质因子情况的总数空间复杂度O(n∗M)O(n*M)O(n∗M)dp数组的额外空间 优化一维dp 先遍历物品再从后往前遍历背包重量确定物品i能否放进背包j中 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; // 空集的方案数为 1for (int x : nums) {int mask NSQ_TO_MASK[x];if (mask 0) // x 是 NSQfor (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 去掉空集}
}作者灵茶山艾府
链接https://leetcode.cn/problems/count-the-number-of-square-free-subsets/solutions/2121032/liang-chong-xie-fa-01bei-bao-zi-ji-zhuan-3ooi/
来源力扣LeetCode
著作权归作者所有。商业转载请联系作者获得授权非商业转载请注明出处。复杂度 时间复杂度O(nM)O(nM)O(nM),n为数组长度M为状态压缩后包含质因子情况的总数空间复杂度O(M)O(M)O(M)dp数组的额外空间
找出对应 LCP 矩阵的字符串【LC2573】 对任一由 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 出现。 按列扫描 思路按规则按列逐个构造 首先由于题目要求返回的合法字符串是字典顺序最小的因此第一个字符一定是a 然后从开头到末尾逐个构造字符当我们构造第iii个字符时前j∈[0,i−1]j \in [0,i-1]j∈[0,i−1]个字符是确定的那么当lcp[j][i]0lcp[j][i]0lcp[j][i]0时第iii个字符就等于第jjj个字符直接退出本层循环如果第iii个字符与前面的字符均不相同那么第iii个字符为当前已经构造的最大字符的下一个字符。 需要注意的是如果构造的字符大于z那么不符合题意返回空字符串 最后还需要验证构造的字符串是否满足矩阵如果不满足也返回空字符串。 验证方法为动态规划 如果s[i]s[j]s[i]s[j]s[i]s[j]那么lcp[i][j]lcp[i1][j1]1lcp[i][j]lcp[i1][j1]1lcp[i][j]lcp[i1][j1]1如果s[i]≠s[j]s[i]\ne s[j]s[i]s[j]那么lcp[i][j]0lcp[i][j]0lcp[i][j]0 实现 按列扫描lcp数组 class Solution {public String findTheString(int[][] lcp) {int n lcp.length;// 如果矩阵对称并且值小于等于字符串长度时有满足的字符串【不全面】// for (int i 0; i n; i){// for (int j 0; j n; j){// if (lcp[i][j] ! lcp[j][i] || lcp[i][j] Math.min(n - i, n - j)){// return ;// }// if (i j lcp[i][j] ! n - i){// return ;// }// }// }StringBuilder sb new StringBuilder();sb.append(a);// 第0个字符一定是a char c a;for (int i 1; i n; i){// 按顺序找第1-n-1个字符for (int j 0; j i; j){// 根据与前面字符的关系确定 int count lcp[j][i];// s[j,jcount-1] s[i,icount-1] if (count 0){// s[i] s[j]sb.append(sb.charAt(j)); break; }}if (sb.length() i 1){if (c z) return ;c 1;sb.append(c);}}// 验证for (int i n - 1; i 0; --i)for (int j n - 1; j 0; --j) {int actualLCP sb.charAt(i) ! sb.charAt(j) ? 0 : i n - 1 || j n - 1 ? 1 : lcp[i 1][j 1] 1;if (lcp[i][j] ! actualLCP) return ;}return sb.toString();}}复杂度 时间复杂度O(n2)O(n^2)O(n2)空间复杂度O(1)O(1)O(1)
按行扫描 思路 如果lcp[i][j]0lcp[i][j]0lcp[i][j]0时s[i]s[i]s[i]一定等于s[j]s[j]s[j]而第一个字符一定是a因此可以先扫描lcp[0]如果lcp[0][j]0lcp[0][j]0lcp[0][j]0那么该字符一定是a然后进行下一轮本轮的字符为b找到从左到右数首个没有填入字符的位置iii将其填入当前已经构造的最大字符的下一个字符然后再扫描lcp[i]如果lcp[0][j]0lcp[0][j]0lcp[0][j]0那么填入本轮的字符。往复循环直至iii大于字符串长度或者字符超过了z如果退出循环时iii小于nnn表示没有构造完直接返回空字符串最后进行验证验证方法同上 实现 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);}
}作者灵茶山艾府
链接https://leetcode.cn/problems/find-the-string-with-lcp/solutions/2120175/tan-xin-gou-zao-yan-zheng-o1e-wai-kong-j-82ik/
来源力扣LeetCode
著作权归作者所有。商业转载请联系作者获得授权非商业转载请注明出处。复杂度 时间复杂度O(n2)O(n^2)O(n2)空间复杂度O(1)O(1)O(1)