Count and print Triplets in a sorted array - java

Given a sorted array of n integers, display triplets such that a[i] < a[j] < a[k].
My code is
public static void countTriplets(int arr[], int index, int arr1[], int position)
{
if (position == 3)
{
System.out.println(Arrays.toString(arr1));
return;
}
for (int i = index; i < arr.length; i++)
{
arr1[position] = arr[i];
countTriplets(arr, index + 1, arr1, position + 1);
}
}
However it prints all possible triplets.Where am i going wrong ?

Count the number of unique elements in the array. Let it be 'N'. Then the answer is n * (n - 1) * (n - 2) / 6.
The reasoning is as follows: for any three distinct numbers a, b, c, we can form a tuple of sorted elements such that say b < c < a. Since we don't want repetitions, we have to count the number of unique elements.
For example, consider {1, 2, 3, 3, 4, 5, 5, 6}
Number of unique elements = 6. The answer is (6 * 5 * 4) / 6 = 20.
Some code in C++:
#include <stdio.h>
int count_triplets(int *a, int n)
{
int counter = 0;
if (n < 3) {
return 0;
}
for (int i = 0; i < n; i++) {
// jump to the last of the repeated values
if ((i < n - 1) && (a[i] == a[i + 1])) {
continue;
}
for (int j = i + 1; j < n; j++) {
// jump to the last of the repeated values
if ((j < n - 1) && (a[j] == a[j + 1])) {
continue;
}
for (int k = j + 1; k < n; k++) {
// jump to the last of the repeated values
if ((k < n - 1) && (a[k] == a[k + 1])) {
continue;
}
printf("[%d, %d, %d]\n", a[i], a[j], a[k]);
counter ++;
}
}
}
return counter;
}
int main(int argc, char *argv[])
{
printf("Enter the number of elements:");
int n = 0;
scanf("%d", &n);
printf("Enter the elements:\n");
int a[100] = {0};
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
int triplets = count_triplets(a, n);
printf("Number of triplets = [%d]\n", triplets);
return 0;
}
This is not the most efficient but should lead you to more efficient solutions.

The simple way to do this is with nested loops:
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++)
{
// output the triplet arr[i], arr[j], arr[k]
++numTriplets;
}
}
}
The code above will do what you're asking. It does not take into account the possibility of duplicates in the source array. Given the array [1, 2, 3, 4, 5], it outputs:
1,2,3
1,2,4
1,2,5
1,3,4
1,3,5
1,4,5
2,3,4
2,3,5
2,4,5
3,4,5
Update
The general solution to this problem is one of creating combinations. That is, selecting combinations of n items from a list of size m. The math tells us that the number of combinations is equal to:
m!
---------
(n!)(m-n)!
Substituting numbers for your example, we have:
c = 5!/((3!) * (5-3)!)
= 120/(6 * 2)
= 120/12
= 10
So you can compute the number of combinations in O(1) easily enough (if you use an approximation for the factorial function), but if you want to enumerate them your time complexity approaches O(m!) (for sufficiently large values of m).
You certainly can't enumerate all the combinations in O(n) or O(n log n). That would be kind of like asking for an algorithm that can enumerate all n-digit numbers in O(n) or O(n log n).

the answer can be reduced to selection of three numbers from n numbers which is nc3 i.e
return (n*(n-1)*(n-2))/3! where n>=3 else return 0

Related

Is there any way to reduce number of operations for finding and returning the number of triplets sum in array which is equals to any integer X

The program is meant to find and return the number of triplets sum in the array/list which is equal to any integer value X.
triplets = (any three elements in array list)
The array can be in any order
Say, array size =7
Sample input :
{1, 2, 3, 4, 5, 6, 7}
X = 12
Sample Output :
5
by reducing operations, I mean to reduce time complexity. As I wrote this code :
public static int tripletSum(int[] arr, int num) {
int count = 0;
for(int i = 0; i<arr.length; i++){
for(int j = i+1; j<arr.length; j++){
for (int k = j+1; k<arr.length; k++){
if ((arr[i] + arr[j] + arr[k])==num){
count++;
}
}
}
}
return count;
}
}
I get O(n^3) time complexity using this code and Time limit Exceeded error with this. Any way to reduce it to O(n^2) ?
Sorting is O(n log n), so if we're looking to reduce the complexity to O(n2), then sort the input so we can take advantage of the order.
Then, for all the elements except for the last 2*, assume that that first element is part of the sum. Compute the target (12 here) minus the first element, call it sum. Maintain two indices, j and k, initialized to the next element and the last element. If the sum of the elements at j and k equals sum, count it. If we have too much, decrement k, else increment j. When j and k meet, you can move on to the next element and restart j and k.
[1, 2, 3, 4, 5, 6, 7]
i j -> <- k
Here's the coded algorithm:
public static int numTripletsSum(int[] input, int target) {
if (input == null || input.length < 3)
return 0;
Arrays.sort(input);
int count = 0;
for (int i = 0; i < input.length - 2; i++) {
int sum = target - input[i];
int j = i + 1, k = input.length - 1;
while (j < k) {
int diff = input[j] + input[k] - sum;
if (diff == 0) {
count++;
//System.out.println("(" + input[i] + ", " + input[j] + ", " + input[k] + ")");
}
if (diff > 0) {
k--;
} else {
j++;
}
}
}
return count;
}
This is two nested loops, O(n2), after an O(n log n) sort, so the algorithm is O(n2). For your input above, I get 5.
* Except for the last 2? You can't get a triplet from the second to last element on.

