Get consecutive subarray size with largest size - java

I have an array of numbers, now I want to find all the consecutive subarray sums whose value matches with less than or equal to k. I want to return the largest subarray size.
This is my program:
public static int process(List<Integer> arr, int k) {
int size = 0;
for (int i = 0; i < arr.size(); i++) {
int sum = 0;
for (int j = i; j < arr.size(); j++) {
sum += arr.get(j);
if (sum <= k) {
size = Math.max(size, j - i + 1);
}
}
}
return size;
}
constraints:
arr size is between 1 to 100000
array elements are between 1 to 100
k is between 1 to 1000000
Explanation:
Arrays.asList(2, 3, 5, 1, 1, 2, 1), 7
arr = 2, 3, 5, 1, 1, 2, 1
k= 7
possible sub arrays:
[2], [3], [5], [1], [1], [2], [1]
[2,3], [5,1], [1,1], [1,2], [2,1]
[5,1,1], [1,1,2], [1,2,1]
[1,1,2,1]
Maximum sub array is [1,1,2,1] = its length is 4. So program should return 4.
I got this task in a competitive exam last week, when I used this code it has passed only 50% test cases. It failed for some hidden test cases saying wrong output, and some test cases saying time out.
What is the issue with my code?
Update:
Modified my code little bit. And added a sample example.

Nested loops means that performance is O(n2). You need to re-think the algorithm.
Below is an O(n) solution, which I will show by example. Writing the code is still your challenge.
What we need is a way to know the sum of values before a particular index. With that we can calculate sumRange(i, j) = sumBefore(j) - sumBefore(i).
Since we're looking for sumRange(i, j) = k, we need to check if we have a sumBefore(i) = sumBefore(j) - k. If we do, we have a candidate range with size = j - i.
So, iterate the values and calculate the accumulated sum. Build a Map of accSum to indexAfter the value leading to that accumulated sum.
Say the array is [1, 6, 5, 3, 2, 8, 4, 2, 7, 1] and k = 13:
Index: 0 1 2 3 4 5 6 7 8 9
Value: 1 6 5 3 2 8 4 2 7 1
accSum: 0 1 7 12 15 17 25 29 31 38 39 sumBefore
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
indexAfter: 0 1 2 3 4 5 6 7 8 9 10 index
Adding the dummy 0 → 0 mapping just simplifies the logic of your code.
As you iterate, you have the accumulated sum up to now, inclusive, i.e. sumBefore(i + 1), so look to see if we have a range, i.e. sumBefore(x) = sumBefore(i + 1) - k = accSum - k, so look in the map for accSum - k, and if found, the value is x, meaning we have a candidate range of x, i+1.
I hope that all made sense.
UPDATE
The question was changed to look for sums <= k, not just sums exactly equal to k.
This is easily done with the logic above by changing the Map to a TreeMap, or more specifically a NavigableMap, and replace the get() call with a ceilingEntry() call:
Returns a key-value mapping associated with the least key greater than or equal to the given key, or null if there is no such key.
If the returned key (sum) is greater than the parameter, the result is a subarray sum that is less than k.

Related

Array Manipulation from HackerRank

I am getting error stating Terminated due to timeout for larger inputs when using ArrayList, for smaller one it works fine.
I watched solutions where they were using PREFIX SUM ALGORITHM and 2-dimension array as parameter. Can we not use ArrayList as parameter instead of array?
Here is the question ---
Starting with a 1-indexed array of zeros and a list of operations, for each operation add a value to each of the array element between two given indices, inclusive. Once all operations have been performed, return the maximum value in your array.
For example, the length of your array of zeros . Your list of queries is as follows:
a b k
1 5 3
4 8 7
6 9 1
Add the values of between the indices and inclusive:
index -> 1 2 3 4 5 6 7 8 9 10
[0,0,0, 0, 0,0,0,0,0, 0]
[3,3,3, 3, 3,0,0,0,0, 0]
[3,3,3,10,10,7,7,7,0, 0]
[3,3,3,10,10,8,8,8,1, 0]
The largest value is returned after all operations are performed.
Here the output will be 10;
My code is
public static long arrayManipulation(int n, List<List<Integer>> queries) {
List<Integer> arr = new ArrayList<Integer>(Collections.nCopies(n+1, 0));
//PREFIX SUM
for(int i = 0; i<queries.size(); i++){
int a = queries.get(i).get(0)-1;
int b = queries.get(i).get(1);
int k = queries.get(i).get(2);
arr.set(a, arr.get(a)+k);
arr.set(b, arr.get(b)-k);
}
long max=0;
for(int i = 1; i < arr.size(); i++)
{
arr.set(i, arr.get(i)+arr.get(i-1));
if(arr.get(i)>max)
{
max=arr.get(i);
}
}
Collections.sort(arr);
return arr.get(n);
}

