首页 > 试题广场 >

数字字符

[编程题]数字字符
  • 热度指数:3340 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
在十进制表示中,任意一个正整数都可以用字符 ’0’-‘9’ 表示出来。但是当 ’0’-‘9’ 这些字符每种字符的数量有限时,可能有些正整数就无法表示出来了。比如你有两个 ‘1’ ,一个 ‘2’ ,那么你能表示出 11,12,121 等等,但是无法表示出 10,122,200 等数。
现在你手上拥有一些字符,它们都是 ’0’-‘9’ 的字符。你可以选出其中一些字符然后将它们组合成一个数字,那么你所无法组成的最小的正整数是多少?

数据范围:字符串长度满足 ,字符串中只包含 '0'-'9' 字符。

输入描述:
第一行包含一个字符串,表示你可以使用的字符。


输出描述:
输出你所无法组成的最小正整数
示例1

输入

55

输出

1
示例2

输入

123456789

输出

10
#include<iostream>
#include<algorithm>
using namespace std;
int num[10]={0,1,2,3,4,5,6,7,8,9};
int a[10]={1};//出现的次数,‘0’的次数初值赋为1,其余为0
bool cmp(int x,int y)//设置比较函数,将10个字符按出现次数从少到多排列
{
    return a[x]<a[y];
}
int main()
{
    string str;
    cin>>str;
    for(auto c:str)
    {
        a[c-48]++;//记录字符出现次数
    }
    stable_sort(num,num+10,cmp);//次数相同时,值小的排在前面
    num[0]==0 ? cout<<1:cout<<num[0];
    for(int i=0;i<a[num[0]];cout<<num[0],i++);
}
本题无法组成的最小数的形式应该只有两种10...0(n个0)或者X...X(X为1到9)。
首先本题要找的是正整数,所以我们先得把0和其他字符分开考虑。
  1. 先记录‘1’~‘9’这9个字符出现的次数,然后找到出现次数最小的,这里次数相同时优先找值小的字符,比方说‘2’,‘3’都出现了2次,而其余的除‘0’外都出现了3次或其以上(0出现2次,下一条解释为什么),那么最小不能组成的数是222,和3无关
  2. 将‘1’~‘9’中出现的最小次数和‘0’出现的次数比较,注意比较的时候‘0’的出现次数得加1。比方说上一条例子中,‘0’出现的次数为1的话,本题答案为100。所以说a[0]=1(0的次数)+1 <= a[2] = 2(2的次数)时,答案的形式为10...0;而a[0]=2 + 1 > a[2] = 2 时,答案形式为X...X。而且通过这个例子我们了解到答案的长度为最小次数加1(‘0’为加2),比方说1中的例子答案3个2(2出现2次),2中的例子答案100(0出现1次)
  3. 通过2我们总结出的方法:找‘1’~‘9’出现次数最少且值最小的数,和‘0’出现的次数加1进行比较。这里代码实现的时候为了简化,记录0出现次数的a[0]初值我直接赋为1,其余为0,输入字符串后,记录的0出现的次数比实际出现多了个1,然后排序直接用<algorithm>的stable_sort。num[]数组一开始是每个字符的标号,这时num[0]=0,a[]是对应字符出现的次数。比较函数cmp:两个数x,y出现次数a[x]<a[y]时返回true。sort完后,num[]数组中的num[0]就是出现次数最少的字符了。至于为什么用stable_sort,好处就是次数相同时,值小的排前面。这时我们判断次数num[0]是不是‘0’,如果是的话,就输出1;不是则输出num[0]。之后再输出a[num[0]]个num[0],注意这里a[]并没排序,还是原来的依次为0~9的出现次数。
  4. 之后我们考虑一下特殊情况:
  • 字符出现最小次数为0时,没有什么区别
  • 字符出现次数全部一样时,定为k次,比较的时候a[0]=k+1 > a[i](i为1~9),此时被挑出来的是1,根据步骤3中的方法最后的答案为1111...11(一共k+1个1)。而事实上它也的确是最小的不能组成的数。这样就顺利地解决了这道题。
编辑于 2019-01-27 00:24:33 回复(0)
/*
    如果字符串缺少1-9中某个数,输出该数
    如果1-9都有,找次数最少的数=>如果该数
                是0,先输出1,然后输出n+1次0(字符串中出现n次0);
                如不是0,直接输出n+1次该数(字符串中出现n次)
*/
#include<iostream>
#include<string>
using namespace std;
int a[12]={0};
int main(){
    string s;
    cin>>s;
    for(int i=0;i<s.length();i++){
        a[s[i]-'0']++;
    }
    bool flag = false;    
    for(int i=1;i<10;i++){
        if(a[i]==0){
            cout<<i<<endl;
            flag = true;
            break;
        }
    }
    if(!flag){
        int min = 10000,index=-1;
    for(int i=0;i<10;i++){
        if(min > a[i]){
            min=a[i];
            index = i;
        }
    }
    if(index==0){
        cout<<1;       
    }for(int i=0;i<=a[index];i++){
            cout<<index;
       }
    }
    
    return 0;
}

