交流讨论丨字节面试题-小于n的最大数(非递归方法)
2501
2024.09.10
2024.09.11
发布于 天津市

小于n的最大数

题目描述: 数组A中给定可以使用的1~9的数,返回由A数组中的元素组成的小于n(n > 0)的最大数。例如:A = {1, 2, 4, 9},n = 2533,返回2499。

该题许多方法用dfs去做,我用非递归的方法去模拟,请各位大佬看看有没有问题。
大致思路

  1. 用数组ans存储每一位应该放什么数
  2. 假如遇到需要回溯的情况,就回溯到可以变小的第一个位置,并将该位置的数变小一个,后面的所有数字就填最大数
  3. 正常情况下就选择不大于当前数字的最大的值
    • 如果可选择的最大数字小于当前数字,那么后面的所有数字填最大数就行
int maxNum(int n, vector<int> nums)
{
	sort(nums.begin(), nums.end());
	if (n <= nums[0]) return -1;

	string s = to_string(n);
	vector<int> ans;

	for(int i=0;i<s.length();i=ans.size())
	{
        // 碰到需要回溯的情况,将能变小的第一个数字变小一个,后面的所有数字填最大值即可
        // 边界1:当前数字小于提供的nums的最小值
        // 边界2:最后一位数等于提供的nums的最小值
		if (s[i] - '0' < nums[0]||(i==s.length()-1&&s[i]-'0'==nums[0]))
		{

            //回溯到数字可减小的位置,并将这个位置的数减小一个
			while (ans.size() > 1 && ans.back() == 0)
			{
				ans.pop_back();
			}
			ans[ans.size() - 1]--;

            //后面的所有数字填最大值
			for (int j = ans.size(); j < s.length(); j++)
			{
				ans.push_back(nums.size() - 1);
			}

		}
        // 正常往后添加符合条件最大的数字
		else
		{
            //可用二分去优化
			for (int j = nums.size() - 1; j >= 0; j--)
			{
				if (s[i] - '0' > nums[j])
				{
					ans.push_back(j);
                    // 因为当前添加的数字小于n,因此后面的数字选最大数就行
                    for (int p = ans.size(); p < s.length(); p++)
                        ans.push_back(nums.size()-1);
					break;
				}
                // 最后一位数不能相等,否则两个数就完全相等了
				else if (s[i] - '0' == nums[j]&&i!= s.length() - 1)
				{
					ans.push_back(j);
					break;
				}
			}
		}
	}
    // 将数组转换成数字
	int x = 0;
	for (auto a : ans)
	{
		if(a>=0)
			x = x * 10 + nums[a];
	}
	return x;
}
评论 (2)