How do I count all possible sums of array elements - java

I’m kind of stuck with my code and I can’t find where the problem is. My task is to find the closest sum in the array to the x value and amount of indexes to sum must not exceed n-value. Indexes to sum might not be consecutive, so the closest sum might be indexes(0,2,3) instead of (0,1,2).
I’ve written some code, but it does not work with n value bigger than 4.
In my code value of sums(n) if called «towns» and x value is called «miles».
Here comes the code
for(int i=0;i<ls.size();i++){
sum=ls.get(i);
counterTowns=1;
if(sum<miles&&counterTowns<towns){
for(int j=i+1;j<ls.size();j++){
sum+=ls.get(j);
counterTowns++;
if(counterTowns==towns){
if(sum<=miles){
if(sum>temp){
result=sum;
}
temp=result;
}
sum=ls.get(i);
counterTowns=1;
if(towns>2){ // I think the problem is in this line
j--;
}
}
}
}
}
To be more clear, "ls" is the ArrayList of Integers.
For example:
ArrayList is {50, 55, 56, 57, 58};
And towns=3, miles = 163 expected output is 163 which is the sum of 50+56+57.
When towns <=3 it works just fine with different miles, but if towns >3 it does not provide right output.
For example, if ArrayList is{91, 74, 73, 85, 73, 81, 87}
and miles= 331 and towns is 4 result is 30 instead of 331( result of 91+74+85+81).
I hope my question is clear and if not feel free to ask any questions.
Thank you in advance.
Peace and love!!!

Basically you want all the combinations of towns elements in the ArrayList.
Then you want to sum all the elements in each combination and find the smallest difference between the sum and miles.
I found the following code for finding all possible combinations of n elements in an array. Hence I used an array of int rather than an ArrayList. Refer to Print all possible combinations of r elements in a given array of size n. I copied the code from that Web page and modified it so that it solves your problem. Note that I used your sample list and value for towns. Explanations of the code appear after it.
Also note that the comments in the code are from the original code that I copied.
public class TownsKms {
private static int counter;
private static int kms;
private static int min = Integer.MAX_VALUE;
private static int[] minArr;
/* arr[] ---> Input Array
data[] ---> Temporary array to store current combination
start & end ---> Staring and Ending indexes in arr[]
index ---> Current index in data[]
r ---> Size of a combination to be printed */
static void combinationUtil(int arr[],
int data[],
int start,
int end,
int index,
int r) {
// Current combination is ready to be printed, print it
if (index == r) {
int sum = 0;
for (int j=0; j<r; j++) {
sum += data[j];
}
int diff = Math.abs(kms - sum);
if (diff < min) {
min = diff;
System.arraycopy(data, 0, minArr, 0, minArr.length);
}
return;
}
// replace index with all possible elements. The condition
// "end-i+1 >= r-index" makes sure that including one element
// at index will make a combination with remaining elements
// at remaining positions
for (int i=start; i<=end && end-i+1 >= r-index; i++) {
data[index] = arr[i];
combinationUtil(arr, data, i+1, end, index+1, r);
}
}
// The main function that prints all combinations of size r
// in arr[] of size n. This function mainly uses combinationUtil()
static void printCombination(int arr[], int n, int r) {
// A temporary array to store all combination one by one
int data[]=new int[r];
// Print all combination using temprary array 'data[]'
combinationUtil(arr, data, 0, n-1, 0, r);
}
/**
* Start here.
*/
public static void main(String[] args) {
int arr[] = {91, 74, 73, 85, 73, 81, 87};
int towns = 4;
minArr = new int[towns];
kms = 331;
int n = arr.length;
printCombination(arr, n, towns);
int sum = 0;
boolean first = true;
for (int i = 0; i < minArr.length; i++) {
if (first) {
first = false;
}
else {
System.out.print(", ");
}
sum += minArr[i];
System.out.print(minArr[i]);
}
System.out.println(" = " + sum);
}
}
Rather than add more parameters to the methods, I decided to use class members instead. Also, rather than miles, I named the variable kms, i.e. kilometers.
The difference between the sum of the elements in a given combination and the value of kms may be negative. You want the difference that is closest to zero. Hence I calculate the absolute difference which is why I call method abs() of class Math.
The only thing that is unclear from your question is whether the size of a combination must be precisely the value of towns or can it be any size from one up to towns. In other words, if towns equals 4, do you want all combinations of 4 elements from the list or do you also want to check combinations of 1, 2 and 3 elements as well? If the latter, then you need to repeat the above code and each time change the value of towns, i.e. set towns = 1 and run the above code. Then set towns = 2, etc. But remember not to reset min.

