【问题标题】:Most efficient method to check for range of numbers within number without duplicates检查数字内数字范围而不重复的最有效方法
【发布时间】:2015-12-28 03:33:36
【问题描述】:

给定一个数 n ,一个最小数 min ,一个最大数 max ,最有效的确定方法是什么

  1. 号码n 是否在范围内,包括min - max

  2. 号码n 是否包含重复号码

  3. 这里的效率意味着方法或方法集需要最少的计算资源并在最少的时间内返回truefalse

  4. 上下文:for 循环内if 的条件,可能需要数千到数十万次迭代才能返回结果;其中返回 truefalse 对于 Number 检查所需的毫秒数可能会影响性能

Profiles 面板DevTools 上的71,3307 迭代项目集合上,下面的RegExp 被列为使用27.2ms 的总1097.3ms 来完成循环。在836,7628 项目的集合中,RegExp 下面使用了193.5ms,总共有11285.3ms

要求:在最短的时间内返回Booleantruefalse的最有效方法。

注意:解决方案不必限于RegExp;下面用作返回预期结果的模式。


当前 js 使用 RegExp re , RegExp.protype.test()

var min = 2
, max = 7
, re = new RegExp("[" + min + "-" + max + "](.)(?!=\1)", "g")
, arr = [81, 35, 22, 45, 49];

for (var i = 0; i < arr.length; i++) {
  console.log(re.test(arr[i]), i, arr[i])
    /*
      false 0 81 
      true 1 35
      false 2 22
      true 3 45
      false 4 49 
    */
}

【问题讨论】:

  • 给你三个不...对吗?
  • 正则表达式不正确,需要转义反斜杠。 new RegExp("[" + min + "-" + max + "](.)(?!=\\1)", "g")
  • @MathewsMathai "给你三个不...对吗?"这个数字可以在两个数字之间;例如,25n 数字,例如,九个数字 271314892
  • @Tushar "正则表达式不正确,需要转义反斜杠。new RegExp("[" + min + "-" + max + "](.)(?!=\\1)", "g")" 其中\1 引用捕获组(.) stackoverflow.com/questions/21880127/… ?
  • @guest271314 如果要测试的数字有可能超出给定范围,这将检查数字是否在范围内,如果不在范围内,它将提前返回,以便保存下一个反向引用正则表达式(这是昂贵的)。

标签: javascript algorithm numbers


【解决方案1】:

关联数组方法:

这具有易于理解的优点。

function checkDigits(min, max, n) {
    var digits = Array(10);                   // Declare the length of the array (the 10 digits) to avoid any further memory allocation
    while (n) {
        d = (n % 10);                         // Get last digit
        n = n / 10 >>0;                       // Remove it from our number (the >>0 bit is equivalent to compose(Math.floor, Math.abs))
        if (d < min || d > max || digits[d])  // Test if "d" is outside the range or if it has been checked in the "digits" array
            return false;
        else
            digits[d] = true;                 // Mark the digit as existing
    }
}

var min = 2
, max = 7
, arr = [81, 35, 22, 45, 49];

function checkDigits(min, max, n) {
    var digits = Array(10);                   // Declare the length of the array (the 10 digits) to avoid any further memory allocation
    while (n) {
        d = (n % 10);                         // Get last digit
        n = n / 10 >>0;                       // Remove it from our number (the >>0 bit is equivalent to compose(Math.floor, Math.abs))
        if (d < min || d > max || digits[d])  // Test if "d" is outside the range or if it has been checked in the "digits" array
            return false;
        else
            digits[d] = true;                 // Mark the digit as existing
    }
    return true;
}

for (var i = 0; i < arr.length; i++) {
  console.log(checkDigits(min, max, arr[i]), i, arr[i])
}

二进制掩码方法:

这会将数组替换为实际上用作位数组的整数。它应该更快。

function checkDigits(min, max, n) {
    var digits = 0;                   
    while (n) {
        d = (n % 10);                         
        n = n / 10 >>0;
        if (d < min || d > max || (digits & (1 << d)))
            return false;
        else
            digits |= 1 << d;
    }
    return true;
}

