当前位置: 首页 > news >正文

LeetCode 2749.得到整数零需要执行的最少操作数:很独特的一道数学题(多公式硬讲——一步步还真能看懂)

【LetMeFly】2749.得到整数零需要执行的最少操作数:很独特的一道数学题(多公式硬讲——一步步还真能看懂)

力扣题目链接:https://leetcode.cn/problems/minimum-operations-to-make-the-integer-zero/

给你两个整数:num1num2

在一步操作中,你需要从范围 [0, 60] 中选出一个整数 i ,并从 num1 减去 2i + num2

请你计算,要想使 num1 等于 0 需要执行的最少操作数,并以整数形式返回。

如果无法使 num1 等于 0 ,返回 -1

 

示例 1:

输入:num1 = 3, num2 = -2
输出:3
解释:可以执行下述步骤使 3 等于 0 :
- 选择 i = 2 ,并从 3 减去 22 + (-2) ,num1 = 3 - (4 + (-2)) = 1 。
- 选择 i = 2 ,并从 1 减去 22 + (-2) ,num1 = 1 - (4 + (-2)) = -1 。
- 选择 i = 0 ,并从 -1 减去 20 + (-2) ,num1 = (-1) - (1 + (-2)) = 0 。
可以证明 3 是需要执行的最少操作数。

示例 2:

输入:num1 = 5, num2 = 7
输出:-1
解释:可以证明,执行操作无法使 5 等于 0 。

 

提示:

  • 1 <= num1 <= 109
  • -109 <= num2 <= 109

解题方法:数学

这个题解我自己也看了很多遍,如果你想搞懂这道题,请静下心来仔细读读,相信你一定可以搞懂这道题的!哪里不懂欢迎留言。

k范围浅分析

假设num1num1num1减去kkk2i+num22^i+num22i+num2后变成了000,那么有:

num1−k∗num2=2i1+2i2+...+2iknum_1 - k * num_2 = 2^{i_1} + 2^{i_2} + ... + 2^{i_k}num1knum2=2i1+2i2+...+2ik

见到2i1+2i2+...+2ik2^{i_1} + 2^{i_2} + ... + 2^{i_k}2i1+2i2+...+2ik应该很敏感才对啊,这不是222的幂之和么,只不过加数可以重复。

令等式左边的num1−k∗num2=xnum_1 - k * num_2 = xnum1knum2=x,那么想让右边的2i1+2i2+...+2ik=x2^{i_1} + 2^{i_2} + ... + 2^{i_k}=x2i1+2i2+...+2ik=xkkk的合法范围是多少?

已知2i+1=2i+2i2^{i+1}=2^i+2^i2i+1=2i+2i,所以想让可以使等式成立的kkk比较大的话,可以把一个2i+12^{i+1}2i+1可以拆成两个2i2^i2i,最小拆成2=1+12=1+12=1+1为止。也就是说,xxx最多可以由1+1+1+⋯+11+1+1+\dots+11+1+1++1(共xxx个)组成,也就是说kkk的最大值是xxx

那么最小值呢?例如5=101(2)=22+205=101_{(2)}=2^2+2^05=101(2)=22+20kkk最小值为222。也就是说对于xxxkkk的最小值为xxx二进制下111的个数。