发表于 2019-03-15 18:36:10 回复(0)
import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        String src=sc.next();
        String[] arr=src.split("");
        int min=Integer.valueOf(arr[0]);
        for(int i=0;i<arr.length;i++){
            for(int j=i+1;j<arr.length;j++){
                int num=Integer.valueOf(arr[i]+arr[j]);
                if(num<min)
                    min=num;
            }
        }
        if(min>1)
            System.out.println(1);
        else
            System.out.println(min-1);
    }
}
编辑于 2019-03-12 14:53:55 回复(0)
nums = input()
num_count = [0,0,0,0,0,0,0,0,0,0]
for n in nums:
    d = (int)(n)
    if d==0:
        num_count[9] += 1
    else:
        num_count[d-1] += 1
        
min_digit = num_count[0]
min_di = 0
for i in range(1,10):
    if num_count[i] < min_digit:
        min_digit = num_count[i]
        min_di = i

if min_di == 9:
    print('1'+'0'*(min_digit+1))
else:
    print(str(min_di+1)*(min_digit+1))

我的思路是,先看看数据具有怎样的特征:
1-9 ,需要有1-9每个最少有一个
10, 需要有一个0(同时还需要有一个1,但是判断到10的时候肯定已经满足了)
11,需要两个1
12-19,需要的条件之前已经满足了,不可能出问题
20,已经满足
21,已经满足
22,需要两个2
如此类推

最后可以发现这样一个规律:最小的数字,总是和0-9这十个数字里谁最少有关

比如说只有一个1,但是其他数字都有两个,那么就是11成为第一个无法输出的数字;就算有的数字超过了2个,它达到多少,还是被最小的1所阻拦

因此思路就很简单了:
1,算出每个数字的数量
2,找到最少的那个数字
3,根据最少数字的次数得到最小量

这个算法的好处就在于只和输入相关,而与这个最小数字能有多大无关,就算是9999999999,也和1没有什么差别

如果要改进的话,那么就是写一个正则直接找到最少出现的数字已经出现的次数,然后答案就出来了
发表于 2019-01-25 13:25:53 回复(0)
先对能用的数字进行统计,然后从1开始检验,对待检验数中的数字进行计数,并检查是否小于等于能用的数字数。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        char[] num = br.readLine().trim().toCharArray();
        int[] counter = new int[10];
        for(int i = 0; i < num.length; i++)
            counter[num[i] - '0']++;
        int start = 1;
        while(judge(String.valueOf(start).toCharArray(), counter))
            start++;
        System.out.println(start);
    }
    
    private static boolean judge(char[] num, int[] counter) {
        int[] cnt = new int[10];
        for(int i = 0; i < num.length; i++){
            // 如果counter中不包含数字num[i],则num无法表示
            if(counter[num[i] - '0'] == 0)
                return false;
            cnt[num[i] - '0']++;
        }
        // num中的数字都包含,则检查数量是否都够
        for(int i = 0; i <= 9; i++){
            if(cnt[i] == 0) continue;
            // 如果组成数字num要求的i数量超出限制,则不能表示
            if(cnt[i] > counter[i])
                return false;
        }
        return true;
    }
}


发表于 2021-02-02 10:17:57 回复(0)
#方法很明了,一看就懂,大家加油!

arr = input()
#输入列表
list1 = []
for i in arr:
list1.append(int(i))
# 0--9
list2 = [0,1,2,3,4,5,6,7,8,9]
#存入缺失的数字(已经有序)
list3 = []
for i in list2:
if i not in list1:
list3.append(i)
list4 = []    #出现次数
#判断缺不缺
if len(list3) == 1:
if list3[0] == 0:
pass
else:
MIN = list3[0]
print(MIN)
elif len(list3) >1:
if list3[0] == 0:
MIN = list3[1]
print(MIN)
else:
MIN = list3[0]
print(MIN)
else:
list4.append(list1.count(1))
list4.append(list1.count(2))
list4.append(list1.count(3))
list4.append(list1.count(4))
list4.append(list1.count(5))
list4.append(list1.count(6))
list4.append(list1.count(7))
list4.append(list1.count(8))
list4.append(list1.count(9))
# 出现最少的次数
min_count = min(list4)
# 出现次数最少的 数字,此处取索引的特点是:相同出现次数,只取第一次出现的位置,再 +1,相当于直接排序

