「小算法」回文数与数值合法性检验

喵喵喵,小夕最近准备复习一下数学和基础算法,尽量每篇推送下面会附带点数学和基础算法的小文章。说不定哪天就用(考)到了呢( ̄∇ ̄)注意哦,与头条位的文章推送不同,「小公式」和「小算法」里的小标题之间可能并无逻辑关联。

回文数

链接:https://leetcode.com/problems/palindrome-number/description/

判断一个整数是否是回文数是leetcode上的一个简单算法题。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

例1:

输入:121
输出:true

例2:

输入:-121
输出:false
解释:从右往左读为121-。

例3:

输入:10
输出:false

解这个题的话,一个很自然而简单的想法就是将整数转换为字符串,并检查字符串是否为回文。但是,这需要额外的非常量空间来创建问题描述中所不允许的字符串。

第二个想法是将数字本身反转,然后将反转后的数字与原始数字进行比较,如果它们是相同的,那么这个数字就是回文。 但是,如果反转后的数字大于 int.MAX,会发生数值溢出啦!

不过,按照第二个想法,为了避免数字反转可能导致的溢出问题,为什么不考虑只反转 int 数字的一半?毕竟如果该数字是回文,其后半部分反转后肯定与原始数字的前半部分相同的呀。

所以直接上代码(原谅我用python写\(//∇//)\)

class Solution(object):
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
        if x < 0 or (x != 0 and x % 10 == 0):
            return False
        invx = 0
        while invx < x:
            invx = invx * 10 + x % 10
            x //= 10
        return invx == x or invx // 10 == x

当然,得益于python自带大数运算的特性(即不存在撞枪int.MAX的情况),在python里直接用第二种方法解也是可以acc的。

class Solution(object):
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
        if x < 0:
            return False
        rawx = x
        invx = 0
        while x > 0:
            invx = invx * 10 + x % 10
            x //= 10
        return invx == rawx

数值合法性检验

链接:https://leetcode.com/problems/valid-number/description/

这个算法题是一个对初学者写到吐,对有基础的人写着玩儿的一道题。题目很简单,就是判断用户的输入(字符串形式)是不是一个合法的数值。这里合法的数值其实就是我们平常所说的数字啦,比如123,-1.0,+423,.4234,2.345e21都是合法数值。当然这里还允许用户在合法数值的前后插入若干空格。

这个问题如果直接用if else while生写的话会写到吐,而且极难debug。但是这个问题一个机智的做法就是直接上确定有限状态自动机(deterministic finite automation, DFA)

DFA是由

  1. 一个非空有限的状态集合Q

  2. 一个输入字母表(非空有限的字符集合)

  3. 一组转移函数(如)

  4. 一个开始状态

  5. 一个接受(终止)状态的集合

所组成的5元组。这个在编译原理、NLP基础里都有讲,忘了的同学自行补上哦。

所以很自然的这个题目画出的状态机如下图

有了状态机,代码就变得简洁多了。这里贴出python实现(来自leetcode讨论区,小夕在此题悲剧)

class Solution(object):
  def isNumber(self, s):
      """
      :type s: str
      :rtype: bool
      """
      #define a DFA
      state = [{}, 
              {'blank': 1, 'sign': 2, 'digit':3, '.':4}, 
              {'digit':3, '.':4},
              {'digit':3, '.':5, 'e':6, 'blank':9},
              {'digit':5},
              {'digit':5, 'e':6, 'blank':9},
              {'sign':7, 'digit':8},
              {'digit':8},
              {'digit':8, 'blank':9},
              {'blank':9}]
      currentState = 1
      for c in s:
          if c >= '0' and c <= '9':
              c = 'digit'
          if c == ' ':
              c = 'blank'
          if c in ['+', '-']:
              c = 'sign'
          if c not in state[currentState].keys():
              return False
          currentState = state[currentState][c]
      if currentState not in [3,5,8,9]:
          return False
      return True


嗯,就酱╮(╯▽╰)╭

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值