LeeCode 1611 DFS

题意

传送门 LeeCode 1611. 使整数变为 0 的最少操作次数

题解

先考虑基本变换,定义 F ( i ) F(i) F(i) 为使 0 0 0 变为 2 i 2^i 2i 或使 2 i 2^i 2i 变为 0 0 0 的操作次数,那么需要 F ( i − 1 ) F(i-1) F(i1) 次操作使将 0 0 0 变为 2 i − 1 2^{i-1} 2i1,将 i i i 位异或 1 1 1 后,在通过 F ( i − 1 ) F(i-1) F(i1) 次操作使 2 i − 1 2^{i-1} 2i1 变为 0 0 0。则有
{ F ( i ) = 2 F ( i − 1 ) + 1 F ( 0 ) = 1 \begin{cases} F(i)=2F(i-1)+1 \\ F(0)=1 \\ \end{cases} {F(i)=2F(i1)+1F(0)=1 求解得到 F ( i ) = 2 i + 1 − 1 F(i)=2^{i+1}-1 F(i)=2i+11

目标是将高位的 1 1 1 翻转,参照基本变换,定义 f ( n ) f(n) f(n) 为使 n n n 变为 0 0 0 的操作次数,定义 g ( n , p ) g(n,p) g(n,p) 为使 n n n 变为 p p p 位为 1 1 1 其余位为 0 0 0,即 1000 … 1000\dots 1000 形式的操作次数。对于 f ( n ) f(n) f(n),首先需要将低位转换为 1000 … 1000\dots 1000 的形式,翻转高位,再将低位转换为 0 0 0;对于 g ( n , p ) g(n,p) g(n,p),若 p p p 位为 1 1 1 那么需要将低位转换为 0 0 0,否则将低位转换为 1000 … 1000\dots 1000 翻转高位,再将低位转换为 0 0 0

class Solution
{
public:
    int f(int n)
    {
        if (!n)
        {
            return 0;
        }
        int p;
        for (int i = 30; i >= 0; i--)
        {
            if ((n >> i) & 1)
            {
                p = i;
                break;
            }
        }
        return (1 << p) + g(n ^ (1 << p), p - 1);
    }
    int g(int n, int p)
    {
        if (p == -1)
        {
            return 0;
        }
        if ((n >> p) & 1)
        {
            return f(n ^ (1 << p));
        }
        return (1 << p) + g(n, p - 1);
    }
    int minimumOneBitOperations(int n)
    {
        return f(n);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值