I'm trying to write the contents of an array after a method call.
EX:
int[] a1 = {7, 5};
mystery(a1);
int[] a3 = {0, 0, 0, 1, 1, 1};
mystery(a3);
int[] a5 = {-1, 1, -2, 16, 3, -3, -4, 5);
mystery(a5);
I've tried to write the output on paper going over each function for each iteration. But unable to make sense of how the method works.
public static void mystery(int[] a) {
int[] b = new int[2];
for (int i = 0; i < a.length; i++) {
if (a[i] >= 0) {
int x = a[i] % 2;
b[x]++;
a[i] = b[x];
}
}
}
Expected output of array a1 is {1, 2}, but I'm trying to make sense of the process behind reaching these values in the new array.
This loop modifies all the non-negative elements of the array a:
x determines if a[i] is even (0) or odd (1)
b[x]++ increments the counter of even (0) or odd (1) elements
if a[i] is the n'th even number, it is assigned the number n
if a[i] is the m'th odd number, it is assigned the number m
Hence, for an input array of two odd numbers - {7,5} - the output would be {1,2}, since 7 is the 1st non-negative odd number and 5 is the 2nd odd non-negative number.
The method works in the following manner:
It keeps a count of all non-negative even numbers in b[0] and all non-negative odd numbers in b[1]
Now, it modifies the non-negative number in the array "a", such that it now represents as follows:
if a[i] were an even number then it now represents it is Nth even number
if a[i] were an odd number then it now represents it is Mth odd number
Or in other words
b[0] gives the count of all non-negative even numbers in the array "a"
b[1] gives the count of all non-negative odd numbers in the array "a"
a[i] is now the count of all non-negative even/odd numbers encountered before and including a[i].
Whether a[i] gives the occurrence of even or odd number can't be determined as the existing values are overwritten. You need to have a copy of original a[i] to determine that!
Please note it makes no changes to the "a[i]" if it were a negative number
Related
I'm working on the following task.
Given an array of n integers and two integer numbers m and k.
You can add any positive integer to any element of the array such that
the total value does not exceed k.
The task is to maximize the
multiples of m in the resultant array.
Consider the following example.
Input:
n = 5, m = 2, k = 2, arr[] = [1, 2, 3, 4, 5]
Let's add 1 to the element arr[0] and 1 to arr[2] then the final array would be:
[2, 2, 4, 4, 5]
Now there are four (4) elements which are multiples of m (2).
I am not getting correct output.
My code:
public class Main {
public static void main(String[] args) {
int n = 5;
int m = 4;
int k = 3;
int count = 0;
int[] arr = {17, 8, 9, 1, 4};
for (int i = 0; i < n; i++) {
for (int j = 0; j <= k; j++) {
// check initial
if (arr[i] % m == 0) {
break;
}
// add
arr[i] = arr[i] + j;
// check again
if (arr[i] % m == 0) {
count++;
break;
}
}
}
System.out.println("Final Array : " + Arrays.toString(arr));
System.out.println("Count : " + count);
}
}
This task boils down to a well-known Dynamic programming algorithm called Knapsack problem after a couple of simple manipulations with the given array.
This approach doesn't require sorting and would be advantages when k is much smaller n.
We can address the problem in the following steps:
Iterate over the given array and count all the numbers that are already divisible by m (this number is stored in the variable count in the code below).
While iterating, for every element of the array calculate the difference between m and remainder from the division of this element by m. Which would be equal to m - currentElement % m. If the difference is smaller or equal to k (it can cave this difference) it should be added to the list (differences in the code below) and also accumulated in a variable which is meant to store the total difference (totalDiff). All the elements which produce difference that exceeds k would be omitted.
If the total difference is less than or equal to k - we are done, the return value would be equal to the number of elements divisible by m plus the size of the list of differences.
Otherwise, we need to apply the logic of the Knapsack problem to the list of differences.
The idea behind the method getBestCount() (which is an implementation Knapsack problem) boils down to generating the "2D" array (a nested array of length equal to the size of the list of differences +1, in which every inner array having the length of k+1) and populating it with maximum values that could be achieved for various states of the Knapsack.
Each element of this array would represent the maximum total number of elements which can be adjusted to make them divisible by m for the various sizes of the Knapsack, i.e. number of items available from the list of differences, and different number of k (in the range from 0 to k inclusive).
The best way to understand how the algorithm works is to draw a table on a piece of paper and fill it with numbers manually (follow the comments in the code, some intermediate variables were introduced only for the purpose of making it easier to grasp, and also see the Wiki article linked above).
For instance, if the given array is [1, 8, 3, 9, 5], k=3 and m=3. We can see 2 elements divisible by m - 3 and 9. Numbers 1, 8, 5 would give the following list of differences [2, 1, 1]. Applying the logic of the Knapsack algorithm, we should get the following table:
[0, 0, 0, 0]
[0, 0, 1, 1]
[0, 1, 1, 2]
[0, 1, 2, 2]
We are interested in the value right most column of the last row, which is 2 plus 2 (number of elements divisible by 3) would give us 4.
Note: that code provided below can dial only with positive numbers. I don't want to shift the focus from the algorithm to such minor details. If OP or reader of the post are interested in making the code capable to work with negative number as well, I'm living the task of adjusting the code for them as an exercise. Hint: only a small change in the countMultiplesOfM() required for that purpose.
That how it might be implemented:
public static int countMultiplesOfM(int[] arr, int k, int m) {
List<Integer> differences = new ArrayList<>();
int count = 0;
long totalDiff = 0; // counter for the early kill - case when `k >= totalDiff`
for (int next : arr) {
if (next % m == 0)
count++; // number is already divisible by `m` we can increment the count and from that moment we are no longer interested in it
else if (m - next % m <= k) {
differences.add(m - next % m);
totalDiff += m - next % m;
}
}
if (totalDiff <= k) { // early kill - `k` is large enough to adjust all numbers in the `differences` list
return count + differences.size();
}
return count + getBestCount(differences, k); // fire the rest logic
}
// Knapsack Algorithm implementation
public static int getBestCount(List<Integer> differences, int knapsackSize) {
int[][] tab = new int[differences.size() + 1][knapsackSize + 1];
for (int numItemAvailable = 1; numItemAvailable < tab.length; numItemAvailable++) {
int next = differences.get(numItemAvailable - 1); // next available item which we're trying to place to knapsack to Maximize the current total
for (int size = 1; size < tab[numItemAvailable].length; size++) {
int prevColMax = tab[numItemAvailable][size - 1]; // maximum result for the current size - 1 in the current row of the table
int prevRowMax = tab[numItemAvailable - 1][size]; // previous maximum result for the current knapsack's size
if (next <= size) { // if it's possible to fit the next item in the knapsack
int prevRowMaxWithRoomForNewItem = tab[numItemAvailable - 1][size - next] + 1; // maximum result from the previous row for the size = `current size - next` (i.e. the closest knapsack size which guarantees that there would be a space for the new item)
tab[numItemAvailable][size] = Math.max(prevColMax, prevRowMaxWithRoomForNewItem);
} else {
tab[numItemAvailable][size] = Math.max(prevRowMax, prevColMax); // either a value in the previous row or a value in the previous column of the current row
}
}
}
return tab[differences.size()][knapsackSize];
}
main()
public static void main(String[] args) {
System.out.println(countMultiplesOfM(new int[]{17, 8, 9, 1, 4}, 3, 4));
System.out.println(countMultiplesOfM(new int[]{1, 2, 3, 4, 5}, 2, 2));
System.out.println(countMultiplesOfM(new int[]{1, 8, 3, 9, 5}, 3, 3));
}
Output:
3 // input array [17, 8, 9, 1, 4], m = 4, k = 3
4 // input array [1, 2, 3, 4, 5], m = 2, k = 2
4 // input array [1, 8, 3, 9, 5], m = 3, k = 3
A link to Online Demo
You must change 2 line in your code :
if(arr[i]%m==0)
{
count++; // add this line
break;
}
// add
arr[i]=arr[i]+1; // change j to 1
// check again
if(arr[i]%m==0)
{
count++;
break;
}
The first is because the number itself is divisible.
and The second is because you add a number to it each time.That is wrong.
for example chenge your arr to :
int[] arr ={17,8,10,2,4};
your output is :
Final Array : [20, 8, 16, 8, 4]
and That is wrong because 16-10=6 and is bigger than k=3.
I believe the problem is that you aren't processing the values in ascending order of the amount by which to adjust.
To solve this I started by using a stream to preprocess the array. This could be done using other methods.
map the values to the amount to make each one, when added, divisible by m.
filter out those that equal to m' (already divisible by m`)
sort in ascending order.
Once that is done. Intialize max to the difference between the original array length and the processed length. This is the number already divisible by m.
As the list is iterated
check to see if k > amount needed. If so, subtract from k and increment max
otherwise break out of the loop (because of the sort, no value remaining can be less than k)
public static int maxDivisors(int m, int k, int[] arr) {
int[] need = Arrays.stream(arr).map(v -> m - v % m)
.filter(v -> v != m).sorted().toArray();
int max = arr.length - need.length;
for (int val : need) {
if (k >= val) {
k -= val;
max++;
} else {
break;
}
}
return max;
}
int m = 4;
int k = 3;
int[] arr ={17,8,9,1,4};
int count = maxDivisors(m, k, arr);
System.out.println(count);
prints
3
I have two arrays and I am trying to assign the values of one array, i.e. arrayOne[0] should be equal to the corresponding index in arrayTwo[0].
I am trying to do this using a forloop so that it loops through the the index of one array assigning the values sequentially.
so far I have:
for (int a =0; a< arrayOne.length; ++) {
// this sets the an int that loops through the value of the arrays(both arrayOne and arrayTwo are the same length)
I am lost however after this how to create the for loop which assigns index 0 = 0 and then incrementally step through this.
I know this is a very basic question but I am, as my name suggests, struggling to learn coding.
I am lost however after this how to create the for loop which assigns index 0 = 0 and then incrementally step through this.
There are many ways to copy arrays. But since you specifically asked for a for loop solution, just create a new array of the same size and use a for loop as shown to index them.
int [] a = {1,2,3,4,5,6,7};
int [] b = new int[a.length];
for (int i = 0; i < a.length; i++) {
b[i] = a[i]; // this copies element a[i] to b[i] where i is the index.
}
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(b));
Prints
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7]
I have done this with consecutive subarray but to find sum of subarray of size k and of every possibility is difficult and I have been facing dead ends.
Please help me out here.
for(int i=0;i<n;i++)
{
a[i] = sc.nextInt();
}
Arrays.sort(a);
for(int j=0;j<k;j++)
{
sum = sum + a[j];
}
}
System.out.println(sum);
This is something I am trying to do get minimum sum but I don't know how can I get subarray of size k.
Now I want to count how many times the subarray size sum repeats in the array.
For Example :
Given array [2, 5, 9, 7, 6, 3] and subarray of length k = 3; Than we have to find check for every possibility sum in the array like [2, 5, 9] = 16; [2, 9, 7] = 18; [5, 6, 3] = 14...Same goes to each number checking for each subsequence of subarray of size k.
In general there are two variants of this problem. I'll present solutions to both to help future readers. You're looking for the smallest sum (others may want largest sum) for an arbitrary subarray (pick any K elements). Another common, similar problem is to find the smallest or largest sum for a contiguous subarray of either given (pick k adjacent elements) or arbitrary length.
Arbitrary Subarray
You can solve this in O(n Log n) time. Sort the subarray then sum the last k elements in the sorted array.
By sorting, the largest elements are at the end of the sorted array. You get the largest sum by summing the largest elements.
That is what your code appears to do.
Contiguous Subarray
K adjacent elements
You can solve this in O(n) time by computing the sum of a sliding window across your array. The first window consists of the elements at index 0..(k-1) and the last of elements (n-2)..n.
Compute the sum for the first window.
For each additional window:
The sum of that window is the sum of the previous window, subtracting the element that just fell out (array element just below the start of the window), and adding the element that was just included (array element that just became included in the current window).
Take the min or max (as needed) of the current window sum and the highest sum recorded so far. That's your current lowest or highest sum.
After processing the last window, your min or max variable represents the lowest or highest sum (as appropriate). If needed, you can also record the starting index of that window whenever max changes.
Arbitrary number of adjacent elements
Interestingly, the highest sum for a subarray of arbitrary length can also be calculated in O(n) time using a clever approach known as Kadane's algorithm.
We can do this:
from itertools import combinations
from heapq import nsmallest
from math import factorial
arr = [2, 3, 2, 1, 1, 1, 1, 1, 2]
k = 3
def optimal(arr, k):
if len(arr) < k:
return 0
k_smallest_elements = nsmallest(k, arr) # n * log(k)
needed_count = k_smallest_elements.count(k_smallest_elements[k - 1])
actual_count = arr.count(k_smallest_elements[k - 1])
# Return actual_count Choose needed_count.
return factorial(actual_count) // factorial(needed_count) // factorial(actual_count - needed_count)
def sub_optimal(arr, k):
if len(arr) < k:
return 0
arr = sorted(arr) # n * log(n)
needed_count = arr[:k].count(arr[k - 1])
actual_count = arr.count(arr[k - 1])
# Return actual_count Choose needed_count.
return factorial(actual_count) // factorial(needed_count) // factorial(actual_count - needed_count)
def brute_force(arr, k):
min_sum = sum(sorted(arr)[:k])
return len([k_len_subset for k_len_subset in combinations(arr, k) if sum(k_len_subset) == min_sum])
count = optimal(arr, k)
assert count == sub_optimal(arr, k) == brute_force(arr, k) # Remove this line in production.
print(count)
Most of the time, problems like "obtain all the non-contiguous subsequences of length K in an array" or "split an array into K subarray" have an extra condition which you should consider it to find an approach.
here your approach is to sort the array in increasing order and calculate the sum of the first K element.
sm = 0
k = 3
arr = [2, 5, 9, 7, 6, 3]
arr.sort()
for i in range(k):
sm += arr[i]
print(sm)
A question in the Barron's APCS book asks to consider the following program segment:
// Precondition: a[0]...a[n-1] is an initialized array of integers, and 0 < n <= a.length.
int c = 0;
for (int i = 0; i < n; i++) {
if (a[i] >= 0) {
a[c] = a[i];
c++;
}
}
n = c;
Given the segment, I am supposed to choose the best postcondition for the segment. The postconditions given are:
A) a[0]...a[n-1] has been stripped of all positive integers.
B) a[0]...a[n-1] has been stripped of all negative integers.
D) a[0]...a[n-1] has been stripped of all nonnegative integers.
C) a[0]...a[n-1] has been stripped of all occurrences of zero.
E) The updated value of n is less than or equal to the value of n before execution of the segment.
The book says the correct answer is B. Why is that? If array a were to contain only negative integers, the value of n at the end of the segment would be 0, and a[0]...a[n-1] would then be a[0]...a[-1].
The answer of the book is wrong.
The correct answer is E.
Suppose n = 5, and you have 5 values a[i = 0, 4] = {-1, -2, -3, 4, 5}
After execution the value of a[i] are: {4, 5, -3, 4, 5}
And n = c = 2
The function read: Loop through the list, if a non-negative int found (n >= 0) then update the beginner of array with a copy value of it.
Hence c = non-negative int count
From this observation, you can choose the correct answer then.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Right now I'm trying to write a function that takes an array and an integer n, and gives a list of each size n combination (so a list of int arrays). I am able to write it using n nested loops, but this only works for a specific size of subset. I can't figure out how to generalize it to work for any size of combination. I think I need to use recursion?
This is the code for all combinations of 3 elements, and I need an algorithm for any number of elements.
import java.util.List;
import java.util.ArrayList;
public class combinatorics{
public static void main(String[] args) {
List<int[]> list = new ArrayList<int[]>();
int[] arr = {1,2,3,4,5};
combinations3(arr,list);
listToString(list);
}
static void combinations3(int[] arr, List<int[]> list){
for(int i = 0; i<arr.length-2; i++)
for(int j = i+1; j<arr.length-1; j++)
for(int k = j+1; k<arr.length; k++)
list.add(new int[]{arr[i],arr[j],arr[k]});
}
private static void listToString(List<int[]> list){
for(int i = 0; i<list.size(); i++){ //iterate through list
for(int j : list.get(i)){ //iterate through array
System.out.printf("%d ",j);
}
System.out.print("\n");
}
}
}
This is a well-studied problem of generating all k-subsets, or k-combinations, which can be easily done without recursion.
The idea is to have array of size k keeping sequence of indices of elements from the input array (which are numbers from 0 to n - 1) in increasing order. (Subset then can be created by taking items by these indices from the initial array.) So we need to generate all such index sequences.
First index sequence will be [0, 1, 2, ... , k - 1], on the second step it switches to [0, 1, 2,..., k], then to [0, 1, 2, ... k + 1] and so on. The last possible sequence will be [n - k, n - k + 1, ..., n - 1].
On each step, algorithm looks for the closest to the end item which can be incremented, increments it and fills up items right to that item.
To illustrate, consider n = 7 and k = 3. First index sequence is [0, 1, 2], then [0, 1, 3] and so on... At some point we have [0, 5, 6]:
[0, 5, 6] <-- scan from the end: "6" cannot be incremented, "5" also, but "0" can be
[1, ?, ?] <-- "0" -> "1"
[1, 2, 3] <-- fill up remaining elements
next iteration:
[1, 2, 3] <-- "3" can be incremented
[1, 2, 4] <-- "3" -> "4"
Thus, [0, 5, 6] is followed by [1, 2, 3], then goes [1, 2, 4] etc.
Code:
int[] input = {10, 20, 30, 40, 50}; // input array
int k = 3; // sequence length
List<int[]> subsets = new ArrayList<>();
int[] s = new int[k]; // here we'll keep indices
// pointing to elements in input array
if (k <= input.length) {
// first index sequence: 0, 1, 2, ...
for (int i = 0; (s[i] = i) < k - 1; i++);
subsets.add(getSubset(input, s));
for(;;) {
int i;
// find position of item that can be incremented
for (i = k - 1; i >= 0 && s[i] == input.length - k + i; i--);
if (i < 0) {
break;
}
s[i]++; // increment this item
for (++i; i < k; i++) { // fill up remaining items
s[i] = s[i - 1] + 1;
}
subsets.add(getSubset(input, s));
}
}
// generate actual subset by index sequence
int[] getSubset(int[] input, int[] subset) {
int[] result = new int[subset.length];
for (int i = 0; i < subset.length; i++)
result[i] = input[subset[i]];
return result;
}
If I understood your problem correctly, this article seems to point to what you're trying to do.
To quote from the article:
Method 1 (Fix Elements and Recur)
We create a temporary array ‘data[]’ which stores all outputs one by
one. The idea is to start from first index (index = 0) in data[], one
by one fix elements at this index and recur for remaining indexes. Let
the input array be {1, 2, 3, 4, 5} and r be 3. We first fix 1 at index
0 in data[], then recur for remaining indexes, then we fix 2 at index
0 and recur. Finally, we fix 3 and recur for remaining indexes. When
number of elements in data[] becomes equal to r (size of a
combination), we print data[].
Method 2 (Include and Exclude every element)
Like the above method, We create a temporary array data[]. The idea
here is similar to Subset Sum Problem. We one by one consider every
element of input array, and recur for two cases:
The element is included in current combination (We put the element in data[] and increment next available index in data[])
The element is excluded in current combination (We do not put the element and do not change index)
When number of elements in data[] become equal to r (size of a
combination), we print it.