Max subarray hints needed - java

Find the contiguous subarray within an array (containing at least one
number) which has the largest sum.
For example, given the array [-2,1,-3,4,-1,2,1,-5,4], the contiguous
subarray [4,-1,2,1] has the largest sum = 6.
I am unable to solve this problem, but I would just like some hints.
It it said this can be solved using Dynamic Programming, but I am struggling to see a connection.
Would the DP connection be taking the sum of the whole array?

A reference for your problem can be found here.
You must use the Kadane's algorithm to solve such a case, which goes something like this:
Initialize:
max_so_far = 0
max_ending_here = 0
Loop for each element of the array
(a) max_ending_here = max_ending_here + a[i]
(b) if(max_ending_here < 0)
max_ending_here = 0
(c) if(max_so_far < max_ending_here)
max_so_far = max_ending_here
return max_so_far
A sample code for your reference:
static int maxSubArraySum(int a[])
{
int size = a.length;
int max_so_far = Integer.MIN_VALUE, max_ending_here = 0;
for (int i = 0; i < size; i++)
{
max_ending_here = max_ending_here + a[i];
if (max_so_far < max_ending_here)
max_so_far = max_ending_here;
if (max_ending_here < 0)
max_ending_here = 0;
}
return max_so_far;
}

PLease find Java Code.
public static void findMaxSubArray(int arr[]){
int max_end_her=arr[0];
int max_so_far=arr[0];
int x=arr[0];
for(int i=1;i<arr.length;i++){
max_end_her=Math.max(x, max_end_her+arr[i]);
max_so_far=Math.max(max_so_far, max_end_her);
}
System.out.println(max_so_far);
}

Related

Implementation of Kadane's Algorithm is not working for one particular array

Below is the code snippet: see that the maximum sum of sub array is 6 but it is getting calculated as 7.
So Kadane's algorithm is failing here?!
public class KadaneAlgo {
public static void main(String[] args) {
int maxSUm = maxSumSubArray(new int []{2,2,2,-2,-2,3,2});
System.out.println(maxSUm); // prints 7
}
static int maxSumSubArray(int [] a){
int size = a.length;
int max_so_far = Integer.MIN_VALUE, max_ending_here = 0;
for (int i = 0; i < size; i++)
{
max_ending_here = max_ending_here + a[i];
if (max_so_far < max_ending_here)
max_so_far = max_ending_here;
if (max_ending_here < 0)
max_ending_here = 0;
}
return max_so_far;
}
}
According to wiki, the correct answer is 7 so the code is correct.
Why? Because subarray also includes the min and max bounds of the array:
A[0..n] -> find subarray with bounds i,j where 0<=i<=j<=n; and in your case i=0 and j=6 (the whole array)
There is nothing wrong with the code, the correct answer is 7 by adding all the numbers together.

Largest number in k swaps