# 即:不缺数字的情况下,出现次数最少的 最小的数字是 :
num = list4.index(min_count) + 1
count = min_count
for i in range(count+1):
print(num,end='')
编辑于 2019-08-07 14:54:25 回复(0)
这题目的测试用例好像有点问题,我按照我想法做了一半想看看能过多少用例结果全过了??
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;

public class Main{
    public static void main(String args[]) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        char c[] = br.readLine().toCharArray();
        int arr[] = new int[c.length];
        
        List list = Arrays.asList(arr);

        for(int i = 1;i < 10;i++){
            if(!list.contains(i)){
                System.out.println(i);
                return ;
            }
        }
        if(!list.contains(0)){
            System.out.println(arr[0] + 0);
            return ;
        }
        
    }
}
这肯定是不对的,但是既然提示过了就看了大佬的思路也算做过了吧嘿嘿嘿..
编辑于 2019-07-23 15:22:03 回复(2)
//不统计哈哈哈
import java.util.Arrays;
import java.util.Map;
import java.util.Scanner;

public class Main
{
    public static void main(String[] args)
    {
        Scanner scan=new Scanner(System.in);
        while(scan.hasNext()){
           String str=scan.nextLine();
            System.out.println(get(str));
        }
    }
    public static int get(String str){
        char[]data=str.toCharArray();
        Arrays.sort(data);
        boolean flag=true;
        int count=1;
        while (flag){
            String tem=count+"";
            char[]arr=tem.toCharArray();
            Arrays.sort(arr);
            int i;
            int j=0;
            for(i=0;i<arr.length&&j<data.length;){
                if(arr[i]!=data[j])
                    j++;
                else{
                    i++;
                    j++;
                }
            }
            if(i!=arr.length){
                flag=false;
                return count;
            }
            else
                count++;
        }
        return 0;
    }
}

发表于 2019-04-23 21:48:35 回复(0)
 package numProblem;

import java.util.Map;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        int number = 0;
        int count;
        int mixcount = 0;
        String result = "";
        Scanner sc=new Scanner(System.in);
        String src=sc.next();
        //统计每一个数字(0~9)的个数,并找到最少的数字及个数
        for (int i = 0; i < 10; i++) {
            count = src.length() - src.replace(Integer.toString(i), "").length();
            //0的话需要+1,因为同样位数时0需要的少一个。
            if (i == 0) {
                count ++;
            }
            //如果是第一个数0,或者数量更少则更新最少的数字和最少个数。
            if (i == 0 || count<mixcount) {
                number = i;
                mixcount = count;
            }
        }
        //输出结果
        //如果是0,则首位为1
        if(number==0){
            result = "1";
            mixcount--;
        }
        for (int i = 0; i <= mixcount; i++) {
            result = result + Integer.toString(number);
        }
        System.out.println(result);
    }
}

发表于 2019-04-10 19:45:27 回复(0)
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int main(){
    string str;
    while(getline(cin,str)){
        int a[10];
        for(int i=0;i<10;i++)
            a[i]=0;
        char ch[20];
        strcpy(ch,str.c_str());
        for(int i=0;i<strlen(ch);i++)
            a[ch[i]-'0']++;
        int min=1;
        bool judge=0;
        for(int i=1,count=0;i<101;i++){
            int check[10]={0,0,0,0,0,0,0,0,0,0};
            int temp=i;
            while(temp>0){
                check[temp%10]++;
                temp/=10;
            }
            for(int j=0;j<10;j++){
                if(a[j]<check[j]){
                    min=i;
                    judge=1;
                    break;
                }
            }
            if(judge==1)
                break;
        }
        cout<<min<<endl;
    }
}

发表于 2019-02-11 17:49:21 回复(0)
思路:
通用情况: 如果数符 min 出现次数最少,而且出现次数少于次最少数符 min_sec:
第一步:扫描输入字符串,并对[0,1,2,3,4,5,6,7,8,9] 十种数符(digits)进行计数,得到统计结果:Integer count[]
    例子:输入字符串:99988877766655544433322200
           count = [3, 3, 3, 3, 3, 3, 3, 3, 0, 2]
第二步:对count进行升序排序,选择出现次数最少的数符和对应出现次数(若没有出现过,记为 0)。
    
