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();
}
}
Related
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.
I am trying to solve the Max Counters codility problem here. In this problem:
You are given N counters, initially set to 0, and you have two possible operations on them:
(i) increase(X) − counter X is increased by 1;
(ii)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:
(i) if A[K] = X, such that 1 ≤ X ≤ N, then operation K is increase(X),
(ii) if A[K] = N + 1 then operation K is max counter.
The goal is to calculate the value of every counter after all operations.
Below is my solution:
// 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 N, int[] A) {
// write your code in Java SE 8
int[] counters = new int[N];
int maxVal = 0;
int MAX_COUNTER = N+1;
for(int i=0;i<A.length;i++) {
if(A[i] == MAX_COUNTER) {
Arrays.fill(counters, maxVal);
} else {
counters[A[i]-1]++;
maxVal = counters[A[i]-1];
}
}
return counters;
}
Codility report shows that the solution produce incorrect output for small_random1 and small_random2.
The way you were updating maxVal was wrong. For example, given integer N = 5 and array A such that:
A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 1
If you run your code, the values of the counters and maxVal after each consecutive operation will be:
(0, 0, 1, 0, 0) maxVal = 1
(0, 0, 1, 1, 0) maxVal = 1
(0, 0, 1, 2, 0) maxVal = 2
(1, 0, 1, 2, 0) maxVal = 1
Clearly, after A[3] the maxVal will still be 2 and not 1. Here I have fixed the issue by updating maxVal correctly:
// you can also use imports, for example:
import java.util.*;
import static java.lang.Math.max;
// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");
class Solution {
public int[] solution(int N, int[] A) {
// write your code in Java SE 8
int[] counters = new int[N];
int maxVal = 0;
int MAX_COUNTER = N+1;
for(int i=0;i<A.length;i++) {
if(A[i] == MAX_COUNTER) {
Arrays.fill(counters, maxVal);
} else {
counters[A[i]-1]++;
maxVal = max(maxVal, counters[A[i]-1]);
}
}
return counters;
}
}
But, with this solution you will not able to pass this test as it will get TIMEOUT ERROR for large inputs. To pass this, you need to use an efficient data structure (e.g., segment-tree with lazy propagation during updates).
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.
I'm trying to execute this so that it prints out the longest sequence of the same number. I've just edited it but it's telling me to place a return statement . Here's my code:
public class A1Q3 {
private static int getLongestRun(int[] array){
int count = 1;
int max = 1;
for (int i = 1; i < array.length; i++) {
if (array[i] == array[i - 1]) {
count++;
} else {
count = 1;
}
if (count > max){
max = count;
}
}
public static void main(String[] args) {
int[] array = new int[]{5, 6, 6, 45, -2, -9, 56};
System.out.println(getLongestRun(array));
}
}
You are missing a closing parenthesis for the getLongestRun() function and a return statement. You want to return the max variable.
Also, instead of
System.out.println(count);
Try:
System.out.println(getLongestRun(array));
to actually use the function you made. Your function is still not correct, however. You are returning the current streak count, not the longest streak count. You correctly reset the count back to 1 after the streak ends, but you need another variable named something like max to store the total maximum in addition to the current streak.
I have been trying to get the range of a Maximum Product of a subarray (studying for job interviews).
This has been already asked here (but no valid answers have been provided).
Getting range of max product subarray using Kadanes algorithm
The trick/algorithm is explained well here: http://www.geeksforgeeks.org/maximum-product-subarray/
I am able to get the maximum product easily, but after a lot of tries, still can't figure out how to get the range (left and right indexes properly). Can anyone please help??
I have pasted my code, so you can just copy and run it quickly..
import java.util.*;
public class ArrayMax {
// maximum product
public static int[] getMaxProduct(int[] list)
{
int max = 1, min = 1, maxProd = 0;
int l = 0, left = 0, right = 0;
for (int i = 0; i < list.length; i++) {
// positive number!
if (list[i] > 0) {
max = max * list[i];
min = Math.min(1, min * list[i]);
}
else if (list[i] == 0) {
max = 1; // reset all
min = 1;
l = i + 1;
}
else {
// hold the current Max
int tempMax = max;
// need to update left here (but how??)
max = Math.max(min * list[i], 1); // [-33, 3]
min = tempMax * list[i]; // update min with prev max
}
// System.out.printf("[%d %d]%n", max, min);
if (max >= maxProd) {
maxProd = max;
right = i;
left = l;
}
}
System.out.println("Max: " + maxProd);
// copy array
return Arrays.copyOfRange(list, left, right + 1);
}
// prints array
public static void printArray(int[] list) {
System.out.print("[");
for (int i = 0; i < list.length; i++) {
String sep = (i < list.length - 1) ? "," : "";
System.out.printf("%d%s", list[i], sep);
}
System.out.print("]");
}
public static void main(String[] args) {
int[][] list = {
{5, 1, -3, -8},
{0, 0, -11, -2, -3, 5},
{2, 1, -2, 9}
};
for (int i = 0; i < list.length; i++) {
int[] res = getMaxProduct(list[i]);
printArray(list[i]);
System.out.print(" => ");
printArray(res);
System.out.println();
}
}
}
Here are sample outputs:
Max: 120
[5,1,-3,-8] => [5,1,-3,-8]
Max: 30
[0,0,-11,-2,-3,5] => [-11,-2,-3,5]
Max: 9
[2,1,-2,9] => [2,1,-2,9]
As you can see, I am getting the maximum product, but the range is wrong.
Case#2, Max is 30 (correct answer: [-2,-3,5], showing: [-11,-2,-3,5])
Case#3, Max is 9 (correct answer: [9], giving: [2,1,-2,9])
Please help.
Easier way is to try to find left position/marker when you have calculated the maxProd (at the end). Your right position is accurate, so set left to right and divide maxProd by list[left] until you hit 1, while decrementing left. Thats when you have reached left.
The following code before the return should solve it.
int temp = maxProd;
left = right;
while (temp != 1) {
temp = temp / list[left--];
}
left++;
// copy array
return Arrays.copyOfRange(list, left, right + 1);
I think you need to keep track of 2 values for l. One will represent the start index for the subarray of numbers that multiply to make max, while the other will represent the start index for the subarray of numbers that multiply to make min.
However, an even easier way is to simply wait until you have found the maximum answer (in maxProd) and its position (in right). At this point you can then loop over the array multiplying the elements of the list until your total reaches maxProd (starting at right and iterating backwards). The last element you multiplied must be the start of the subarray.