Related
A non-empty array A consisting of N integers is given.
A peak is an array element which is larger than its neighbors. More precisely, it is an index P such that 0 < P < N − 1, A[P − 1] < A[P] and A[P] > A[P + 1].
For example, the following array A:
A[0] = 1
A[1] = 2
A[2] = 3
A[3] = 4
A[4] = 3
A[5] = 4
A[6] = 1
A[7] = 2
A[8] = 3
A[9] = 4
A[10] = 6
A[11] = 2
has exactly three peaks: 3, 5, 10.
We want to divide this array into blocks containing the same number of elements. More precisely, we want to choose a number K that will yield the following blocks:
A[0], A1, ..., A[K − 1],
A[K], A[K + 1], ..., A[2K − 1],
...
A[N − K], A[N − K + 1], ..., A[N − 1].
What's more, every block should contain at least one peak. Notice that extreme elements of the blocks (for example A[K − 1] or A[K]) can also be peaks, but only if they have both neighbors (including one in an adjacent blocks).
The goal is to find the maximum number of blocks into which the array A can be divided.
Array A can be divided into blocks as follows:
one block (1, 2, 3, 4, 3, 4, 1, 2, 3, 4, 6, 2). This block contains three peaks.
two blocks (1, 2, 3, 4, 3, 4) and (1, 2, 3, 4, 6, 2). Every block has a peak.
three blocks (1, 2, 3, 4), (3, 4, 1, 2), (3, 4, 6, 2). Every block has a peak. Notice in particular that the first block (1, 2, 3, 4) has a peak at A[3], because A[2] < A[3] > A[4], even though A[4] is in the adjacent block.
However, array A cannot be divided into four blocks, (1, 2, 3), (4, 3, 4), (1, 2, 3) and (4, 6, 2), because the (1, 2, 3) blocks do not contain a peak. Notice in particular that the (4, 3, 4) block contains two peaks: A[3] and A[5].
The maximum number of blocks that array A can be divided into is three.
Write a function:
class Solution { public int solution(int[] A); }
that, given a non-empty array A consisting of N integers, returns the maximum number of blocks into which A can be divided.
If A cannot be divided into some number of blocks, the function should return 0.
For example, given:
A[0] = 1
A[1] = 2
A[2] = 3
A[3] = 4
A[4] = 3
A[5] = 4
A[6] = 1
A[7] = 2
A[8] = 3
A[9] = 4
A[10] = 6
A[11] = 2
the function should return 3, as explained above.
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1..100,000];
each element of array A is an integer within the range [0..1,000,000,000].
My Understanding of the problem :
Each sub array should contain at least one peak
An element which forms a peak can be in an Adjacent sub array.
Return max possible sub arrays
My Question
Consider Main Array : [0,1,0,1,0]
Possible sub arrays as per understanding : [0,1] [0,1,0]
Each subarray has a peak.
Subarray 1 [0,1] has peak element shared with adjacent array [0,1,0].
Subarray 2 [0,1,0] contains peak 0<1>0.
So max possible sub arrays are 2 but a test case in Codility returns max possible sub arrays as 1.
Below is my code
// you can also use imports, for example:
import java.util.*;
// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");
class Solution {
public int solution(int[] A) {
// write your code in Java SE 8
int count=0,size=A.length;
if(size<2)
return 0;
System.out.println(Arrays.toString(A));
for(int i=1;i<size-1;i++){
if(A[i-1]<A[i] && A[i]>A[i+1]){
count++;
i++;
}
}
return count;
}
}
Test case which failed in Codility click here
I believe there is a gap in my understanding. Any help would be helpful :)
https://app.codility.com/demo/results/training5KP2PK-P4M/
https://github.com/niall-oc/things/blob/master/codility/peaks.py
Breaking an array into even parts is another way of factorizing the length of the array.
Array of length 12
[0,1,0,1,0,0,0,1,0,0,1,0,]
Factors of 12.
The square root of 12 is 3.464... so start with 3 and irterate down to 1 and divide each number into 12. This gives you a set of numbers {1, 2, 3, 4, 6, 12}.
Process
Because of how a peak is defined you cannot have 12 peaks in this array so remove 12 from the set. Starting d as the largest number divide the array int d parts. And check each part has a peak, if so then d is the maximum number of equal parts to all contain at least one peak. If not so then iterate to the next largest divisor and try that until you find a solution.
First of all you need to be congratulated to write a concise program to calculate the number of peaks. But the question is not to count the peaks.
It is to find the number of equal sized array and each having at least one peak. And a peak cannot be the first or last element as stated in the problem 0 < P < N − 1
Now quoting your question:
Consider Main Array : [0,1,0,1,0]
Possible sub arrays as per understanding : [0,1] [0,1,0] Each subarray has a peak. Subarray 1 [0,1] has peak element shared with adjacent array [0,1,0]. Subarray 2 [0,1,0] contains peak 0<1>0.
So max possible sub arrays are 2 but a test case in Codility returns max possible sub arrays as 1.
I see below issues:
your sub array sizes are not equal
array [0,1] does not have a peak
So, the array cannot be divided in equal parts each having a peak and hence only one array remains [0,1,0,1,0].
This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 3 years ago.
I'm reviewing arrays and for loops among other things in my computer science course. One of the examples used was the code below. After being run, the array displays 2, 3, 4, 2. How is this?
int[] numbers = {1, 2, 3, 4};
for (int i = 0; i < numbers.length; i++) {
numbers[i] = numbers[(i+1) % numbers.length];
}
System.out.println(numbers);
An important concept in understanding the code you are looking it, especially the block inside the for loop, is the modulus operator (%) also known as the remainder operator. When applied, the % operator returns the remainder of two numbers.
Hence, the computation:
(i+1) % numbers.length
will always return a remainder.
Walking through it with a debugger (or print statements as suggested) while evaluating the values (and operations) at each iteration is a great way of understanding it.
You can also read more about it: https://www.baeldung.com/modulo-java
As you are doing the operation on the same array in place.
original array [1, 2, 3, 4]
when i - 0 => number [2,2,3,4] // moving index 1 item to index 0
when i - 2 => number [2,3,3,4] // moving index 2 item to index 1 from the
immediate previous array
when i - 2 => number [2,3,4,4] // moving index 3 item to index 2 from the
immediate previous array
when i - 3 => number [2,3,4,2] // moving index 0 item to index 3 from the
previous array
Keep in mind that % is modular arithmetic - it's the remainder when you divide the left-hand side by the right-hand side. For example, 2 % 4 = 2, 4 % 4 = 0, 6 % 4 = 2, and 8 % 4 = 0.
Here are the steps:
i = 0. (i + 1) % 4 = 1 % 4 = 1. Value at index 1 is 2. Array now contains {2, 2, 3, 4}.
i = 1. (i + 1) % 4 = 2 % 4 = 2. Value at index 2 is 3. Array now contains {2, 3, 3, 4}.
i = 2. (i + 1) % 4 = 3 % 4 = 3. Value at index 3 is 4. Array now contains {2, 3, 4, 4}.
i = 3. (i + 1) % 4 = 4 % 4 = 0. Value at index 0 is 2. Array now contains {2, 3, 4, 2}.
I'd encourage you to step through this with a debugger and/or use print statements to convince yourself that this is true and to understand why this is the case (doing so will help with understanding; if you're not convinced by a statement, either it's not true or there's something you don't understand or know about yet).
Your loop reassignes each index in your array with the value currently stored in the next index by doing (i+1).
Therefor on index [0] you get the value 2 which was on index [1] before. Same for second and third index. For the last one it is a little bit special since there is no next index the % numbers.length computation basically wraps the index so that for index [3] you will get the value of index [0] since (3+1)%4 = 0.
Note on index [3] you are getting value 2 and not 1 since you already changed the value on index [0] before that.
1st iteration
numbers[i] = numbers[1 % 4]; // answer is 1 so numbers[1] = 2
2nd iteration
numbers[i] = numbers[2 % 4]; // answer is 2 so numbers[2] = 3
Like this it will go until I becomes 3
I've been doodling around with this little piece of code that's supposed to calculate and print out which powers of 2 are summarized into a given number. It works fine with small odd numbers but gets lost when I want it to calculate even numbers or bigger ones.
I don't even know what I could try, the code looks alright, but I probably keep failing to notice.
System.out.println("Give a number");
int gigaInt = si.nextInt();
String gigaBit = Integer.toBinaryString(gigaInt);
String[] gigaBitArray = gigaBit.split("");
System.out.println("Binary: " + gigaBit);
List<Integer> powers = new ArrayList<Integer>();
for(int counter = gigaBitArray.length-1; counter >= 0; counter--){
if (gigaBitArray[counter].equals("1"))
powers.add((int)Math.pow(2,counter));
else if(gigaBitArray[counter].equals("0")){
powers.add(0);
}
}
System.out.println("Powers: " + powers);
So, obviously, the program is supposed to calculate the powers, and it does! in some cases... here, when given 9
Give a number
9
Binary: 1001
Powers: [8, 0, 0, 1]
But when I want it to calculate an even number, it always shows "1" as the only component, like this:
Give a number
8
Binary: 1000
Powers: [0, 0, 0, 1]
And whenever asked to deal with a big number, it just goes completely crazy:
Give a number
542
Binary: 1000011110
Powers: [0, 256, 128, 64, 32, 0, 0, 0, 0, 1]
I would be amazingly grateful for any kind of advice on this. It's probably just an infantile kind of mistake, so please, do point it out.
As per the comment by Dawood ibn Kareem, you are testing the low order bits first. If you want the high order powers listed first you will need an index variable and a power variable. Also, no need to check for "0". If it is not "1" then it must be "0".
int iIndex;
int iLength = gigaBitArray.length;
int iPower = iLength - 1;
for ( iIndex = 0; iIndex < iLength; ++iIndex, --iPower )
{
if ( gigaBitArray[iIndex].equals("1") )
{
powers.add((int)Math.pow(2, iPower));
}
else
{
powers.add(0);
}
}
The problem with your code is the array index you are looking at.
When you input the number 8, its binary representation is 1000. And when you split it into an array you get:
index: 0 1 2 3
value: 1 0 0 0
Because you are starting at the end of the list, index 0 will be processed last (and will be the same as 2^0).
All you need to do to fix this is to inverse the order of the elements you are looking at while keeping the same order of the for loop.
Eg:
Instead of:
gigaBitArray[counter]
It should be:
gigaBitArray[gigaBitArray.length -1 - counter]
In addition to both answers above you could also get rid of the if else by multiplying the 0s and 1s:
int len = gigaBitArray.length;
for (int i = 0; i < gigaBitArray.length; i++) {
powers.add((int)Math.pow(2, --len)*Integer.parseInt(gigaBitArray[i]));
}
Here is one way to do it. Comments in code where not obvious. The idea here is that all information inside a computer is binary. Characters and numbers are printed out based on context. Since all information is in binary it can be shifted left or right to move the field of bits the same direction. This permits detecting a 1 or 0 bit without resorting to the overhead of String manipulation.
for (int number : new int[] { 8, 10, 23, 11, 2, 4, 99
}) {
List<Integer> powers = new ArrayList<>();
// starting bits to shift
int shift = 0;
// save number for printout
int save = number;
while (number > 0) {
// ANDing the number with 1 will mask the
// low order bit to a 1 or 0.
// Then shift that bit "shift" number
// of bits (first time thru is 0) and store
// the power in p. Then increment # of bits
// to shift.
int p = (number & 1) << shift++;
//add power to beginning of list.
powers.add(0, p);
// now shift the number right by 1 to position
// for next bit.
number >>= 1;
}
System.out.printf("%3d -> %s%n", save, powers);
}
The above prints the following:
8 -> [8, 0, 0, 0]
10 -> [8, 0, 2, 0]
23 -> [16, 0, 4, 2, 1]
11 -> [8, 0, 2, 1]
2 -> [2, 0]
4 -> [4, 0, 0]
99 -> [64, 32, 0, 0, 0, 2, 1]
I was trying to solve a problem from the Codility with a given solution. The problem is provided below:
You are given N counters, initially set to 0, and you have two possible operations on them:
increase(X) − counter X is increased by 1,
max counter − all counters are set to the maximum value of any counter.
A non-empty array A of M integers is given. This array represents consecutive operations:
if A[K] = X, such that 1 ≤ X ≤ N, then operation K is increase(X),
if A[K] = N + 1 then operation K is max counter.
For example, given integer N = 5 and array A such that:
A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 6
A[4] = 1
A[5] = 4
A[6] = 4
the values of the counters after each consecutive operation will be:
(0, 0, 1, 0, 0)
(0, 0, 1, 1, 0)
(0, 0, 1, 2, 0)
(2, 2, 2, 2, 2)
(3, 2, 2, 2, 2)
(3, 2, 2, 3, 2)
(3, 2, 2, 4, 2)
The goal is to calculate the value of every counter after all operations.
Write a function:
class Solution { public int[] solution(int N, int[] A); }
that, given an integer N and a non-empty array A consisting of M integers, returns a sequence of integers representing the values of the counters.
The sequence should be returned as:
a structure Results (in C), or
a vector of integers (in C++), or
a record Results (in Pascal), or
an array of integers (in any other programming language).
For example, given:
A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 6
A[4] = 1
A[5] = 4
A[6] = 4
the function should return [3, 2, 2, 4, 2], as explained above.
Assume that:
N and M are integers within the range [1..100,000];
each element of array A is an integer within the range [1..N + 1].
Complexity:
expected worst-case time complexity is O(N+M);
expected worst-case space complexity is O(N) (not counting the storage required for input arguments).
I have a solution provided,
public static int[] solution(int N, int[] A) {
int[] counters = new int[N];
int currMax = 0;
int currMin = 0;
for (int i = 0; i < A.length; i++) {
if (A[i] <= N) {
counters[A[i] - 1] = Math.max(currMin, counters[A[i] - 1]);
counters[A[i] - 1]++;
currMax = Math.max(currMax, counters[A[i] - 1]);
} else if (A[i] == N + 1) {
currMin = currMax;
}
}
for (int i = 0; i < counters.length; i++) {
counters[i] = Math.max(counters[i], currMin);
}
return counters;
}
It seems they use 2 storage to hold and update the min/max values and use them inside the algorithm. Obviously, there is a more direct way to solve the problem ie. increase the value by 1 or set all the values to max as suggested and I can do that. The drawback will be to lower perfromance and increased time complexity.
However, I would like to understand what is going on here. I spend times debugging with the example array but the algorithm is still little confusing.
Anyone understand it and can explain to me briefly?
It is quite simple, they do lazy update. You keep track at all times of what is the value of the counter that has the highest value (currMax). Then, when you get a command to increase all counters to that maxValue, as that is too expensive, you just save that the last time you had to increase all counters to maxValue, that value was currMin.
So, when do you update a counter value to that value? You do it lazily, you just update it when you get a command to update that counter (increase it). So when you need to increase a counter, you update the counter to the max between its old value and currMin. If this was the first update on this counter since a N + 1 command, the correct value it should have is actually currMin, and that will be higher (or equal) to its old value. One you updated it, you add 1 to it. If now another increase happens, currMin doesn't actually matter, as the max will take its old value until another N + 1 command happens.
The second for is to account for counters that did not get an increase command after the last N + 1 command.
Note that there can be any number of N + 1 commands between 2 increase operations on a counter. It still follows that the value it should have is the maxValue at the time of the last N + 1 command, it doesn't really matter that we didn't update it before with the other maxValue from a previous N + 1, we only care about latest.
I am looking for a way to search for a subsequence in a given sequence that sums up to a given number (sum, here 4) with a lexicographical priority.
Take for instance the following example:
1,2,2,4,1,1
Different subsequences can sum up to 4. For instance 1,2,1, 2,2 2,1,1. In case multiple of such sequences exists, the lexicographical first of the corresponding index-array should be returned: so if it is possible to find such sequence with the first element, one has to returned that one, if not, aim for the second and so one (both iterative (take the next one), and recursively (after selecting the first, the next but first should be closest to the head of the sequence as well).
So for this example, we select 1,2,1. Now 2,4,1 is left. If we repeat this problem we cannot make a match with 2: 2,4 is greater than 4 and 2,1 is less than 4. Thus we select 4. Finally we have to select 2 and 1.
A practical application of this concept is a queue of a roller coaster. You need 4 people for a ride, but some people are in groups with their friends and would like to all get on the same ride together.
In this example 1 is a single person at the front of the line, 2 is a group of 2 friends behind him. Now we need a total of 4 people for this ride and we already have 3, so we cut the line (2 and 4) and take the first single person, which gives us 4 people total.
If I understand the problem correctly, what you basically try to do is grouping the numbers such that the sum is 4 and you give priority to adding numbers in the queue first.
You can do this using a dynamic programming approach. I'm here using a int[] and an int as sum, but the problem can be generalized to work with most datastructures.
First you must define a comparator that compares lists of indices for instance a lexicographical one:
public class LexComp<T extends Comparable<T>> implements Comparator<List<T>> {
#Override
public int compare (List<T> la, List<T> lb) {
Iterator<T> ita = la.iterator();
Iterator<T> itb = lb.iterator();
while(ita.hasNext() && itb.hasNext()) {
T ea = ita.next();
T eb = itb.next();
int cr = ea.compareTo(eb);
if(cr != 0x00) {
return cr;
}
}
if(itb.hasNext()) {
return 1;
} else if(ita.hasNext()) {
return -1;
}
return 0;
}
}
Next you can use the following method:
public ArrayList<Integer> groupSum (int[] values, int sum) {
ArrayList[] memory = new ArrayList[sum+1];
memory[0] = new ArrayList<Integer>();
LexComp<Integer> lc = new LexComp<Integer>();
int index = 0;
for(int val : values) {
for(int i = sum-val; i >= 0 ; i--) {
if(memory[i] != null) {
ArrayList<Integer> tmp = (ArrayList<Integer>) memory[i].clone();
tmp.add(index);
if(memory[i+val] == null || lc.compare(tmp,(ArrayList<Integer>) memory[i+val]) < 0) {
memory[i+val] = tmp;
}
}
}
index++;
}
return memory[sum];
}
This method returns an ArrayList<Integer> of indices whose corresponding elements will sum up to sum and null if no such group can be created. It will give priority to some groups according to the LexComp comparator.
For your given input:
groupSum(new int[] {1,2,2,4,1,1},4);
groupSum(new int[] {1,2,3,2,2,2},4);
groupSum(new int[] {1,2,2,3},4);
groupSum(new int[] {1,2,2,3,1},4);
It results in:
[0, 1, 4]
[0, 2]
[0, 3]
[0, 1, 4]
So you should pick the first, second and fifth element which indeed sum up to 4. You then will have to remove these items out of the array yourself and rerun the process. In case no such sum can be constructed, or there are not enough elements to sum up to 4 - as said before - the algorithm will return null. In that case you have to invent a fallback mechanism. Perhaps returning the group the differs the least from sum.
Background
This is a dynamic programming approach. You generate a memory which stores - for each sum - the thus far best found solution. Initially we haven't seen any values so all items contain null except memory[0] which contains an empty arraylist (because the sum of zero elements is 0). So the memory looks like:
Mem
4 -> null
3 -> null
2 -> null
1 -> null
0 -> []
Now the algorithm iterates over the values. The first value we encounter for the example case is a 1. Now we look for lists already defined and the only one is memory[0] we can upgrade that list into a list [0] (the arrays store indices) whose sum results in 1. Since at that moment the value for that list is null there is no alternative, thus we add this list to to memory[1]:
Mem
4 -> null
3 -> null
2 -> null
1 -> [0]
0 -> []
The next item is 2: we can upgrade two lists [] -> [1] and [0] -> [1] these will results in lists with sums 2 and 3 respectively, so we store them at these indices of the memory:
Mem
4 -> null
3 -> [0,1]
2 -> [1]
1 -> [0]
0 -> []
The next item is again a 2. Now we can upgrade 4 lists: [] -> [2], [0] -> [0,2], [1] -> [1,2] and [0,1] -> [0,1,2]. A first problem is that the sum of [0,1,2] is 5 which is higher than sum. That's not interesting, so we drop that one. The problem is however, that some of the places contain already lists:
Mem
4 -> null
3 -> [0,1] <> [0,2]
2 -> [1] <> [2]
1 -> [0]
0 -> []
For the conflicting lists, we need to look for a resolution. In that case the comparator - in this case the LexComp resolves the errors. Since we do this lexicographically, [0,1] wins from [0,2] and [1] from [2]. After resolution the lists looks like:
Mem
4 -> [3]
3 -> [0,1]
2 -> [1]
1 -> [0]
0 -> []
The next element is a 4. The only list we can upgrade such that the sum is still less than or equal to sum is [] -> [3]
Mem
4 -> [3]
3 -> [0,1]
2 -> [1]
1 -> [0]
0 -> []
The next element is 1. We can upgrade all lists except the one 4 -> [3] (otherwise the sum would be larger than 4). But again this results in a lot of conflicts:
Mem
4 -> [3] <> [0,1,4]
3 -> [0,1] <> [1,4]
2 -> [1] <> [0,4]
1 -> [0] <> [4]
0 -> []
Now if we run the lexicographically comparator, it will sometimes accept new lists and sometimes the old lists. After resolution, the memory looks like:
Mem
4 -> [0,1,4]
3 -> [0,1]
2 -> [0,4]
1 -> [0]
0 -> []
Now our current best solution to generate a group that sums up to four has changed from [3] to [0,1,4]. Finally the last element 1 won't change much to the game:
Mem
4 -> [0,1,4] <> [0,1,5]
3 -> [0,1] <> [0,4,5]
2 -> [0,4] <> [0,5]
1 -> [0] <> [5]
0 -> []
Which after resolution reads:
Mem
4 -> [0,1,4]
3 -> [0,1]
2 -> [0,4]
1 -> [0]
0 -> []
Now we have considered all elements and the best solution to generate 4 is memory[4] or [0,1,4].
Different order
This approach can be generalized in the sense that providing a different Comparator on List<T> (here the LexComp<T>) will give priority to another index array. The comparator should always fulfill at least the transitivity constraint: if x is less than y and y is less than z: x must be less than z. Furthermore the list of indices will always increase. An index array of [4,1,0] is thus impossible.
The correct answer to this question depends a lot on how you define your priorities.
Should we always pick the first group in the line if possible or is the optimal solution to have as many people from the front of the queue?
I.e. given
1, 2, 2, 3, 3, 4, 2, 2, 3, 1
is the optimal solution
1, 2, 1
or
1, 3
To get you started, here's a recursive solution that does the first:
private static List<Integer> getSumIndices(int sum, List<Integer> queue) {
return getSumIndices(sum, new ArrayList<>(queue), 0);
}
private static List<Integer> getSumIndices(int sum, List<Integer> queue, int offset) {
System.out.printf("Looking for sum %s in values of %s with offset %s%n", sum, queue, offset);
if(sum == 0) {
//Base case
return new ArrayList<>();
}
for(int i = 0; i < queue.size(); i++) {
int value = queue.get(i);
// Can we actually use this group
if(value <= sum) {
try {
// See if we can find the remainder if we use this group
ArrayList<Integer> list = new ArrayList<>();
list.add(i + offset);
list.addAll(getSumIndices(sum - value, queue.subList(i + 1, queue.size()), offset + i + 1));
return list;
} catch(IllegalArgumentException e) {
// We couldn 't, continue looking
}
}
}
// We could not construct the sum using the values in the queue
System.out.printf("Failed to construct sum %s from values in %s%n", sum, queue);
throw new IllegalArgumentException(String.format("Could not construct sum %s from values in %s%n", sum, queue));
}
Results:
q=[1, 2, 2, 3, 3, 4, 2, 2, 3, 1]
Looking for sum 4 in values of [1, 2, 2, 3, 3, 4, 2, 2, 3, 1] with offset 0
Looking for sum 3 in values of [2, 2, 3, 3, 4, 2, 2, 3, 1] with offset 1
Looking for sum 1 in values of [2, 3, 3, 4, 2, 2, 3, 1] with offset 2
Looking for sum 0 in values of [] with offset 10
Index: Group Size
0: 1
1: 2
9: 1
Remaining q=[2, 3, 3, 4, 2, 2, 3]
q=[1, 2, 3, 2, 3, 4, 2, 2, 3, 2]
Looking for sum 4 in values of [1, 2, 3, 2, 3, 4, 2, 2, 3, 2] with offset 0
Looking for sum 3 in values of [2, 3, 2, 3, 4, 2, 2, 3, 2] with offset 1
Looking for sum 1 in values of [3, 2, 3, 4, 2, 2, 3, 2] with offset 2
Failed to construct sum 1 from values in [3, 2, 3, 4, 2, 2, 3, 2]
Looking for sum 0 in values of [2, 3, 4, 2, 2, 3, 2] with offset 3
Index: Group Size
0: 1
2: 3
Remaining q=[2, 2, 3, 4, 2, 2, 3, 2]
q=[1, 2, 2]
Looking for sum 4 in values of [1, 2, 2] with offset 0
Looking for sum 3 in values of [2, 2] with offset 1
Looking for sum 1 in values of [2] with offset 2
Failed to construct sum 1 from values in [2]
Looking for sum 1 in values of [] with offset 3
Failed to construct sum 1 from values in []
Failed to construct sum 3 from values in [2, 2]
Looking for sum 2 in values of [2] with offset 2
Looking for sum 0 in values of [] with offset 3
Index: Group Size
1: 2
2: 2
Remaining q=[1]
q=[2, 3, 3]
Looking for sum 4 in values of [2, 3, 3] with offset 0
Looking for sum 2 in values of [3, 3] with offset 1
Failed to construct sum 2 from values in [3, 3]
Looking for sum 1 in values of [3] with offset 2
Failed to construct sum 1 from values in [3]
Looking for sum 1 in values of [] with offset 3
Failed to construct sum 1 from values in []
Failed to construct sum 4 from values in [2, 3, 3]
Could not construct sum 4 from values in [2, 3, 3]
You can loop through the list and add in order until it is larger than the value you are looking for.
Code:
public static int addListValues(int[] list, int num){//Returns number which can not be added by anything else in the list to be <= num.
boolean b[] = new boolean[list.length];//List of numbers already taken care of. True for not, false for cleared.
for(int i = 0; i < b.length; i++){
b[i] = true;
}
int count = 0;//Amount of numbers in int[] list which have been added to equal less than or equal to num.
int total = 0;
while(true){//loops until values left can not be added to equal or be less than num.
int check = 0;
for(int i = 0; i < list.length; i++){//Loops through list.
if(b[i]){//If the number has not been added already.
System.out.println("CHECKING: " + i);
if(total + list[i] > num){//Adds to check if the number is greater than num.
check++;
}
if(total + list[i] <= num){//Adds numbers together to equal num or less than num.
System.out.println("TEST: " + list[i] + " TOTAL: " + total);
if(total + list[i] != num){
boolean contains = false;
int index = 0;
for(int o = 0; o < list.length; o++){
if(list[o] == num - total && b[o] && o != i){
contains = true;
index = o;
break;
}
}
if(contains){
System.out.println("1: " + index + ", " + list[index]);
b[index] = false;
count++;
total = 0;
}else{
System.out.println("2");
b[i] = false;
count++;
total+= list[i];
}
}else{
System.out.println("3");
b[i] = false;
count++;
total = 0;
}
}else if(check == list.length - count){//Check if "check" is equal to the amount left over. In other words, if the numbers left are higher than the number you are looking for.
System.out.println("FINAL: 3");
int t = 0;
for(int j = 0; j < list.length; j++){
if(b[j]){
t += list[j];
}
}
return t;//More than one number is left and is higher than num. Returns numbers left added together
}else if(count == list.length-1){
System.out.println("FINAL: 2");
return list[i];//returns list[i] if it is the only number left over.
}
}else if(count >= list.length){
System.out.println("FINAL: 1");
return total;//Returns total if there is nothing left over. The total may be anything less than the "num".
}
}
}
}
I have tested this method with multiple sets of numbers and it works. I was unsure what to return if more than one value were left over and were higher than 4, so I added the left over values and returned this.
This code does not require any imports.