旋转数字的解法

旋转数字问题:

我们称一个数 X 为好数, 如果它的每位数字逐个地被旋转 180 度后,我们仍可以得到一个有效的,且和 X 不同的数。
要求每位数字都要被旋转。

如果一个数的每位数字被旋转以后仍然还是一个数字, 则这个数是有效的。
0, 1, 和 8 被旋转后仍然是它们自己;
2 和 5 可以互相旋转成对方;
6 和 9 同理,除了这些以外其他的数字旋转以后都不再是有效的数字。

现在我们有一个正整数 N, 计算从 1 到 N 中有多少个数 X 是好数?

示例:
输入: 10
输出: 4
解释:
在[1, 10]中有四个好数: 2, 5, 6, 9。
注意 1 和 10 不是好数, 因为他们在旋转之后不变。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/rotated-digits
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

粗暴解法

首先我拿到这个题目的思路就是分两个不同功能的方法。

一个负责检查数字是否有效并且如果有效的话输出其反转后的数字,无效的话输出none,并且输出一个code,code的值表示了这个数的检查结果。

检查功能代码如下:

def check_active_turn_180(num):#只能处理单个数字
    i_turned=int()
    code=0  #0表示数字有效但反转后仍是其本身,1表示数字有效 3表示数字无效
    if num in active_nums:
        if num ==0 or num==1 or num==8:
            i_turned=num
            code = 0
        elif num ==2:
            i_turned=5
            code = 1
        elif num==5:
            i_turned=2
            code = 1
        elif num==6:
            i_turned=9
            code = 1
        elif num==9:
            i_turned=6
            code = 1
    else:
        code=3
        i_turned=None
    return (code,i_turned)

这个功能的实现还是很粗暴的,简单地将所有有效数字储存在active_nums中,通过将输入的数字与active_nums中的数字进行检索和对比,由于有效数字样式较少,所以直接采用多个if分枝的方法实现识别特定数字并将其转换输出为i_turned。同时在输入非有效数字(如3,4,7)时输出None以及code=3。

但是此功能只支持检查单个10以下数字,如137这样的数字就识别不了

正因为识别不了二位数以上的数字,所以需要另外一个方法将数字转换成字符串,字符串再转换成列表,列表中的每个元素再转换成int然后使用check_active_turn_180方法检查每个数字,然后拿到的返回值,在str操作后加入一个新的列表,再将新的列表用join方法转换成一整个字符串。最后将新字符串进行int处理与原数字进行对比,如果与原数字相等,则丢弃,并break跳出循环。

代码如下:

def solution(N):
    i=1
    count=0
    while i <= N:
        if i <=10:
            check=check_active_turn_180(i)
            if check[0] ==1:
                count+=1
        else:
            j=0 #控制循环次数 当大于拆分后的数字个数时停止循环
            lt_new=[] #用于暂存经过check后的单个数字,等待转为int
            lt=list(str(i))
            while j < len(lt):
                num_in_lt=int(lt[j])
                check=check_active_turn_180(num_in_lt)
                if check[0] == 3:
                    i += 1
                    break
                else:
                    lt_new.append(str(check[1]))
                j += 1
            if  check[0] ==3:  #如果出现无效数字,跳出本次一层循环,进行下一次
                continue
            else:#用于正常循环结束后
                i_new=int(''.join(lt_new))
            if i_new != i:
                count+=1
        i+=1
    return count

虽然通过了leetcode的测试,但是成绩着实辣眼睛

所以,在看了大神们的题解后,我看到了一个以我现在的python水平也能看得懂的答案。思路不同,但用的方法也很基础,没有涉及到我没学到的领域。

其代码如下:

def rotatedDigits(self, N):
    """
    :type N: int
    :rtype: int
    """
    changeDic = {
        '0' : '0',
        '1' : '1',
        '2' : '5',
        '5' : '2',
        '6' : '9',
        '8' : '8',
        '9' : '6'
    }
    result = 0
    for num in range(1, N + 1):
        num = str(num)
        value = ''.join([changeDic[x] for x in num if x in changeDic])
        if value != num and len(value) == len(num):
            result += 1
    return result

分析了这种题解后,我将之对比我的解题方法,其不同主要体现在以下几个方面:

  • 采用了字典储存,将字典的key值对应数字值,而value值则对应反转后的数字,基本上一个字典就完成了我的整个检查功能
  • 格式设置较我的程序大幅完善,一次循环中仅用到一次str转换

思考

在下次设计程序中要事先考虑到最合适的数据类型的选择,避免通过多次类型转换将程序复杂化,到最后自己也看不懂

posted @ 2019-07-25 18:25  Sheppard_xxx  阅读(761)  评论(0编辑  收藏  举报