Path with maximum average value

import java.util.Scanner;
public class maxAvgPath {
public static void main(String [] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] c = new int[n+1][n+1];
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
c[i][j]=sc.nextInt();
}
}
float sum = c[0][0];
float m = 0;
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
if (c[i][j + 1] < c[i + 1][j]) {
sum = sum + c[i + 1][j];
m++;
} else {
sum = sum + c[i][j + 1];
m++;
}
}
}
System.out.println((sum/m));
}
}
Given a square matrix of size N*N, where each cell is associated with a specific cost. A path is defined as a specific sequence of cells which starts from the top-left cell move only right or down and ends on bottom right cell. We want to find a path with the maximum average over all existing paths. Average is computed as total cost divided by the number of cells visited in the path.
Input : Matrix = [1, 2, 3,
4, 5, 6,
7, 8, 9]
Output : 5.8
Path with maximum average is, 1 -> 4 -> 7 -> 8 -> 9
Sum of the path is 29 and average is 29/5 = 5.8
But I am not getting the correct output can some tell where is my mistake?
Your m should always be 2 * n - 1. Regardless of the chosen path, you will always move either right or down, starting from top-left corner. You have n - 1 rows and n - 1 columns, so you're moving right exactly n - 1 and moving down exactly n - 1 times. In total, counting the top-left, you have 1 + (n - 1) + (n - 1) numbers on your ideal path. Therefore, you're not looking for a max average, you're actually looking for a maximum sum.
Your loops are not exactly in sync with what you're trying to do. Let's say, for the given matrix, when i = 0, j is 0, that you discover that 4 is bigger than 2. You pick the 4, m[1][0], and then you should check the max of m[1][1] and m[2][0] ... but your loop moves to ... i = 0, j = 1, allowing you to check m[1][2] and m[1][1].
You're also using a Greedy aproach which won't always give you the best result, e.g. [1 2 9, 3 4 9, 5 2 9], your algorithm will pick 1, move down to 3 and 5 then right to 2 and 9, giving you a total of 20. However, the ideal path is 1, right to 2 and 9, then down to 9 and 9, for a grand total of 30.
One approach to solve this is to keep the loops, but instead of maintaining one sum, you need to keep track of multiple sums and picking a max at every step.
e.g. for [1 2 9, 3 4 9, 5 2 9], you initialize your sum matrix with 0 and start navigating.
For sum[0][0], there is only one possible sum, which is picking up m[0][0]. This continues for the entire 1st row, so your sum matrix is now [1 3 12, 0 0 0, 0 0 0]. For sum[1][0], there is also only one possible sum, moving down from m[0][0], so sum[1][0] is m[0][0] + m[1][0]. And here the fun starts.
For sum[1][1], you need to pick between sum[0][1] and sum[1][0] and add m[1][1]. You will of course pick sum[1][0] (which is really m[0][0] + m[1][0]) and add m[1][1] to it, so sum[1][1] is 8. Therefore, if your maximal path ever travels to r1c1, you know that you've picked the maximum possible sum so far.
I will also highlight the next step, sum[1][2], where you have to pick between sum[0][2] and sum[1][1] and add m[1][2]. We know sum[0][2] is 12, sum[1][1] is 8, so, if our path ever reaches cell r1c2, we know that we need to pick first row entirely and then move down instead(m[0][0], m[0][1], m[0][2], m[1][2]) of moving down and picking the next row (m[0][0], m[1][0], m[1][1], m[1][2]), so your current maximal sum in sum[1][2] is 21 and your sum matrix is [1 3 12, 4 8 21, 0 0 0].
Final row is the same thing:
sum[2][0] = sum[1][0] + m[2][0]
sum[2][1] = max(sum[1][1], sum[2][0]) + m[2][1]
sum[2][2] = max(sum[1][2], sum[2][1]) + m[2][2]
Your sum matrix eventually becomes [ 1 3 12, 4 8 21, 9 11 30 ], therefore your
max is 30. You have picked up 2 * 3 - 1 = 5 numbers, so your average is 6.
Illustrating the sum matrix is also interesting:
1 3 12
4 8 21
9 11 30
If you ever want to determine what was the path you've chosen from top-left to bottom-right, you just need to follow the sums, in descending order(keeping in mind the move-right or move-down rule), 30 -> 21 -> 12 -> 3 -> 1.
I will leave the coding part as an exercise, you have all the details you need.
(sorry for bad formatting and long text)