综上,只要popcount(x)≤k≤xpopcount(x)\leq k\leq xpopcount(x)kx,就能找到一种方法使得2i1+2i2+...+2ik=x2^{i_1} + 2^{i_2} + ... + 2^{i_k}=x2i1+2i2+...+2ik=x。(其中popcount(x)popcount(x)popcount(x)xxx二进制下111的个数,x>0x\gt 0x>0

请记住这两个条件:

  1. k≤xk\leq xkx
  2. k≥popcount(x)k\geq popcount(x)kpopcount(x)

枚举k

但是别忘了,xxx中还含有变量kkk呢!其中x=num1−k∗num2x=num_1 - k * num_2x=num1knum2。想要判断是返回kkk还是返回−1-11,还得看能不能找到一个kkk使得popcount(x)≤k≤xpopcount(x)\leq k\leq xpopcount(x)kx,其中x=num1−k∗num2x=num_1 - k * num_2x=num1knum2

最简单的办法就是暴力枚举。令kkk111开始枚举,1,2,⋯1, 2, \cdots1,2,,直到kkk超出“上界”,即k>xk\gt xk>x,也就是说k>num1−k∗num2k\gt num_1 - k * num_2k>num1knum2停止。

这里你一定会思考,现在kkk超出上界了,那么我继续增大kkk的话,待会儿kkk会不会就不超出上界了呢?

为了探究这个问题,我们把kkk的合法范围处理一下:k≤num1−k∗num2⇔k∗(1+num2)≤num1k\leq num_1 - k * num_2\Leftrightarrow k*(1+num_2)\leq num_1knum1knum2k(1+num2)num1

  • 1+num2≤01+num_2\leq 01+num20时,由于数据范围限制num1≥1num_1\geq 1num11,所以k∗(1+num2)≤num1k*(1+num_2)\leq num_1k(1+num2)num1恒成立;
  • 1+num2>01+num_2\gt 01+num2>0时,可得k≤num11+num2k\leq \frac{num_1}{1+num_2}k1+num2num1k∗(1+num2)≤num1k*(1+num_2)\leq num_1k(1+num2)num1成立,一旦kkk大于num11+num2\frac{num_1}{1+num_2}1+num2num1该等式就再也不会成立;

综上,符合假设,不考虑实际算力限制下的超时问题的话,kkk1,2,⋯1,2,\cdots1,2,枚举到k>xk\gt xk>x为止,如果存在kkk满足第二个条件即k≥popcount(x)k\geq popcount(x)kpopcount(x),我们就能找到了符合条件的kkk;否则,这个枚举范围内没有满足第二个条件的kkk就返回−1-11

那么kkk的范围究竟是多少呢?暴力枚举会不会超时呢?你别说,还真不会。

因为要想找到一个满足两个条件的kkk,除了一个限制枚举范围的k≤xk\leq xkx外,还有一个条件,就是k≥popcount(x)k\geq popcount(x)kpopcount(x)

我们一直担心的就是会不会k≤xk\leq xkx这个条件范围太大,导致kkk一直从111枚举到一个非常大的数字(甚至是无穷?),从而超时。

但是别忘了第二个条件k≥popcount(x)k\geq popcount(x)kpopcount(x)是非常容易满足的,要知道popcount(x)popcount(x)popcount(x)可是xxx在二进制下111的个数,所以先告诉你结论再去证明:kkk最大枚举到几十就会满足第二个条件了。

kkk的量级是几十(按10310^3103),numnumnum的量级是10910^9109,所以x=num1−k∗num2x=num_1 - k * num_2x=num1knum2的量级最多为101210^{12}10122402^40240已经大于101210^{12}1012了(不信可以执行下python -c "print(len(str(2**40)))"试试),xxx二进制下位数不超过404040位,就找到满足第二个条件的kkk了。

也就是说实际kkk111开始枚举,最多枚举到404040,就知道答案了,时间复杂度甚至可以认为是O(1)O(1)O(1)

  • 时间复杂度O(1)O(1)O(1)
  • 空间复杂度O(1)O(1)O(1)

然后结合实现代码说一下:

int makeTheIntegerZero(int num1, int num2) {for (int k = 1; k <= num1 - (long long)num2 * k; k++) {if (k >= __builtin_popcountll(num1 - (long long)num2 * k)) {return k;}}return -1;
}

关于这个循环的范围:

  • 如果1+num2>11+num_2\gt 11+num2>1,那么要么for循环先终止返回-1(如num1=16, num2=10会在k=2时结束for循环),要么if条件先命中return k
  • 如果1+num2≤01+num_2\leq 01+num20for循环相当于while true,但是里面的if条件一定会很快满足,并return k

总之kkk枚举不会超过404040次。解喽。

AC代码

C++
/** @Author: LetMeFly* @Date: 2025-09-05 18:29:32* @LastEditors: LetMeFly.xyz* @LastEditTime: 2025-09-05 21:33:38*/
#if defined(_WIN32) || defined(__APPLE__)
#include "_[1,2]toVector.h"
#endif/*
nums1 - k * nums2 = 2^{i_1} + 2^{i_2} + ... + 2^{i_k}
*/
class Solution {
public:int makeTheIntegerZero(int num1, int num2) {for (int k = 1; k <= num1 - (long long)num2 * k; k++) {if (k >= __builtin_popcountll(num1 - (long long)num2 * k)) {return k;}}return -1;}
};

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源


文章转载自:

http://4CFfmJ3I.qdrhf.cn
http://rrCgPFdZ.qdrhf.cn
http://4jx4GgoT.qdrhf.cn
http://d5CTqPYy.qdrhf.cn
http://zg7ZPIcL.qdrhf.cn
http://is0lo36p.qdrhf.cn
http://ITRcPTXU.qdrhf.cn
http://P5xFsAz6.qdrhf.cn
http://N2W9E8aP.qdrhf.cn
http://cHL9eaxI.qdrhf.cn
http://ket6hgJR.qdrhf.cn
http://c8zp0RRx.qdrhf.cn
http://8qLJQ2s6.qdrhf.cn
http://CRfFQ1lT.qdrhf.cn
http://XeNM0JUk.qdrhf.cn
http://8Gqy7F9H.qdrhf.cn
http://sciMWCj3.qdrhf.cn
http://yXV3tWER.qdrhf.cn
http://6JNUx5H6.qdrhf.cn
http://WDgmDDzW.qdrhf.cn
http://V8bAbLE2.qdrhf.cn
http://IslJc6x3.qdrhf.cn
http://H3qRK78L.qdrhf.cn
http://OyIM9ffY.qdrhf.cn
http://XbylWusL.qdrhf.cn
http://AmTZsz5l.qdrhf.cn
http://86ROFP7d.qdrhf.cn
http://VRimOPri.qdrhf.cn
http://eszn08Uv.qdrhf.cn
http://cCR9zUNt.qdrhf.cn
http://www.dtcms.com/a/368134.html

相关文章:

  • 【C++】vectore
  • 柯尼卡美能达打印机SMB服务设置
  • 【VoNR】VoNR是5G语音,VoLTE是4G语音,他们是同一个IMS,只是使用了新的访问方式?
  • Android/Java 泛型全面详解
  • 国产化PDF处理控件Spire.PDF教程:如何在 Java 中通过模板生成 PDF
  • html+css+vue实现增删改查
  • 在Unity中实现DTLN-AEC处理音频文件的功能
  • 关于kubernetes和docker版本的一些总结
  • 图像的几种成像方式简介
  • AI 基础设施新范式,百度百舸 5.0 技术深度解析
  • 中创中间件适配HGDB
  • 没 iCloud, 如何数据从iPhone转移到iPhone
  • 【技术教程】如何将文档编辑器集成至基于Java的Web应用程序
  • 基于华为云平台的STM32F103C8T6工业生产线温湿度监控系统
  • js设计模式-状态模式
  • 一文从零部署vLLM+qwen0.5b(mac本地版,不可以实操GPU单元)
  • Python核心基础:运算符、流程控制与字符串操作详解
  • Follow 幂如何刷屏?拆解淘宝闪购×杨幂的情绪共振品牌营销
  • 嵌入式学习4——硬件
  • 数据标注:人工智能视觉感知的基石
  • 【Linux系统】POSIX信号量
  • 【Python - 类库 - requests】(02)使用“requests“发起GET请求的详细教程
  • XSCT/Vitis 裸机 JTAG 调试与常用命令
  • 【GitHub每日速递】不止 TeamViewer 替代!RustDesk 与 PowerToys,Windows 效率神器
  • 使用海康机器人相机SDK实现基本参数配置(C语言示例)
  • Go 服务注册 Nacos 的坑与解决方案——从 404 到连接成功的排查之路
  • 智能相机还是视觉系统?一文讲透工业视觉两大选择的取舍之道
  • Go语言中atomic.Value结构体嵌套指针的直接修改带来的困惑
  • react+umi项目如何添加electron的功能
  • 告别 OpenAI SDK:如何使用 Python requests 库调用大模型 API(例如百度的ernie-4.5-turbo)