Related

Find the sum of custom number of elements in an array of Integers

I was interviewing for one of the big techs where I was asked a programming question in the problem solving round. The question is very similar to the Two Sum problem in Leet Code except for one tricky constraint. The question goes like this :
Given an array of integers nums, an integer target and an integer limit, return exactly one set of elements that counts up to the given limit and adds up to the given target.
Input: nums = [2,7,11,15], target = 20, limit = 3
Output: [2, 7, 11]
Explanation : The target is 20 and the limit is 3, so, we will have to find 3 numbers from the array that add up to 20.
I wasn't able to solve this during the interview and have been searching for a solution ever since.
The brute force approach is to run as many loops as the limit, which is not viable, considering the fact that the limit may be <= 10,000
And another is to extract sub-arrays of length = limit, run through each and every one, add their elements and return a sub-array that adds up to Target.
But, I am sure there must be a more efficient approach to solve this.
Any ideas?
Edit :
The output that we return may be random and not necessarily contiguous.
The limit has to be met and the number of elements that we return must be equal to the limit.
There is no limit on the size of the array
Use Stack (recursively) to find the array elements which will sum to the desired target within the required array elements limit. Doing it this way will actually find all combinations but only those which use fall on the elements limit are placed into a List.
Please read the comments in code. Delete them later if you like. Here is a runnable to demonstrate this process:
package sumtargetlimit_demo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
public class SumTargetLimit_Demo {
// The desired Target Sum
private int targetSum = 20;
/* The max allowable array elements to use in order to acquire
the desired Target Sum. */
private int numbersLimit = 3;
// A Stack to hold the Array elements which sum to the desired Target Sum.
private Stack<Integer> stack = new Stack<>();
// Store the summation of current elements held in stack.
private int sumInStack = 0;
/* A List Interface of Integer[] array to hold all the
combinations of array elements which sum to target. */
private List<Integer[]> combinationsList = new ArrayList<>();
public static void main(String[] args) {
// Demo started this way to avoid the need for statics.
new SumTargetLimit_Demo().startDemo(args);
}
private void startDemo(String[] args) {
// The int array to work against.
int[] intData = {2, 7, 11, 15};
/* See which array elements can acquire the desired
Target Sum with the maximum number of array elements
specified in the numbersLimit member variable. */
getSummations(intData, 0, intData.length);
// Display the found results to Console window...
if (combinationsList.isEmpty()) {
System.err.println("No integer elements within the supplied Array will");
System.err.println("provide a Taget Sum of " + targetSum + " with a maximum number");
System.err.println("limit of " + numbersLimit + ".");
}
else {
for (Integer[] intArray : combinationsList) {
System.out.println(Arrays.toString(intArray).replaceAll("[\\[\\]]", ""));
}
}
}
// Note: This method is recursive...
public void getSummations(int[] data, int startIndex, int endIndex) {
/* Check to see if the sum of array elements stored in the
Stack is equal to the desired Target Sum. If it is then
convert the array elements in the Stack to an Integer[]
Array and add it to the conmbinationsList List. */
if (sumInStack == targetSum) {
if (stack.size() <= numbersLimit) {
combinationsList.add(stack.toArray(new Integer[stack.size()]));
}
}
for (int currIndex = startIndex; currIndex < endIndex; currIndex++) {
if (sumInStack + data[currIndex] <= targetSum) {
stack.push(data[currIndex]);
sumInStack += data[currIndex];
// Make the currentIndex +1, and then use recursion to carry on.
getSummations(data, currIndex + 1, endIndex);
sumInStack -= stack.pop();
}
}
}
}
Try a much larger int[] array and play with the Target Sum and Number Limit to see how things work.
Another way, to look at this problem is through the eyes of dynamic programming. For any element in the array, there are two cases:
It will be a part of the elements, which make up the sum, in that case, we recursively, find the elements that make the remaining sum, with limit - 1.
It will not be part of the elements, which make up the sum, in this case, we look for the target, in the remaining part of the array.
Here, is the sample following the above logic:
import java.util.*;
class HelloWorld {
static Map<Integer, List<Integer>> cache = new HashMap<>();
public static void main(String[] args) {
int[] array = {9, 2, 15, 11, 7, 23, 54, 50, 12};
int limit = 4;
int target = 35;
// This is to optimize the search for element in case the limit is 1
Arrays.sort(array);
List<Integer> subarray = getElementsWithSumEqualToTarget(array, 0, limit, target);
System.out.println(subarray);
}
static List<Integer> getElementsWithSumEqualToTarget(int[] array, int startingIndex, int limit, int target) {
// If limit is 0, or we have reached the end of the array then sum doesn't exists.
if(limit == 0 || startingIndex >= array.length) {
return null;
} else if(limit == 1) {
// For limit 1, we can do a simple binary search, or linear search in that case Arrays.sort can be removed
int index = Arrays.binarySearch(array, startingIndex, array.length - 1, target);
if(index < 0) {
return null;
}
ArrayList<Integer> list = new ArrayList();
list.add(target);
return list;
} else if (cache.containsKey(target)) {
// If for a given sum, the subarray of elements, is already present, we can return it from the cache.(Memoization)
return cache.get(target);
}
// Case 1: The current element will be part of the sum.
List<Integer> subarray = getElementsWithSumEqualToTarget(array, startingIndex + 1, limit - 1, target - array[startingIndex]);
if(subarray != null) {
subarray.add(array[startingIndex]);
// Add target and subarray to the cache
cache.put(target, subarray);
return subarray;
}
// Case 2: Current element is not part of the sum
subarray = getElementsWithSumEqualToTarget(array, startingIndex + 1, limit, target);
if(subarray != null) {
cache.put(target, subarray);
}
return subarray;
}
}
Please try it out on large datasets, and see how it works. Hopefully, it helps.

