[编程题3][牛客]电话号码分身

题目描述:原题链接

继MIUI8推出手机分身功能之后,MIUI9计划推出一个电话号码分身的功能:首先将电话号码中的每个数字加上8取个位,然后使用对应的大写字母代替 ("ZERO", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE"), 然后随机打乱这些字母,所生成的字符串即为电话号码对应的分身。

题目分析:

整个过程是从数字到字母的映射过程,题目要求是实现其逆过程,分为两步:

  • 从随机打乱的字母转换为数字
  • 将中间数字减8还原到原来的数字
  • 此外:输出要求是分身前的最小号码,允许0为先导

基本思路:

数字减8的操作很容易实现,即通过字母转换的数字中8-9对应0-1; 0-7对应2-9

对于输出要求最小号码,只需要将数字从小到大排列即可

重点在于从打乱的字母到数字的映射,仔细观察以下特点:

  • 某些字母与数字(下文的红色字母)之间有一一映射的关系:'Z' -->0;  ''W'-->2;  'X'-->6;  'G'-->8。那么只要有对应的字母存在,就意味着有该数字,且数字出现的次数与字母出现的次数相同
  • 通过第一步操作,我们得出了数字0/2/6/8出现的次数,我们可以推算出仅仅与他们有字母交集的其他数字,如’S‘仅存在6和7中,那么7出现的次数就等于'S'出现的次数-6的次数。同理我们可以得到一下几个数字
    • ’S‘-6=7 
    • 'V'-7=5
    • 'F'-5=4
    • 'H'-8=3
  • 最后剩下数字1和9,有公共的字幕N和E,因此,1需要通过’O‘来确定,1 = ’O‘-0-2-4; 9通过字母’I‘来确定,9=’I‘-5-6

       ZERO    ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE 

源代码@Python

  1 def deriveNum(str):
  2     n = [0 for i in range(10)]
  3     n[0] = str.count('Z')
  4     n[2] = str.count('W')
  5     n[6] = str.count('X')
  6     n[8] = str.count('G')
  7     n[7] = str.count('S')-n[6]
  8     n[5] = str.count('V')-n[7]
  9     n[4] = str.count('F')-n[5]
 10     n[3] = str.count('H')-n[8]
 11     n[1] = str.count('O')-n[0]-n[2]-n[4]
 12     n[9] = str.count('I')-n[5]-n[6]-n[8]
 13     """
 14     tab = [0 for i in range(26)]
 15     for s in str:
 16         tab[ord(s)-ord('A')] +=1
 17     if tab[ord('Z')-ord('A')]:
 18         tmp = tab[ord('Z')-ord('A')]    # the number of symbol 0
 19         n[0]=tmp
 20         tab[ord('Z')-ord('A')] = 0
 21         tab[ord('E')-ord('A')] -=tmp
 22         tab[ord('R')-ord('A')] -=tmp
 23         tab[ord('O')-ord('A')] -=tmp
 24         
 25     if tab[ord('W')-ord('A')]:
 26         tmp = tab[ord('W')-ord('A')]    # the number of symbol 2
 27         n[2]=tmp
 28         tab[ord('W')-ord('A')] = 0
 29         tab[ord('T')-ord('A')] -=tmp
 30         tab[ord('O')-ord('A')] -=tmp
 31         
 32         
 33     if tab[ord('X')-ord('A')]:  
 34         tmp = tab[ord('S')-ord('A')]    # the number of symbol 6
 35         n[6]=tmp
 36         tab[ord('X')-ord('A')] = 0
 37         tab[ord('S')-ord('A')] -=tmp
 38         tab[ord('I')-ord('A')] -=tmp
 39         
 40     if tab[ord('G')-ord('A')]:
 41         tmp = tab[ord('G')-ord('A')]   # the number of symbol 8
 42         n[8]=tmp
 43         tab[ord('G')-ord('A')] = 0
 44         tab[ord('E')-ord('A')] -=tmp
 45         tab[ord('I')-ord('A')] -=tmp
 46         tab[ord('H')-ord('A')] -=tmp
 47         tab[ord('T')-ord('A')] -=tmp
 48         
 49     if tab[ord('S')-ord('A')]:    # S only in 6 and 7
 50         tmp = tab[ord('G')-ord('A')]    # the number of symbol 7
 51         n[7]=tmp
 52         tab[ord('S')-ord('A')] = 0
 53         tab[ord('E')-ord('A')] -=2*tmp
 54         tab[ord('V')-ord('A')] -=tmp
 55         tab[ord('N')-ord('A')] -=tmp
 56         
 57     if tab[ord('V')-ord('A')]:    #V only for 5 and 7, since 7 has been removed
 58         tmp = tab[ord('V')-ord('A')]    # the number of symbol 5
 59         n[5]=tmp
 60         tab[ord('V')-ord('A')] = 0
 61         tab[ord('F')-ord('A')] -=tmp
 62         tab[ord('I')-ord('A')] -=tmp
 63         tab[ord('E')-ord('A')] -=tmp
 64         
 65     if tab[ord('F')-ord('A')]:    #V only for 5 and 4, since 5 has been removed
 66         tmp = tab[ord('F')-ord('A')]    # the number of symbol 4
 67         n[4]=tmp
 68         tab[ord('F')-ord('A')] = 0
 69         tab[ord('I')-ord('A')] -=tmp
 70         tab[ord('V')-ord('A')] -=tmp
 71         tab[ord('E')-ord('A')] -=tmp
 72         
 73     if tab[ord('I')-ord('A')]:    # I only in 5,6,8,9
 74         tmp = tab[ord('I')-ord('A')]   # the number of 9
 75         n[9]=tmp
 76         tab[ord('I')-ord('A')] = 0
 77         tab[ord('N')-ord('A')] -=2*tmp
 78         tab[ord('E')-ord('A')] -=tmp
 79 
 80     if tab[ord('T')-ord('A')]:    # I only in 2,3,8
 81         tmp = tab[ord('T')-ord('A')]   # the number of 3
 82         n[3] =tmp
 83         tab[ord('T')-ord('A')] = 0
 84         tab[ord('H')-ord('A')] -=tmp
 85         tab[ord('R')-ord('A')] -=tmp
 86         tab[ord('2')-ord('A')] -=2*tmp
 87         
 88     if tab[ord('O')-ord('A')]: 
 89         tmp = tab[ord('O')-ord('A')]   # the number of 1
 90         n[1]=tmp
 91         tab[ord('O')-ord('A')] = 0
 92         tab[ord('N')-ord('A')] -=tmp
 93         tab[ord('E')-ord('A')] -=tmp
 94     """
 95     return n 
 96 
 97 
 98 
 99 t = input()
100 for i in range(t):
101     line = raw_input()
102     n1 = deriveNum(line)
103     n = n1[8:10]+n1[0:8]
104     out = ''
105     for i in range(10):
106         out = out+n[i]*str(i)
107     print out

注:

  • 用str.count('x')可以直接统计str中字符‘x’出现的次数,从而避免line15-16行通过循环统计次数
  • 用包含10个元素的列表来记录数字0-9出现的次数,在第i个位置存储数字i的个数
  • 某个字母出现多次时,采用 out = out+n[i]*str(i) 实现多个连续重复字符 

posted on 2017-08-18 11:25  小鱼吐泡泡  阅读(1121)  评论(1编辑  收藏  举报

导航