小于等于 K 的最长二进制子序列
难度:
标签:
题目描述
代码结果
运行时间: 22 ms, 内存: 16.1 MB
/*
* 思路:
* 1. 从字符串s中获取所有字符'0'。
* 2. 从右向左检查字符串中的'1',逐个添加到结果中,直到结果的二进制值超过k。
* 3. 返回结果的长度。
*/
import java.util.stream.IntStream;
public class LongestSubsequence {
public int longestSubsequence(String s, int k) {
int[] value = {0};
int[] power = {1};
long count = s.chars().filter(c -> c == '0').count();
IntStream.range(0, s.length())
.map(i -> s.length() - 1 - i)
.filter(i -> s.charAt(i) == '1')
.forEach(i -> {
if (value[0] + power[0] <= k) {
value[0] += power[0];
count++;
}
power[0] *= 2;
});
return (int) count;
}
}
解释
方法:
这个题解利用了二进制数的性质和长度限制的思想。首先,计算给定整数 k 的二进制表示的长度 m。理论上,任何长度超过 m 的二进制序列都会大于 k,因此不需要考虑 s 中长度超过 m 的部分。接着,检查 s 中最后 m 位形成的二进制数是否小于等于 k;如果是,这 m 位都可用;如果不是,则只能使用 m-1 位。最后,除了最后 m 位的其他部分,可以贪心地加入所有 '0'(因为 '0' 不增加数值但可以增加长度),从而得到最长的符合条件的子序列。这种方法直接通过数学计算和贪心策略找到结果,避免了复杂的搜索或动态规划算法。
时间复杂度:
O(n)
空间复杂度:
O(1)
代码细节讲解
🦆
为什么在分析问题时,我们首先需要计算整数 k 的二进制表示的长度 m?
▷🦆
题解中提到,如果 s 的最后 m 位二进制数小于等于 k,那么可以使用这 m 位,否则只能使用 m-1 位。这种处理方式是否有可能遗漏某些情况?
▷🦆
为什么在除最后 m 位之外的部分,我们可以贪心地加入所有的 '0'?是否存在特殊情况这种方法不适用?
▷🦆
题解中提到避免了复杂的搜索或动态规划算法,这样做的主要优势是什么?
▷