确定添加到另一个数组中任何数字的一个数组中的任何数字是否等于目标数

时间:2017-03-04 22:12:19

标签: javascript arrays algorithm

我在解决问题时遇到问题。我得到了2个数组和一个目标数字。

如果可以通过将第一个数组中的任何数字添加到第二个数组中的任何数字来创建目标数字,那么如何编写返回true的函数,否则会false

以下示例有效,但我想要一个更优化的解决方案。



var a = [1, 2, 3], b = [10, 20, 30, 40];

function sumOfTwo(a, b, v) {
  b = b.sort();

  for (var i = a.length - 1; i > 0; i--) {
    if (b.indexOf(v - a[i]) >= 0) {
      return true;
    }
  }
  return false
}

console.log(sumOfTwo(a, b, 42)); // true
console.log(sumOfTwo(a, b, 44)); // false




谢谢。

4 个答案:

答案 0 :(得分:1)

你可以使用它。

website.com/news

答案 1 :(得分:1)

您可以使用哈希表和两个循环。



function sumOfTwo(left, right, sum) {
    var hash = Object.create(null),
        i;

    for (i = 0; i < left.length; i++) {
        hash[sum - left[i]] = true;
    }
    for (i = 0; i < right.length; i++) {
        if (hash[right[i]]) {
            return true;
        }
    }
    return false;
}

var a = [1, 2, 3],
    b = [10, 20, 30, 40],
    v = 42;

console.log(sumOfTwo(a, b, 42));
&#13;
&#13;
&#13;

答案 2 :(得分:1)

您编码的方法具有O(n ^ 2)时间复杂度,因为对于在一个数组中访问的每个元素,调用indexOf,如果目标不是,则可以遍历整个第二个数组找到。以下是在O(n)时间内执行此检查的两种方法(其中一种方法需要对数组进行排序):

  1. 将其中一个数组的值存储为哈希映射(或集)中的键。然后迭代 其他数组并检查密钥(sum - a[i])是否在哈希映射中。

  2. 给定两个排序的数组,使用两个指针,一个从一个数组的末尾开始,另一个从第二个数组的开头开始。如果总和太小,则递增从一个数组的开头开始的指针。否则,如果总和太大,则减少从第二个数组末尾开始的指针。

答案 3 :(得分:1)

此方法假定已排序数据,因为提供的示例数据已排序。如果数据未排序,则需要从第二个循环中删除“大于”检查。

  • 如果第二个数组比第一个数组短,则交换数组。
  • 迭代第一个数组,每次迭代:
    • 将变量初始化为v的值减去当前元素的值。
    • 在每次迭代时迭代第二个数组:
      • 如果当前元素的值大于先前存储的值,则断开循环。
      • 如果当前元素的值等于先前存储的值,则返回true
    • 如果未找到匹配值,则返回false

const a = [1, 2, 3], b = [10, 20, 30, 40]

const sumOfTwo = (a, b, v) => {
  if (a.length > b.length) var b = t = a, a = t
  var vnum, ai, bi, al = a.length, bl = b.length
  for (ai = 0; ai < al; ai++) {
    vnum = v - a[ai]
    for (bi = 0; bi < bl; bi++) {
      if (b[bi] > vnum) break
      if (b[bi] == vnum) return true
    }
  }
  return false
}

// This is tests the function based on every integer from 1, 49
new Int32Array(50).forEach((e, i) => console.log(i, sumOfTwo(a, b, i)))

基准

我已经包含了两个基准测试,其中包括到目前为止提供的所有示例。一个带有排序数据,另一个带有未排序数据。我的计算机上每个基准测试生成的结果示例(Windows 7桌面上的Chrome稳定版)将显示在每个代码段上方,但我建议您运行基准测试,看看您的计算机上是否有不同的结果。

基准测试将多次运行。每个基准测试将使用两个输入数组和一个递增的输入数字。一个数组将定义为[1,3,5,7,9],另一个数组将定义为分别运行基准测试的100,1000,10000,100000和1000000个元素。第二个数组中的元素将增加10。

运行多个基准测试,因为给定算法在给定数量的元素上具有比在其他元素下更好的性能。

示例将采用以下格式:

["String", Boolean, Number, Number, Number, Number, Number]
  • 第一个元素是该示例作者的句柄。
  • 第二个要素是示例是否提供了正确的结果。
  • 剩余的Number元素是每秒的操作,其中第二个数组分别具有100,1000,10000,100000和1000000个元素

每秒操作数最高的示例是该数据集的最快示例。

对于以下测试,我必须稍微修改@ FatihYavus的示例以返回正确的结果,我必须从this JSPerf link中提取@גלעדברקן的示例,因为他们的答案中没有包含该示例。

排序数据

["גלעד ברקן",  true, 2596321, 2564350, 26323,  2305,   264]
["Tiny Giant",  true,  428615,   57129, 35887, 35855, 35788]
["Fatih Yavuz", true,  483956,   63193,  8946,   927,    92]
["Nina Scholz", true,  257122,   47083,  9479,  1472,   188]