第三步:这个【最少次数:k 次】的【数符:'i'】组成【最终结果】==> iiii...(k+1 次)。
    如上例: 数符 '1' 出现 0 次, 最终结果 ==> 1 (0+1次)。  if(...)    
    else {
            int digit = 0;
            if(min == 0 && count[min] == count[min_sec]) digit = min_sec;
            else digit = min;
            int ans = digit;
            for(int i = count[digit]; i > 0; i--)
                ans += digit * (int) Math.pow(10, i);
            return ans;
        
        } 第四步:
特殊情况一:数符 min: '0' 出现次数最少,而且出现次数少于【次最少】数符 min_sec:
输入字符串:99988877766655544433322211
按通用情况处理,输出结果为 0,但 0 非正,不满足题意。所以单独处理。
正确结果应该是10  //1个次最少数符 '1', 外加 k+1个最少数符 '0'(k==0, k+1==1)
if(min == 0 && count[min] != count[min_sec])
            return (int) Math.pow(10, count[min]+1);

特殊情况二:数符 min: '0' 出现次数最少,而且等于【次最少】数符 min_sec:
这种情况和通用情况一样。唯一区别是用要使用 min_sec 来构成最后答案。

/*完整代码*/
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.*;
 
public class Main {
    static Integer[] count = new Integer[10];
    public Main() {
        super();
    }
     
    public static void main(String[] args) {
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String str = br.readLine();
            System.out.println(find(str));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static int find(String str) {
        // Integer[] count = new Integer[10];
    // 计数初始化为 0
        for(int i = 0; i < 10; i++) count[i] = 0;

    // 数符集
        Integer[] digits = new Integer[10];
  for(int i = 0; i < 10; i++) digits[i] = i;

     /* count 计数 */
        for(char c : str.toCharArray()) count[c - '0'] += 1;
 
    /* 排序*/
        Arrays.sort(digits, new myComp());
        int min = digits[0];
        int min_sec = digits[1];

/* 特例1:数符 '0' 出现次数最少*/
        if(min == 0 && count[min] != count[min_sec])
            return (int) Math.pow(10, count[min]+1);

  /* 通用+特例2:*/
        else {
            int digit = 0;
            if(min == 0 && count[min] == count[min_sec]) digit = min_sec;
            else digit = min;
            int ans = digit;
            for(int i = count[digit]; i > 0; i--)
                ans += digit * (int) Math.pow(10, i);
            return ans;
        
        }
    }

/* class for customized Comparator*/
    private static class myComp implements Comparator<Integer> {
        public int compare(Integer a, Integer b) {
            return count[a] < count[b] ? -1 : count[a] > count[b] ? 1 : a-b;
        }
    }
}

发表于 2019-02-01 07:09:50 回复(0)
 #include <bits/stdc++.h>

using namespace std;

int main()
{     string s;     while(cin>>s){         int n = s.length();         int a[11] = {0};         for(int i=0;i<n;i++){                         if(s[i]=='0')                 a[10]++;             else                 a[s[i]-'0']++;         }         int d = a[1], m=1;         for(int i=1;i<=10;i++){             if(a[i]<d){                 d = a[i];                 m = i;             }         }         if(m==10){             cout<<1;             for(int i=1;i<=d+1;i++)                 cout<<0;         }else{             for(int i=1;i<=d+1;i++)                 cout<<m;         }         cout<<endl;     }     return 0;
}

发表于 2019-02-02 03:25:17 回复(0)
#include<stdio.h>
#include<string.h>
int main(){
    char a[1001];
    gets(a);
    int len=strlen(a);
    int b[10];
    memset(b,0,sizeof(b));
    //数组b记录有某个元素,b[1]=1表示有1,0则是没有
    for(int i=0;i<len;i++)
        b[a[i]-48]=1;
    //从1到9遍历,如果b[i]=0那么i最小,否则10最小
    for(int i=1;i<10;i++)
        if(!b[i]){
            printf("%d",i);
            break;
        }
        else{
            if(i==10){
                printf("10");
                break;
            }
        } 
    return 0;
}


发表于 2019-01-24 17:12:19 回复(4)
#include <iostream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
string str;
while(cin>>str)
{
cout<<1<<endl;
}
return 0;
}
编辑于 2019-01-29 12:52:16 回复(1)
#include <iostream>
#include <vector>
#include <algorithm>
#include<math.h>
using namespace std;

int main(void)
{
    string s;
    cin >> s; 
    long check[10]={0};
    for (int i = 0; i < s.size(); i++)
    {
        char temp=s[i];
        int num=temp-'0';
        check[num]++;
    }
    int cntmin=99999;
    int nummin;
    for(int i=9;i>0;i--)
    {
        if(check[i]<=cntmin)
        {
            cntmin=check[i];
            nummin=i;
        }
    }
    long long minnot=1;
    
    
    char nummin_char=nummin+'0';
    string output=string(cntmin+1,nummin_char);
    
    string zeros=string(check[0]+1,'0');
    zeros='1'+zeros;
    if(zeros<'0'+output)
        cout<<zeros;
    else
        cout<<output;
    return 0;
}

