I am trying to create a method which returns an int - the value of the largest integer in the sent array.
The way I want this method to work, is to check the first and the last element of the array in a for-loop, and work their way to the middle. So i = first integer, k = last integer. When i = 0, k = n-1 (indexes), when i = 1, k = n-2 if you catch my drift. In every loop it needs to check if a[i]>a[k]. Then they switch places. Then I know that the largest number is in the leading half of the array, and then I want it to check that half, so ultimately the largest int is at index 0.
I tried like this:
public static int maxOfArray(int[] a)
{
int length = a.length;
if(length<1)
throw new NoSuchElementException("Not at least one integer in array");
while (length > 1)
{
int k = length;
for(int i = 0; i < length/2; i++)
{
k--;
if(a[i]<a[k])
{
int j = a[i];
a[i] = a[k];
a[k] = j;
}
}
length /=2;
}
return a[0];
}
..but I don't really get it.. I'm having a hard time "picturing" what's happening here.. But it's not always working.. (though sometimes).
EDIT
Also: The array {6,15,2,5,8,14,10,16,11,17,13,7,1,18,3,4,9,12}; will spit out 17 as the largest number. I realize I have to fix the odd-length bug, but I would like to solve this even-length array first..
A bug is when encountering length is odd.
In these cases, you "miss" the middle element.
Example: for input int[] arr = { 8, 1, 5, 4, 9, 4, 3, 7, 2 }; - the element 9 will be compared and checked against itself, but then you reduce the size of length, you exclude 9 from the array you are going to iterate next.
I believe it can be solved by reducing the problem to ceil(length/2) instead of length/2 (and handling special case of length==1)
The other issue as was mentioned in comments is: you need to iterate up to length/2 rather then up to length, otherwise you are overriding yourself.
Lastly - the sign is wrong.
if(a[i]>a[k])
should be
if(a[i]<a[k])
Remember - you are trying to swap the elements if the first is smaller the the second in order to push the larger elements to the head of your array.
but I don't really get it.. I'm having a hard time "picturing" what's happening here.. But it's not always working.. (though sometimes).
In that case you should use a debugger to step through the code to get a picture of what each line of code does.
What I would do is:
public static int maxOfArray(int[] a) {
int max = a[0];
for (int i : a)
if (max < i)
max = i;
return max;
}
public static int findMaxTheHardWay(int[] array) {
for (int length = array.length; length > 1; length = (length + 1) / 2) {
for (int i = 0; i < length / 2; i++) {
if (array[i] < array[length - i - 1])
array[i] = array[length - i - 1]; // don't need to swap.
}
}
return array[0];
}
public static void main(String... args) {
Random rand = new Random(1);
for (int i = 1; i <= 1000; i++) {
int[] a = new int[i];
for (int j = 0; j < i; j++) a[j] = rand.nextInt();
int max = maxOfArray(a);
int max2 = findMaxTheHardWay(a);
if (max != max2)
throw new AssertionError(i + ": " + max + " != " + max2);
}
}
This is rather a crazy way to solve the problem, but I'll play along.
The problem is in the inner loop.
You start out with i = 0 and k = length - 1.
If a[i] > a[k] you swap them.
...
You end up with k = 0 and i = length - 1
If a[i] > a[k] you swap them.
If you look at that carefully you will notice that if we swapped the elements in the first swap, we will also swap them in the last swap; i.e. we will UNDO the effects of the first swap. And the same applies pair-wise through the entire array slice.
See?
What you need to do is to stop the inner loop half way ... and then take account of the case where length is odd.
By the way, the reason I called this "rather crazy", because the obvious and simple way is much faster: O(N) versus O(NlogN)
int a[] = {1,7,3};
List<Integer> list = Arrays.asList(a);
Integer largest = Collections.max(list);
This will give you Largest number in Array.
Here is a solution that fits the specifications that you want (unlike many other here, humm, humm):
final Integer[] input = {1, 2, 6, 32, 4, 44 ,12, 42, 3, 7, 17, 22, 57, 23, 102, 103 };
int half = (input.length / 2);
int mod = input.length % 2;
while (half >= 0) {
for (int i = 0, j = (half * 2) + mod - 1; i <= half && j >= half; i++, j--) {
if (input[i] < input[j]) {
final int tmp = input[i];
input[i] = input[j];
input[j] = tmp;
}
}
if (half == 0) break;
half = half / 2;
mod = half % 2;
}
//Here, input[0] = the biggest number in the original input.
Edit: Added mod, so it works if the last element is the largest..
I think your code is working, you just have to ceil the length / 2 in case of odd array but my tests return proper result:
package org.devince.largestinteger;
import java.util.NoSuchElementException;
public class LargestInteger {
final static int[] input = {1, 2, 6, 32, 4, 44 ,12, 42, 3, 7, 17, 22, 57, 23, 102, 103 };
// final static int[] input = { 8, 1, 5, 4, 9, 4, 3, 7, 2 };
// final static int[] input = {1,3,7};
/**
* #param args
*/
public static void main(String[] args) {
System.out.println(String.valueOf(maxOfArray(input)));
}
public static int maxOfArray(int[] a)
{
int length = a.length;
if(length<1)
throw new NoSuchElementException("Not at least one integer in array");
while (length > 1)
{
int k = length;
for(int i = 0; i < length; i++)
{
k--;
if(a[i]>a[k])
{
int j = a[i];
a[i] = a[k];
a[k] = j;
}
}
length = (int) Math.ceil(length / 2f);
}
return a[0];
}
}
Why not just store the first value of the array to a variable max.
After that just loop through the array starting from second position till the last ,
in the loop just check if the current value is greater than max or not.If it is greater just assign max that value.
Return max and you have the largest number.
public int FindLargest()
{
int[] num = { 1, 2, 5, 12, 13, 56, 16, 4 };
int max = num[0];
for (int i = 1; i <num.length; i++)
{
if (num[i] > max)
{
max = num[i];
}
}
return max;
}
As the same u can approach like also,
int length = a.length;
while (length > 1)
{
int k = length;
for(int i = 0; i < length; i++)
{
for(int y = k-1; y >= i; y--)
{
if(a[i]<a[y])
{
int j = a[i];
a[i] = a[y];
a[y] = j;
}
}
}
length /=2;
}
final int validSampleRates[] = new int[]{
5644800, 2822400, 352800, 192000, 176400, 96000,
88200, 50400, 50000, 4800,47250, 44100, 44056, 37800, 32000, 22050, 16000, 11025, 4800, 8000};
ArrayList <Integer> YourArray = new ArrayList <Integer> ():
for (int smaple : validSampleRates){
YourArray.add(smaple);
}
Integer largest = Collections.max(YourArray);
System.out.println("Largest " + String.valueOf(largest));
The best way is to use Array that extends List Collection as ArrayList
Related
The problem description:
Given an ArrayList of Integers. Find a subarray with the maximum sum of any potential subarray within the ArrayList.
A subarray a is a combination of consecutive numbers.
The subarray can be of any length n, where the size of n >= 0.
Example
Input:
[-1, 10, -11, -1, 17, 0, 0, 9, 20, 7, -8, -6, -18]
Solution
[17, 0, 0, 9, 20, 0, 7]
Here is the code that I have so far.
public class MaxSubArray {
public ArrayList<Integer> solution(ArrayList<Integer> nums) {
int maxSubArrSum = Integer.MIN_VALUE;
int greatest = Integer.MAX_VALUE;
int smallest = 0;
int start;
int end;
ArrayList<Integer> maxSubArr;
ArrayList<ArrayList<Integer>> lists = new ArrayList();
try {
for (int left = 0; left < nums.size(); left++) {
int runningSum = 0;
for (int right = left; right < nums.size(); right++) {
runningSum += nums.get(right);
if (runningSum >= maxSubArrSum) {
ArrayList<Integer> temp = new ArrayList<>();
maxSubArrSum = runningSum;
start = left;
end = right;
for (int i = start; i <= end; i++) {
temp.add(nums.get(i));
}
lists.add(temp);
}
}
}
for (int i = 0; i < lists.size(); i++) {
if (lists.get(i).size() < greatest) {
greatest = lists.get(i).size();
smallest = i;
}
}
maxSubArr = lists.get(smallest);
return maxSubArr;
} catch (Exception e) {
e.printStackTrace();
return nums;
}
}
}
I am trying to iterate through the nums ArrayList and figuring out the first and last indexes of the subarrays with the maximum sum and putting them in a list of ArrayLists.
After that, I am trying to figure out which of the subarrays has the smallest size and returning it.
What I am doing wrong here?
Here is a more concise solution
private List<Integer> solution(List<Integer> nums) {
int biggestSumSoFar = Integer.MIN_VALUE;
List<Integer> biggestSubListSoFar = new ArrayList<>();
for (int left = 0; left < nums.size(); ++left) {
for (int right = left + 1; right < nums.size(); ++right) {
List<Integer> currentSubList = subListSum(nums, left, right);
int currentSum = sum(currentSubList);
if (currentSum > biggestSumSoFar) {
biggestSumSoFar = currentSum;
biggestSubListSoFar = currentSubList;
}
}
}
return biggestSubListSoFar;
}
private List<Integer> subListSum(final List<Integer> nums, final int left, final int right)
{
final List<Integer> sublist = new ArrayList<>();
for (int i = left; i < right; i++)
{
sublist.add(nums.get(i));
}
return sublist;
}
private int sum(List<Integer> arr) {
int sum = 0;
for(int a : arr){
sum += a;
}
return sum;
}
Adding a third inner for-loop can make the task probably easier. Just think about how you would do it with a pen and paper. Imagine you have an array of 6 elements with indices from 0 to 5, then all possible subarrays would have the following start and end indices (strat inclusive, end exclusive)
0 - 1 1 - 2 2 - 3 3 - 4 4 - 5
0 - 2 1 - 3 2 - 4 3 - 5
0 - 3 1 - 4 2 - 5
0 - 4 1 - 5
0 - 5
Having the above all you need is to calculate the subsum and store the relevant start and end indices
public List<Integer> solution(List<Integer> nums) {
int maxSubArrSum = Integer.MIN_VALUE;
int start = 0;
int end = 0;
for (int left = 0; left < nums.size(); left++){
for (int right = left+1; right < nums.size(); right++){
int subSum = 0;
for (int k = left; k < right; k++){
subSum += nums.get(k);
}
if (subSum > maxSubArrSum){
maxSubArrSum = subSum;
start = left;
end = right;
}
}
}
return nums.subList(start,end);
}
You are quiet close with your approach.
There are two problems with the last part:
int greatest = Integer.MAX_VALUE; should be Integer.MIN_VALUE instead.
You check for the size of a subarray but you have to check for the sum of the subarray.
if you change the last part to:
int greatest = Integer.MIN_VALUE;
for (int i = 0; i < lists.size(); i++) {
if (sum(lists.get(i)) > greatest) {
greatest = lists.get(i).size();
smallest = i;
}
}
by utilizing
public static int sum(List<Integer> arr) {
int sum = 0;
for(int a : arr){
sum += a;
}
return sum;
}
it yields the desired result.
Here is a modified version of Kadane's Algorithm to find the largest sum of contiguous elements in a list. It is adapted from a solution given in Python and works in a single pass.
List<Integer> list = List.of(-1, 10, -11, -1, 17, 0, 0, 9, 20, 7, -8, -6, -18);
List<Integer> subList = maxSubArray(list);
System.out.println(subList);
prints
[17, 0, 0, 9, 20, 7]
public static List<Integer> maxSubArray(List<Integer> list) {
int max = Integer.MIN_VALUE;
int sum = max;
int end = 0;
int cstart = 0, start = 0;
for (int i = 0; i < list.size(); i++) {
int val = list.get(i);
if (sum <= 0) {
sum = val;
cstart = i;
} else {
sum += val;
}
if (sum > max) {
max = sum;
start = cstart;
end = i;
}
}
return list.subList(start,end+1);
}
Basically, you are trying to approach this task with a brute-force algorithm, which in the worse case scenario will have the O(n^2) both time and space complexity.
It could be done with a linear (i.e. O(n)) both time and space complexity, without nested loops.
With this approach, first, we need to find the maximum possible sum of the subarray by using the Kadane's algorithm.
And then perform the iteration with over the source list in a single loop tracking the current sum. When it becomes equal to the maximum sum it would mean the target subarray of consecutive elements was found.
Variables start and end denote the starting and ending indices of the resulting subarray.
Method subList() creates a view over the source list and every modification of the view will be reflected in the source and vice versa. Hence, as a precaution it's being wrapped with with a new instance of ArrayList.
public static List<Integer> solution(List<Integer> nums) {
if (nums.size() == 0) {
return Collections.emptyList();
}
final int maxSum = getMaxSum(nums); // getting max sum by using Kadane's algorithm
int curSum = nums.get(0);
int start = 0; // beginning of the resulting subarray
int end = 0; // end of the resulting subarray exclusive
for (int i = 1; i < nums.size(); i++) {
if (curSum == maxSum) {
end = i;
break; // maximus sub-array was found
}
if (nums.get(i) > curSum + nums.get(i)) {
start = i; // setting start to current index
curSum = nums.get(i); // assigning the current element the sum
} else {
curSum += nums.get(i); // adding the current element to the sum
}
}
return new ArrayList<>(nums.subList(start, end));
}
Kadane's algorithm implementation.
The overall idea is to maintain two variables denoting the global and a local maximum. There are to ways in which the local maximum changes with each iteration, we either
adding the current element to the local maximum;
or assigning the current element's value to the local maximum.
At the end of every iteration, the global maximum is being compared with a local maximum and adjusted if needed.
public static int getMaxSum(List<Integer> nums) {
int maxSum = Integer.MIN_VALUE;
int curSum = nums.get(0);
for (int i = 1; i < nums.size(); i++) {
curSum = Math.max(nums.get(i), curSum + nums.get(i));
maxSum = Math.max(maxSum, curSum);
}
return maxSum;
}
main()
public static void main(String[] args) {
List<Integer> source = List.of(-1, 10, -11, -1, 17, 0, 0, 9, 20, 7, -8, -6, -18);
System.out.println(solution(source));
}
output
[17, 0, 0, 9, 20, 7]
public static int[][] Matrix(int n, int max, int min) {
int[][] grid = new int[3][3];
Random rand = new Random();
rand.setSeed(System.currentTimeMillis());
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
int value = Math.abs((min + rand.nextInt((max - min) + 1)));
grid[i][j] = value;
grid[j][i] = value;
}
}
return grid;
}
The following code prints a 2D symmetric array where the values are random numbers between a range (min and max) which prints the following result as example:
0 14 11
14 0 17
11 17 0
My problem with the code is it only prints 0 as the diagonal value. How can I change it to print the diagonal values where they are set as int min instead of 0? For example, in the code above int min is 8 hence it would give this result:
8 14 11
14 8 17
11 17 8
If you want to set the diagonal to the lower variable, you need to do two things.
One, because you set j < i, j will never equal i, meaning the diagonal will be set to 0 because Java initializes integers to 0 if they aren't given an explicit initialization value. I was able to access the diagonal by simply changing the < to an <=:
for(int i = 0; i < n; i++)
{
for(int j = 0; j <= i; j++)
{
...
}
}
Two, once i equals j, you need to add an if statement that checks for the case where they're equal. When they are, simply set the current grid cell to the lower variable. Don't forget to enclose the other half of the second for code block with an else block or you'll get unintended behavior:
for(int j = 0; j <= i; j++)
{
if(i == j)
{
grid[i][j] = lower;
}
else
{
...
}
}
Finally, your whole for loop block should look like this:
for(int i = 0; i < n; i++)
{
for( int j = 0; j <= i; j++)
{
if(i == j)
{
grid[i][j] = lower;
}
else
{
int value = Math.abs((lower + rand.nextInt((upper - lower) + 1)));
grid[i][j] = value;
grid[j][i] = value;
}
}
}
You are generating random value for all i and j except when i==j, which are the diagonal values. Also, all the values of the diagonals will be same. So before returning the grid, you can generate one last random value and put it to the diagonals. Something like this
int diagonalValue = Math.abs((min+ rand.nextInt((max- min) + 1)));
for( int k=0 ; k<n ; k++)
{
grid[k][k] = diagonalValue;
}
Code review:
Add invalid syntax checks to the beginning of the method;
Math.abs is redundant;
The inner loop should include the upper bound;
Your code might look something like this:
public static int[][] matrix(int n, int max, int min) {
// incorrect matrix size
if (n <= 0)
return new int[][]{{}};
int[][] grid = new int[n][n];
// incorrect random value bound
if (max - min <= 0)
return grid;
Random rand = new Random();
// interval excluding upper bound
IntStream.range(0, n).forEach(i ->
// interval including upper bound
IntStream.rangeClosed(0, i).forEach(j -> {
if (i == j) {
// main diagonal
grid[i][j] = min;
} else {
// peripheral elements
int value = min + rand.nextInt((max - min) + 1);
grid[i][j] = value;
grid[j][i] = value;
}
}));
return grid;
}
public static void main(String[] args) {
Arrays.stream(matrix(5, 9, 1))
.map(Arrays::toString)
.forEach(System.out::println);
}
Output:
[1, 6, 3, 3, 2]
[6, 1, 9, 4, 2]
[3, 9, 1, 6, 7]
[3, 4, 6, 1, 9]
[2, 2, 7, 9, 1]
This is the question:
codility.com/programmers/task/number_solitaire
and below link is my result (50% from Codility):
https://codility.com/demo/results/training8AMJZH-RTA/
My code (at the first, I tried to solve this problem using Kadane's Algo):
class Solution {
public int solution(int[] A) {
int temp_max = Integer.MIN_VALUE;
int max = 0;
int k = 1;
if(A.length == 2) return A[0] + A[A.length-1];
for(int i = 1; i < A.length-1; i++) {
if(temp_max < A[i]) temp_max = A[i];
if(A[i] > 0) {
max += A[i];
temp_max = Integer.MIN_VALUE;
k = 0;
} else if(k % 6 == 0) {
max += temp_max;
temp_max = Integer.MIN_VALUE;
k = 0;
}
k++;
}
return A[0] + max + A[A.length-1];
}
And below is the solution (100% from Codility result) that I found from web:
class Solution {
public int solution(int[] A) {
int[] store = new int[A.length];
store[0] = A[0];
for (int i = 1; i < A.length; i++) {
store[i] = store[i-1];
for (int minus = 2; minus <= 6; minus++) {
if (i >= minus) {
store[i] = Math.max(store[i], store[i - minus]);
} else {
break;
}
}
store[i] += A[i];
}
return store[A.length - 1];
}
}
I have no idea what is the problem with my code:(
I tried several test cases but, nothing different with the solution & my code
but, codility test result shows mine is not perfectly correct.
(https://codility.com/demo/results/training8AMJZH-RTA/)
please anyone explain me the problem with my code~~
Try this test case[-1, -2, -3, -4, -3, -8, -5, -2, -3, -4, -5, -6, -1].
you solution return -4 (A[0],A[1],A[length-1],Here is the mistake), but the correct answer is -6 (A[0],A[6],A[length-1]).
Here is a my solution,easy to understand:
public int solution(int[] A) {
int lens = A.length;
int dp[] = new int[6];
for (int i = 0; i < 6; i++) {
dp[i] = A[0];
}
for (int i = 1; i < lens; i++) {
dp[i%6] = getMax6(dp) + A[i];
}
return dp[(lens-1)%6];
}
private int getMax6(int dp[]){
int max = dp[0];
for (int i = 1; i < dp.length; i++) {
max = Math.max(max, dp[i]);
}
return max;
}
Readable solution from Java:
public class Solution {
public static void main(String[] args) {
System.out.println(new Solution().solution(new int[]{1, -2, 0, 9, -1, -2}));
}
private int solution(int[] A) {
int N = A.length;
int[] dp = new int[N];
dp[0] = A[0];
for (int i = 1; i < N; i++) {
double sm = Double.NEGATIVE_INFINITY;
for (int j = 1; j <= 6; j++) {
if (i - j < 0) {
break;
}
double s1 = dp[i - j] + A[i];
sm = Double.max(s1, sm);
}
dp[i] = (int) sm;
}
return dp[N-1];
}
}
Here is a solution similar to #0xAliHn but using less memory. You only need to remember the last 6 moves.
def NumberSolitaire(A):
dp = [0] * 6
dp[-1] = A[0]
for i in range(1, len(A)):
maxVal = -100001
for k in range(1, 7):
if i-k >= 0:
maxVal = max(maxVal, dp[-k] + A[i])
dp.append(maxVal)
dp.pop(0)
return dp[-1]
Based on the solutions posted, I made nice readable code. Not best performance.
int[] mark = new int[A.length];
mark[0] = A[0];
IntStream.range(1, A.length)
.forEach(i -> {
int max = Integer.MIN_VALUE;
mark[i] = IntStream.rangeClosed(1, 6)
.filter(die -> i - die >= 0)
.map(r -> Math.max(mark[i - r] + A[i], max))
.max().orElse(max);
});
return mark[A.length - 1];
Because you are not using dynamic programming, you are using greedy algorithm. Your code will fail when the max number in a range will not be the right choice.
function solution(A) {
// This array contains a maximal value at any index.
const maxTill = [A[0]];
// It's a dynamic programming so we will choose maximal value at each
// Index untill we reach last index (goal)
for (let i = 1; i < A.length; i++) {
// Step 1 . max value of each index will be atleast equal to or greater than
// max value of last index.
maxTill[i] = maxTill[i - 1];
// For each index we are finding the max of last 6 array value
// And storing it into Max value.
for (let dice = 1; dice <= 6; dice++) {
// If array index is itself less than backtrack index
// break as you dont have 6 boxes in your left
if (dice > i) {
break;
} else {
// The most important line .
// Basically checking the max of last 6 boxes using a loop.
maxTill[i] = Math.max(
maxTill[i - dice],
maxTill[i]
);
}
}
// Until this point maxStill contains the maximal value
// to reach to that index.
// To end the game we need to touch that index as well, so
// add the value of the index as well.
maxTill[i] += A[i];
}
return maxTill[A.length - 1];
}
console.log(solution([-1, -2, -3, -4, -3, -8, -5, -2, -3, -4, -5, -6, -1]));
This is my solution. I try to make the code easy to apprehend. It might not save space as much as it can.
private static int solution(int A[])
{
// N // N is an integer within the range [2..100,000];
// A[] // each element of array A is an integer within the range [−10,000..10,000].
int N = A.length;
int[] bestResult = new int[N]; // record the current bestResult
Arrays.fill(bestResult, Integer.MIN_VALUE); // fill in with the smallest integer value
// initialize
bestResult[0] = A[0];
for (int i = 0;i < A.length;i++) {
// calculate six possible results every round
for (int j = i + 1; (j < A.length) && (i < A.length) && j < (i + 1) + 6; j++) {
// compare
int preMaxResult = bestResult[j]; // the max number so far
int nowMaxResult = bestResult[i] + A[j]; // the max number at bestResult[i] + A[j]
bestResult[j] = Math.max(preMaxResult, nowMaxResult);
}
}
return bestResult[bestResult.length-1];
}
Here is the simple Python 3 solution:
import sys
def solution(A):
dp = [0] * len(A)
dp[0] = A[0]
for i in range(1, len(A)):
maxVal = -sys.maxsize - 1
for k in range(1, 7):
if i-k >= 0:
maxVal = max(maxVal, dp[i-k] + A[i])
dp[i] = maxVal
return dp[len(A)-1]
100% c++ solution(
results)
#include <climits>
int solution(vector<int>& A) {
const int N = A.size();
if (N == 2)
return A[0] + A[1];
vector<int> MaxSum(N, INT_MIN);
MaxSum[0] = A[0];
for (int i = 1; i < N; i++) {
for (int dice = 1; dice <= 6; dice++) {
if (dice > i)
break;
MaxSum[i] = max(MaxSum[i], A[i] + MaxSum[i - dice]);
}
}
return MaxSum[N-1];
}
100% python solution
with the help of the answers above and https://sapy.medium.com/cracking-the-coding-interview-30eb419c4c57
def solution(A):
# write your code in Python 3.6
# initialize maxUntil [0]*n
n = len(A)
maxUntil = [0 for i in range(n)]
maxUntil[0]=A[0]
# fill in maxUntil, remember to chack limits
for i in range(1, n): # for each
maxUntil[i] = maxUntil [i-1]
# check the max 6 to the left:
# for 1,..,6:
for dice in range(1,7):
if dice > i: # if dice bigger than loc - we are out of range
break
#else: check if bigger than cur elem, if so - update elem
maxUntil[i] = max(maxUntil[i],maxUntil[i-dice])
# add the current jump:
maxUntil[i] +=A[i]
# must reach the last sq:
return maxUntil[n-1]
I would like to explain the algorithm I have come up with and then show you the implementation in C++.
Create a hash for the max sums. We only need to store the elements within reach, so the last 6 elements. This is because the dice can only go back so much.
Initialise the hash with the first element in the array for simplicity since the first element in this hash equals to the first element of the inputs.
Then go through the input elements from the second element.
For each iteration, find the maximum values from the last 6 indices. Add the current value to that to get the current max sum.
When we reach the end of the inputs, exit the loop.
Return the max sum of the last element calculated. For this, we need clipping with module due to the space optimisation
The runtime complexity of this dynamic programming solution is O(N) since we go through element in the inputs. If we consider the dice range K, then this would be O(N * K).
The space complexity is O(1) because we have a hash for the last six elements. It is O(K) if we does not consider the number of dice faces constant, but K.
int solution(vector<int> &A)
{
vector<int> max_sums(6, A[0]);
for (size_t i = 1; i < A.size(); ++i) max_sums[i % max_sums.size()] = *max_element(max_sums.cbegin(), max_sums.cend()) + A[i];
return max_sums[(A.size() - 1) % max_sums.size()];
}
Here's my answer which gives 100% for Kotlin
val pr = IntArray(A.size) { Int.MIN_VALUE }
pr[0] = A.first()
for ((index, value) in pr.withIndex()) {
for (i in index + 1..min(index + 6, A.lastIndex)) {
pr[i] = max(value + A[i], pr[i])
}
}
return pr.last()
I used forwarded prediction, where I fill the next 6 items of the max value the current index can give.
I have the following problem:
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 zero-indexed 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 zero-indexed array A consisting of M integers, returns a sequence of integers representing the values of the counters.
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), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
I have answered this problem using the following code, but only got 80% as opposed to 100% performance, despite having O(N+M) time complexity:
public class Solution {
public int[] solution(int N, int[] A) {
int highestCounter = N;
int minimumValue = 0;
int lastMinimumValue = 0;
int [] answer = new int[N];
for (int i = 0; i < A.length; i++) {
int currentCounter = A[i];
int answerEquivalent = currentCounter -1;
if(currentCounter >0 && currentCounter<=highestCounter){
answer[answerEquivalent] = answer[answerEquivalent]+1;
if(answer[answerEquivalent] > minimumValue){
minimumValue = answer[answerEquivalent];
}
}
if (currentCounter == highestCounter +1 && lastMinimumValue!=minimumValue){
lastMinimumValue = minimumValue;
Arrays.fill(answer, minimumValue);
}
}
return answer;
}
}
Where is my performance here suffering? The code gives the right answer, but does not perform up-to-spec despite having the right time complexity.
Instead of calling Arrays.fill(answer, minimumValue); whenever you encounter a "max counter" operation, which takes O(N), you should keep track of the last max value that was assigned due to "max counter" operation, and update the entire array just one time, after all the operations are processed. This would take O(N+M).
I changed the variables names from min to max to make it less confusing.
public class Solution {
public int[] solution(int N, int[] A) {
int highestCounter = N;
int maxValue = 0;
int lastMaxValue = 0;
int [] answer = new int[N];
for (int i = 0; i < A.length; i++) {
int currentCounter = A[i];
int answerEquivalent = currentCounter -1;
if(currentCounter >0 && currentCounter<=highestCounter){
if (answer[answerEquivalent] < lastMaxValue)
answer[answerEquivalent] = lastMaxValue +1;
else
answer[answerEquivalent] = answer[answerEquivalent]+1;
if(answer[answerEquivalent] > maxValue){
maxValue = answer[answerEquivalent];
}
}
if (currentCounter == highestCounter +1){
lastMaxValue = maxValue;
}
}
// update all the counters smaller than lastMaxValue
for (int i = 0; i < answer.length; i++) {
if (answer[i] < lastMaxValue)
answer[i] = lastMaxValue;
}
return answer;
}
}
The following operation is O(n) time:
Arrays.fill(answer, minimumValue);
Now, if you are given a test case where the max counter operation is repeated often (say n/3 of the total operations) - you got yourself an O(n*m) algorithm (worst case analysis), and NOT O(n+m).
You can optimize it to be done in O(n+m) time, by using an algorithm that initializes an array in O(1) every time this operation happens.
This will reduce worst case time complexity from O(n*m) to O(n+m)1
(1)Theoretically, using the same idea, it can even be done in O(m) - regardless of the size of the number of counters, but the first allocation of the arrays takes O(n) time in java
This is a bit like #Eran's solution but encapsulates the functionality in an object. Essentially - keep track of a max value and an atLeast value and let the object's functionality do the rest.
private static class MaxCounter {
// Current set of values.
final int[] a;
// Keeps track of the current max value.
int currentMax = 0;
// Min value. If a[i] < atLeast the a[i] should appear as atLeast.
int atLeast = 0;
public MaxCounter(int n) {
this.a = new int[n];
}
// Perform the defined op.
public void op(int k) {
// Values are one-based.
k -= 1;
if (k < a.length) {
// Increment.
inc(k);
} else {
// Set max
max(k);
}
}
// Increment.
private void inc(int k) {
// Get new value.
int v = get(k) + 1;
// Keep track of current max.
if (v > currentMax) {
currentMax = v;
}
// Set new value.
a[k] = v;
}
private int get(int k) {
// Returns eithe a[k] or atLeast.
int v = a[k];
return v < atLeast ? atLeast : v;
}
private void max(int k) {
// Record new max.
atLeast = currentMax;
}
public int[] solution() {
// Give them the solution.
int[] solution = new int[a.length];
for (int i = 0; i < a.length; i++) {
solution[i] = get(i);
}
return solution;
}
#Override
public String toString() {
StringBuilder s = new StringBuilder("[");
for (int i = 0; i < a.length; i++) {
s.append(get(i));
if (i < a.length - 1) {
s.append(",");
}
}
return s.append("]").toString();
}
}
public void test() {
System.out.println("Hello");
int[] p = new int[]{3, 4, 4, 6, 1, 4, 4};
MaxCounter mc = new MaxCounter(5);
for (int i = 0; i < p.length; i++) {
mc.op(p[i]);
System.out.println(mc);
}
int[] mine = mc.solution();
System.out.println("Solution = " + Arrays.toString(mine));
}
My solution: 100\100
class Solution
{
public int maxCounterValue;
public int[] Counters;
public void Increase(int position)
{
position = position - 1;
Counters[position]++;
if (Counters[position] > maxCounterValue)
maxCounterValue = Counters[position];
}
public void SetMaxCounter()
{
for (int i = 0; i < Counters.Length; i++)
{
Counters[i] = maxCounterValue;
}
}
public int[] solution(int N, int[] A)
{
if (N < 1 || N > 100000) return null;
if (A.Length < 1) return null;
int nlusOne = N + 1;
Counters = new int[N];
int x;
for (int i = 0; i < A.Length; i++)
{
x = A[i];
if (x > 0 && x <= N)
{
Increase(x);
}
if (x == nlusOne && maxCounterValue > 0) // this used for all maxCounter values in array. Reduces addition loops
SetMaxCounter();
if (x > nlusOne)
return null;
}
return Counters;
}
}
( #molbdnilo : +1 !) As this is just an algorithm test, there's no sense getting too wordy about variables. "answerEquivalent" for a zero-based array index adjustment? Gimme a break ! Just answer[A[i] - 1] will do.
Test says to assume A values always lie between 1 and N+1. So checking for this is not needed.
fillArray(.) is an O(N) process which is within an O(M) process. This makes the whole code into an O(M*N) process when the max complexity desired is O(M+N).
The only way to achieve this is to only carry forward the current max value of the counters. This allows you to always save the correct max counter value when A[i] is N+1. The latter value is a sort of baseline value for all increments afterwards. After all A values are actioned, those counters which were never incremented via array entries can then be brought up to the all-counters baseline via a second for loop of complexity O(N).
Look at Eran's solution.
This is how we can eliminate O(N*M) complexity.
In this solutions, instead of populating result array for every A[K]=N+1, I tried to keep what is min value of all elements, and update result array once all operation has been completed.
If there is increase operation then updating that position :
if (counter[x - 1] < minVal) {
counter[x - 1] = minVal + 1;
} else {
counter[x - 1]++;
}
And keep track of minVal for each element of result array.
Here is complete solution:
public int[] solution(int N, int[] A) {
int minVal = -1;
int maxCount = -1;
int[] counter = new int[N];
for (int i = 0; i < A.length; i++) {
int x = A[i];
if (x > 0 && x <= N) {
if (counter[x - 1] < minVal) {
counter[x - 1] = minVal + 1;
} else {
counter[x - 1]++;
}
if (maxCount < counter[x - 1]) {
maxCount = counter[x - 1];
}
}
if (x == N + 1 && maxCount > 0) {
minVal = maxCount;
}
}
for (int i = 0; i < counter.length; i++) {
if (counter[i] < minVal) {
counter[i] = minVal;
}
}
return counter;
}
This is my swift 3 solution (100/100)
public func solution(_ N : Int, _ A : inout [Int]) -> [Int] {
var counters = Array(repeating: 0, count: N)
var _max = 0
var _min = 0
for i in A {
if counters.count >= i {
let temp = max(counters[i-1] + 1, _min + 1)
_max = max(temp, _max)
counters[i-1] = temp
} else {
_min = _max
}
}
return counters.map { max($0, _min) }
}
Lets say array one [2/3, 0, -1, 0, 7/2] and array two [0, 0, -2/3, 1, 0, 0] so I want my result array to be [0, 2/3, -2/3, 0, 0, 7/2]. The result array length will be the max length between the two arrays. How can I do this in Java?
Pretty much I want the specific index locations to add each other however I don't know how to do this with unequal arrays.
Edit: It adds the locations and anything that is unmatched is left untouched in the largest array. [0, 0, -2/3, 1, 0, 0] has location 0, 1, 2, 3, 4, 5 and array [2/3, 0, -1, 0, 7/2] has locations that coincide with the larger array as 1, 2, 3, 4, 5 so I want the same location values to be added and placed into the resultant array. I created a new resultant array and set it equal to the largest array so all that has to be done is the adding of similar location values.
Here is an elaborate and easy to understand way that I've devised:
What it does it it adds the last elements of the arrays together and moves backwards from there; if one array ends before the other, it just substitutes the value of the non-existent element with zero, then adds them:
public class ArrayAddition
{
public static void main(String[] args)
{
double array1[] = {2./3, 0, -1, 0, 7./2}; // first array
double array2[] = {0, 0, -2./3, 1, 0, 0}; // second array
int length = Math.max(array1.length, array2.length); // length of longest array
double newArray[] = new double[length]; // result must be length of longest array
int index1 = array1.length - 1; // last element of first array
int index2 = array2.length - 1; // last element of second array
int indexRes = length - 1; // result will be placed in last spot of result
for (int i = length -1; i >= 0; i--) // adds elements of two arrays together bckwrd
{
double val1, val2; // value holders for array elements
try // try to get value of the array 1 at certain position
{
val1 = array1[index1];
}
catch(ArrayIndexOutOfBoundsException e) // if empty, make it zero
{
val1 = 0;
}
try // try to get value of array 2 at certain position
{
val2 = array2[index2];
}
catch(ArrayIndexOutOfBoundsException e) // if empty make it zero
{
val2 = 0;
}
newArray[indexRes] = val1 + val2; // array[?] result is val1 + val 2
index1--; // decrement to the next lower value
index2 --; // decrement to the next lower value
indexRes--; // go the next lower spot
}
for (int i = 0; i < newArray.length; i ++) // this loop prints out the results
System.out.println(newArray[i]);
}
}
You need to enter your values as doubles or the answers will be incorrect (2./3 instead of 2/3)
0.0
0.6666666666666666
-0.6666666666666666
0.0
0.0
3.5
Answers will be in decimal form, for obvious reasons (if answer is 2 / 3, it actually divides 2 by 3, still the correct answer, you can convert it back)
Hopefully this helps! :)
Go through your arrays starting at the end and add the 2 values putting them into a new array with the size of the largest array.
int a = arrayA.length-1;
int b = arrayB.length-1;
double [] result = new double[Math.max(arrayA.length, arrayB.length)];
double sum = 0;
while(a >= 0 || b >= 0) {
if(a>=0) sum+=arrayA[a];
if(b>=0) sum+=arrayB[b];
result[Math.max(a, b)] = sum;
sum = 0;
a--;
b--;
}
This should do it. Note that this code is missing the declarations of the array variables.
if (array1.length > array2.length)
array3 = addArrays(array1, array2);
else
array3 = addArrays(array2, array1);
int [] addArrays(longArray, shortArray) {
int index;
for (index = 0; index < longArray.length - shortArray.length; index++) {
array3[index] = longArray[index] + 0;
}
for (int i = 0; i < shortArray.length; i++, index++) {
array3[index] = longArray[index] + shortArray[i];
}
return array3;
}
import java.util.Scanner;
public class ArrayAdd {
public static void main(String args[]) {
Scanner a = new Scanner(System.in);
int m = a.nextInt();// First array's size
int n = a.nextInt();// Second array's size
int arr1[] = new int[m];
int arr2[] = new int[n];
for (int i = 0; i < m; i++) {
arr1[i] = a.nextInt();
}
for (int i = 0; i < n; i++) {
arr2[i] = a.nextInt();
}
a.close();
if (m < n) {
int difference = n - m;
int arr3[] = new int[n];
for (int i = 0; i < n; i++) {
if (i < difference) {
arr3[i] = arr2[i];
} else {
arr3[i] = arr1[i-difference] + arr2[i];
}
System.out.println(arr3[i]);
}
} else {
int difference = m - n;
int arr3[] = new int[m];
for (int i = 0; i < m; i++) {
if (i < difference) {
arr3[i] = arr1[i];
} else {
arr3[i] = arr1[i] + arr2[i-difference];
}
System.out.println(arr3[i]);
}
}
}
}