const benchmark = (name, func) => new Promise((resolve, reject) => setTimeout(() => {
  const test = func => {
    const a = [1, 2, 3], b = [10, 20, 30, 40]
    const testArrayFactory = (m, e, i, arr) => Object.assign(arr, { [i]: func(a, b, i) })
    const testCheck = (e, i) => e === [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0][i]
    return new Int32Array(50).reduce(testArrayFactory).every(testCheck)
  }
  const inputArrayFactory = (m, e, i, a) => Object.assign(a, { [i]: i * 10 })
  const a = [1, 3, 5, 7, 9], m = 1000, r = [name, test(func)]
  for(let i = 2; i < 7; ++i) {
    const b = new Int32Array(10**i).reduce(inputArrayFactory), s = performance.now()
    let ops = 0
    while (performance.now() - s < m) func(a, b, ops++)
    r.push(parseInt((ops * m) / (performance.now() - s)))
  }
  resolve(r)
}))

const funcs = {
  "גלעד ברקן": (arr1,arr2,num) => {
    var p1 = 0, p2 = arr2.length - 1;

    while (p1 < arr1.length && p2 > -1){
      if (arr1[p1] + arr2[p2] === num)
        return true;
      if (arr1[p1] + arr2[p2] < num)
        p1++;
      else
        p2--;
    }
    return false;
  },
  "Tiny Giant": (a, b, v) => {
    if (a.length > b.length) var b = t = a, a = t
    var vnum, ai, bi, al = a.length, bl = b.length
    for (ai = 0; ai < al; ai++) {
      vnum = v - a[ai]
      for (bi = 0; bi < bl; bi++) {
        if (b[bi] > vnum) break
        if (b[bi] == vnum) return true
      }
    }
    return false
  },
  "Fatih Yavuz": (a, b, v) => {
    for (var i = 0; i < a.length; i++) {
      for (var j = 0; j < b.length; j++) {
        if (a[i] + b[j] == v) {
          return true;
        }
      }
    }
    return false;
  },
  "Nina Scholz": (left, right, sum) => {
    var hash = Object.create(null), i;
    for (i = 0; i < left.length; i++) {
      hash[sum - left[i]] = true;
    }
    for (i = 0; i < right.length; i++) {
      if (hash[right[i]]) {
        return true;
      }
    }
    return false;
  }
}

for (let key in funcs) benchmark(key, funcs[key]).then(v => console.log(JSON.stringify(v)))

未分类的数据

此基准使用已使用How to randomize (shuffle) a JavaScript array?

中提供的示例进行了混洗的数组
["גלעד ברקן",  true,  84753,  7534,   174,   10,   1]
["Tiny Giant",  true, 733737,105199, 13473, 1440, 133]
["Fatih Yavuz", true, 488651, 63840,  8349,  812,  78]
["Nina Scholz", true, 225331, 41079,  6898, 1137, 115]

// https://stackoverflow.com/a/2450976/4639281
function shuffle(array) {
  var currentIndex = array.length, temporaryValue, randomIndex;
  while (0 !== currentIndex) {
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }
  return array;
}

const benchmark = (name, func) => new Promise((resolve, reject) => setTimeout(() => {
  const test = func => {
    const a = [1, 2, 3], b = [10, 20, 30, 40]
    const testArrayFactory = (m, e, i, arr) => Object.assign(arr, { [i]: func(a, b, i) })
    const testCheck = (e, i) => e === [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0][i]
    return new Int32Array(50).reduce(testArrayFactory).every(testCheck)
  }
  const inputArrayFactory = (m, e, i, a) => Object.assign(a, { [i]: i * 10 })
  const a = shuffle([1, 3, 5, 7, 9]), m = 1000, r = [name, test(func)]
  for(let i = 2; i < 7; ++i) {
    const b = shuffle(new Int32Array(10**i).reduce(inputArrayFactory)), s = performance.now()
    let ops = 0
    while (performance.now() - s < m) func(a, b, ops++)
    r.push(parseInt((ops * m) / (performance.now() - s)))
  }
  resolve(r)
}))

const funcs = {
  "גלעד ברקן": (arr1,arr2,num) => {
    var p1 = 0, p2 = arr2.length - 1;
    arr1 = arr1.sort((a, b) => a - b);
    arr2 = arr2.sort((a, b) => a - b);

    while (p1 < arr1.length && p2 > -1){
      if (arr1[p1] + arr2[p2] === num)
        return true;
      if (arr1[p1] + arr2[p2] < num)
        p1++;
      else
        p2--;
    }
    return false;
  },
  "Tiny Giant": (a, b, v) => {
    if (a.length > b.length) var b = t = a, a = t
    var vnum, ai, bi, al = a.length, bl = b.length
    for (ai = 0; ai < al; ai++) {
      vnum = v - a[ai]
      for (bi = 0; bi < bl; bi++) {
        // if (b[bi] > vnum) break
        if (b[bi] == vnum) return true
      }
    }
    return false
  },
  "Fatih Yavuz": (a, b, v) => {
    for (var i = 0; i < a.length; i++) {
      for (var j = 0; j < b.length; j++) {
        if (a[i] + b[j] == v) {
          return true;
        }
      }
    }
    return false;
  },
  "Nina Scholz": (left, right, sum) => {
    var hash = Object.create(null), i;
    for (i = 0; i < left.length; i++) {
      hash[sum - left[i]] = true;
    }
    for (i = 0; i < right.length; i++) {
      if (hash[right[i]]) {
        return true;
      }
    }
    return false;
  }
}

for (let key in funcs) benchmark(key, funcs[key]).then(v => console.log(JSON.stringify(v)))