Find the smallest elements in a matrix and check if they already exist

I have a matrix which is two dimensional. This has exactly four rows and columns. I now want to create a offer, which contains four elements.
A offer can be calculated as follows: Offer1 = Matrix_ce + Matrix_ef + Matrix_fg = (c, e, f, g). The following cost matrix can be seen below. I am now looking for an offer which is the lowest cost. An offer may now contain unequal numbers, i.e. it may not contain the same number. Formally said c ≠ e ≠ f ≠ g
// Note: It looks like every row is the same, but only in this example.
// I have another matrix where all rows are different.
Matrix = [[14 16 18 20]
[14 16 18 20]
[14 16 18 20]
[14 16 18 20]]
Calculation example:
If I now consider the offer, which is [1 2 3 4], If we now apply the offer to the Matrix the procedure is as follows to calculate the cost.
For A:
First I go to row 1 and select the second element there (in this case the number 2 in the cost matrix A).
Then in row 2, column 3 (value: 7)
Then in row 3, column 4 (value: 12)
So the costs for the Offer are Offer = 16 + 18 + 20 = 54. These are high, so look for the smallest possible order. For example, a better offer would be Offer = [4 1 2 3] = 14 + 16 +18 = 48.
Matrix and
Matrix with explanation
I want to find the I would like to find the items with the small total amount.
How can I now create a offer as low as possible? I have started to create two loops and in this loop always the smallest elements in the matrix should be found, thereby the following conditions must not be violated. For example: Offer1 = Matrix_ce + Matrix_ef + Matrix_fg = (c, e, f, g), c ≠ e ≠ f ≠ g. Such a solution with [1 1 1 1] or [1 2 3 1], ... would not be correct. Does anyone have an idea how to calculate this? There are several solutions, and therefore several offers. However, I am only looking for one.
int[][] matrix = new int[][]{[14,16,18,20],
[14,16,18,20],
[14,16,18,20],
[14,16,18,20]}
int[] elements = new int[matrix.length];
int[] offer = new int[matrix.length];
for(int i=0; i<matrix.length; i++) {
for(int j=0; j<matrix[i].length; i++) {
// What is the best way to find the smallest elements?
Check that values are not duplicated, if the value is already present, skip it.
//if(Arrays.asList(elements).contains(matrix[i][j])) {
// continue;
//}
}
}
System.out.println(Arrays.toString(offer));
int min = matrix[0];
int lowestIndex = 0;
for(int j = 1; j < matrix[i].length; j++){
if(matrix[I][j] < min){
lowestIndex = j;
min = matrix[j];
}
}

Selection sort comparisons and swaps on an already sorted list

