获取字符串尾部数字的最快方法

时间:2010-09-30 10:37:19

标签: algorithm string

鉴于我们有这种字符串“XXXXXXX XXXXX 756”,“XXXXX XXXXXX35665”,(X是一个字符),这是在字符串末尾获取数字的禁食方式?

编辑:嗯,这只是一个有趣的问题。解决这个问题很简单,但我想知道最快的算法来归档这个。摇滚吧!

8 个答案:

答案 0 :(得分:4)

在C中,快速O(n),一次通过算法(看不到负号)是:

int suffixedNumber(char* string) {
  int result = 0;
  char ch;
  while (ch = *string++)
    // Check whether <= '9' first, because most characters are > '9'.
    result = (ch <= '9' && ch >= '0') ? 10*result + (ch - '0') : 0;
  return result;
}

如果你对goto你没问题,你可以得到一个快20%的算法(按重要性排序):

  1. string
  2. 末尾没有数字时返回-1
  3. 避免在ch >= '0'
  4. 时检查字符串结尾
  5. 避免在result为非数字
  6. 时将ch重置为零
  7. 避免在数字开始时将result乘以10
  8. 避免在开始时将result设置为零
  9. int suffixedNumber(char* string) {
      int result;
      char ch;
    
      nonnumber: // STATE: Waiting for the start of a number.
      ch = *string++;
      if (ch > '9') goto nonnumber; // Decide this boundary first (> '9' most frequent)
      if (ch < '0') {               // Decide this boundary next
        if (ch == '\0') return -1;  // Decide this boundary last  ('\0' least frequent)
        goto nonnumber;
      }
      result = ch - '0';
    
      number:    // STATE: In the middle of a number.
      ch = *string++;
      if (ch > '9') goto nonnumber;    // Decide this boundary first (> '9' most frequent)
      if (ch < '0') {                  // Decide this boundary next
        if (ch == '\0') return result; // Decide this boundary last  ('\0' least frequent)
        goto nonnumber;
      }
      result = 10*result + (ch - '0');
    
      goto number;
    }
    

答案 1 :(得分:1)

假设文本可以按相反顺序流式传输(合理的假设,因为大多数语言中的字符串都由具有O(1)访问权限的字符数组支持),请通过向后读取文本来构造数字,直到您点击一个字符这不是数字或文本已完全消耗。

numDigits = 0
number = 0

while(numDigits <> length and characterAt[length - numDigits] is a digit)
   number = number + (parseCharacterAt[length - numDigits] * (10 ^ numDigits))
   numDigits = numDigits + 1
end while

if(numDigits is 0)
  Error ("No digits at the end")

else return number

注意:(10 ^ numDigits)可以使用另一个变量进行简单优化。

答案 2 :(得分:0)

在不知道语言或上下文的情况下,如果数字或字符的数量是固定长度,则简单子字符串可以做,否则正则表达式匹配连续数字(即/\d+/)。

如果你下降到C ++级别,可能会有一些更快的算法,但我更喜欢表现力。

答案 3 :(得分:0)

使用正则表达式:

/^.+?(\d+)$/

并获取第一个匹配捕获组(\ d +)

修改 如果你不能使用正则表达式,最快的方式将是这样的:

i = string.len
while i > 0:
  break if string[i].isNotNum
  i--
end

out = substring(string, i,string.len)

答案 4 :(得分:0)

我只是调用String对象的lastIndexOf('X')并从那里继续。没有向后循环的混乱。

答案 5 :(得分:0)

陈述问题:

  

我们希望找到最后一位非数字字符的索引

的Reflexion:

  

这意味着我们检查此点后面的每个字符是否为数字,这意味着我们需要至少执行O(k)比较,其中k是字符串末尾的位数< / p>

实现:

  

线性向后搜索,可能涉及按位欺骗以“向量化”操作(一次比较多个字符)或利用多线程工作。

答案 6 :(得分:0)

绝对不要使用正则表达式 - 方式太慢。只需向后循环,直到找到第一个非数字字符:

string s = "XXXXX XXXXXX35665";
int i = s.Length;
while (--i >= 0 && Char.IsNumber(s[i]));
s=s.Substring(i + 1);

应该做的伎俩.. ??

答案 7 :(得分:0)

提取尾号

    str="XXXXXx....XXXX333"; 
    parseInt(str.match(/\d*$/)

如果浮点数需要

    parseInt(str.match(/\d|\.*$/)

增加尾号:

    str.replace(/(\d*)$/,function(){return parseInt(arguments[0])+1;})