आप दिए गए N
संख्याओं के जोड़ के सभी संभावित संयोजनों के परीक्षण के बारे में कैसे जाएंगे ताकि वे किसी अंतिम संख्या में जोड़ दें?
एक संक्षिप्त उदाहरण:
- जोड़ने के लिए संख्याओं का समूह:
N = {1,5,22,15,0,...}
- वांछित परिणाम:
12345
आप दिए गए N
संख्याओं के जोड़ के सभी संभावित संयोजनों के परीक्षण के बारे में कैसे जाएंगे ताकि वे किसी अंतिम संख्या में जोड़ दें?
एक संक्षिप्त उदाहरण:
N = {1,5,22,15,0,...}
12345
जवाबों:
इस समस्या को उन सभी संभावित रकमों के पुनरावर्ती संयोजनों के साथ हल किया जा सकता है जो लक्ष्य तक पहुंचते हैं। यहाँ अजगर में एल्गोरिथ्म है:
def subset_sum(numbers, target, partial=[]):
s = sum(partial)
# check if the partial sum is equals to target
if s == target:
print "sum(%s)=%s" % (partial, target)
if s >= target:
return # if we reach the number why bother to continue
for i in range(len(numbers)):
n = numbers[i]
remaining = numbers[i+1:]
subset_sum(remaining, target, partial + [n])
if __name__ == "__main__":
subset_sum([3,9,8,4,5,7,10],15)
#Outputs:
#sum([3, 8, 4])=15
#sum([3, 5, 7])=15
#sum([8, 7])=15
#sum([5, 10])=15
इस प्रकार के एल्गोरिदम को निम्नलिखित स्टैंडफोर्ड के सार प्रोग्रामिंग व्याख्यान में बहुत अच्छी तरह से समझाया गया है - यह वीडियो यह समझने के लिए बहुत अनुशंसित है कि समाधान की क्रमपरिवर्तन उत्पन्न करने के लिए कैसे पुनरावर्तन कार्य करता है।
संपादित करें
एक जनरेटर फ़ंक्शन के रूप में ऊपर, यह थोड़ा अधिक उपयोगी बनाता है। के कारण अजगर 3.3+ की आवश्यकता है yield from
।
def subset_sum(numbers, target, partial=[], partial_sum=0):
if partial_sum == target:
yield partial
if partial_sum >= target:
return
for i, n in enumerate(numbers):
remaining = numbers[i + 1:]
yield from subset_sum(remaining, target, partial + [n], partial_sum + n)
यहाँ एक ही एल्गोरिथ्म का जावा संस्करण है:
package tmp;
import java.util.ArrayList;
import java.util.Arrays;
class SumSet {
static void sum_up_recursive(ArrayList<Integer> numbers, int target, ArrayList<Integer> partial) {
int s = 0;
for (int x: partial) s += x;
if (s == target)
System.out.println("sum("+Arrays.toString(partial.toArray())+")="+target);
if (s >= target)
return;
for(int i=0;i<numbers.size();i++) {
ArrayList<Integer> remaining = new ArrayList<Integer>();
int n = numbers.get(i);
for (int j=i+1; j<numbers.size();j++) remaining.add(numbers.get(j));
ArrayList<Integer> partial_rec = new ArrayList<Integer>(partial);
partial_rec.add(n);
sum_up_recursive(remaining,target,partial_rec);
}
}
static void sum_up(ArrayList<Integer> numbers, int target) {
sum_up_recursive(numbers,target,new ArrayList<Integer>());
}
public static void main(String args[]) {
Integer[] numbers = {3,9,8,4,5,7,10};
int target = 15;
sum_up(new ArrayList<Integer>(Arrays.asList(numbers)),target);
}
}
यह ठीक उसी तरह का अनुमान है। मेरा जावा थोड़ा कठोर है लेकिन मुझे लगता है कि इसे समझना आसान है।
जावा समाधान का C # रूपांतरण: (@JeremyThompson द्वारा)
public static void Main(string[] args)
{
List<int> numbers = new List<int>() { 3, 9, 8, 4, 5, 7, 10 };
int target = 15;
sum_up(numbers, target);
}
private static void sum_up(List<int> numbers, int target)
{
sum_up_recursive(numbers, target, new List<int>());
}
private static void sum_up_recursive(List<int> numbers, int target, List<int> partial)
{
int s = 0;
foreach (int x in partial) s += x;
if (s == target)
Console.WriteLine("sum(" + string.Join(",", partial.ToArray()) + ")=" + target);
if (s >= target)
return;
for (int i = 0; i < numbers.Count; i++)
{
List<int> remaining = new List<int>();
int n = numbers[i];
for (int j = i + 1; j < numbers.Count; j++) remaining.Add(numbers[j]);
List<int> partial_rec = new List<int>(partial);
partial_rec.Add(n);
sum_up_recursive(remaining, target, partial_rec);
}
}
रूबी समाधान: (@emaillenin द्वारा)
def subset_sum(numbers, target, partial=[])
s = partial.inject 0, :+
# check if the partial sum is equals to target
puts "sum(#{partial})=#{target}" if s == target
return if s >= target # if we reach the number why bother to continue
(0..(numbers.length - 1)).each do |i|
n = numbers[i]
remaining = numbers.drop(i+1)
subset_sum(remaining, target, partial + [n])
end
end
subset_sum([3,9,8,4,5,7,10],15)
संपादित करें: जटिलता चर्चा
जैसा कि अन्य उल्लेख करते हैं कि यह एक एनपी-कठिन समस्या है । यह घातीय समय O (2 ^ n) में हल किया जा सकता है, उदाहरण के लिए n = 10 के लिए 1024 संभव समाधान होंगे। यदि आप जिन लक्ष्यों तक पहुंचने की कोशिश कर रहे हैं, वे कम रेंज में हैं तो यह एल्गोरिथम काम करता है। उदाहरण के लिए:
subset_sum([1,2,3,4,5,6,7,8,9,10],100000)
1024 शाखाएँ उत्पन्न करता है क्योंकि लक्ष्य कभी संभव समाधानों को फ़िल्टर करने के लिए नहीं मिलता है।
दूसरी ओर subset_sum([1,2,3,4,5,6,7,8,9,10],10)
केवल 175 शाखाएँ उत्पन्न करती हैं, क्योंकि पहुँचने का लक्ष्य 10
कई संयोजनों को फ़िल्टर करना है।
यदि N
और Target
बड़ी संख्या में हैं, तो समाधान के एक अनुमानित संस्करण में जाना चाहिए।
[1, 2, 0, 6, -3, 3], 3
- यह केवल [1,2], [0,3], [3]
गुमशुदा मामलों जैसे कि[6, -3, 3]
[1, 2, 5], 5
केवल आउटपुट [5]
, कब [1, 1, 1, 1, 1]
, [2, 2, 1]
और [2, 1, 1, 1]
समाधान हैं।
i+1
है remaining = numbers[i+1:]
। ऐसा लगता है कि एल्गोरिथ्म डुप्लिकेट की अनुमति नहीं देता है।
[1, 1, 3]
पर एक नज़र है
इस समस्या का समाधान इंटरनेट पर एक मिलियन बार दिया गया है। समस्या को सिक्का बदलने की समस्या कहा जाता है । कोई व्यक्ति http://rosettacode.org/wiki/Count_the_coins और इसके गणितीय मॉडल http://jaqm.ro/issues/volume-5,issue-2/pdfs/patterson_harmel.pdf (या Google सिक्का परिवर्तन) पर समाधान पा सकता है समस्या )।
वैसे, त्सगाडाई द्वारा स्काला समाधान, दिलचस्प है। यह उदाहरण 1 या 0. पैदा करता है। साइड इफेक्ट के रूप में, यह कंसोल पर सभी संभावित समाधानों को सूचीबद्ध करता है। यह समाधान प्रदर्शित करता है, लेकिन इसे किसी भी तरह से उपयोग करने योग्य नहीं बनाता है।
जितना संभव हो उतना उपयोगी होने के लिए, कोड को List[List[Int]]
समाधान की संख्या (सूचियों की सूची की लंबाई), "सर्वश्रेष्ठ" समाधान (सबसे छोटी सूची), या सभी संभव समाधान प्राप्त करने की अनुमति देने के लिए वापस लौटना चाहिए ।
यहाँ एक उदाहरण है। यह बहुत अक्षम है, लेकिन इसे समझना आसान है।
object Sum extends App {
def sumCombinations(total: Int, numbers: List[Int]): List[List[Int]] = {
def add(x: (Int, List[List[Int]]), y: (Int, List[List[Int]])): (Int, List[List[Int]]) = {
(x._1 + y._1, x._2 ::: y._2)
}
def sumCombinations(resultAcc: List[List[Int]], sumAcc: List[Int], total: Int, numbers: List[Int]): (Int, List[List[Int]]) = {
if (numbers.isEmpty || total < 0) {
(0, resultAcc)
} else if (total == 0) {
(1, sumAcc :: resultAcc)
} else {
add(sumCombinations(resultAcc, sumAcc, total, numbers.tail), sumCombinations(resultAcc, numbers.head :: sumAcc, total - numbers.head, numbers))
}
}
sumCombinations(Nil, Nil, total, numbers.sortWith(_ > _))._2
}
println(sumCombinations(15, List(1, 2, 5, 10)) mkString "\n")
}
जब चलता है, तो यह प्रदर्शित होता है:
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2)
List(1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2)
List(1, 1, 1, 1, 1, 2, 2, 2, 2, 2)
List(1, 1, 1, 2, 2, 2, 2, 2, 2)
List(1, 2, 2, 2, 2, 2, 2, 2)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5)
List(1, 1, 1, 1, 1, 1, 1, 1, 2, 5)
List(1, 1, 1, 1, 1, 1, 2, 2, 5)
List(1, 1, 1, 1, 2, 2, 2, 5)
List(1, 1, 2, 2, 2, 2, 5)
List(2, 2, 2, 2, 2, 5)
List(1, 1, 1, 1, 1, 5, 5)
List(1, 1, 1, 2, 5, 5)
List(1, 2, 2, 5, 5)
List(5, 5, 5)
List(1, 1, 1, 1, 1, 10)
List(1, 1, 1, 2, 10)
List(1, 2, 2, 10)
List(5, 10)
sumCombinations()
समारोह अपने आप में इस्तेमाल किया जा सकता है, और परिणाम आगे "सर्वश्रेष्ठ" समाधान (कम से कम सूची), या समाधान की संख्या (सूचियों की संख्या) प्रदर्शित करने के लिए विश्लेषण किया जा सकता है।
ध्यान दें कि इस तरह भी, आवश्यकताओं को पूरी तरह से संतुष्ट नहीं किया जा सकता है। ऐसा हो सकता है कि समाधान में प्रत्येक सूची का क्रम महत्वपूर्ण हो। ऐसे मामले में, प्रत्येक सूची को कई बार नकल करना होगा क्योंकि इसके तत्वों के संयोजन हैं। या हम केवल उन संयोजनों में दिलचस्पी ले सकते हैं जो अलग हैं।
उदाहरण के लिए, हम विचार कर सकते हैं कि List(5, 10)
दो संयोजन देने चाहिए: List(5, 10)
और List(10, 5)
। इसके List(5, 5, 5)
लिए आवश्यकताओं के आधार पर तीन संयोजन या केवल एक ही दे सकता है। पूर्णांक के लिए, तीन क्रमांकन समतुल्य हैं, लेकिन अगर हम सिक्कों के साथ काम कर रहे हैं, जैसे "सिक्का बदलने की समस्या" में, वे नहीं हैं।
आवश्यकताओं में भी नहीं कहा गया है कि क्या प्रत्येक नंबर (या सिक्का) का उपयोग केवल एक बार या कई बार किया जा सकता है। हम कर सकते हैं (और हमें चाहिए!) प्रत्येक संख्या की घटनाओं की सूची की समस्या को सामान्य करें। यह वास्तविक जीवन में "सिक्के के एक सेट (और सिक्के के मूल्यों का एक सेट नहीं) के साथ एक निश्चित राशि बनाने के लिए संभावित तरीके क्या हैं" में अनुवाद करता है। मूल समस्या केवल इस एक का एक विशेष मामला है, जहाँ हमारे पास प्रत्येक सिक्के के मूल्य के साथ कुल राशि बनाने के लिए आवश्यकतानुसार प्रत्येक सिक्के की कई घटनाएं हैं।
में हास्केल :
filter ((==) 12345 . sum) $ subsequences [1,5,22,15,0,..]
और जे :
(]#~12345=+/@>)(]<@#~[:#:@i.2^#)1 5 22 15 0 ...
जैसा कि आप देख सकते हैं, दोनों एक ही दृष्टिकोण लेते हैं और समस्या को दो भागों में विभाजित करते हैं: पावर सेट के प्रत्येक सदस्य को उत्पन्न करते हैं, और प्रत्येक सदस्य की राशि को लक्ष्य पर जाँचते हैं।
अन्य समाधान हैं लेकिन यह सबसे सीधा है।
क्या आपको किसी एक के साथ या एक अलग दृष्टिकोण खोजने में मदद की ज़रूरत है?
not in scope: 'subsequences'
कोई संकेत?
import Data.List
एक जावास्क्रिप्ट संस्करण:
function subsetSum(numbers, target, partial) {
var s, n, remaining;
partial = partial || [];
// sum partial
s = partial.reduce(function (a, b) {
return a + b;
}, 0);
// check if the partial sum is equals to target
if (s === target) {
console.log("%s=%s", partial.join("+"), target)
}
if (s >= target) {
return; // if we reach the number why bother to continue
}
for (var i = 0; i < numbers.length; i++) {
n = numbers[i];
remaining = numbers.slice(i + 1);
subsetSum(remaining, target, partial.concat([n]));
}
}
subsetSum([3,9,8,4,5,7,10],15);
// output:
// 3+8+4=15
// 3+5+7=15
// 8+7=15
// 5+10=15
remaining = numbers.slice();
remaining.slice(i + 1);
अन्यथा numbers.slice(i + 1);
संख्याओं को
slice
रिटर्न (उथली) प्रति, यह numbers
सरणी को संशोधित नहीं करता है ।
उसी एल्गोरिथ्म का C ++ संस्करण
#include <iostream>
#include <list>
void subset_sum_recursive(std::list<int> numbers, int target, std::list<int> partial)
{
int s = 0;
for (std::list<int>::const_iterator cit = partial.begin(); cit != partial.end(); cit++)
{
s += *cit;
}
if(s == target)
{
std::cout << "sum([";
for (std::list<int>::const_iterator cit = partial.begin(); cit != partial.end(); cit++)
{
std::cout << *cit << ",";
}
std::cout << "])=" << target << std::endl;
}
if(s >= target)
return;
int n;
for (std::list<int>::const_iterator ai = numbers.begin(); ai != numbers.end(); ai++)
{
n = *ai;
std::list<int> remaining;
for(std::list<int>::const_iterator aj = ai; aj != numbers.end(); aj++)
{
if(aj == ai)continue;
remaining.push_back(*aj);
}
std::list<int> partial_rec=partial;
partial_rec.push_back(n);
subset_sum_recursive(remaining,target,partial_rec);
}
}
void subset_sum(std::list<int> numbers,int target)
{
subset_sum_recursive(numbers,target,std::list<int>());
}
int main()
{
std::list<int> a;
a.push_back (3); a.push_back (9); a.push_back (8);
a.push_back (4);
a.push_back (5);
a.push_back (7);
a.push_back (10);
int n = 15;
//std::cin >> n;
subset_sum(a, n);
return 0;
}
@Msalvadores कोड उत्तर का # संस्करण
void Main()
{
int[] numbers = {3,9,8,4,5,7,10};
int target = 15;
sum_up(new List<int>(numbers.ToList()),target);
}
static void sum_up_recursive(List<int> numbers, int target, List<int> part)
{
int s = 0;
foreach (int x in part)
{
s += x;
}
if (s == target)
{
Console.WriteLine("sum(" + string.Join(",", part.Select(n => n.ToString()).ToArray()) + ")=" + target);
}
if (s >= target)
{
return;
}
for (int i = 0;i < numbers.Count;i++)
{
var remaining = new List<int>();
int n = numbers[i];
for (int j = i + 1; j < numbers.Count;j++)
{
remaining.Add(numbers[j]);
}
var part_rec = new List<int>(part);
part_rec.Add(n);
sum_up_recursive(remaining,target,part_rec);
}
}
static void sum_up(List<int> numbers, int target)
{
sum_up_recursive(numbers,target,new List<int>());
}
मैंने सोचा कि मैं इस प्रश्न का उत्तर दूंगा, लेकिन मैं ऐसा नहीं कर सका, इसलिए यहाँ मेरा उत्तर है। यह कंप्यूटर प्रोग्राम की संरचना और व्याख्या में एक उत्तर के संशोधित संस्करण का उपयोग कर रहा है । मुझे लगता है कि यह एक बेहतर पुनरावर्ती समाधान है और अधिक शुद्धतावादियों को खुश करना चाहिए।
मेरा जवाब स्काला में है (और माफी अगर मेरा स्काला बेकार है, तो मैंने इसे सीखना शुरू कर दिया है)। FindSumCombinations पागलपन प्रत्यावर्तन ड्यूप्स को रोकने के लिए के लिए तरह और अद्वितीय मूल सूची में है।
def findSumCombinations(target: Int, numbers: List[Int]): Int = {
cc(target, numbers.distinct.sortWith(_ < _), List())
}
def cc(target: Int, numbers: List[Int], solution: List[Int]): Int = {
if (target == 0) {println(solution); 1 }
else if (target < 0 || numbers.length == 0) 0
else
cc(target, numbers.tail, solution)
+ cc(target - numbers.head, numbers, numbers.head :: solution)
}
इसके प्रयेाग के लिए:
> findSumCombinations(12345, List(1,5,22,15,0,..))
* Prints a whole heap of lists that will sum to the target *
Thank you.. ephemient
मैंने अजगर से php तक तर्क से ऊपर रूपांतरण किया है।
<?php
$data = array(array(2,3,5,10,15),array(4,6,23,15,12),array(23,34,12,1,5));
$maxsum = 25;
print_r(bestsum($data,$maxsum)); //function call
function bestsum($data,$maxsum)
{
$res = array_fill(0, $maxsum + 1, '0');
$res[0] = array(); //base case
foreach($data as $group)
{
$new_res = $res; //copy res
foreach($group as $ele)
{
for($i=0;$i<($maxsum-$ele+1);$i++)
{
if($res[$i] != 0)
{
$ele_index = $i+$ele;
$new_res[$ele_index] = $res[$i];
$new_res[$ele_index][] = $ele;
}
}
}
$res = $new_res;
}
for($i=$maxsum;$i>0;$i--)
{
if($res[$i]!=0)
{
return $res[$i];
break;
}
}
return array();
}
?>
एक और अजगर समाधान itertools.combinations
मॉड्यूल का उपयोग इस प्रकार होगा:
#!/usr/local/bin/python
from itertools import combinations
def find_sum_in_list(numbers, target):
results = []
for x in range(len(numbers)):
results.extend(
[
combo for combo in combinations(numbers ,x)
if sum(combo) == target
]
)
print results
if __name__ == "__main__":
find_sum_in_list([3,9,8,4,5,7,10], 15)
आउटपुट: [(8, 7), (5, 10), (3, 8, 4), (3, 5, 7)]
यहाँ आर में एक समाधान है
subset_sum = function(numbers,target,partial=0){
if(any(is.na(partial))) return()
s = sum(partial)
if(s == target) print(sprintf("sum(%s)=%s",paste(partial[-1],collapse="+"),target))
if(s > target) return()
for( i in seq_along(numbers)){
n = numbers[i]
remaining = numbers[(i+1):length(numbers)]
subset_sum(remaining,target,c(partial,n))
}
}
subset_sum(numbers = c(1:2), target = 5)
रिटर्न "sum(1+2+2)=5"
। लेकिन संयोजन 1 + 1 + 1 + 1 + 1 गायब है। उच्चतर संख्याओं (जैसे 20) के लिए लक्ष्य निर्धारित करना और भी संयोजनों को याद कर रहा है।
subset_sum(1:2, 4)
कोई समाधान नहीं लौटाना चाहिए क्योंकि 1 और 2 का कोई संयोजन नहीं है जो 4 में जोड़ता है। मेरे फ़ंक्शन में जोड़े जाने की आवश्यकता क्या है, यदि बच गया है i
लंबाई से अधिक होने परnumbers
यहां एक जावा संस्करण है जो छोटे एन और बहुत बड़े लक्ष्य योग के लिए अच्छी तरह से अनुकूल है, जब जटिलता O(t*N)
(गतिशील समाधान) घातीय एल्गोरिदम से अधिक है। मेरा संस्करण बीच के हमले में एक मुलाकात का उपयोग करता है, साथ ही क्लासिक भोलेपन से जटिलता को कम करने के लिए थोड़ा सा बदलाव O(n*2^n)
करता है O(2^(n/2))
।
यदि आप 32 और 64 तत्वों के बीच के सेट के लिए इसका उपयोग करना चाहते हैं, तो आपको int
चरण फ़ंक्शन में वर्तमान सबसेट का प्रतिनिधित्व करने वाले को बदलना चाहिए long
हालांकि प्रदर्शन स्पष्ट रूप से बहुत कम हो जाएगा क्योंकि सेट आकार बढ़ता है। यदि आप विषम संख्या वाले तत्वों के सेट के लिए इसका उपयोग करना चाहते हैं, तो आपको इसे क्रमांकित बनाने के लिए सेट में 0 जोड़ना चाहिए।
import java.util.ArrayList;
import java.util.List;
public class SubsetSumMiddleAttack {
static final int target = 100000000;
static final int[] set = new int[]{ ... };
static List<Subset> evens = new ArrayList<>();
static List<Subset> odds = new ArrayList<>();
static int[][] split(int[] superSet) {
int[][] ret = new int[2][superSet.length / 2];
for (int i = 0; i < superSet.length; i++) ret[i % 2][i / 2] = superSet[i];
return ret;
}
static void step(int[] superSet, List<Subset> accumulator, int subset, int sum, int counter) {
accumulator.add(new Subset(subset, sum));
if (counter != superSet.length) {
step(superSet, accumulator, subset + (1 << counter), sum + superSet[counter], counter + 1);
step(superSet, accumulator, subset, sum, counter + 1);
}
}
static void printSubset(Subset e, Subset o) {
String ret = "";
for (int i = 0; i < 32; i++) {
if (i % 2 == 0) {
if ((1 & (e.subset >> (i / 2))) == 1) ret += " + " + set[i];
}
else {
if ((1 & (o.subset >> (i / 2))) == 1) ret += " + " + set[i];
}
}
if (ret.startsWith(" ")) ret = ret.substring(3) + " = " + (e.sum + o.sum);
System.out.println(ret);
}
public static void main(String[] args) {
int[][] superSets = split(set);
step(superSets[0], evens, 0,0,0);
step(superSets[1], odds, 0,0,0);
for (Subset e : evens) {
for (Subset o : odds) {
if (e.sum + o.sum == target) printSubset(e, o);
}
}
}
}
class Subset {
int subset;
int sum;
Subset(int subset, int sum) {
this.subset = subset;
this.sum = sum;
}
}
यह एक सिक्का बदलने की समस्या के समान है
public class CoinCount
{
public static void main(String[] args)
{
int[] coins={1,4,6,2,3,5};
int count=0;
for (int i=0;i<coins.length;i++)
{
count=count+Count(9,coins,i,0);
}
System.out.println(count);
}
public static int Count(int Sum,int[] coins,int index,int curSum)
{
int count=0;
if (index>=coins.length)
return 0;
int sumNow=curSum+coins[index];
if (sumNow>Sum)
return 0;
if (sumNow==Sum)
return 1;
for (int i= index+1;i<coins.length;i++)
count+=Count(Sum,coins,i,sumNow);
return count;
}
}
बहुत कुशल एल्गोरिथ्म का उपयोग करते हुए मैंने एक साल पहले सी ++ युगल में लिखा था।
यदि आप PRINT 1 सेट करते हैं, तो यह सभी संयोजनों को प्रिंट करेगा (लेकिन यह कुशल विधि का उपयोग नहीं करेगा)।
यह इतना कुशल है कि यह 10ms से कम में 10 ^ 14 से अधिक संयोजनों की गणना करता है।
#include <stdio.h>
#include <stdlib.h>
//#include "CTime.h"
#define SUM 300
#define MAXNUMsSIZE 30
#define PRINT 0
long long CountAddToSum(int,int[],int,const int[],int);
void printr(const int[], int);
long long table1[SUM][MAXNUMsSIZE];
int main()
{
int Nums[]={3,4,5,6,7,9,13,11,12,13,22,35,17,14,18,23,33,54};
int sum=SUM;
int size=sizeof(Nums)/sizeof(int);
int i,j,a[]={0};
long long N=0;
//CTime timer1;
for(i=0;i<SUM;++i)
for(j=0;j<MAXNUMsSIZE;++j)
table1[i][j]=-1;
N = CountAddToSum(sum,Nums,size,a,0); //algorithm
//timer1.Get_Passd();
//printf("\nN=%lld time=%.1f ms\n", N,timer1.Get_Passd());
printf("\nN=%lld \n", N);
getchar();
return 1;
}
long long CountAddToSum(int s, int arr[],int arrsize, const int r[],int rsize)
{
static int totalmem=0, maxmem=0;
int i,*rnew;
long long result1=0,result2=0;
if(s<0) return 0;
if (table1[s][arrsize]>0 && PRINT==0) return table1[s][arrsize];
if(s==0)
{
if(PRINT) printr(r, rsize);
return 1;
}
if(arrsize==0) return 0;
//else
rnew=(int*)malloc((rsize+1)*sizeof(int));
for(i=0;i<rsize;++i) rnew[i]=r[i];
rnew[rsize]=arr[arrsize-1];
result1 = CountAddToSum(s,arr,arrsize-1,rnew,rsize);
result2 = CountAddToSum(s-arr[arrsize-1],arr,arrsize,rnew,rsize+1);
table1[s][arrsize]=result1+result2;
free(rnew);
return result1+result2;
}
void printr(const int r[], int rsize)
{
int lastr=r[0],count=0,i;
for(i=0; i<rsize;++i)
{
if(r[i]==lastr)
count++;
else
{
printf(" %d*%d ",count,lastr);
lastr=r[i];
count=1;
}
}
if(r[i-1]==lastr) printf(" %d*%d ",count,lastr);
printf("\n");
}
नीचे एक्सेल VBA संस्करण। मुझे वीबीए में इसे लागू करने की आवश्यकता थी (मेरी प्राथमिकता नहीं, मुझे जज मत करो!), और दृष्टिकोण के लिए इस पृष्ठ पर उत्तर का उपयोग किया। मैं दूसरों के VBA संस्करण की भी आवश्यकता होने पर अपलोड कर रहा हूँ।
Option Explicit
Public Sub SumTarget()
Dim numbers(0 To 6) As Long
Dim target As Long
target = 15
numbers(0) = 3: numbers(1) = 9: numbers(2) = 8: numbers(3) = 4: numbers(4) = 5
numbers(5) = 7: numbers(6) = 10
Call SumUpTarget(numbers, target)
End Sub
Public Sub SumUpTarget(numbers() As Long, target As Long)
Dim part() As Long
Call SumUpRecursive(numbers, target, part)
End Sub
Private Sub SumUpRecursive(numbers() As Long, target As Long, part() As Long)
Dim s As Long, i As Long, j As Long, num As Long
Dim remaining() As Long, partRec() As Long
s = SumArray(part)
If s = target Then Debug.Print "SUM ( " & ArrayToString(part) & " ) = " & target
If s >= target Then Exit Sub
If (Not Not numbers) <> 0 Then
For i = 0 To UBound(numbers)
Erase remaining()
num = numbers(i)
For j = i + 1 To UBound(numbers)
AddToArray remaining, numbers(j)
Next j
Erase partRec()
CopyArray partRec, part
AddToArray partRec, num
SumUpRecursive remaining, target, partRec
Next i
End If
End Sub
Private Function ArrayToString(x() As Long) As String
Dim n As Long, result As String
result = "{" & x(n)
For n = LBound(x) + 1 To UBound(x)
result = result & "," & x(n)
Next n
result = result & "}"
ArrayToString = result
End Function
Private Function SumArray(x() As Long) As Long
Dim n As Long
SumArray = 0
If (Not Not x) <> 0 Then
For n = LBound(x) To UBound(x)
SumArray = SumArray + x(n)
Next n
End If
End Function
Private Sub AddToArray(arr() As Long, x As Long)
If (Not Not arr) <> 0 Then
ReDim Preserve arr(0 To UBound(arr) + 1)
Else
ReDim Preserve arr(0 To 0)
End If
arr(UBound(arr)) = x
End Sub
Private Sub CopyArray(destination() As Long, source() As Long)
Dim n As Long
If (Not Not source) <> 0 Then
For n = 0 To UBound(source)
AddToArray destination, source(n)
Next n
End If
End Sub
आउटपुट (तत्काल विंडो में लिखा जाना चाहिए):
SUM ( {3,8,4} ) = 15
SUM ( {3,5,7} ) = 15
SUM ( {8,7} ) = 15
SUM ( {5,10} ) = 15
बेहतर आउटपुट स्वरूपण और C ++ 11 सुविधाओं के साथ यहां एक बेहतर संस्करण है:
void subset_sum_rec(std::vector<int> & nums, const int & target, std::vector<int> & partialNums)
{
int currentSum = std::accumulate(partialNums.begin(), partialNums.end(), 0);
if (currentSum > target)
return;
if (currentSum == target)
{
std::cout << "sum([";
for (auto it = partialNums.begin(); it != std::prev(partialNums.end()); ++it)
cout << *it << ",";
cout << *std::prev(partialNums.end());
std::cout << "])=" << target << std::endl;
}
for (auto it = nums.begin(); it != nums.end(); ++it)
{
std::vector<int> remaining;
for (auto it2 = std::next(it); it2 != nums.end(); ++it2)
remaining.push_back(*it2);
std::vector<int> partial = partialNums;
partial.push_back(*it);
subset_sum_rec(remaining, target, partial);
}
}
जावा गैर-पुनरावर्ती संस्करण जो बस तत्वों को जोड़ता रहता है और उन्हें संभावित मूल्यों के बीच पुनर्वितरित करता है। 0
तय सूचियों को अनदेखा किया जाता है और काम किया जाता है (जो आपको दिया जाता है वही आप के साथ खेल सकते हैं) या दोहराने योग्य संख्याओं की सूची।
import java.util.*;
public class TestCombinations {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>(Arrays.asList(0, 1, 2, 2, 5, 10, 20));
LinkedHashSet<Integer> targets = new LinkedHashSet<Integer>() {{
add(4);
add(10);
add(25);
}};
System.out.println("## each element can appear as many times as needed");
for (Integer target: targets) {
Combinations combinations = new Combinations(numbers, target, true);
combinations.calculateCombinations();
for (String solution: combinations.getCombinations()) {
System.out.println(solution);
}
}
System.out.println("## each element can appear only once");
for (Integer target: targets) {
Combinations combinations = new Combinations(numbers, target, false);
combinations.calculateCombinations();
for (String solution: combinations.getCombinations()) {
System.out.println(solution);
}
}
}
public static class Combinations {
private boolean allowRepetitions;
private int[] repetitions;
private ArrayList<Integer> numbers;
private Integer target;
private Integer sum;
private boolean hasNext;
private Set<String> combinations;
/**
* Constructor.
*
* @param numbers Numbers that can be used to calculate the sum.
* @param target Target value for sum.
*/
public Combinations(ArrayList<Integer> numbers, Integer target) {
this(numbers, target, true);
}
/**
* Constructor.
*
* @param numbers Numbers that can be used to calculate the sum.
* @param target Target value for sum.
*/
public Combinations(ArrayList<Integer> numbers, Integer target, boolean allowRepetitions) {
this.allowRepetitions = allowRepetitions;
if (this.allowRepetitions) {
Set<Integer> numbersSet = new HashSet<>(numbers);
this.numbers = new ArrayList<>(numbersSet);
} else {
this.numbers = numbers;
}
this.numbers.removeAll(Arrays.asList(0));
Collections.sort(this.numbers);
this.target = target;
this.repetitions = new int[this.numbers.size()];
this.combinations = new LinkedHashSet<>();
this.sum = 0;
if (this.repetitions.length > 0)
this.hasNext = true;
else
this.hasNext = false;
}
/**
* Calculate and return the sum of the current combination.
*
* @return The sum.
*/
private Integer calculateSum() {
this.sum = 0;
for (int i = 0; i < repetitions.length; ++i) {
this.sum += repetitions[i] * numbers.get(i);
}
return this.sum;
}
/**
* Redistribute picks when only one of each number is allowed in the sum.
*/
private void redistribute() {
for (int i = 1; i < this.repetitions.length; ++i) {
if (this.repetitions[i - 1] > 1) {
this.repetitions[i - 1] = 0;
this.repetitions[i] += 1;
}
}
if (this.repetitions[this.repetitions.length - 1] > 1)
this.repetitions[this.repetitions.length - 1] = 0;
}
/**
* Get the sum of the next combination. When 0 is returned, there's no other combinations to check.
*
* @return The sum.
*/
private Integer next() {
if (this.hasNext && this.repetitions.length > 0) {
this.repetitions[0] += 1;
if (!this.allowRepetitions)
this.redistribute();
this.calculateSum();
for (int i = 0; i < this.repetitions.length && this.sum != 0; ++i) {
if (this.sum > this.target) {
this.repetitions[i] = 0;
if (i + 1 < this.repetitions.length) {
this.repetitions[i + 1] += 1;
if (!this.allowRepetitions)
this.redistribute();
}
this.calculateSum();
}
}
if (this.sum.compareTo(0) == 0)
this.hasNext = false;
}
return this.sum;
}
/**
* Calculate all combinations whose sum equals target.
*/
public void calculateCombinations() {
while (this.hasNext) {
if (this.next().compareTo(target) == 0)
this.combinations.add(this.toString());
}
}
/**
* Return all combinations whose sum equals target.
*
* @return Combinations as a set of strings.
*/
public Set<String> getCombinations() {
return this.combinations;
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder("" + sum + ": ");
for (int i = 0; i < repetitions.length; ++i) {
for (int j = 0; j < repetitions[i]; ++j) {
stringBuilder.append(numbers.get(i) + " ");
}
}
return stringBuilder.toString();
}
}
}
नमूना इनपुट:
numbers: 0, 1, 2, 2, 5, 10, 20
targets: 4, 10, 25
नमूना उत्पादन:
## each element can appear as many times as needed
4: 1 1 1 1
4: 1 1 2
4: 2 2
10: 1 1 1 1 1 1 1 1 1 1
10: 1 1 1 1 1 1 1 1 2
10: 1 1 1 1 1 1 2 2
10: 1 1 1 1 2 2 2
10: 1 1 2 2 2 2
10: 2 2 2 2 2
10: 1 1 1 1 1 5
10: 1 1 1 2 5
10: 1 2 2 5
10: 5 5
10: 10
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2
25: 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2
25: 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2
25: 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2
25: 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2
25: 1 1 1 2 2 2 2 2 2 2 2 2 2 2
25: 1 2 2 2 2 2 2 2 2 2 2 2 2
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 5
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 5
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 5
25: 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 5
25: 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 5
25: 1 1 1 1 1 1 1 1 2 2 2 2 2 2 5
25: 1 1 1 1 1 1 2 2 2 2 2 2 2 5
25: 1 1 1 1 2 2 2 2 2 2 2 2 5
25: 1 1 2 2 2 2 2 2 2 2 2 5
25: 2 2 2 2 2 2 2 2 2 2 5
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 5
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 2 5 5
25: 1 1 1 1 1 1 1 1 1 1 1 2 2 5 5
25: 1 1 1 1 1 1 1 1 1 2 2 2 5 5
25: 1 1 1 1 1 1 1 2 2 2 2 5 5
25: 1 1 1 1 1 2 2 2 2 2 5 5
25: 1 1 1 2 2 2 2 2 2 5 5
25: 1 2 2 2 2 2 2 2 5 5
25: 1 1 1 1 1 1 1 1 1 1 5 5 5
25: 1 1 1 1 1 1 1 1 2 5 5 5
25: 1 1 1 1 1 1 2 2 5 5 5
25: 1 1 1 1 2 2 2 5 5 5
25: 1 1 2 2 2 2 5 5 5
25: 2 2 2 2 2 5 5 5
25: 1 1 1 1 1 5 5 5 5
25: 1 1 1 2 5 5 5 5
25: 1 2 2 5 5 5 5
25: 5 5 5 5 5
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 10
25: 1 1 1 1 1 1 1 1 1 1 1 1 1 2 10
25: 1 1 1 1 1 1 1 1 1 1 1 2 2 10
25: 1 1 1 1 1 1 1 1 1 2 2 2 10
25: 1 1 1 1 1 1 1 2 2 2 2 10
25: 1 1 1 1 1 2 2 2 2 2 10
25: 1 1 1 2 2 2 2 2 2 10
25: 1 2 2 2 2 2 2 2 10
25: 1 1 1 1 1 1 1 1 1 1 5 10
25: 1 1 1 1 1 1 1 1 2 5 10
25: 1 1 1 1 1 1 2 2 5 10
25: 1 1 1 1 2 2 2 5 10
25: 1 1 2 2 2 2 5 10
25: 2 2 2 2 2 5 10
25: 1 1 1 1 1 5 5 10
25: 1 1 1 2 5 5 10
25: 1 2 2 5 5 10
25: 5 5 5 10
25: 1 1 1 1 1 10 10
25: 1 1 1 2 10 10
25: 1 2 2 10 10
25: 5 10 10
25: 1 1 1 1 1 20
25: 1 1 1 2 20
25: 1 2 2 20
25: 5 20
## each element can appear only once
4: 2 2
10: 1 2 2 5
10: 10
25: 1 2 2 20
25: 5 20
एक्सेल का उपयोग करके संयोजनों को खोजने के लिए - (इसकी काफी आसान)। (आपको कंप्यूटर बहुत धीमा नहीं होना चाहिए)
"Sum to Target" एक्सेल फ़ाइल डाउनलोड करें।
वेबसाइट पेज पर दिए गए निर्देशों का पालन करें।
उम्मीद है की यह मदद करेगा।
जावा समाधान के स्विफ्ट 3 रूपांतरण: (@JeremyThompson द्वारा)
protocol _IntType { }
extension Int: _IntType {}
extension Array where Element: _IntType {
func subsets(to: Int) -> [[Element]]? {
func sum_up_recursive(_ numbers: [Element], _ target: Int, _ partial: [Element], _ solution: inout [[Element]]) {
var sum: Int = 0
for x in partial {
sum += x as! Int
}
if sum == target {
solution.append(partial)
}
guard sum < target else {
return
}
for i in stride(from: 0, to: numbers.count, by: 1) {
var remaining = [Element]()
for j in stride(from: i + 1, to: numbers.count, by: 1) {
remaining.append(numbers[j])
}
var partial_rec = [Element](partial)
partial_rec.append(numbers[i])
sum_up_recursive(remaining, target, partial_rec, &solution)
}
}
var solutions = [[Element]]()
sum_up_recursive(self, to, [Element](), &solutions)
return solutions.count > 0 ? solutions : nil
}
}
उपयोग:
let numbers = [3, 9, 8, 4, 5, 7, 10]
if let solution = numbers.subsets(to: 15) {
print(solution) // output: [[3, 8, 4], [3, 5, 7], [8, 7], [5, 10]]
} else {
print("not possible")
}
इसका उपयोग सभी उत्तरों को प्रिंट करने के लिए भी किया जा सकता है
public void recur(int[] a, int n, int sum, int[] ans, int ind) {
if (n < 0 && sum != 0)
return;
if (n < 0 && sum == 0) {
print(ans, ind);
return;
}
if (sum >= a[n]) {
ans[ind] = a[n];
recur(a, n - 1, sum - a[n], ans, ind + 1);
}
recur(a, n - 1, sum, ans, ind);
}
public void print(int[] a, int n) {
for (int i = 0; i < n; i++)
System.out.print(a[i] + " ");
System.out.println();
}
समय जटिलता घातीय है। 2 ^ एन का आदेश
मैं एक स्कैला असाइनमेंट के लिए कुछ ऐसा ही कर रहा था। यहाँ मेरे समाधान पोस्ट करने की बात:
def countChange(money: Int, coins: List[Int]): Int = {
def getCount(money: Int, remainingCoins: List[Int]): Int = {
if(money == 0 ) 1
else if(money < 0 || remainingCoins.isEmpty) 0
else
getCount(money, remainingCoins.tail) +
getCount(money - remainingCoins.head, remainingCoins)
}
if(money == 0 || coins.isEmpty) 0
else getCount(money, coins)
}
मैंने C # नमूने को Objective-c में पोर्ट किया और प्रतिक्रियाओं में नहीं देखा:
//Usage
NSMutableArray* numberList = [[NSMutableArray alloc] init];
NSMutableArray* partial = [[NSMutableArray alloc] init];
int target = 16;
for( int i = 1; i<target; i++ )
{ [numberList addObject:@(i)]; }
[self findSums:numberList target:target part:partial];
//*******************************************************************
// Finds combinations of numbers that add up to target recursively
//*******************************************************************
-(void)findSums:(NSMutableArray*)numbers target:(int)target part:(NSMutableArray*)partial
{
int s = 0;
for (NSNumber* x in partial)
{ s += [x intValue]; }
if (s == target)
{ NSLog(@"Sum[%@]", partial); }
if (s >= target)
{ return; }
for (int i = 0;i < [numbers count];i++ )
{
int n = [numbers[i] intValue];
NSMutableArray* remaining = [[NSMutableArray alloc] init];
for (int j = i + 1; j < [numbers count];j++)
{ [remaining addObject:@([numbers[j] intValue])]; }
NSMutableArray* partRec = [[NSMutableArray alloc] initWithArray:partial];
[partRec addObject:@(n)];
[self findSums:remaining target:target part:partRec];
}
}
@ किथबेलर का उत्तर थोड़ा बदले हुए चर नामों और कुछ टिप्पणियों के साथ।
public static void Main(string[] args)
{
List<int> input = new List<int>() { 3, 9, 8, 4, 5, 7, 10 };
int targetSum = 15;
SumUp(input, targetSum);
}
public static void SumUp(List<int> input, int targetSum)
{
SumUpRecursive(input, targetSum, new List<int>());
}
private static void SumUpRecursive(List<int> remaining, int targetSum, List<int> listToSum)
{
// Sum up partial
int sum = 0;
foreach (int x in listToSum)
sum += x;
//Check sum matched
if (sum == targetSum)
Console.WriteLine("sum(" + string.Join(",", listToSum.ToArray()) + ")=" + targetSum);
//Check sum passed
if (sum >= targetSum)
return;
//Iterate each input character
for (int i = 0; i < remaining.Count; i++)
{
//Build list of remaining items to iterate
List<int> newRemaining = new List<int>();
for (int j = i + 1; j < remaining.Count; j++)
newRemaining.Add(remaining[j]);
//Update partial list
List<int> newListToSum = new List<int>(listToSum);
int currentItem = remaining[i];
newListToSum.Add(currentItem);
SumUpRecursive(newRemaining, targetSum, newListToSum);
}
}'
PHP संस्करण , केथ बेलर के सी # संस्करण से प्रेरित है।
बाला के PHP संस्करण ने मेरे लिए काम नहीं किया, क्योंकि मुझे समूह संख्याओं की आवश्यकता नहीं थी। मैं एक लक्ष्य मूल्य और संख्याओं के एक पूल के साथ एक सरल कार्यान्वयन चाहता था। यह फ़ंक्शन किसी भी डुप्लिकेट प्रविष्टियों को भी prune करेगा।
/**
* Calculates a subset sum: finds out which combinations of numbers
* from the numbers array can be added together to come to the target
* number.
*
* Returns an indexed array with arrays of number combinations.
*
* Example:
*
* <pre>
* $matches = subset_sum(array(5,10,7,3,20), 25);
* </pre>
*
* Returns:
*
* <pre>
* Array
* (
* [0] => Array
* (
* [0] => 3
* [1] => 5
* [2] => 7
* [3] => 10
* )
* [1] => Array
* (
* [0] => 5
* [1] => 20
* )
* )
* </pre>
*
* @param number[] $numbers
* @param number $target
* @param array $part
* @return array[number[]]
*/
function subset_sum($numbers, $target, $part=null)
{
// we assume that an empty $part variable means this
// is the top level call.
$toplevel = false;
if($part === null) {
$toplevel = true;
$part = array();
}
$s = 0;
foreach($part as $x)
{
$s = $s + $x;
}
// we have found a match!
if($s == $target)
{
sort($part); // ensure the numbers are always sorted
return array(implode('|', $part));
}
// gone too far, break off
if($s >= $target)
{
return null;
}
$matches = array();
$totalNumbers = count($numbers);
for($i=0; $i < $totalNumbers; $i++)
{
$remaining = array();
$n = $numbers[$i];
for($j = $i+1; $j < $totalNumbers; $j++)
{
$remaining[] = $numbers[$j];
}
$part_rec = $part;
$part_rec[] = $n;
$result = subset_sum($remaining, $target, $part_rec);
if($result)
{
$matches = array_merge($matches, $result);
}
}
if(!$toplevel)
{
return $matches;
}
// this is the top level function call: we have to
// prepare the final result value by stripping any
// duplicate results.
$matches = array_unique($matches);
$result = array();
foreach($matches as $entry)
{
$result[] = explode('|', $entry);
}
return $result;
}
उत्तर के रूप में अनुशंसित:
यहाँ es2015 जनरेटर का उपयोग कर एक समाधान है :
function* subsetSum(numbers, target, partial = [], partialSum = 0) {
if(partialSum === target) yield partial
if(partialSum >= target) return
for(let i = 0; i < numbers.length; i++){
const remaining = numbers.slice(i + 1)
, n = numbers[i]
yield* subsetSum(remaining, target, [...partial, n], partialSum + n)
}
}
जनरेटर का उपयोग करना वास्तव में बहुत उपयोगी हो सकता है क्योंकि यह आपको एक मान्य सबसेट खोजने पर तुरंत स्क्रिप्ट निष्पादन को रोक देता है। यह जनरेटर के बिना समाधान के विपरीत है (अर्थात राज्य की कमी) जिसके हर एक सबसेट के माध्यम से पुनरावृति होती हैnumbers
पहले स्थान पर 0 को कम करें। ज़ीरो इसके अलावा एक पहचान है, इसलिए इस विशेष मामले में यह मोनोइड कानूनों द्वारा बेकार है। यदि आप एक सकारात्मक संख्या पर चढ़ना चाहते हैं तो नकारात्मक संख्या भी घटा सकते हैं। अन्यथा आपको घटाव संचालन की भी आवश्यकता होगी।
तो ... इस विशेष नौकरी पर आप सबसे तेज़ एल्गोरिथम प्राप्त कर सकते हैं जो जेएस में दिए गए हैं।
function items2T([n,...ns],t){
var c = ~~(t/n);
return ns.length ? Array(c+1).fill()
.reduce((r,_,i) => r.concat(items2T(ns, t-n*i).map(s => Array(i).fill(n).concat(s))),[])
: t % n ? []
: [Array(c).fill(n)];
};
var data = [3, 9, 8, 4, 5, 7, 10],
result;
console.time("combos");
result = items2T(data, 15);
console.timeEnd("combos");
console.log(JSON.stringify(result));
यह एक बहुत ही तेजी से एल्गोरिथ्म है लेकिन अगर आप को सॉर्ट data
सरणी उतरते यह भी तेजी से किया जाएगा। .sort()
एल्गोरिथ्म बहुत कम पुनरावर्ती इनवोकेशन के साथ समाप्त हो जाएगा क्योंकि का उपयोग करना नगण्य है ।
पर्ल संस्करण (अग्रणी उत्तर का):
use strict;
sub subset_sum {
my ($numbers, $target, $result, $sum) = @_;
print 'sum('.join(',', @$result).") = $target\n" if $sum == $target;
return if $sum >= $target;
subset_sum([@$numbers[$_ + 1 .. $#$numbers]], $target,
[@{$result||[]}, $numbers->[$_]], $sum + $numbers->[$_])
for (0 .. $#$numbers);
}
subset_sum([3,9,8,4,5,7,10,6], 15);
परिणाम:
sum(3,8,4) = 15
sum(3,5,7) = 15
sum(9,6) = 15
sum(8,7) = 15
sum(4,5,6) = 15
sum(5,10) = 15
जावास्क्रिप्ट संस्करण:
const subsetSum = (numbers, target, partial = [], sum = 0) => {
if (sum < target)
numbers.forEach((num, i) =>
subsetSum(numbers.slice(i + 1), target, partial.concat([num]), sum + num));
else if (sum == target)
console.log('sum(%s) = %s', partial.join(), target);
}
subsetSum([3,9,8,4,5,7,10,6], 15);
जावास्क्रिप्ट वन-लाइनर जो वास्तव में परिणाम लौटाता है (इसे प्रिंट करने के बजाय):
const subsetSum=(n,t,p=[],s=0,r=[])=>(s<t?n.forEach((l,i)=>subsetSum(n.slice(i+1),t,[...p,l],s+l,r)):s==t?r.push(p):0,r);
console.log(subsetSum([3,9,8,4,5,7,10,6], 15));
और मेरे पसंदीदा, वन-लाइनर कॉलबैक के साथ:
const subsetSum=(n,t,cb,p=[],s=0)=>s<t?n.forEach((l,i)=>subsetSum(n.slice(i+1),t,cb,[...p,l],s+l)):s==t?cb(p):0;
subsetSum([3,9,8,4,5,7,10,6], 15, console.log);
function solve(n){
let DP = [];
DP[0] = DP[1] = DP[2] = 1;
DP[3] = 2;
for (let i = 4; i <= n; i++) {
DP[i] = DP[i-1] + DP[i-3] + DP[i-4];
}
return DP[n]
}
console.log(solve(5))
यह जेएस के लिए एक डायनामिक सॉल्यूशन है, जिसमें बताया गया है कि किसी को कितने योग हैं। यदि आप समय और स्थान की जटिलता के बारे में सोचते हैं तो यह सही समाधान हो सकता है।
import java.util.*;
public class Main{
int recursionDepth = 0;
private int[][] memo;
public static void main(String []args){
int[] nums = new int[] {5,2,4,3,1};
int N = nums.length;
Main main = new Main();
main.memo = new int[N+1][N+1];
main._findCombo(0, N-1,nums, 8, 0, new LinkedList() );
System.out.println(main.recursionDepth);
}
private void _findCombo(
int from,
int to,
int[] nums,
int targetSum,
int currentSum,
LinkedList<Integer> list){
if(memo[from][to] != 0) {
currentSum = currentSum + memo[from][to];
}
if(currentSum > targetSum) {
return;
}
if(currentSum == targetSum) {
System.out.println("Found - " +list);
return;
}
recursionDepth++;
for(int i= from ; i <= to; i++){
list.add(nums[i]);
memo[from][i] = currentSum + nums[i];
_findCombo(i+1, to,nums, targetSum, memo[from][i], list);
list.removeLast();
}
}
}
मुझे जावास्क्रिप्ट सॉल्यूशन पसंद नहीं था, मैंने देखा कि मैं आंशिक अप्लाई, क्लोजर और रिकर्सन का उपयोग करके अपने आप को क्यों बनाता हूं:
ठीक है, मैं मुख्य रूप से इस बारे में चिंतित था कि क्या संयोजन सरणी आवश्यकता लक्ष्य को संतुष्ट कर सकती है, लेकिन इस दृष्टिकोण के साथ आप बाकी संयोजनों को ढूंढना शुरू कर सकते हैं
यहां सिर्फ लक्ष्य निर्धारित करें और संयोजन सरणी पास करें।
function main() {
const target = 10
const getPermutationThatSumT = setTarget(target)
const permutation = getPermutationThatSumT([1, 4, 2, 5, 6, 7])
console.log( permutation );
}
वर्तमान में कार्यान्वयन मैं साथ आया था
function setTarget(target) {
let partial = [];
return function permute(input) {
let i, removed;
for (i = 0; i < input.length; i++) {
removed = input.splice(i, 1)[0];
partial.push(removed);
const sum = partial.reduce((a, b) => a + b)
if (sum === target) return partial.slice()
if (sum < target) permute(input)
input.splice(i, 0, removed);
partial.pop();
}
return null
};
}