How to calculate the number of combinations of 3 integers less than n whose sum is greater than n * 2?

I am solving some java algorithm-analysis questions and this problem has me stumped. This particular problem asks for the value that is returned by x(10) where is x is the following function:
public static int x(int n)
{
int count = 0;
for(int i = 0; i <= n; i++)
{
for (int j = 0; j <= n; j++)
{
for (int k = 0; k <= n; k++)
{
System.out.println(i+","+j+","+k);
if (i + j + k > 2 * n)
count++;
}
}
}
return count;
}
Essentially, the problem is asking for the number of combinations of 3 integers less than n whose sum is greater than n * 2.
What is the fastest problem-solving technique for this problem, and just general "complicated" nested loop problems?
I set up a variable table and kept track of variables a, b, and c representing the 3 integers and a count variable which increments each time 'a+b+c > n*2' but after n=3, the tables became unnecessarily tedious. There must be a mathematical solution.
x(10) returns 220, but I do not know how the algorithm arrives at that answer and how to find, say, x(7).
Your code is incorrect.
First, the for loops should be corrected as
i < n,
j < n,
k < n,
because you mentioned "less than".
As you mentioned "Combination", but your code doesn't remove some repeated combinations, for example, if n = 5, there are only two combinations which satisfise the conditions, they are (4, 4, 4) and (4, 4, 3), thus the result is 2,
apparently your code will return a bigger number which is incorrect.
Could the result of this problem be a mathmatic expression ? think about this follow equation:
n1 + n2 + n3 = 2 * n
this equation is a typical se called "Diophantine Equation", which is proved that
there doesn't exist general algorithm to resolve all of them, and this equation is so relative to the origin problem, so i guess no.
I've changed your code, using hashset to remove all repeated combinations, hope is helpful.
public static int getCombinationNumber(int num) {
HashSet<String> hs = new HashSet(); // To save the unic form (or representation) for each combination
int count = 0;
for (int i = 0; i < num; i++)
for (int j = 0; j < num; j++)
for (int k = 0; k < num; k++) {
int[] nums = {i, j, k};
sort(nums); // To ensure all the combinations of i, j, k form a unic array
String unicForm = Arrays.toString(nums); // Convert array to string in order to compare and save
if (i + j + k > 2 * num && !hs.contains(unicForm)) {
count++;
hs.add(unicForm);
System.out.println(i + ", " + j + ", " + k);
}
}
return count;
}

Algorithm to generate an array with n length and k number of inversions in O(n log n) time?