Given a number K and string str of digits denoting a positive integer, build the largest number possible by performing swap operations on the digits of str at most K times.
Example 1:
Input:
K = 4
str = "1234567"
Output:
7654321
Explanation:
Three swaps can make the
input 1234567 to 7654321, swapping 1
with 7, 2 with 6 and finally 3 with 5
I am trying to solve it using two loops. For every index i, I am finding the largest integer between (i+1)th index to (N-1)th index, where N is the size of string. If the largest number is greater than arr[i], then swap it. Below is the code I have written.
public static String findMaximumNum(String str, int k) {
int N = str.length();
int[] arr = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = Integer.valueOf(str.charAt(i) + "");
}
int swaps = 0;
for (int i = 0; i < N - 1; i++) {
if(swaps == k)
break;
int maxIndex = findMaxInRange(arr, i + 1, N - 1);
if (arr[i] < arr[maxIndex]) {
swap(arr, i, maxIndex);
swaps++;
}
}
String out = "";
for (int i = 0; i < N; i++) {
out = out + arr[i] + "";
}
return out;
}
private static int findMaxInRange(int[] arr, int i, int j) {
int max = Integer.MIN_VALUE;
int maxIndex = i;
for (int k = i; k <= j; k++) {
if (arr[k] >= max) {
max = arr[k];
maxIndex = k;
}
}
return maxIndex;
}
private static void swap(int[] arr, int i, int j) {
System.out.println("swapping "+arr[i]+" and "+arr[j]+" from "+Arrays.toString(arr));
int ch = arr[i];
arr[i] = arr[j];
arr[j] = ch;
}
public static void main(String[] args) {
System.out.println(findMaximumNum("61892795431", 4));
}
It is failing for few test cases. One of the test cases where it is failing is
Input:
4
61892795431
Its Correct output is:
99876215431
And MyCode's output is:
99876125431
I am not able to figure out how the output is '99876215431' and what is wrong in my approach. Please help me understand. Thanks a lot in advance :)
The basic steps how to solve this problem:
0. cast string to array of integers
make a loop K times
in this loop go from i+1 (LOOP VAR) to end of a collection and search for higher value
when we find higher value then collection[i], we will remember its value and index on witch it is. Important thing to note is that we want to swap biggest number but i also has to be last possible number.
at the end of iteration we swap the elements (i with best index)
we are done so all its left is convert our int list back to string.
code: (its python because java is pain)
def sort(swaps, string):
l = list(map(int, list(string)))
print(l)
for i in range(swaps):
best = l[i] + 1
bestIndex = i
for j in range(i+1, len(l)):
if best <= l[j]:
best = l[j]
bestIndex = j
print(i, bestIndex)
l[i], l[bestIndex] = l[bestIndex], l[i]
return "".join(map(str, l))
print(sort(4, "61892795431"))
Your code is correct. The problem comes from the parameter 4 (max number of swaps). If you use 10, the sorting is completed successfully.
Maybe the deeper problems comes from the fact that you are comparing the swaps of your algorithm with the swaps that you would do efficiently to sort the numbers. Your algorithm may work but probably it is not the most efficient, so the number of swaps needed is above the optimum.

After counting sort the result array has one more element (0) than the original one

So I have a problem, this method is supposed to sort an array of integers by using counting sort. The problem is that the resulting array has one extra element, zero. If the original array had a zero element (or several) it's fine, but if the original array didn't have any zero elements the result starts from zero anyway.
e.g. int input[] = { 2, 1, 4 }; result -> Sorted Array : [0, 1, 2, 4]
Why would this be happening?
public class CauntingSort {
public static int max(int[] A)
{
int maxValue = A[0];
for(int i = 0; i < A.length; i++)
if(maxValue < A[i])
maxValue = A[i];
return maxValue;
}
public static int[] createCountersArray(int[] A)
{
int maxValue = max(A) + 1;
int[] Result = new int[A.length + 1];
int[] Count = new int[maxValue];
for (int i = 0; i < A.length; i++) {
int x = Count[A[i]];
x++;
Count[A[i]] = x;
}
for (int i = 1; i < Count.length; i++) {
Count[i] = Count[i] + Count[i - 1];
}
for (int i = A.length -1; i >= 0; i--) {
int x = Count[A[i]];
Result[x] = A[i];
x--;
Count[A[i]] = x;
}
return Result;
}
}
You are using int[] Result = new int[A.length + 1]; which makes the array one position larger. But if you avoid it, you'll have an IndexOutOfBounds exception because you're supposed to do x-- before using x to access the array, so your code should change to something like:
public static int[] createCountersArray(int[] A)
{
int maxValue = max(A) + 1;
int[] Result = new int[A.length];
int[] Count = new int[maxValue];
for (int i = 0; i < A.length; i++) {
int x = Count[A[i]];
x++;
Count[A[i]] = x;
}
for (int i = 1; i < Count.length; i++) {
Count[i] = Count[i] + Count[i - 1];
}
for (int i = A.length -1; i >= 0; i--) {
int x = Count[A[i]];
x--;
Result[x] = A[i];
Count[A[i]] = x;
}
return Result;
}
Here you go: tio.run
int maxValue = max(A) + 1;
Returns the highest value of A + 1, so your new array with new int[maxValue] will be of size = 5;
The array Result is of the lenght A.lenght + 1, that is 4 + 1 = 5;
The first 0 is a predefinied value of int if it is a ? extends Object it would be null.
The leading 0 in your result is the initial value assigned to that element when the array is instantiated. That initial value is never modified because your loop that fills the result writes only to elements that correspond to a positive number of cumulative counts.
For example, consider sorting a one-element array. The Count for that element will be 1, so you will write the element's value at index 1 of the result array, leaving index 0 untouched.
Basically, then, this is an off-by-one error. You could fix it by changing
Result[x] = A[i];
to
Result[x - 1] = A[i];
HOWEVER, part of the problem here is that the buggy part of the routine is difficult to follow or analyze (for a human). No doubt it is comparatively efficient; nevertheless, fast, broken code is not better than slow, working code. Here's an alternative that is easier to reason about:
int nextResult = 0;
for (int i = 0; i < Count.length; i++) {
for (int j = 0; j < Count[i]; j++) {
Result[nextResult] = i;
nextResult++;
}
}
Of course, you'll also want to avoid declaring the Result array larger than array A.