How to copy only certain elements of one Array to another in Java

I am struggling to create an array with the correct size according to my parameters I have set up. Long story short this program is dealing with a set number of elements in the first array. Those elements are as follows
int [] myWeights = {258, 58, 209, 91, 79, 182, 172, 27, 7, 29, 128, 198};
Now those elements are in ounces. I get the program to run everything correctly, now my professor wants us to separate the ones that are over 8 pounds into a new array. Those elements in the new array in this case are 258, 209, 182, 172, and 198. The problem is that the program, at the beginning, can create a randomly sized array with varying sized elements between the numbers 1-320. Is there a way to have some sort of loop instantiate the proper amount of "boxes" needed. Or am I just supposed to instantiate some arbitrary number and hope that is what I will need? My current code for this is
public static int [] overGivenPounds(int x, int [] array){
int pounds = 0;
int arrayLength = 0;
int arrayOverEightPounds[];
int k = 0;
for(int i = 0; i < array.length; i++){
pounds = array[i] / 16;
if(x < pounds){
arrayOverEightPounds[k] = array[i];
k++;
}
}
return arrayOverEightPounds;
If any of this seems unclear please ask, there is no need to be rude. I am very new to Java.
Use a loop to determine the size of the target array
Create the target array of the needed size
Use a second loop to put values in the target array
Without that first step, you cannot know the right size of the array. If you create an array that's even one element too small or one element two big, that will be a waste,
because you will be forced to create a 3rd array to return an array of the right size.
So your solution should look something like:
public static int[] overGivenPounds(int x, int[] array) {
int size = 0;
for (int value : array) {
if (satisfies(x, value)) {
size++;
}
}
int[] result = new int[size];
// ??? -> for you to complete this
for (int value : array) {
if (satisfies(x, value)) {
// ??? -> for you to complete this
}
}
return result;
}
public static int[] overGivenPounds(int x, int[] array){
Arrays.sort(array);
boolean foundSomething = false;
int startIndex = 0;
for (int i = 0; i < array.length; i++) {
if(array[i]/16>=x){
startIndex = i;
foundSomething = true;
break;
}
}
if(foundSomething)
return Arrays.copyOfRange(array, startIndex, array.length);
return null;
}
Are you allowed to use Java streams? If so, the solution would be:
return Arrays.stream(myWeights).filter(n -> n/16 > x).toArray();
If not then you could use Arrays.copyOfto create an array of the correct length:
int[] heavyWeights = int[myWeights.length];
int size = 0;
for (int weight: myWeights)
if (weight / 16 > x)
heavyWeights[size++] = weight;
return Arrays.copyOf(heavyWeights, size);
Are you allowed to use other classes? If so, you could just use an ArrayList and then use
//int arrayOverEightPounds[];
List<Integer> listOverEightPounds = new ArrayList<>();
//...
//arrayOverEightPounds[k] = array[i];
listOverEightPounds.add(array[i]);
//....
return listOverEightPounds.toArray(new Integer[0]);
to return an array of the proper size. In this case you can get rid of k. ArrayList uses an array internally but will resize it automatically if it needs more space so you don't have to do that micro-management. The toArray method on ArrayList will return a new array of the proper size if the array that's passed in is not big enough. A common thing you see is to just pass in an array of size 0 into toArray which means the returned value will always be the correctly sized array.
The usual way to do it is to create an array that you know can hold everything, add your items to that array, while keeping track of how many items you have added. At the end you return a copy of the array, truncated to the number of items.
Or, with Java 8, you can write it as a stream one-liner:
return Arrays.stream(array).filter(i -> (i / 16) > x).toArray();

Comparing Two Arrays & Get the Percent that Match - Java

Background: Very new at Java, have little understanding. Would prefer a "point in the right direction" with explanation, if possible, than a copy/paste answer without explanation. If I want to stop being a novice, I need to learn! :)
Anyway, my goal is, as simply as possible, to be given 2 arrays numberList and winningNumbers, compare them, and return the percentage that numberList matches winningNumbers. Both array lengths will always be 10.
I have no idea where to start. I have been googling and going at this for 2 hours. My idea is to write a for loop that compares each individually integer in a string to one in the other, but I am not sure how to do that, or if there is a simpler method. I have little knowledge of arrays, and the more I google the more confused I become.
So far the only thing I have is
public double getPercentThatMatch(int[] winningNumbers) {}
numberList is preset.
one way you could approach it is to:
1) convert both lists to sets.
2) subtract one from the other. ie if 4 are the same, the resulting set will have the 6 values not the same
3) 10 - (size of resulting set) * 100 = %
Here's a runnable example of how you would compare the two arrays of ints to get a percent match.
public class LotteryTicket {
int[] numberList;
LotteryTicket(int... numbers) {
numberList = numbers;
}
public int getPercentThatMatch(int[] winningNumbers) {
Arrays.sort(numberList);
Arrays.sort(winningNumbers);
int i = 0, n = 0, match = 0;
while (i < numberList.length && n < winningNumbers.length) {
if (numberList[i] < winningNumbers[n]) {
i++;
} else if (numberList[i] > winningNumbers[n]) {
n++;
} else {
match++;
i++;
n++;
}
}
return match * 100 / winningNumbers.length;
}
public static void main(String[] args)
{
int[] winningNumbers = { 12, 10, 4, 3, 2, 5, 6, 7, 9, 1 };
LotteryTicket ticket = new LotteryTicket(5, 2, 6, 7, 8, 4, 3, 1, 9, 0);
int percentMatching = ticket.getPercentThatMatch(winningNumbers);
System.out.println(percentMatching + "%");
}
}
Output:
80%
Since you wanted to be pointed in the right direction, rather than havving proper code, and assuming you want to use arrays to solve the problem, try to put something like this in your method:
(loop through arrayA){
(loop through arrayB){
if (current arrayA number is equal to current arrayB number){
then increase match counter by one, since this exists.
also break out of current arrayB loop. (Check next arrayA now.)
}
}
}
When done: return 100*matchCount/totalCount, as a double
So for every index in one array, you check against every other index of the other array. Increase a counter each time there's a match, and you'll be able to get a ratio of matches. If you use an integer as a counter, remember that division with integers acts funky, so you'd need to throw to a double:
double aDoubleNumber = (double) intNumber / anotherIntNumber
The problem would be easier if we consider them set. Let you have two set -
Set<Integer> s1 = //a HashSet of Integer;
Set<Integer> s2 = //a HashSet of Integer;
Now make a copy of s1 for example s11 and do the following thing -
s1.retainAll(s2);
Now s1 contains only element of both sets - that is the intersection.
After that you can easily calculate the percentage
Edit: You can convert the array to a set easily by using the following code snippet (I am assuming you have array of int) -
Set<Integer> s1 = new HashSet<Integer>(Arrays.asList(somePrimiteiveIntArray));
I think this trick will works for other primitive type also.
Hope this will help.
Thanks a lot.
I am going to attempt to beat a dead horse and explain the easiest (conceptual) way to approach this problem I will include some code but leave a lot up to interpretation.
You have two arrays so I would change the overall method to something like this:
public double getPercentage(int[] arrayA, int[] arrayB) {
double percentage=0;
for(/*go through the first array*/) {
for(/*go through second array*/) {
if(arrayA[i]==arrayB[j]) { /*note the different indices*/
percentage++; /*count how many times you have matching values*/
/* NOTE: This only works if you don't have repeating values in arrayA*/
}
}
}
return (percentage/arrayA.length)*100; /*return the amount of times over the length times 100*/
}
You are going to move through the first array with the first loop and the second array with the second loop. So you go through every value in arrayB for each value in arrayA to check.
In my approach I tried storing the winning numbers in a Hashset (one pass iteration, O(n) )
And when iterating on the numberList, I would check for presence of number in Hashset and if so, I will increment the counter. (one pass iteration, so O(n) )
The percentage is thus calculated by dividing the counter with size of array.
See if the sample code makes sense:
import java.util.HashSet;
public class Arraycomparison {
public static void main(String ... args){
int[] arr0 = {1,4,2,7,6,3,5,0,3,9,3,5,7};
int[] arr1 = {5,2,4,1,3,7,8,3,2,6,4,4,1};
HashSet set = new HashSet();
for(int j = 0; j < arr1.length; j++){
set.add(arr1[j]);
}
double counter = 0;
for(int i = 0; i < arr0.length; i++){
if(set.contains(arr0[i])){
counter++;
}
}
System.out.println("Match percentage between arrays : " + counter/arr0.length*100);
}
}
You should use List over array, because that's a convenient way, but with array:
public class Winner {
public static void main(String... args) {
double result = getPercentThatMatch(new int[]{1,2,3,4,5}, new int[]{2,3,4,5,6});
System.out.println("Result="+result+"%");
}
public static double getPercentThatMatch(int[] winningNumbers,
int[] numberList) { // it is confusing to call an array as List
int match = 0;
for (int win : winningNumbers) {
for (int my : numberList ){
if (win == my){
System.out.println(win + " == " + my);
match++;
}
}
}
int max = winningNumbers.length; // assume that same length
System.out.println("max:"+max);
System.out.println("match:"+match);
double devide = match / max; // it won't be good, because the result will be intm so Java will trunc it!
System.out.println("int value:"+devide);
devide = (double) match / max; // you need to cast to float or double
System.out.println("float value:"+devide);
double percent = devide * 100;
return percent;
}
}
Hope this helps. ;)
//For unique elements
getpercentage(arr1, arr2){
res = arr1.filter(element=>arr2.includes(element))
return res.lenght/arr2.lenght * 100;
}
//For duplicate elements
getpercentage(arr1, arr2){
const setA = Set(arr1);
const setB = Set(arr2);
Let res = [ ];
for(let i of setB){
if(setA.has(i)){
res.push(i);
}
}
return res.lenght/setA.size* 100;

find a solution to subset sum using dynamic programming

What I want to do
I want to find a subset of an array that sums to a target T. I also want to use to a dynamic programming approach (and a bottom-up solution at that) to do this.
What I currently have
Currently I only found a way to see if amongst all subsets of size N, whether or not there is at least one subset that has the desired sum. See code below.
public boolean solve(int[] numbers, int target) {
//Safeguard against invalid parameters
if ((target < 0) || (sum(numbers) < target)){
return false;
}
boolean [][] table = new boolean [target + 1] [numbers.length + 1] ;
for (int i = 0; i <= numbers.length; ++i) {
table[0][i] = true;
}
/* Base cases have been covered.
* Now look set subsets [1..n][target] to be true or false.
* n represents the number of elements from the start that have a subset
* that sums to target
*/
for (int i = 1; i <= target; ++i){
for (int j = 1; j <= numbers.length; ++j){
/* Mark index j as one of the numbers in the array
* which is part of the solution with the given subtarget */
table [i][j] = table[i][j-1];
if (i >= numbers[j-1])
table[i][j] = table[i][j] || table[i - numbers[j-1]] [j-1];
}
}
return table[target][numbers.length];
}
Where I am stuck
Right now, I know if there is a solution, but I can't think of a way to actually output a solution.
I am not looking for anyone to provide me specific code, but pseudocode is welcome as are hints to how a solution may be saved.
The algorithm you provided can stay the same, you don't need to store anything else besides the DP-table table[][]. You just need an additional post-processing phase in which you step "backwards" through table[][] to get the solution set.
Just to recall:
You've computed the table table[i][j], which stores for every value 0<=i<=t(:=target) and every 0<=j<=n(:=numbers.length) whether there is a subset of numbers in numbers[0..j-1] that sum to i.
Consider the subset S corresponding to table[i][j] (, which is true). Note that:
The subset S contains the number numbers[j] only if table[ i-numbers[j] ][j-1] is true.
(Proof: recursively take the solution subset S' for table[ i-numbers[j] ][j-1], and add numbers[j])
On the other hand, this subset S does not contain the number numbers[j] only if table[ i-numbers[j] ][j-1] is false.
(Proof: assume S contains numbers[j], trow numbers[j] out of S, this implies table[ i-numbers[j] ][j-1], contradiction)
So to get the subset, simply use the above property to check whether numbers[n-1] is in the subset summing to t.
If so, recursively compute whether numbers[n-2] is in the subset summing to t-numbers[n-1],
else recursively compute whether numbers[n-2], is in the subset summing to t
Here are the two Java solutions for the subset sum problem.
First using Recursive Approach.
Second using Dynamic Programming Approach.
/*
Question: Given a set of non-negative integers, and a value sum, determine if there is a subset of the given set
with sum equal to given sum.
Examples: set[] = {3, 34, 4, 12, 5, 2}, sum = 9
Output: True //There is a subset (4, 5) with sum 9.
Let isSubSetSum(int set[], int n, int sum) be the function to find whether there is a subset of set[] with
sum equal to sum. n is the number of elements in set[].
*/
package SubsetSumProblem;
import java.util.Scanner;
public class UsingResursiveAndDPApproach {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
try{
System.out.println("Enter the number of elements in the array");
int n =in.nextInt();
System.out.println("Enter the elements of the array");
int[] a=new int[n];
for(int i=0;i<n;i++)
a[i]=in.nextInt();
System.out.println("Enter the sum, which you need to find");
int sum = in.nextInt();
System.out.println("Using recursion, the result is: "+usingRecursion(a,a.length,sum));
System.out.println("Using Dynamic Programming, the result is: "+usingDP(a,sum));
}
finally{
in.close();
}
}
private static boolean usingRecursion(int[] a,int length, int sum) {
// 1. Base Cases
if(sum==0)
return true;
if(length==0 && sum!=0)
return false;
// 2. To avoid unnecessary steps, we will optimize the recursion method by avoiding
// recursive calls to areas where we are definite that we can SAFELY ignore the case since
// the SOLUTION does not exist there.
// If last element is greater than sum, then ignore it
if(a[a.length-1]>sum)
return usingRecursion(a,length-1,sum);
// 3. This is the recursion step where we will call the method again and again
/* else, check if sum can be obtained by any of the following
(a) including the last element
(b) excluding the last element */
return (usingRecursion(a, length-1, sum-a[length-1])|| usingRecursion(a, length-1, sum));
}
/*
Analysis:
Time Complexity = O(2^n)
Space Complexity = // Don't know
*/
private static boolean usingDP(int[] a, int sum) {
// using boolean matrix for DP
boolean dp[][] = new boolean[a.length+1][sum+1]; // +1 in row and column
// if the length of the array is variable (and sum is 0) then fill TRUE, since the SUM=0
for(int row=0;row<dp.length;row++){
dp[row][0] = true; // NOTE: dp[length=VARIABLE][sum=0], thus we satisfy the condition where length is VARIABLE
// and the SUM=0
}
// if the SUM is variable and length is 0 then FALSE, since (sum=variable && length=0)
for(int column=1;column<dp[0].length;column++){
dp[0][column] = false; // NOTE: dp[length=0][sum=VARIABLE], thus we satisfy the condition where
// (length=0 && sum=variable)
}
for(int i=1;i<dp.length;i++){
for(int j=1;j<dp[0].length;j++){
/* Check if sum can be obtained by any of the following
(a) including the last element
(b) excluding the last element */
// VERY VERY IMP: This is same as "excluding the last element" which is represented in DP
dp[i][j] = dp[i-1][j]; // the current position[i][j] would be same as previous position.
// the previous position means that SUM is ACHIEVED OR NOT-ACHIEVED
// int the previous position then it will ofcourse be ACHIEVED or NOT-ACHIEVED
// in the current position.
// VERY VERY IMP: This is same as "including the last element" which is represented in DP
// if the column[ sum is represented in column of the matrix i.e this sum exist] > = sum-a[last_index]
// then decrease the sum
if(j>=a[i-1]) // i.e sum >= array[last index element]. If it is true then include this last element by
// deducting it from the total sum
dp[i][j] = dp[i][j] || dp[i-1][j-a[i-1]]; // VERY VERY IMP NOTE: Here dp[i][j] on R.H.S represent
// dp[i-1][j] which we have assigned in the previous step
}
}
return dp[a.length][sum];
}
/*
Analysis:
Time Complexity = O(a.length*sum)
Space Complexity = O(a.length*sum)
*/
}
Here is my solution is an iterative dp, but with only one dimension: Hope it can help you.
#include <iostream>
#include <cstring>
using namespace std;
const int maxN=1000;
int memo[maxN];
int pi[maxN];
int main(){
int a[]={7,8,5,1,4};
memset(memo,-1,sizeof memo);
memset(pi,-1,sizeof pi);
int n;
cin>>n;
memo[0]=0;
pi[0]=0;
for(int i=0;i<(int)sizeof(a)/4;i++){
for(int num=n;num>=0;num--){
if(num-a[i]>=0 and memo[num-a[i]]!=-1 and (memo[num]==-1 or memo[num]>1+memo[num-a[i]])){
memo[num]=1+memo[num-a[i]];
pi[num]=num-a[i];
}
}
}
int N=n;
while(N!=0){
cout<<N-pi[N]<<" ";
N=pi[N];
}
cout<<endl;
cout<<memo[n]<<endl;
return 0;
}

Sum of the maximum downsequence number in an array

Given this array
int [] myArray = {5,-11,2,3,14,5,-14,2};
You are to find the maximum sum of the values in any downsequence in an unsorted array of integers. If the array is of length zero then maxSeqValue must return Integer.MIN_VALUE.
You should print the number, 19 because the downsequence with the maximum sum is 14,5.
Downsequence number is a series of non-increasing number.
These are the codes that i used but i guess that there are some cases which is still not accounted for.
Any ideas, thanks in advance.
public class MaxDownSequence{
public int maxSeqValue(int[] a){
int sum=Integer.MIN_VALUE;
int maxsum=Integer.MIN_VALUE;
for (int i=1;i<a.length;i++){
if(a[i]<a[i-1]){
sum = a[i] + a[i-1];
if (sum>maxsum){
maxsum=sum;
}
}
else {
sum=a[i];
if (sum>maxsum){
maxsum=sum;
}
}
}
if (a.length==0){
return Integer.MIN_VALUE;
}
else{
return maxsum;
}
}
public static void main(String args[]){
MaxDownSequence mySeq = new MaxDownSequence();
int [] myArray = {5,-11,2,3,14,5,-14,2};
System.out.println(mySeq.maxSeqValue(myArray));
}
}
Take the input {3,2,1} the answer should be 6 your program gives 5.
Your approach is correct, every time you test a number in the array you check if its less than (actually this should be <=) previous array element.
If it is you update sum as: sum = a[i] + a[i-1]; this is incorrect. sum in your program represents the running rum of the current subsequence. You should not be overwriting it.
Dynamic programming is the way to go.
http://en.wikipedia.org/wiki/Dynamic_programming
I know, maybe that doesn't help at all, but since I don't want to post a solution for your problem the best thing I can do is to give you this hint :)
you haven't considered sequences of more than two numbers. If you had [3,2,1] the result should be 6. But your code would give 5, because it only looks at the sum of the current number and the previous, whereas you should keep track of a current downsequence and add the current number to the running total of that downsequence. Once you hit a number that breaks the downsequence update maxsum if needed then reset the running total to 0.
not sure why you have the else in the loop?? If a[i] is not less than a[i-1] then it is not a downsequence, therefore surely maxsum should not be updated. If you take just the first 3 numbers in your sample array, it would return the number 2. Because the first downsequence [5,-11] would give a sum of -6 and on the next iteration it would just look at 2, which is greater than -6 and therefore maxsum is updated.
No need for:
if (a.length==0){
return Integer.MIN_VALUE;
}
if the array length is 0 then you never enter the loop and therefore never change maxsum, so it will still be equal to Integer.MIN_VALUE, so you can just return maxsum at the end regardless.
You are suppose to have a running sum i think. Meaning Sum = Sum + A[i]. Just make sure to initialize the sum to the first member of the array and you are in business.
package sree;
import java.util.ArrayList;
import java.util.List;
import javax.lang.model.element.NestingKind;
public class MaximumSumSequence {
private final int[] theArray;
private MaximumSumSequence(int[] theArray) {
this.theArray = theArray;
}
private void maximumSequence() {
int currentMax = 0,currentSum = 0, start = 0, end = 0, nextStart = 0;
for (int i=0; i< theArray.length; i++) {
currentSum += theArray[ i ];
if (currentMax < currentSum) {
currentMax = currentSum;
start = nextStart;
nextStart = end;
end = i;
} else if (currentSum < 0) {
currentSum = 0;
}
}
System.out.println("Max Sum :" + currentMax);
System.out.println("Start :" + start);
System.out.println("End :" + end);
}
public static void main(String[] args) {
//int[] anArray = {4, -1, 2, -2, -1, -3};
int[] anArray ={-2, 1, -3, 4, -1, 2, 1, -5, 4};
new MaximumSumSequence(anArray).maximumSequence();
}
}

Categories