- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
本文已收录到 AndroidFamily ,技术和职场问题,请关注公众号 [彭旭锐] 提问.
大家好,我是小彭.
上周末是 LeetCode 第 337 场周赛,你参加了吗?这场周赛第三题有点放水,如果按照题目的数据量来说最多算 Easy 题,但如果按照动态规划来做可以算 Hard 题.
小彭的技术交流群 02 群来了,公众号回复 “加群” 加入我们~ 。
2595. 奇偶位数(Easy) 。
2596. 检查骑士巡视方案(Medium) 。
2597. 美丽子集的数目(Medium) 。
2598. 执行操作后的最大 MEX(Medium) 。
https://leetcode.cn/problems/number-of-even-and-odd-bits/ 。
给你一个 正 整数 n .
用 even 表示在 n 的二进制形式(下标从 0 开始)中值为 1 的偶数下标的个数.
用 odd 表示在 n 的二进制形式(下标从 0 开始)中值为 1 的奇数下标的个数.
返回整数数组 answer ,其中 answer = [even, odd] .
简单模拟题.
写法 1:枚举二进制位 。
class Solution {
fun evenOddBit(n: Int): IntArray {
val ret = intArrayOf(0, 0)
for (index in 0..30) {
if (n and (1 shl index) != 0) {
ret[index % 2]++
}
}
return ret
}
}
复杂度分析:
写法 2:不断取最低位,然后右移 n,当 n 为 0 时跳出:
class Solution {
fun evenOddBit(n: Int): IntArray {
val ret = intArrayOf(0, 0)
var x = n
var index = 0
while (x != 0) {
ret[i] += x and 1 // 计数
x = x ushr 1 // 右移
i = i xor 1 // 0 -> 1 或 1 -> 0
}
return ret
}
}
复杂度分析:
使用二进制掩码 01010101 取出偶数下标,再使用 Integer.bitCount() 计算位 1 的个数:
class Solution {
fun evenOddBit(n: Int): IntArray {
val mask = 0b0101_0101_0101_0101_0101_0101_0101_0101
return intArrayOf(
Integer.bitCount(n and mask),
Integer.bitCount(n) - Integer.bitCount(n and mask)
)
}
}
复杂度分析:
https://leetcode.cn/problems/check-knight-tour-configuration/ 。
骑士在一张 n x n 的棋盘上巡视。在有效的巡视方案中,骑士会从棋盘的 左上角 出发,并且访问棋盘上的每个格子 恰好一次 .
给你一个 n x n 的整数矩阵 grid ,由范围 [0, n * n - 1] 内的不同整数组成,其中 grid[row][col] 表示单元格 (row, col) 是骑士访问的第 grid[row][col] 个单元格。骑士的行动是从下标 0 开始的.
如果 grid 表示了骑士的有效巡视方案,返回 true ;否则返回 false .
注意 ,骑士行动时可以垂直移动两个格子且水平移动一个格子,或水平移动两个格子且垂直移动一个格子。下图展示了骑士从某个格子出发可能的八种行动路线.
二维简单模拟题.
class Solution {
fun checkValidGrid(grid: Array<IntArray>): Boolean {
if (grid[0][0] != 0) return false
val directions = arrayOf(
intArrayOf(1, 2),
intArrayOf(2, 1),
intArrayOf(2, -1),
intArrayOf(1, -2),
intArrayOf(-1, -2),
intArrayOf(-2, -1),
intArrayOf(-2, 1),
intArrayOf(-1, 2)
)
val n = grid.size
var row = 0
var column = 0
var count = 1
outer@ while (count < n * n) {
for (direction in directions) {
val newRow = row + direction[0]
val newColumn = column + direction[1]
if (newRow < 0 || newRow >= n || newColumn < 0 || newColumn >= n) continue
if (count == grid[newRow][newColumn]) {
row = newRow
column = newColumn
count++
continue@outer
}
}
return false
}
return true
}
}
复杂度分析:
https://leetcode.cn/problems/the-number-of-beautiful-subsets/ 。
给你一个由正整数组成的数组 nums 和一个 正 整数 k .
如果 nums 的子集中,任意两个整数的绝对差均不等于 k ,则认为该子数组是一个 美丽 子集.
返回数组 nums 中 非空 且 美丽 的子集数目.
nums 的子集定义为:可以经由 nums 删除某些元素(也可能不删除)得到的一个数组。只有在删除元素时选择的索引不同的情况下,两个子集才会被视作是不同的子集.
如果 x % m == y % m ,则称 x 和 y 对模 m 同余,即为 x ≡ (y mod m) 。
如果某个任务有 n 个环节,每个环节分别有 ${m_1, m_2, m_3, …, m_n}$ 种方案,那么完成任务的总方案数就是 $m_1 m_2 m3 … m_n$.
由于题目的数据量非常小(数组长度只有 20),所以可以直接使用暴力算法.
算法:枚举所有子集,并且增加约束条件:如果已经选择过 x - k 或 x + k ,则不能选择 x .
class Solution {
private var ret = 0
fun beautifulSubsets(nums: IntArray, k: Int): Int {
subsets(nums, 0, k, IntArray(k + 1001 + k)/* 左右增加 k 避免数组下标越界 */)
return ret - 1 // 题目排除空集
}
// 枚举子集
private fun subsets(nums: IntArray, start: Int, k: Int, cnts: IntArray) {
// 记录子集数
ret++
if (start == nums.size) return
for (index in start until nums.size) {
val x = nums[index] + k // 偏移 k
if (cnts[x - k] != 0 || cnts[x + k] != 0) continue // 不允许选择
// 选择
cnts[x]++
// 递归
subsets(nums, index + 1, k, cnts)
// 回溯
cnts[x]--
}
}
}
复杂度分析:
这道题如果不使用暴力解法,难度应该算 Hard.
根据同余性质,如果 x 和 y 对模 k 同余,那么 x 和 y 有可能相差 k;如果 x 和 y 对模 k 不同余,那么 x 和 y 不可能相差 k。 因此,我们可以将原数组按照模 k 分组,然后单独计算每个分组内部方案数,再根据乘法定理将不同分组的方案数相乘即得到最终结果.
那么,现在的是如何计算分组内部的方案数?
我们发现, “如果已经选择过 x - k 或 x + k ,则不能选择 x ” 的语义跟经典动态规划题 198.打家劫舍 的 “如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警” 的语义非常类似,我们可以套用相同的解题思路:
1、先对分组内部排序,因为只有相邻的数才有可能不能同时选择; 。
2、定义 dp[i] 表示选择到 i 为止的方案数,则有递推关系:
$$ dp[i] = \begin{cases} dp[i-1] + dp[i-2] &\text{if } a_i - a_{i-1} =k\ dp[i-1]*2 &\text{if } a_i - a_{i-1} \not=k \end{cases} $$ 。
如果不选 $a_i$,那么 $a_{i-1}$ 一定可选,即 $dp[i-1]$ 的方案数.
如果选择 $a_i$,那么需要考虑 $a_{i-1}$ 与 $a_i$ 的关系:
最后,还需要考虑数字重复的情况,设 c_i 表示 a_i 的出现次数:
整理到递归公式中有:
$$ dp[i] = \begin{cases} dp[i-1] + dp[i-2] (2^{c_i}-1) &\text{if } a_i - a_{i-1} =k\ dp[i-1] (2^{c_i}) &\text{if } a_i - a_{i-1} \not=k \end{cases} $$ 。
以 [2, 3, 4, 5, 10], k = 2 为例,按照模 2 分组后:
class Solution {
fun beautifulSubsets(nums: IntArray, k: Int): Int {
// 1、同余分组
// <余数 to <元素,元素计数>>
val buckets = HashMap<Int, TreeMap<Int, Int>>()
for (num in nums) {
val cntMap = buckets.getOrPut(num % k) { TreeMap<Int, Int>() }
cntMap[num] = cntMap.getOrDefault(num, 0) + 1
}
// 2、枚举分组
var ret = 1
for ((_, bucket) in buckets) {
// 3、动态规划
val n = bucket.size
// dp[i] 表示选择到 i 位置的方案数,这里使用滚动数组写法
// val dp = IntArray(n + 1)
var pre2 = 0 // dp[i-2]
var pre1 = 1 // dp[i-1]
var index = 1
var preNum = -1
for ((num, cnt) in bucket) {
if (index > 1 && num - preNum == k) {
// a_i 不可选
val temp = pre1
pre1 = pre1 + pre2 * ((1 shl cnt) - 1)
pre2 = temp
} else {
// a_i 可选可不选
val temp = pre1
pre1 = pre1 * (1 shl cnt)
pre2 = temp
}
preNum = num
index++
}
ret *= pre1
}
return ret - 1
}
}
复杂度分析:
相似题目 。
近期周赛子集问题:
LeetCode 周赛 333 · 无平方子集计数(Medium) 。
https://leetcode.cn/problems/smallest-missing-non-negative-integer-after-operations/ 。
给你一个下标从 0 开始的整数数组 nums 和一个整数 value .
在一步操作中,你可以对 nums 中的任一元素加上或减去 value .
nums = [1,2,3]
且 value = 2
,你可以选择 nums[0]
减去 value
,得到 nums = [-1,2,3]
。 数组的 MEX (minimum excluded) 是指其中数组中缺失的最小非负整数.
[-1,2,3]
的 MEX 是 0
,而 [1,0,3]
的 MEX 是 2
。 返回在执行上述操作 任意次 后, nums 的最大 MEX .
如果 x % m == y % m ,则称 x 和 y 对模 m 同余,即为 x ≡ (y mod m) 。
如果 x 和 y 都大于 0,则 x ≡ (y mod m) 等价于 x % m == y % m 。
$$ \begin{matrix} 10\ % \ 3 == 1\ -4\ %\ 3 == 1 \end{matrix} $$ 。
如果 x 和 y 都小于 0,则 x ≡ (y mod m) 等价于 x % m == y % m 。
$$ \begin{matrix} -10\ %\ 3== -1\ -4\ %\ 3==-1 \end{matrix} $$ 。
如果 x < 0,而 y≥0,则 x ≡ (y mod m) 等价于 x % m + m == y % m 。
$$ \begin{matrix} -10\ %\ 3== -1 + 3 == 2\ -4\ %\ 3 == -1 + 3 == 2\ 5\ %\ 3==2 \end{matrix} $$ 。
可以看到,为了避免考虑正负数,可以统一使用 (x % m + m) % m 对 x 取模,如此无论 x 为正负数,余数都能转换到 [0,m) 范围内.
这道题依然考同余性质.
根据同余性质,如果 x 和 y 对模 value 同余,那么经过若干次操作后 x 总能转换为 y。如果 x 和 y 对模 value 不同余,那么无论经过多少次操作 x 也无法转换为 y.
举个例子:{-10、-4、-1、2、5} 都对模 3 同余,而 1 对模 3 不同余。只要经过若干次 +value/-value,总能转换为同余的其他数; 。
贪心思路:继续分析题目,由于不同分组中的数不可能转换为其它分组的数,为了让目标 “确实的最小非负整数尽可能大” ,应该取尽可能小的同余数,否则无法使结果更优.
举个例子,假设 value 为 3,且不同分组的个数如下:
如果余数为 0 的分组取 0、6、9,则缺失的元素会变成 4.
class Solution {
fun findSmallestInteger(nums: IntArray, value: Int): Int {
// 同余分组
val buckets = HashMap<Int, Int>()
for (num in nums) {
val mod = (num % value + value) % value
buckets[mod] = buckets.getOrDefault(mod, 0) + 1
}
// 试错
var mex = 0
while (true) {
val mod = mex % value // mex 一定是非负数
buckets[mod] = buckets.getOrDefault(mod, 0) - 1
// 计数不足
if (buckets[mod]!! < 0) break
mex++
}
return mex
}
}
复杂度分析:
相似题目:
OK,这场周赛就讲这么多,我们下周见.
最后此篇关于刷爆LeetCode周赛337,位掩码/回溯/同余/分桶/动态规划·打家劫舍/贪心的文章就讲到这里了,如果你想了解更多关于刷爆LeetCode周赛337,位掩码/回溯/同余/分桶/动态规划·打家劫舍/贪心的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
在 JavaScript 中,我们可以动态创建 元素并附加到 部分,以便为大量元素应用 CSS 规则。 这种方法的优点或缺点是什么? 如果它确实提供了与元素上的 javascript 迭代相比的性
我有这个代码 import "./HTTPMethod.dart"; import '../../DataModel/DataModel.dart'; mixin RouterMixin { HT
哪些 OLAP 工具支持动态、动态地创建维度或层次结构? 例如,层次结构将成员定义为:“前 5 名”、“前 6-10 名”、“其他”... 计算成员是通常的答案,我正在寻找不同的东西。计算器的问题。成
我正在 CakePHP 中创建一个“表单编辑器”。 该界面允许用户选择要应用于字段的验证,例如数字、电子邮件等 因此,我需要根据用户输入为模型动态创建验证。为此,我可以使用验证对象:https://b
这是一个场景: 我有一个Web服务,我们将其称为部署在tomcat(轴)上的StockQuoteService。通过此 Web 服务公开了 getStockQuote() 方法。 现在,我想构建一个
我正在尝试从服务器获取 JSON 响应并将其输出到控制台。 Future login() async { var response = await http.get( Uri.
我从另一个问题中得到了这段代码(感谢 chunhunghan)。我需要创建一个登录屏幕,并尝试根据服务器发回给我的响应来验证用户凭据,但是每次我尝试运行代码时,它都会给我“未处理的异常:Interna
当我在“Dart”主程序中运行它时,一切正常,并且我得到了一个与会者列表。但是,当我在我的 Flutter 应用程序中调用它时,出现错误: flutter:“List”类型不是“List>”类型的子类
本文实例为大家分享了js实现验证码动态干扰的具体代码,供大家参考,具体内容如下 效果一 效果二 代码一 ?
目前我正在为我的网站使用 No-Ip,我想使用 cloudflare 来抵御 ddos 和机器人程序。我注意到您需要一个用于 cloudflare 的域。我还搜索了网络,发现了一个叫做 cloud
有没有办法在 Excel VBA 中构建动态 if 语句?基本上我正在尝试创建一个参数化计算,用户将能够输入不同的变量,即 变量 1 “变量 2” “变量 3” 在这种情况下 变量 1 是单元格引用
大家好, 请查看上面的图片,我有两张 table 。在下面代码的第一个表中,我得到了这种格式。 但我想像 Table2 那样格式化,每个合并单元格中的行数是动态的,而且不一样。 有没有办法像table
如何根据我添加的 View 修改标题部分的高度?heightForHeaderInSection在 viewForHeaderInSection 之前被调用我不知道 View 大小,直到我创建它。 最
是否存在在运行时生成 AST/解析树的解析器?有点像一个库,它会接受一串 EBNF 语法或类似的东西并吐出数据结构? 我知道 antlr、jlex 和他们的同类。他们生成可以做到这一点的源代码。 (喜
我在持有汽车制造商的表格上有一个 MultipleChoiceField。我想将我的汽车数据库过滤到已检查的品牌,但这会导致问题。如何动态获取所有 Q(make=...) 语句? 我如何开始:['va
$end = preg_replace($pattern, $replacement, $str); 如何使替换字符串 $replacement 随 $str 中的每次匹配而变化?例如,我想用关联的图
我正在编写一个 VBA 程序,用于过滤表中的值。我试图使其成为一个适用于您提供的所有表格的通用程序。在我的程序中,我必须设置它正在过滤的表的范围:Set rng = dataSheet.Range("
我正在循环一个元素数组,并且我想使用给定的模板递归地显示该元素 然后在该模板内使用带有切换功能的按钮来显示/隐藏给定元素的Child的更深级别模板(Child也是一个元素) 这是我的模板
从客户端(html)发送表单,服务器端通过选择选项之一决定运行哪个函数。 const decideWho = (form) => { const choice = form.choice; c
我有一个具有以下属性的按钮: circle_normal.xml(在 res/drawable 中) circle.xml(在 res/drawable 中)
我是一名优秀的程序员,十分优秀!