JavaScript在数组中找到小于等于给定数字的第一个数字

时间:2018-11-24 21:07:27

标签: javascript lodash

我有一个素数数组:

const primes = [3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]

我想在此列表中找到第一个数字,即<=给定的数字。

例如... getHighestPrimeNumber(58) ...应该返回53,即最大数值也小于或等于58的素数

预期结果:

  

getHighestPrimeNumber(58)=== 53

     

getHighestPrimeNumber(53)=== 53

     

getHighestPrimeNumber(52)=== 47

我目前的方法是遍历素数,但这效率很低,特别是考虑到列表中可能有10,000+个数字-谢谢

香草JS或Lodash都很好

3 个答案:

答案 0 :(得分:4)

自从您使用lodash标签发布此标签以来,仅供参考,由于_.sortedIndex,此标签不重要

const primes = [3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]

const closestPrime = (n) => {
  let index = _.sortedIndex(primes, n)
  return primes[index] == n ? primes[index] : primes[index-1]
}

console.log(closestPrime(58))
console.log(closestPrime(53))
console.log(closestPrime(52))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

答案 1 :(得分:1)

对于binary search,这是一项好任务:

const bisect = (needle, haystack) => {
  let lo = 0;
  let hi = haystack.length;
  
  while (lo <= hi) {
    const mid = ~~((hi - lo) / 2 + lo);
    
    if (haystack[mid] === needle) {
      return needle;
    }
    else if (haystack[mid] > needle) {
      hi = mid - 1;
    }
    else {
      lo = mid + 1;      
    }
  }
  
  return haystack[hi];
};

const getHighestPrimeNumber = n => {
  const primes = [3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97];
  return bisect(n, primes);
};

console.log(getHighestPrimeNumber(58) === 53);
console.log(getHighestPrimeNumber(53) === 53);
console.log(getHighestPrimeNumber(52) === 47);

一些注意事项:

  • 您可能希望将素数数组作为getHighestPrimeNumber的参数,这样就不会在每次函数调用时都创建它并对其进行垃圾回收。此时,您最好直接调用二进制搜索。
  • 如果您担心数组边界上和边界下的查询,则可以根据某些策略进行处理,例如:return haystack[Math.min(hi,haystack.length-1)];
  • 二进制搜索的时间复杂度为O(n log(n))。集合查找为O(1),因此,如果您除了维护数组外还维护一个集合,并首先尝试在该位置进行查找,则可能会提高性能。

答案 2 :(得分:1)

似乎是分而治之的领域。类似于Binary search

const primes = [3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]

function findHighestPrimeNumberRecursive(arr, ceiling) {
  const midpoint = arr.length/2
  if(arr[midpoint ] === ceiling){
    // we found it!
    return primes[arr.length-1];
  } else {
    if(arr[midpoint] <== ceiling) {
      return findHighestPrimeNumberRecursive(arr.slice(0, midpoint), ceiling);
    } else {
      return findHighestPrimeNumberRecursive(arr.slice(midpoint, arr.length), ceiling);
    }
  }
}

function getHighestPrimeNumber(ceiling) {
  return findHighestPrimeNumberRecursive(primes, ceiling);
}