力扣1016高效解法:剪枝优化技巧

核心思路与优化策略

力扣 1016 题要求判断二进制字符串 S 是否包含从 1 到 N 所有整数的二进制表示作为子串。直接暴力遍历 1 到 N 并检查子串在 N 较大时会超时,因此需要利用数学性质进行剪枝优化。

关键优化点:

  1. 上限剪枝 :如果 N \> 2047(即 2\^{11}-1),直接返回 false。因为长度为 L 的二进制串最多包含 L-k+1 个长度为 k 的不同子串。对于 N 很大时,所需的二进制串长度总和远超 S 的最大长度限制(题目中 S.length \\le 1000)。具体而言,若要表示 1 到 2048,至少需要长度为 11 的二进制串 10000000000,而 S 的长度不足以容纳所有必要的组合 。
  2. 范围缩减:只需检查 \[\\lfloor N/2 \\rfloor + 1, N\] 范围内的数字。如果 S 包含了 x 的二进制串,那么它必然包含 x 右移一位(即 \\lfloor x/2 \\rfloor)的二进制串(因为 x 的二进制串去掉最后一位就是 \\lfloor x/2 \\rfloor 的二进制串)。因此,若 \[\\lfloor N/2 \\rfloor + 1, N\] 均存在,则 \[1, \\lfloor N/2 \\rfloor\] 也必然存在 。

算法实现 (Python)

以下代码实现了上述优化逻辑。首先处理 N 过大的情况,然后仅遍历 N/2 到 N 的数字,将其转换为二进制字符串并在 S中查找。

python 复制代码
class Solution:
    def queryString(self, s: str, n: int) -> bool:
        # 优化点 1: 当 N > 2047 时,由于字符串 S 长度限制 (<=1000),不可能包含所有子串
        # 2^11 = 2048,二进制长度为 11。若 N 过大,所需子串总长度超过 S 的最大可能容量
 if n > 2047:
            return False
        
        # 优化点 2: 只需检查 [n//2 + 1, n] 区间
        # 原理:如果 x 的二进制是 S 的子串,那么 x>>1 (即 x//2) 的二进制也是 S 的子串
        # 只要最大的那一半数字都在,较小的一半自然也在
        for i in range(n // 2 + 1, n + 1):
            # 将整数转换为二进制字符串 (去掉 '0b' 前缀)
            binary_rep = bin(i)[2:]
            
            # 检查是否为子串
            if binary_rep not in s:
                return False
                
        return True

复杂度分析

指标 说明
时间复杂度 O(\\min(N, K) \\cdot L),其中 K=2047 是剪枝上限,L 是二进制串平均长度。由于 N 被限制在常数范围内,实际复杂度接近 $O(L \cdot
空间复杂度 O(L),用于存储临时生成的二进制字符串,L 为 \\log_2 N。
适用场景 适用于 S 长度较小 (\\le 1000) 但 N 可能很大的情况,通过数学剪枝避免无效计算 。

示例推导

假设输入 S = "0110", N = 3:

  1. 剪枝检查:3 \\le 2047,继续。
  2. 确定范围:需检查 \[\\lfloor 3/2 \\rfloor + 1, 3\] 即 \[2, 3\]。
  3. 执行检查 :
    • i=2: 二进制为 "10"。S 中包含 "10" 吗?是的 ( 0 10 ... 这里的索引有点问题,实际上是 0110 中包含 10 吗? 0110 的子串有 01, 11, 10。是的,包含)。
    • i=3:二进制为 "11"。S 中包含 "11" 吗?是的。
  4. 结论 :所有检查通过,返回 true 。

假设输入 S = "0110", N = 4:

  1. 确定范围:需检查 \[\\lfloor 4/2 \\rfloor + 1, 4\] 即 \[3, 4\]。
  2. 执行检查 :
    • i=3: "11" 在 S 中。
    • i=4: 二进制为 "100"。S ( 0110) 中不包含 "100"。
  3. 结论 :返回 false 。

参考来源

相关推荐
码客-ygluu3 小时前
一个通用游戏数据服务器
c++·架构
another heaven3 小时前
【C/C++ Ranges 是零开销抽象吗?拆开管道、惰性求值和编译期膨胀】
c语言·开发语言·c++
Code_Solitude3 小时前
C语言动态内存 + 柔性数组 + 数组名退化
c语言·算法·柔性数组
上海潭龙东海科技有限公司3 小时前
客运站管控之动态孪生技术方案(新增一屏管控模块
数据仓库·人工智能·算法·重构·动态规划
文丑颜不良啊4 小时前
LeetCode2821~2840题目解析
java·leetcode
SomeOtherTime4 小时前
Rust 闭包语法和原理(AI回答)
开发语言·后端·rust
apcipot_rain5 小时前
C++转Java日记(10)
java·开发语言
总要学点什么5 小时前
第105篇:三维特效-流动图片墙体效果——让箭头沿墙长滚,它俩竟是同一份代码
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
YLCHUP5 小时前
【思维&图论建模】题解:债权(debt)_图论_建模_思路转化_思维题目_C++算法竞赛
c++·笔记·算法·数学建模·贪心算法·深度优先·图论