一堆数字里,不能凑出的最小正整数

转自:【作者:FlushHip链接:https://www.nowcoder.com/discuss/70063

很直观的思路,首先想想如果暴力该怎么搞,是不是要从1开始往上枚举。那么这题的思路差不多,从十进制位数开始枚举;

先不要看0,0这个字符待会再说,先来看看给出的这些字符能不能凑出一位数,能不能凑出一位数就看看1 - 9是不是都有,如果都有,那么就可以;然后看看能不能凑出两位数,如果枚举到了两位数,那么就说明1 - 9这些数字的个数大于等于1,什么时候会出现凑不出来的情况呢,对了,就是需要两个一样的数字时,比如1 - 9这些数字的个数都为1,你就绝对凑不出11,对吧;然后来看三位数,后面其实是一样的了,如果只有两个1,是凑不出111的,但是112129这些数字都是可以的,因为1 - 9这枚举三位数时就保证的这些字符的个数大于等于2……依次类推就可以了;

等等,好像还有0没有考虑,那么现在考虑一下。要凑最小三位数100,最少需要两个0,少了就不行,那么只有10的情况,能凑出来的最小的数就是10

想到这一步这个题就解决了啊,先统计1 - 9的个数,然后找出里面的最小值,最小值表示这些数字至少能凑出几位数(这里还没有考虑字符0),然后看下0字符的个数是不是大于等于最小值减一,这里举个例子说明后面的步骤,比如1 - 9每个字母都有3个,03个,111110000都是不可以凑出来的,答案就是1111;比如1 - 9每个字母都有3个,0只有2个,那么11111000都是不可以凑出来的,答案就是1000

#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main()
{
       for (string str; cin >> str;){
		vector<int>used(10, 0);//用0初始化10个坑
		int digit = -1, theMin = 0x3f3f3f3f;//计录出现次数theMin最少的数字(因为是从1开始,所以 该数字是出现次数最小的数字中最小数值的数)
		for (auto it = str.begin(); it!= str.end(); ++it)
			++used[*it - '0'];//每个坑装对应编号出现的次数
		//0----9出现的次数分别为:a[0]---a[9]
		for (int i= 1; i <= 9; ++i)
			if (theMin > used[i])
				theMin = used[i], digit = i;
		
		//能凑出的最小位数是theMin位,假设theMin=3,那么最小的3位数的100,就要判断0个出现次数+1是否等于theMin
			if (used[0] +1<= theMin)//0的个数凑不够3位
				cout << "1" + string(theMin, '0') << endl;
			else//0的个数能凑出来
				cout << string(theMin + 1, digit + '0') << endl;
	}
	system("pause");
	return 0;
}

  

原文地址:https://www.cnblogs.com/beihaidao/p/8631541.html