[英]Java - find all combinations of three numbers in sorted array that have a sum smaller than a number
[英]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.