簡體   English   中英

查找所有可以表示為數組三個不同元素之和的數字

[英]Find all the numbers that can be represented as sum of three distinct elements of an array

您有一個包含N個不同的正整數的數組A。 您也有一個空的集合S。您的任務是添加盡可能多的整數以設置集合S。如果可以將整數表示為數組A的三個不同元素的和,並且不存在於集合S中,則可以將整數添加到集合S中。集合S。

示例-如果N = 5,並且數組包含2、4、6、8、9。則該集合包含9個元素-> 12,14,15,15,16,17,18,19,21,23

O(n ^ 3)方法很簡單,但是對於大型數組將花費很多時間。 有人可以提出解決此問題的有效方法嗎?

不知道我的解決方案是否真的比蠻力解決方案快(期望咯咯地笑和低聲投票)。 但是,我的解決方案使用動態編程...我認為:)

基本思想是問題(N,1)的解決方案很簡單。 輸入數組中每個1元組值的總和就是輸入數組。

問題(N,M)的解決方案可以通過簡單地映射(N,M-1)解決方案中的所有元素(類似於Map [Int] Int )來使用問題(N,M-1)的解決方案Map [Int] Int 現在,需要將(N,M-1)解決方案的特定元素中尚未使用的所有索引與(N,M-1)解決方案中的每個鍵以及(N,M -1)解決方案+未使用索引的值創建(N,M)解決方案的元素。

在這里,我們有遞歸。 以及我們對“更簡單”的結果(N,M-1)解決方案的記憶,用於解決(N,M)。 因此,我們進行了動態編程。 (遞歸+記憶=動態編程)。

使用我目前嘗試學習的語言(Haskell),我想到了這種實現方式(很多人可能認為它很丑陋;)

import Data.Array
import Data.List
import qualified Data.Map.Strict as Map


type Lut = Map.Map [Int] Int

foo :: Array Int Int -> Int -> Int -> Lut
-- This is our trivial base case. Create a map for the (N,1) case.
-- "input ! i" means what other languages would write as input[i].
foo input n 1 = Map.fromList [([i],input ! i) | i <- [1..n]]
-- This is the general case, which uses recursion.
foo input n m =
    (Map.fromList . fixKeys . concat . fmap sums) (Map.keys lut)
    where 
        lut :: Lut
        -- Here, the recursion happens. (lut stands for LookUp Table)
        lut = foo input n (m-1)
        all = [1..n]
        sums k =
            -- Here we use our (N,M-1) data to create the output
            -- for this recursion step. 
            -- (forall unused element indices do input[i] + lut[k])
            fmap (\(i,k) -> (i:k,input ! i + query k) ) unused
            where 
                -- The \\ means: difference. 
                -- All indices minus the indices used in a key of a (N,M-1) 
                -- element.
                unused = fmap (\i -> (i,k)) (all \\ k)

        query k =
            case Map.lookup k lut of
                Just v -> v
                Nothing -> error "key cannot not be in the map!"
        -- Remove duplicates (e.g. [1,2,3] and [1,3,2]) by sorting them.
        fixKeys l =
            fmap (\(k,v) -> (sort k,v)) l




to1BasedArray l = listArray (1,length l) l

raw = [2, 4, 6, 8, 9]
input = to1BasedArray raw 

output = foo input (length raw) 3

根據大眾的需求,這里是...的C ++版本:)

#include "stdafx.h"
#include <vector>
#include <map>
#include <algorithm> // sort()
#include <iostream>

typedef std::vector<int32_t> Data;
typedef std::vector<size_t> Key;
typedef std::map<Key, int32_t> Lut;

auto contains(const Key& indices, size_t index) -> bool
{
    for (auto x : indices)
    {
        if (x == index)
            return true;
    }
    return false;
}

auto unused(size_t n, const Key& k) -> Key
{
    Key result;
    result.reserve(n);
    for (size_t i = 1; i <= n; i++)
    {
        if (!contains(k, i))
        {
            result.push_back(i);
        }
    }
    return result;
}

// 'input' is a vector we use as 1-based (not 0 based) array.
auto foo(const Data& input, size_t n, size_t m) -> Lut
{
    Lut result;
    switch (m)
    {
    case 1:
        for (size_t i = 1; i <= n; i++)
        {
            Key k = { i };
            result[k] = input[i];
        }
        break;
    default:
        {
            Lut lut = foo(input, n, m - 1);
            for (const auto& kv : lut)
            {
                auto uns = unused(n, kv.first);
                for (auto i : uns)
                {
                    auto nk = Key(kv.first.begin(), kv.first.end());
                    nk.push_back(i);
                    std::sort(nk.begin(), nk.end());
                    result[nk] = kv.second + input[i];
                }
            }
        }
        break;
    }
    return result;
}

std::ostream& operator<<(std::ostream& os, const Key& values)
{
    bool first = true;
    os << "[";
    for (const auto v : values)
    {
        if (first)
        {
            os << v;
            first = false;
        }
        else
        {
            os << ", " << v;
        }
    }
    os << "]";
    return os;
}

int main()
{
    // leading 0 because it is a 1 based array.
    Data data = { 0, 2, 4, 6, 8, 9 }; 
    Lut result = foo(data, 5, 3);
    for (auto kv : result)
    {
        std::cout << kv.first << " = " << kv.second << std::endl;
    }
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM