程序员面试金典——面试题 05.04. 下一个数

一、题目介绍

下一个数。给定一个正整数,找出与其二进制表达式中1的个数相同且大小最接近的那两个数(一个略大,一个略小)。

示例1:

 输入:num = 2
 输出:[4, 1] 
示例2:

 输入:num = 1
 输出:[2, -1]
提示:

1、num的范围在[1, 2147483647]之间;
2、如果找不到前一个或者后一个满足条件的正数,那么输出 -1。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/closed-number-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、解题思路

有两种理解本题的思路:

方法1

(1)求较小值:将输入的正整数转成二进制串(右边低位,左边高位),从右向左遍历找到第一个“10”,将其转成“01”,且将该位置右边所有的“1”向左移动,但不能超过“01”的位置,其余位置均置零。

(2)求较大值:将输入的正整数转成二级制串,从右向左遍历找到第一个“01”,将其转成“10”,且将该位置右边所有的“1”向右移动,其余位置均置零。

(3)注意bitset保存的二进制串,低位在前,高位在后。

方法2

(1)较小值的取值范围为 [num-1, num >> 1],记为F1。

(2)较大值的取值范围为[num+1, num << 1],记为F2。

(3)统计num转成二进制串后,1的个数为n。在F1和F2中分别找到一个与num最接近的,且1的个数也为n的数,即为结果。

三、解题代码

方法一的代码如下


class Solution {
public:
    vector<int> findClosedNumbers(int num) {
        bitset<32> s(num);
        bitset<32> b(num);
        //求略小的值
        int a1 = -1;
        for(int i = 1; i < 32; ++i)
        {
            if(s[i] == 1 && s[i-1] == 0)
            {
                s.flip(i-1);
                s.flip(i);
                for(int left = 0, right = i-2; left < right;)
                {
                    while(left < right && s[left] == 0) left++;
                    while(left < right && s[right] == 1) right--;
                    s.flip(left);
                    s.flip(right);
                }
                a1 = (int)s.to_ulong();
                break;
            }
        }

        //求略大值
        int a2 = -1;
        for(int i = 1; i < 32; ++i)
        {
            if(b[i] == 0 && b[i-1] == 1)
            {
                b.flip(i);
                b.flip(i-1);
                for(int left = 0, right = i-2; left < right;)
                {
                    while(left < right && b[left] == 1) left++;
                    while(left < right && b[right] == 0) right--;
                    b.flip(left);
                    b.flip(right);
                }
                a2 = (int)b.to_ulong();
                break;
            }
        }
        return {a2, a1};
    }
};

四、解题结果

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是代码的优化版本,包括添加了判断是否存在同样的据和导入完成后删除源文本的功能: ``` Dim filePaths(5) As String Dim i As Integer ' 设置文件路径 filePaths(0) = "C:\Users\icd\Desktop\5月场景使用清单(按日)\场景服务方案使用清单05.01.xlsx" filePaths(1) = "C:\Users\icd\Desktop\5月场景使用清单(按日)\场景服务方案使用清单05.02.xlsx" filePaths(2) = "C:\Users\icd\Desktop\5月场景使用清单(按日)\场景服务方案使用清单05.03.xlsx" filePaths(3) = "C:\Users\icd\Desktop\5月场景使用清单(按日)\场景服务方案使用清单05.04.xlsx" filePaths(4) = "C:\Users\icd\Desktop\5月场景使用清单(按日)\场景服务方案使用清单05.05.xlsx" filePaths(5) = "C:\Users\icd\Desktop\5月场景使用清单(按日)\场景服务方案使用清单05.06.xlsx" ' 遍历文件路径组,逐个导入Excel据 For i = 0 To UBound(filePaths) ' 判断是否存在同样的据 Dim rs As DAO.Recordset Set rs = CurrentDb.OpenRecordset("SELECT COUNT(*) FROM 场景使用清单 WHERE 文件路径 = '" & filePaths(i) & "'") If rs.Fields(0).Value > 0 Then MsgBox "文件 " & filePaths(i) & " 中的据已经存在于据库中。" Else ' 导入Excel据 DoCmd.TransferSpreadsheet acImport, 10, "场景使用清单", filePaths(i), True, "" ' 添加文件路径到新导入的记录 CurrentDb.Execute "UPDATE 场景使用清单 SET 文件路径 = '" & filePaths(i) & "' WHERE 文件路径 IS NULL" ' 删除源文本 Kill filePaths(i) End If Next i ``` 需要注意的是,上述代码中的 `场景使用清单` 表需要自行创建,其中需要包含至少以下字段: - ID:主键,自增长 - 文件路径:文本类型,记录导入的Excel文件路径 - 其他字段:根据具体情况添加 此外,还需要添加对 DAO 库的引用。在 VBA 编辑器中,依次点击“工具”→“引用”,勾选“Microsoft DAO 3.6 Object Library”即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值