One of the questions in my sample final paper is: How many comparisons and swaps do selection sort algorithm make if the input, of size n, is already sorted? Show your work how you derive the numbers. Assume swap is done only when it is necessary. https://imgur.com/a/bemaL
My logic for {1, 3, 4, 5, 7} is that
1 is compared to 3 4 5 7, so n-1 comparisons and 0 swaps
3 is compared to 4 5 7, so n-2 comparisons and 0 swaps
4 compared to 5 7, so n-3 comparisons and 0 swaps
5 is compared to 7, so n-4 comparisons and 0 swaps.
So the number of comparisons would n-1 + n-2 + n-3 + n-4. And the number of swaps would be zero.
Is my logic correct? And if so, how do I answer this question for any n length elements?
No your logic is wrong. You don't understand how it works.These are two loops for insertion sort.
for (int i = 0; i < n; i++) {
for (int j = i; j > 0 && less(a[j], a[j-1]); j--) {
exch(a, j, j-1);
}
assert isSorted(a, 0, i);
1 is not compare to 3 4 5 but 3 is compared to 1 and since it is greater then inner for loop breaks, then 4 is compare to 3 since 4 > 3 then again inner loops breaks.
Try to plug in values and see that inner loop will break and no exchange will take place. So in total you have O(n-1) compares which is O(n).
If you reverse the input array then it will have worst time complexity, namely O(n^2) compares and swaps.

Algorithm to partition a list into groups

I have a list of names.
I want to partition this list into groups of a specified size. All groups should be equal to or less than the specified size, with an equal as possible group size across the groups, and as close to the specified size as possible.
What algorithm (Java-esque pseudo code if possible please!) determines the most appropriate group sizes?
For example:
List contains 13 names - max team size 3.
Output (group sizes): 3, 3, 3, 2, 2
List contains 13 names - max team size 4.
Output: 4, 3, 3, 3
List contains 31 names - max team size 5.
Output: 5, 5, 5, 4, 4, 4, 4
List contains 31 names - max team size 6.
Output: 6, 5, 5, 5, 5, 5
List contains 31 names - max team size 10.
Output: 8, 8, 8, 7
It's pretty straightforward. You calculate the result of N div M and add 1 to have the correct number of arrays (N is the list length and M the max team size), then you iterate on all arrays to add an item until you run out of items
example : 43 names, max team number 4 => 43 mod 4 + 1 = 11, remains 3. so 11 arrays (10 with 4 and 1 with 3)
I'm not going to write code for this, but
If the list size is a multiple of the max team size, divide by team size to get the number of groups, all of max size, and stop.
Integer-divide the list size by the max team size, then add one. That's the number of groups.
Subtract the list size from that next higher multiple; that's the number of teams that are one less than the max size.
This obviously only works for inputs that are close to working out; it fails if the max team size is large compared to the size of the list.
If the number of items in the list is N and the max number of items in sublist is K, the solution of your problem comes from solving a Linear Diophantine Equation
K*x + (K-1)*y = N
with additional constraints
x > 0
y >= 0
Where x is the number of sublists of the exact size K, and y is the number of sublists of length K-1.
EDIT : Because of the coefficients to the equation are always off by one from each other, the solution is rather straightforward:
int m = (N+K-1)/K;
int x = N - (K-1)*m; // Number of "full" lists
int y = K*M - N; // Number of off-by-one lists
Example 1:
N = 31, K = 5
m = (31+5-1)/5 = 7
x = 31 - (5-1)*7 = 3 // 3 lists of 5 items
y = 5*7 - 31 = 4 // 4 lists of 4 items
Example 2:
N = 32, K = 4
m = (32+4-1)/4 = 8
x = 32 - (4-1)*8 = 8 // 8 lists of 4 items
y = 4*8 - 32 = 0 // no lists of 3 items
Look up an algorithm for solving linear Diophantine equations on the net - it is not that complicated, if you understand Euclidean algorithm well. The number of solutions of the equation without constraints is infinite, but once you add the constraints, you should get a single solution.
public class Q {
public static void q(int size, int maxTeamSize) {
int numOfTeams = size / maxTeamSize;
int mod = size % maxTeamSize;
numOfTeams += (mod > 0) ? 1 : 0;
System.out.print("\n(" + size + ":" + maxTeamSize + ")");
for (int i = 0; i < numOfTeams; i++) {
System.out.print(" " + (size / numOfTeams + ((i < mod) ? 1 : 0)));
}
}
public static void main(String[] args) {
q(13, 3);
q(12, 4);
q(31, 5);
q(31, 6);
}
}

Categories