Optimal solution for the maximum single sell profit algorithm

The input array is:
A[0] = 23171
A[1] = 21015
A[2] = 21123
A[3] = 21366
A[4] = 21013
A[5] = 21367
Mission is to find maximum profit. E.g A[3] - A[2] = 243
and my code is:
class Solution {
int profit = 0;
public int solution(int[] A) {
for (int i = 0;i < A.length; i++){
for (int j = i + 1; j < A.length; j++){
if(A[j] - A[i] > profit)
profit = A[j] - A[i];
}
}
return profit;
}
}
The result is suppose to be 365 but it blows up on larger inputs.
This code has a time complexity of O(N2) but is possible to do with O(N). I can't really see how to avoid nesting here... Any pointers in the right direction appreciated.
You only need to get max value and min value from your array and substract them both, so in a O(N) iteration, get the min and the max values.
class Solution {
public int solution(int[] A) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int i = 0;i < A.length; i++){
if(A[i] > max) max = A[i];
if(A[i] < min) min = A[i];
}
return max - min;
}
}
I think that most of you got it wrong. The problem in the post is the maximum single sell profit problem which is a typical interview question.
The most optimal solution:
public int dynamicProgrammingSingleSellProfit(int[] arr) {
if(arr.length == 0) {
return 0;
}
int profit = 0;
int cheapest = arr[0];
for (int i = 0; i < arr.length; i++) {
cheapest = Math.min(cheapest, arr[i]);
profit = Math.max(profit, arr[i] - cheapest);
}
return profit;
}
It has O(n) time and O(1) space complexity.
If you examine the original question the op is looking for profit and since we can't travel in time (yet) you can't just compare the minimum and the maximum in the array.

IndexOutOfBoundsException

Rather trivial piece of Java code here.. But getting an OutOfBoundsException and I'm not quite sure why? Any help would be great!
Before anyone asks if this is homework, no it isn't it's for exam prep.
import java.util.Scanner;
public class exampractice {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int[] a = {1,2,3};
int min = a[0];
int max = a[0];
for (int i = 0; i <= a.length; i++){
if(a[i] < min)
min = a[i];
else
if(a[i] > max)
max = a[i];
}
System.out.println("Min is"+min+ "\nMax is: " + max);
}
}
It should be < not <=. Zero based indices on an array vary from 0 to length - 1.
Update
Someone in grad school taught me to build up a collection of mental patterns like this and use them; you'll avoid bugs. This one is that any array in a C-like language is always searched as
for(index = 0; index < array.length ; index++)
Having trained myself over the years with this, I saw this bug at, literally, first glance, which is how I got in at the head of the line.
Here's are some more examples, for C:
char aString[MAXLENTH]; // declare a string array
char * aString ;
aString = (char *) malloc(MAXLENGTH]; // or malloc it
// constructing a string with catenation
aString[0] = '\0'; // now either way this is guaranteed an empty string
But of course I should have used another pattern:
if((aString = (char *) malloc(MAXLENGTH) == NULL){
// report out of memory
exit(BAD);
}
Think about what other patterns might be good.
Arrays use 0 based counting and in your for loop you go i<= a.length which means you'll be accessing a element that doesn't exists. just remove the = and your good.
for (int i = 0; i < a.length; i++)
for (int i = 0; i <= a.length; i++)
should be
for (int i = 0; i < a.length; i++)
While a is an array and arrays are zero-based indexed, you have to loop it from 0 to a.length -1. It's enough to change i <= a.length to i < a.length.
for (int i = 0; i < a.length; i++)
i should be between 0 and a.length - 1, since the first element of an array starts with key 0.
So the for condition should be strictly less than instead of less than or equal to a.length.
Your for loop should be < a.length and not <= a.length:
for (int i = 0; i < a.length; i++) {

Categories

Resources