I'm writing an algorithm that will return an array with determined length and number of inversions (number pairs, where the left side number is larger than the right side number). I.e. array [3, 1, 4, 2] contains three inversions (3, 1), (3, 2) and (4, 2). So in practice, when given the length of n=3 and number of inversions k=3, the algorithm should generate an array [3, 1, 4, 2] (or another array that fulfills these requirements).
Since the number of inversions is also the number of swaps that has to be made for the array to be sorted in ascending order, I approached this problem by creating an array from 1 to n - 1 and using an insertion sort algorithm in reverse to make k swaps.
This approach works just fine for smaller inputs, but the algorithm should be able to efficiently generate arrays up to n=10^6 and k=n(n-1)/2 and anything in between, so the algorithm should be working in O(n log n) time instead of O(n^2). Below is the code:
import java.util.*;
public class Inversions {
public int[] generate(int n, long k) {
// Don't mind these special cases
if (n == 1) {
int[] arr = {1};
return arr;
}
if (k == 0) {
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = 1;
}
return arr;
}
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = i + 1;
}
int inversions = 0;
int i = 0;
while (inversions < k && i < n) {
int j = i - 1;
while (j >= 0 && arr[j] < arr[j + 1] && inversions < k) {
int helper = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = helper;
inversions++;
j--;
}
i++;
}
return arr;
}
}
And the main class for testing with different input arrays:
public class Main {
public static void main(String[] args) {
Inversions in = new Inversions();
int[] arr1 = in.generate(4,3);
int[] arr2 = in.generate(4,0);
int[] arr3 = in.generate(4,6);
System.out.println(Arrays.toString(arr1)); // [3,1,4,2]
System.out.println(Arrays.toString(arr2)); // [1,1,1,1]
System.out.println(Arrays.toString(arr3)); // [4,3,2,1]
}
}
The algorithm does not return exactly the same arrays as the sample results, but passes all the tests, except the ones where the input size is very large. I have also tried different variations with merge sort, since it's working in O(n log n time) but with no avail.
It would be great if you guys have some ideas. If you are not familiar with Java, doesn't matter, pseudocode or any other kinds of suggestions are more than welcome!
If you reverse the initial m elements in the array, you create m(m-1)/2 inversions.
If you reverse the initial m+1 elements, you create m(m+1)/2 inversions.
The difference between these is only m.
So:
Generate a sorted array
Find the largest m such that m(m-1)/2 <= k
Reverse the first m elements in the array to create m(m-1)/2 inversions
Shift the next element forward k - m(m-1)/2 positions to create the remaining required inversions.
This takes O(n) time, which is better than you require.
Another O(n) algorithm: Start with a sorted array. When you swap the first and last elements, you get x = 2 * (n-2) + 1 inversions. Consider these two elements fixed and work on the remaining array only. If x is too large, consider a smaller array. Repeat this as long as needed.
Untested code:
for (int first=0, last = n-1; remainingInversions>0; ) {
int x = 2 * (last-first-1) + 1;
if (x <= remainingInversion) {
first++;
last--;
remainingInversion -= x;
} else {
last--; // consider a smaller array
}
}
If k >= n - 1, put element n - 1 first in the array, so that it is inverted with n - 1 elements; otherwise put it last in the array, so that it is inverted with 0 elements. Continue this greedy approach to determine where the rest of the elements go.
Here's a solution that implements generate() to run in linear time with a little bit of math.
public class Inversions {
public static int[] generate(int n, long k) {
int[] array = new int[n];
// locate k in various sums of (n-1), (n-2), ..., 1
int a = (int) Math.sqrt((n * (n - 1) - 2 * k)); // between the sum of [(n-1)+...+(n-a)] and the sum of [(n-1)+...+(n-a-1)]
int b = n - 1 - a; // counts of (n-1), (n-2), ..., (n-a)
int c = (int) (k - n * b + (b * b + b) / 2); // spillover = k - [(n-1)+(n-b)]*b/2;
// put elements in the array
for (int i = 0; i < b; i++) {
array[i] = n - 1 - i;
}
for (int i = b; i < n - 1 - c; i++) {
array[i] = i - b;
}
array[n - 1 - c] = n - 1 - b;
for (int i = n - c; i < n; i++) {
array[i] = i - b - 1;
}
return array;
}
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
long k = Long.parseLong(args[1]);
for (int i = 0; i < n; i++) {
StdOut.print(generate(n, k)[i] + " ");
}
}
}
In fact, every time you exchange the last element with the one before it, the number of inversions increments. Here is a java solution:
public static int[] generate(int n, long k) {
int[] arr = new int[n];
for(int i = 0; i < n; i++) {
arr[i] = i;
}
long inversions = 0;
int j = (n-1);
int s = 0;
while(inversions < k) {
int temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
inversions++;
j--;
if(j == s) {
j = (n-1);
s++;
}
}
return arr;
}
I got an implementation in Python with O(n) complexity.
It is based on two rules.
Reversing an array of size m gives m*(m-1)/2 inversions.
Shifting an element by m positions, creates m inversions.
def get_m(k):
m=0
while m*(m-1)/2<=k:
m+=1
else:
m-=1
return m
def generate(l, k):
"""
Generate array of length l with k inversions.
"""
# Generate a sorted array of length l
arr = list(range(0,l))
# If no inversions are needed, return sorted array.
if k==0:
return arr
# Find largest m such that m*(m-1)/2 <= k
m=get_m(k)
# Reverse first m elements in the array which will give m*(m-1)/2 inversions
arr = arr[m-1::-1]+arr[m:]
# Calculate for any remaining inversions
remaining_k = k-(m*(m-1)/2)
# For remaining inversions, move the last element to its left by remaining_k
if remaining_k>0:
arr.insert(int(len(arr)-remaining_k - 1), arr[-1])
arr = arr[:-1]
return arr
if __name__ == '__main__':
l = int(sys.argv[1])
k = int(sys.argv[2])
arr = generate(l, k)
print(arr)
There's a very easy way to create n inversions...
That is to move the last element to the front.
It's not exactly efficient due to the additional memory used, but I would do something like this:
Create an array that is twice the length n.
Fill it from the start to the middle with a sentinel (i.e. null) if we use an Integer[] instead of int[].
Fill it from the middle, ascending.
Then do something like the below...
I'm sure I have off by one errors and other bugs but the general idea is captured in the below code.
int start = 0;
int mid = arr.length / 2;
int end = arr.length - 1;
while (v > 0)
{
if (v < (end - mid))
{
arr[start++] = arr[mid + v];
arr[mid + v] = null;
}
else
{
arr[start++] = arr[end];
v -= (end - mid);
end--;
}
}
So we have an array filled with the starting values, a bunch of nulls, then the original incremental values, with one that may have become null, and an "end" pointer that points to the middle of the original zone.
So the final step is to copy from 0 -> endPos, ignoring the nulls, to the final array.
The logic is not much difficult. For example, we have 10 numbers [0,1,2,3,4,5,6,7,8,9] say, to generate like 18 inversions. Firstly, insert 9 before 0, --->[9,0,1,2,3,4,5,6,7,8], which generates 9 inversions. Still 9 inversions left, so we insert 8 before 0, ---->[9,8,0,1,2,3,4,5,6,7], so we get additional 8 inversions. Finally, 1 inversions left, we insert 7 before 6----->[9,8,0,1,2,3,4,5,7,6]. I only use arrays in this case. This program works in O(n) complexity. The following code only considering n numbers (0,1,2.....n-1) and their inversions.
public static int[] generate(int n, long k) {
int[] a = new int[n];
int[] b = new int[n];
for (int i = 1; i < n; i++) {
a[i] = 1 + a[i - 1];
}
if (n == 0 || k == 0) return a;
else {
int i = 0;
while (k > 0) {
if (k > n - i - 1) {
b[i] = a[n - 1 - i];
}
else {
//auxilary array c to store value
int[] c = new int[(int) (k + 1)];
for (int j = i; j < n - 1 - k; j++) {
b[j] = j - i;
}
for (int j = (int) (n - 1 - k); j < n; j++) {
c[j - (int) (n - 1 - k)] = j - i;
}
b[(int) (n - 1 - k)] = c[(int) k];
for (int j = (int) (n - k); j < n; j++) {
b[j] = c[j - (int) (n - k)];
}
break;
}
k = k - (n - 1 - i);
i++;
}
return b;
}
}
#zhong yang: It works nicely in the expected range 0 <= k <= n(n-1)/2 but it should be better to throw either an exception or null if k is out of this range instead of returning some array!