function checkDigits(min, max, n) {
    var digits = 0;                   
    while (n) {
        d = (n % 10);                         
        n = n / 10 >>0;
        if (d < min || d > max || (digits & (1 << d)))
            return false;
        else
			digits |= 1 << d;
    }
    return true;
}

二进制掩码方法说明:

1 &lt;&lt; d 创建一个位掩码,这是一个整数,其中d 位已设置,所有其他位设置为 0。
digits |= 1 &lt;&lt; d 将位掩码标记的位设置为整数digits
digits &amp; (1 &lt;&lt; d) 将我们的位掩码标记的位与digits(先前标记位的集合)进行比较。
如果您想详细了解这一点,请参阅bitwise operators 上的文档。

所以,如果我们检查 626,我们的数字会是这样的:

________n_____626_______________
           |
        d  |  6
     mask  |  0001000000
   digits  |  0000000000
           |
________n_____62________________
           |
        d  |  2
     mask  |  0000000100
   digits  |  0001000000
           |
________n_____6_________________
           |
        d  |  6
     mask  |  0001000000
   digits  |  0001000100
                 ^
               bit was already set, return false

【讨论】:

  • 可以在js 包含cmets 描述方法吗?
  • @guest271314 完成了,如果还有什么不清楚的地方欢迎询问。
  • 为什么在声明三个参数的地方传了五个参数?
  • 检查括号,3个参数传递给checkDigits,其他为console.log
  • 这似乎是一个很好的答案...我将根据 OP 完成的性能测试和您的二进制方法在这里投票.....
【解决方案2】:

解决方案 1

使用正则表达式测试

var min = 2;
var max = 7;
res = "";
arr = [81, 35, 22, 45, 49]
arr.push("");
regex=new RegExp("[" + min + "-" + max + "](.)(?!=\1)", "g")
var result = arr.reduce(function(a, b) {
  if (regex.test(a)) {
    res = res + a + " is true\n"
  } else {
    res = res + a + " is false\n"
  };
  return b
});
console.log(res)

reduce 方法在某种意义上是不同的,它就像 python 中的生成器函数(即时生成输出)

它只是使用回调函数循环遍历数组中的每个元素。我不能说 reduce 函数的效率有多高。

不过考虑数组中的两个元素

81                             35          
^
take this value            take the result
and do something           from the previous 
                           element and add it
                           to the result computed
                           for this element  

更多信息https://msdn.microsoft.com/en-us/library/ff679975%28v=vs.94%29.aspx

解决方案 2

使用列表存储值及其布尔值

var min = 2;
var max = 7;
res = [""];
arr = [81, 35, 22, 45, 49]
arr.push("");
regex=new RegExp("[" + min + "-" + max + "](.)(?!=\1)", "g")
var result = arr.reduce(function(a, b) {
  if (regex.test(a)) {
    res.push([a,true])
  } else {
    res.push([a,false])
  };
  return b
});
console.log(res)

【讨论】:

  • 3545 应该返回 trueres 出现undefined ?
  • 我使用 2 和 7 作为最大值,我定义了 var min=2 和 var max =7..我进行了编辑
  • @reprezo 似乎从.reduce() 返回空字符串?预期返回值为Booleantruefalse
  • 输出是控制台中的日志......它返回“”,这是数组中的最后一个元素......输出也存储在变量“res”中......你可以打印这个...... ..确保在重新运行迭代器方法之前将变量 res 重置为 ""
  • 好的..我添加了另一个解决方案,其中值及其对应的布尔值存储在列表中......对我来说就是这样......晚安......:D
猜你喜欢
  • 2017-03-28
  • 1970-01-01
  • 1970-01-01
  • 2021-04-01
  • 2017-05-16
  • 2017-06-08
  • 2021-04-27
  • 1970-01-01
  • 2012-12-03
相关资源
最近更新 更多