如何在javascript或3sum中计算3个元素的总和?

Posted

技术标签:

【中文标题】如何在javascript或3sum中计算3个元素的总和?【英文标题】:how to calculate the sum of 3 element in javascript or 3sum? 【发布时间】:2020-05-07 00:25:35 【问题描述】:

我正在努力解决这个问题

给定一个由 n 个整数组成的数组 nums,在 nums 中是否存在元素 a、b、c 使得 a + b + c = 0?查找数组中所有唯一的三元组,其总和为零。

 var threeSum = function(nums) 
    let result = [],
        target = 0;
    if(nums.length < 3) return result;

    nums.sort((a,b)=>a-b);
    console.log(nums);
    for (let i = 0; i < nums.length -2 ; i++) 

        if(nums[i] > target) break;
        if( i > 0&& nums[i] == nums[i-1]) continue;
        let j = i + 1;

        let k = nums.length - 1;

        while (j < k)
            let sum = nums[i] + nums[j] + nums[k];
            if(sum === target)
                result.push([nums[i,nums[j],nums[k]]])
                j++;
                k--
            else if(sum < target)
                j++
            else 
                k--
            

        
    

return result

;

输入输出

Given array nums = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

当我调用我的函数时

console.log(threeSum([-1, 0, 1, 2, -1, -4]))

我收到stack overflow exception

【问题讨论】:

如果(sum === target) 的计算结果为true,您将陷入无限循环,但在每次迭代中,都会将另一个元素推入result 堆栈。顺便说一句,有一个错字,是`result.push([nums[i],nums[j],nums[k]]),对吧? 好的..!!有更好的方法来实现这一点。 查看我更新的代码仍然没有得到预期的输出 【参考方案1】:

这里有一个解决方案 .. 不是最佳的,但有效...

let nums = [-1, 0, 1, 2, -1, -4];


function findTriples(arr, t)
    let target = [];
    for(let i=0; i<arr.length; i++)

        for(let j=0; j<arr.length; j++)
    
            for(let k=0; k<arr.length; k++)
                
                if((arr[i] + arr[j] + arr[k]) == t)
                    target.push([arr[i], arr[j], arr[k]]);
                
            
    
        

    
    
    target = target.map(a => a.sort()).map(i => i.join(","));
    target = [...new Set(target)];
    return target.map(i => i.split(","));


console.log(findTriples(nums, 0));

【讨论】:

【参考方案2】:

一个不太考虑效率的有点幼稚的解决方案将给定数组拆分为负数和非负数数组。

总和为 0 的三元组必须正好有 2 个负数或 2 个非负数,(0,0,0) 除外。

因此,如果求反的和是相应另一个数组的元素,则检查从负数或非负数中提取的所有对,如果成立,则添加三元组。

记住在上述步骤中选择的单个数字可以防止结果数组中的重复。

function threeSum (nums) 
    let result = []
      , an_pos = []
      , an_neg = []
      , bdict_seen = 
      , n_gotcha
      , n_zerocount = 0
      ;

    // Shortcut for short arrays ...
    console.log ( nums + ' ...' );
    if ( nums.length < 3) 
        console.log('... []');
        return result;
    

    // Partition source array into negatives and non-negatives
    nums.forEach ( (pn_number) => 
        if ( pn_number < 0) 
            an_neg.push(pn_number);
         else 
            an_pos.push(pn_number);
            if (pn_number === 0)  n_zerocount++; 
        
    );
    
    // 2 negatives, 1 non-negative
    for (let i = 0; i < an_neg.length-1; i++) 
        for (let j = i+1; j < an_neg.length; j++) 
            if (n_gotcha = an_pos.find ( pn_pos => pn_pos === -(an_neg[i] + an_neg[j]) )) 
                if (!bdict_seen[n_gotcha]) 
                    result.push ( [an_neg[i], an_neg[j], n_gotcha] );
                    bdict_seen[n_gotcha] = true;
                
            
        
            

    // 2 non-negatives, 1 negative
    for (let i = 0; i < an_pos.length-1; i++) 
        for (let j = i+1; j < an_pos.length; j++) 
            if (n_gotcha = an_neg.find ( pn_neg => pn_neg === -(an_pos[i] + an_pos[j]) )) 
                if (!bdict_seen[n_gotcha]) 
                    result.push ( [an_pos[i], an_pos[j], n_gotcha] );
                    bdict_seen[n_gotcha] = true;
                
            
        
            

    // Special case: triple-0
    if (n_zerocount >= 3) 
        result.push ( [0,0,0] );
    

    // Sorting not needed but added for a more readable output 
    result.sort ( (a,b) => a-b );
    console.log('... ' + JSON.stringify(result));
    
    return result;
 // threeSum


threeSum ( [-1, 0, 1, 2, -1, -4] );

【讨论】:

【参考方案3】:

我们可以实现solver 来接受一个数字数组并遍历pchooseN(3, nums) 的所有可能性。当sum(p) 等于0 时,产生p -

const solver = function* (nums = [])
 for (const p of chooseN(3, nums))
    if (sum(p) === 0)
      yield p


const result =
  Array.from(solver([-1, 0, 1, 2, -1, -4]))

console.log(result)
// [[-1, 0, 1], [-1, 2, -1], [0, 1, -1]]

现在我们实现sumchooseN -

const sum = (nums = []) =>
  nums.reduce((r, num) => r + num, 0)

const chooseN = function* (n = 0, iter = [])
 const loop = function* (r, m, i)
   if (m === 0) return yield r
    if (i >= iter.length) return
    yield* loop([...r, iter[i]], m - 1, i + 1)
    yield* loop(r, m, i + 1)
  
  yield* loop([], n, 0)

在下面的浏览器中运行代码 -

const sum = (nums = []) =>
  nums.reduce((r, num) => r + num, 0)
  
const chooseN = function* (n = 0, iter = [])
 const loop = function* (r, m, i)
   if (m === 0) return yield r
    if (i >= iter.length) return
    yield* loop([...r, iter[i]], m - 1, i + 1)
    yield* loop(r, m, i + 1)
  
  yield* loop([], n, 0)


const solver = function* (nums = [])
 for (const p of chooseN(3, nums))
    if (sum(p) === 0)
      yield p


const result =
  Array.from(solver([-1, 0, 1, 2, -1, -4]))

console.log(JSON.stringify(result))
// [[-1,0,1],[-1,2,-1],[0,1,-1]]

如果您还没有了解 javascript 的生成器,请不要担心。您也可以使用直接样式来执行此操作 -

const chooseN = (n = 0, [ x, ...more ], r = []) =>
  n <= 0                          // base
    ? [r]
: x === undefined                 // inductive: n > 0
    ? []
: chooseN(n - 1, more, [...r, x]) // inductive: n > 0, iterable is not empty
    .concat(chooseN(n, more, r))

const sum = (nums = []) =>
  nums.reduce((r, num) => r + num, 0)

const solver = (nums = []) =>
  chooseN(3, nums)
    .filter(p => sum(p) === 0)

const result =
  solver([-1, 0, 1, 2, -1, -4])

console.log(JSON.stringify(result))
// [[-1,0,1],[-1,2,-1],[0,1,-1]]

【讨论】:

以上是关于如何在javascript或3sum中计算3个元素的总和?的主要内容,如果未能解决你的问题,请参考以下文章

我如何在Javascript中拥有可变长度数组的前3个元素[重复]

Javascript如何改变数组的长度?

Javascript如何改变数组的长度?

如何在 unordered_map 中插入 3 个元素或其他奇数个元素?

如何从javascript或jquery中的元素数组中删除特定元素

计算元素列表的 Javascript 像素宽度