Test Cases fail to satisfy

I'm just a beginner. I came across this question for which my code fails to satisfy all/most of the test cases.
Question:
Given an array of numbers, find the number of non-empty sub-arrays in which the minimum and maximum element are identical.
Example:
Input: Array = [1, 1, 3]
Output: 4
Explanation:
The required sub-arrays are [1], [1], [3], [1,1]
My solution:
Sort the array and solve the problem.
Code:
for(int i = 0; i < testCases; i++){
int arraySize = in.nextInt();
int array[] = new int[arraySize];
for(int j = 0; j < arraySize; j++){
array[j] = in.nextInt();
}
temp[i] = (findSubArrays(array));
}
for(int i = 0; i < testCases; i++){
System.out.println(temp[i]);
}
private static int findSubArrays(int[] array) {
Arrays.sort(array);
//Since each element can form a sub-array of its own
int noOfSubArrays = array.length;
for(int i = 0; i < array.length-1; i++){
if(array[i] == array[i+1]){
noOfSubArrays++;
}
}
return noOfSubArrays;
}
So you're sorting the array to keep begin points and end points adjacent so you don't need a nested traversal. That makes sense. The problem is that you're counting adjacent duplicates, but what you really need is T(n), or the triangle number of consecutive duplicates. Consider a simple scenario:
[1, 1, 1]
Your algorithm returns 5, but there are actually 6 subsets (by start & end index):
0, 0
0, 1
0, 2
1, 1
1, 2
2, 2
So let's update the algorithm to calculate the triangle number of each sequence:
private static int findSubArrays(int... array) {
Arrays.sort(array);
int sequenceCount = 0;
int total = 0;
for (int i = 0; i < array.length + 1; i++) {
if (i == array.length || (i > 0 && array[i] != array[i - 1])) {
total += triangle(sequenceCount);
sequenceCount = 0;
}
sequenceCount++;
}
return total;
}
private static int triangle(int n) {
return (n * (n + 1)) / 2;
}
Now calling findSubArrays(1, 1, 1) returns 6 and findSubArrays(1, 1, 3) returns 4.

Dynamic Programming (Codility Q: NumberSolitaire)

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.

Categories