面试题 05.04. 下一个数

题目链接:leetcode.

思路错误,想着比它大的是把最左边的1和其右边第一个0交换,比它小的是把最左边的0和其右边第一个1交换
所以9我求出来就是[10,3],而实际上是[10,6]

class Solution {
public:
    vector<int> findClosedNumbers(int num) {
        int f0 = -1, f01 = -1;
        int f1 = -1, f10 = -1;
        int tmp = num;
        for(int i = 0;i < 32;++i)
        {
        	if(num & 1)
        	{
        		if(f1 == -1)
        		{
        			f1 = i;
        		}
        		if(f0 != -1 && f01 == -1)
        		{
        			f01 = i;
        		}
        	}
        	else
        	{
        		if(f0 == -1)
        		{
        			f0 = i;
        		}
        		if(f1 != -1 && f10 == -1)
        		{
        			f10 = i;
        		}
        	}
        	num >>= 1;
        }
        cout <<f0 <<' ' << f01 << endl;
        cout << f1<<' ' << f10 << endl;
        int maxx, minn;
        if(f1 != -1 && f10 != -1)
        {
        	maxx = tmp ^ (1 << f1);
        	maxx = maxx | (1 << f10);
        }
        else
        	maxx = -1;
        if(f0 != -1 && f01 != -1)
        {
        	minn = tmp | (1 << f0);
        	minn = minn ^ (1 << f01);
        }
        else
        	minn = -1;
        return {maxx, minn};
    }
};

我太笨了,暴力暴力!不会做的时候就暴力!!!
分别向上和向下找,计算1的个数是否相同

正确思路:
下一个大的数:最右边的01变成10,再把右边的1都移到最右边
下一个小的数:最左边的10变成01,再把右边的1都向左移到01紧右边

/*
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:5.9 MB, 在所有 C++ 提交中击败了91.12%的用户
*/ 
class Solution {
public:
    vector<int> findClosedNumbers(int num) {
        //先找第一个01,和它右边的1的个数
		int cnt = 0, f01 = -1; 
		for(int i = 0;i < 30;++i)//最高位为0不算,符号位 
		{
			if((num & (1 << i)) && !(num & (1 << (i + 1))))
			{
				f01 = i;
				break;
			}
			if(num & (1 << i))
				cnt++;
		} 
		int maxx = -1;
		if(f01 != -1)
		{
			//01反转,右侧置0
			maxx = num ^ (1 << (f01 + 1));
			maxx = maxx ^ (1 << f01);
			for(int i = 0;i < f01;++i)
			{
				if(maxx & (1 << i))
					maxx = maxx ^ (1 << i);
			}
			int t = 1; 
			while(cnt--)
			{
				maxx += t;
				t <<= 1;
			}
		}
		//找第一个10,和它右边的1的个数
		int f10 = -1;
		cnt = 0; 
		for(int i = 1;i < 32;++i)
		{
			if((num & (1 << i)) && !(num & (1 << (i - 1))))
			{
				f10 = i;
				break;
			}
			if(num & (1 << (i - 1)))
				cnt++;
		} 
		int minn = -1;
		if(f10 != -1)
		{
			//先反转 
			minn = num ^ (1 << f10);
			minn = minn ^ (1 << (--f10));
			//再置0
			for(int i = 0;i < f10;++i)
			{
				if(minn & (1 << i))
					minn = minn ^ (1 << i);
			} 
			while(cnt--)
			{
				minn = minn ^ (1 << (--f10));
			}
		}
		return {maxx, minn};
    }
};

太辛苦了,这小破题做了一天。位运算还是一步一步来吧,别想着怎么把它一步到位,我脑子不够的○| ̄|_

以下是代码的优化版本,包括添加了判断是否存在同样的据和导入完成后删除源文本的功能: ``` 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、付费专栏及课程。

余额充值