发表于 2022-03-06 16:41:33 回复(0)
采用哈希计数
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int main(){
    string s;
    cin>>s;
    vector<int> v(10,0);
    vector<int> res;
    for(int i=0;i<s.length();i++){
        v[s[i]-'0']=1;
    }
    for(int i=0;i<10;i++){
        if(v[i]==0) res.push_back(i);
    }
    if(res.size()==1) cout<<res[0];
    else if(res.size()>1&&res[0]==0) cout<<res[1];
    return 0;
}
发表于 2020-08-31 17:43:54 回复(0)

数字字符

1,2,3,4,5,6,7,8,9, 10

11, 12,13,..., 20

...

100, 101, 102,...

我们先统计0-9每个数字可以使用的数量。

我们可以很容易发现,如果是1-9之间数字某一个数字没有可以使用的,显然无法组成最小正整数就是该数字,如果是0没有,则无法组成的就是10。

(1)如果某位数字比较少,其他数字数量大于该为数字数量至少一个,必然最少的数字最先短缺,而其他数字相对充足。

如果1只有x个,其他数字充足, 则最小正整数一定是111..11(共x+1)位数字,因为该数字最先使用x+1个1,因此,出现不足。

类似的,有2,3,9 都是如此。

如果0只有x个,其他数字充足,那么最先消耗到,x+1个0的最小正整数就是1000..0(共x+1个0)。

(2)还有一种情况,如果有多位数字都一样最少,则一定会出现数字越小的越出现短缺(此时的0应该看做10,排在最后;如果题目要求的是最小自然数,此时0将最先短缺)。

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        char[] c = sc.next().toCharArray();
        int[][] cnt = new int[10][2];
        for(int i=0;i < 10; i++) cnt[i][1] = i;
        cnt[0][1] = 10;
        for(int i=0; i < c.length; i++) cnt[c[i]-'0'][0] ++;
        Arrays.sort(cnt, (o1, o2)-> o1[0] == o2[0]? o1[1] - o2[1] : o1[0] - o2[0]);
        StringBuilder sb = new StringBuilder();
        if(cnt[0][1] == 10) {
            sb.append(1);
            for(int i=0; i <= cnt[0][0]; i++)
                sb.append(0);
        } else {
            for(int i=0; i <= cnt[0][0]; i++)
                sb.append(cnt[0][1]);
        }
        System.out.println(sb.toString());
    }
}
发表于 2020-06-24 18:15:12 回复(0)
#include<bits/stdc++.h>
using namespace std;
int main(){
    string s;
    cin>>s;
  
    map<int,int>mp;
    for(int i=0;i<10;++i)
        mp.insert(make_pair(i,0));
    for(char c:s)
        mp[c-'0']+=1;
    int ans = INT_MAX;
   
    char c;
    for(auto it=mp.begin();it!=mp.end();++it)
    {
        if(it->second<ans){
            ans = it->second;
            c = it->first+'0';
        }
    }
    if(ans==0){
        if(c=='0'){

            int flag = 0;
            for(auto t:mp){
                if((t.second==0)&&(t.first!=0))
                {
                    cout<<t.first<<endl; return 0;
                }
            }
            cout<<10;
        }
        else cout<<c;
        return 0;
    }
    string res = "";
    for(int i=0;i<mp[c];++i)
        res+=c;
    if(c=='0')
        res = '1'+res;
    cout<<res<<endl;
    return 0;
}
编辑于 2020-06-13 23:40:15 回复(0)

其他语言永远也体会不到C语言的快乐(尤其是C++)
#include <stdio.h>

int sum[10];

int main()
{
	int i,j;
	char c;
	for(c=getchar();c^'\n';c=getchar())
		sum[c-'0']++;
	for(i=0;i<0x7fffffff;i++)
	{
		int used[10]={0};
		for(j=i;j;j/=10)
		{
			used[j%10]++;
			if(used[j%10]>sum[j%10])
			{
				printf("%d\n",i);
				return 0;
			}
		}
	}
}

发表于 2019-08-19 11:02:16 回复(0)
默认字符都是存在一些,所以结果只能是从1-10的结果
发表于 2019-07-06 09:32:53 回复(0)

问题信息

上传者:小小
难度:
47条回答 7940浏览

热门推荐

通过挑战的用户

查看代码