I am implementing an algorithm to solve the Coin Change problem, where given an array that indicates types of coins (i.e. int[] coinValues = {1,4,6};) and a value to achieve (i.e. int totalAmount=8;), an array is returned where the value at position 0 indicates the minimum number of coins needed to achieve totalAmount. The rest of the array will keep a track of how many coins are needed to achieve the total sum.
An example input of coins = {1,4,6} and total = 8 should return the array [3,2,0,1]. However, my code is returning [1,2,0,1].
Another example would be coins = {2,4,8,16,34,40,64} and total = 50 should return the array [2, 0, 0, 0, 1, 1, 0, 0]. My code is not returning that result.
The algorithm is implemented with 2 methods: CoinChange and CoinCount. CoinChange creates the coin matrix and CoinCount keeps track of the coins required to achieve the total sum.
package P5;
import java.util.Arrays;
public class CoinChange7 {
public static int[] CoinChange(int[] v, int sum) {
int[][] aux = new int[v.length + 1][sum + 1];
// Initialising first column with 0
for(int i = 1; i <= v.length; i++) {
aux[i][0] = 0;
}
// Implementing the recursive solution
for(int i = 1; i <= v.length-1; i++) {
for(int j = 1; j <= sum; j++) {
if(i == 1) {
if(v[1] > j) {
aux[i][0]=999999999; //instead of Integer.MAX_VALUE
} else {
aux[i][j]=1 + aux[1][j-v[1]];
}
} else {
if(v[i] > j) { //choose best option ,discard this coin or use it.
aux[i][j] = aux[i - 1][j];
} else
aux[i][j] = Math.min(aux[i-1][j],1 + aux[i][j-v[i]]);
}
}
}
int []z=CoinCount(sum,aux,v);
return z; // Return solution to the initial problem
}
public static int[] CoinCount(int A, int[][] aux, int[] d){
int coin = d.length-1;
int limit=A;
int [] typo=new int[d.length+1]; //We create solution array, that will count no of coins
for (int k=0;k<typo.length;k++) {
typo[k]=0;
} while (coin>0 || limit>0){
if(limit-d[coin]>=0 && coin-1>=0){
if(1+aux[coin][limit-d[coin]]<aux[coin-1][limit]){
typo[coin+1]=typo[coin+1]+1;
limit=limit-d[coin];
} else {
coin=coin-1;
}
} else if(limit-d[coin]>=0) {
typo[coin+1]=typo[coin+1]+1;
limit=limit-d[coin];
} else if(coin-1>=0) {
coin=coin-1;
}
}
typo[0]= aux[d.length-1][A];
return typo; //return the final array with solutions of each coin
}
public static void main(String[] args) {
int[] coins = {1,4,6};
int sum = 8;
int[] x=CoinChange(coins,sum);
System.out.println("At least " + Arrays.toString(x) +" from set "+ Arrays.toString(coins)
+ " coins are required to make a value of " + sum);
}
}
Clarification
I don't know if you still need the answer to this question but I will try to answer it anyway.
First, there are a few things I would like to clarify. The coin change problem does not have a unique solution. If you want both the minimum of coins used to make the change and frequencies of coins usage, I think that depends on the approach used to solve the program and the arrangement of the coins.
For example: Take the coins to be [4,6,8] and amount = 12. You'll quickly see that the minimum coins required to make this change is 2. Going by your choice of output, the following are all correct: [2,0,2,0] and [2,1,0,1].
By the way, the Coin change problem can be solved in many ways. A simple recursive DP approach in Java is here. It only returns the min coins needed to make the change at O(nlog(n)) time and O(n) space.
Another approach is by using a 2D DP matrix (same with the approach you tried using) at both O(n^2) time and space. Explanation on how to use this approach is here. Please be careful with the explanation because it is not generally correct. I noticed it's almost the same as the one you used.
Your solution
I will mention a few things about your solution that may have affected the result.
The number of rows of the DP matrix is v.length not v.length + 1.
Based on your solution, this should not affect the result because I noticed you don't seem comfortable with zero indexes.
I think it is not necessary to initialize the first column of the DB matrix since the data type you used is int, which is 0 by default. Again, this does not affect the answer, though.
The way you filled row 1 (supposed to be the first row, but you ignored row 0) is not good and may affect the result of some solutions.
The only mistake I see there is that there is no uniform value to specify amounts (i.e. j) that cannot be solved using the single coin (i.e. v[0]). Negative numbers could have been better because any positive integer is a potential valid solution for the cell. You could use -1 (if you're going by the Leetcode instruction). This way, you'll easily know cells that contain invalid values while filling the rest of the matrix.
The way you compute aux[i][j] is wrong because you are using the wrong coins. you are using v[i] instead of v[i-1] since you aux.length is one bigger than the v.length.
I did not look at the countCoint method. It looks complex for a seemingly simple problem. Please see my solution.
My Solution
public int[] change(int[] coins, int amount){
int[][] DP = new int[coins.length][amount+1];
//fill the first column with 0
//int array contains 0 by default, so this part is not necessary
/*
for (int i = 0; i < coins.length; i++) {
DP[i][0] =0;
}
*/
//fill the first row.
//At 0th row, we are trying to find the min number of ways to change j amount using only
//one coin i.e. coins[0] (that is the meaning of DP[0][j];
for (int j = 1; j <= amount; j++) {
if(coins[0] > j || j % coins[0] != 0){
DP[0][j] = -1;
}else{
DP[0][j] = j /coins[0];
}
}
//iterate the rest of the unfilled DP
for (int i = 1; i < coins.length; i++) {
for (int j = 1; j < amount+1; j++) {
if(coins[i] > j){
DP[i][j] = DP[i-1][j];
}else {
int prev = DP[i-1][j];
int cur = 1+DP[i][j-coins[i]];
if(cur == 0){
DP[i][j] = DP[i-1][j];
} else if(prev == -1) {
DP[i][j] = 1 + DP[i][j - coins[i]];
}else{
DP[i][j] = Math.min(DP[i-1][j],1+DP[i][j-coins[i]]);
}
}
}
}
return countCoin(coins,amount,DP);
}
public int[] countCoin(int[] coins, int amount, int[][] DP){
int[] result = new int[coins.length+1];//The 1 added is to hold result.
int i = coins.length -1;
int j = amount;
//while the rest will contain counter for coins used.
result[0] = DP[i][j];
if(result[0] ==0 || result[0] ==-1)return result;
while (j > 0 ){
if(i-1 >= 0 && DP[i][j] == DP[i-1][j]){
i = i-1;
}else{
j = j - coins[i];
result[i+1] += 1;
}
}
return result;
}
Related
I always understood that defining a local variable within a loop does not slow it down because they are reused between iterations of the same loop.
I was surprised to find that when I move the definition of the local variable outside the loop, then it reduces memory significantly (39.4Mb vs 40 Mb).
Between iterations of the same loop, are local variables reused or reallocated?
I did also see Allocation of space for local variables in loops
Duplicate Zeroes Problem (leetcode): Given a fixed length array arr of integers, duplicate each occurrence
of zero, shifting the remaining elements to the right.
Note that elements beyond the length of the original array are not
written.
Do the above modifications to the input array in place, do not return
anything from your function.
import java.util.Arrays;
/**
* algorithm: the zeroes divide the array into sub-arrays or subsets.
* we move or shift the elements exactly once, to their final resting place R.I.P. ;)
* The last subset will be shifted n0s places, the one before it, n0s -1 places and so on...
* O(n)
* #author likejudo
*
*/
public class DuplicateZeroes {
static void arrayCopy(int[] arr, int begin, int end, int n) {
for (int i = end + 1; i >= begin ; i--) {
int destination = i + n;
if (destination < arr.length) {
arr[destination] = arr[i];
}
}
}
public static void duplicateZeros(int[] arr) {
int n0s = 0; // number of zeroes
int last0At = -1; // last zero at index
int boundary = 0; // rightmost boundary
// find total n0s, last0At
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 0) {
n0s++;
last0At = i;
}
}
// System.out.format("n0s=%d last0At=%d \n", n0s, last0At);
// if no zeroes or all zeroes, we are done
if(n0s == 0 || n0s == arr.length) {
return;
}
boundary = arr.length - n0s;
while (n0s > 0) {
// System.out.format("before arrayCopy(%s, %d, %d, %d) ", Arrays.toString(arr), last0At, boundary, n0s);
// move subset of all elements from last0At till boundary-1, by n0s spaces.
arrayCopy(arr, last0At, boundary, n0s);
// set start of subset to 0
arr[last0At] = 0;
// System.out.format("after arrayCopy : %s assigned arr[last0At=%d]=0\n", Arrays.toString(arr),last0At);
// update boundary
boundary = last0At - 1;
// next subset to the left will have one less zero
n0s--;
last0At--;
// find the next last zer0 At index
while (last0At > 0 && arr[last0At] != 0)
last0At--;
// if no more...
if (last0At <0 || arr[last0At] != 0) {
return;
}
}
}
public static void main(String[] args) {
// input: [1, 0, 2, 3, 0, 4, 5, 0]
// output: [1, 0, 0, 2, 3, 0, 0, 4]
int[] arr = {0,0,0,0,0,0,0};
System.out.println("input: " + Arrays.toString(arr));
duplicateZeros(arr);
System.out.println("output: " + Arrays.toString(arr));
}
}
In the method arrayCopy, when I move the local variable destination outside the loop,
Before
static void arrayCopy(int[] arr, int begin, int end, int n) {
for (int i = end + 1; i >= begin ; i--) {
int destination = i + n; // >>>>>>>>>>>>>>>>>>>>>>>
if (destination < arr.length) {
arr[destination] = arr[i];
}
}
}
After
memory usage improved! (39.4 Mb vs 40 Mb)
static void arrayCopy(int[] arr, int begin, int end, int n) {
int destination = 0; // >>>>>>>>>>>>>>>>>
for (int i = end + 1; i >= begin ; i--) {
destination = i + n;
if (destination < arr.length) {
arr[destination] = arr[i];
}
}
}
About your question
I always understood that defining a local variable within a loop does
not slow it down because they are reused between iterations of the
same loop.
declaring local variable inside loop does not slow it down?
Yes, you are right. Declaring local vars does not increase the time complexity, or if it does change the runtime just a bit, it's too insignificant to be considered.
Runtime and memory measurements of LeetCode are highly inaccurate, especially runtime. For instance, I just resubmitted the following solution and it says 39.6 MB, some days ago said 43.3 MB for the exact same solution without a byte change:
Their test cases are usually limited because it is costly I guess, thus their benchmarking is not valuable.
public final class Solution {
public static final void duplicateZeros(int[] arr) {
int countZero = 0;
for (int index = 0; index < arr.length; index++)
if (arr[index] == 0) {
countZero++;
}
int length = arr.length + countZero;
for (int indexA = arr.length - 1, indexB = length - 1; indexA < indexB; indexA--, indexB--)
if (arr[indexA] != 0) {
if (indexB < arr.length) {
arr[indexB] = arr[indexA];
}
} else {
if (indexB < arr.length) {
arr[indexB] = arr[indexA];
}
indexB--;
if (indexB < arr.length) {
arr[indexB] = arr[indexA];
}
}
}
}
Overall it'd be best to focus on asymptotically efficient algorithms mostly, because benchmarking has lots of "how-tos" and we'd want to have really good resources (CPU, memory, etc.) with isolated test systems.
References
For additional details, please see the Discussion Board where you can find plenty of well-explained accepted solutions with a variety of languages including low-complexity algorithms and asymptotic runtime/memory analysis1, 2.
I have the following problem taken from Codility's code testing exercises:
A zero-indexed array A consisting of N different integers is given. The array contains integers in the range [1..(N + 1)], which means that exactly one element is missing.
Your goal is to find that missing element.
Write a function:
class Solution { public int solution(int[] A); }
that, given a zero-indexed array A, returns the value of the missing element.
For example, given array A such that:
A[0] = 2
A[1] = 3
A[2] = 1
A[3] = 5
the function should return 4, as it is the missing element.
Assume that:
N is an integer within the range [0..100,000];
the elements of A are all distinct;
each element of array A is an integer within the range [1..(N + 1)].
Complexity:
expected worst-case time complexity is O(N);
expected worst-case space complexity is O(1), beyond input storage (not >counting the storage required for input arguments).
Elements of input arrays can be modified.
My approach was to convert the given array into an ArrayList, use the ArrayList to find the lowest and highest values inside the array, and iterate through all possible values from lowest to highest, and then return the missing value.
This solves the example problem, but my problem seems to be that I cannot get right answers under the following conditions of the given array:
"empty list and single element"
"the first or the last element is missing"
"single element"
"two elements"
What am I doing wrong, and what is the proper way to go about solving this problem?
This problem has a mathematical solution, based on the fact that the sum of consecutive integers from 1 to n is equal to n(n+1)/2.
Using this formula we can calculate the sum from 1 to N+1. Then with O(N) time complexity we calculate the actual sum of all elements in the array.
The difference between the full and actual totals will yield the value of the missing element.
Space complexity is O(1).
This problem is part of the Lessons of Time Complexity.
https://codility.com/media/train/1-TimeComplexity.pdf
In fact at the end there is the explanation on how to compute the sum of the elements in an array, without do any loop.
This is the final solution in Python3:
def solution(A):
n = len(A)+1
result = n * (n + 1)//2
return result - sum(A)
The problem statement clearly specifies that the array will consist of "N different integers", thus N must be at least 2. N=0 and N=1 simply do not make sense if we write them in English, e.g. "An array consisting of 0 different integers...".
A zero-indexed array A consisting of N different integers is given. The array contains integers in the range [1..(N + 1)], which means that exactly one element is missing.
With these initial conditions and stated assumptions, tests like "single element", "empty list", etc., are completely inappropriate.
Proper production code would most likely have to test for invalid conditions, but that wasn't a stated goal of the challenge.
Another 100% solution:
There is actually not even a need to use 64-bit integers to avoid the overflows that a couple of tests try to trigger (the ones with array size of 100000 at the time of writing). And you can get away with only one sum variable. The last line avoids overflows further by implementing n(n+1)/2 differently so that the division by two occurs "early":
C#:
class Solution {
public int solution(int[] A) {
var sum = 0;
for(int i = 0; i < A.Length; i++)
sum += A[i];
return A.Length % 2 == 0 ? -sum + (A.Length/2 + 1) * (A.Length+1)
: -sum + (A.Length/2 + 1) * (A.Length+2);
}
}
my solution in java 100%
Detected time complexity:
O(N)
import java.util.*;
class Solution {
public int solution(int[] arr) {
if(arr.length == 0) return 1;
int sumArr = 0;
for(int i=0; i < arr.length; i++){
sumArr = sumArr + arr[i];
}
int sumN = 0;
for(int i=1; i <= arr.length+1; i++){
sumN = sumN + i;
}
if(sumArr == sumN) return arr.length;
return sumN - sumArr;
}
}
You can use an Array to sort the element first and then use simple for loop to iterate over it, and find the missing value.
Here is my simple code with detected time complexity of O(N) or O(N * log(N)) in codility.
public static int solution(int[] A) {
int size = A.length;
int count = 1;
Arrays.sort(A);
for (int i = 0; i < size; i++) {
if (A[i] != count)
return count;
count++;
}
return count;
}
Here is the solution in PHP using the sum of consecutive integers from 1 to n is equal to n(n+1)/2.
function solution($A) {
$size = count($A) + 1;
$total = ($size * ($size + 1)) / 2;
return $total - array_sum($A);
}
java solution:
public int solution(int[] A) {
int nExpected = A.length + 1;
long seriesSumExpected = nExpected * (nExpected + 1L) / 2;
long seriesSum = getSum(A);
return (int) (seriesSumExpected - seriesSum);
}
private long getSum(int[] A) {
long sum = 0L;
for (int i : A) {
sum += i;
}
return sum;
}
Task Score: 100%
Correctness: 100%
Performance: 100%
private static int getMissingElementInArrayNew(int[] A) throws IOException {
double n = A.length + 1;
double totalSum = (double) ((n * (n + 1)) / 2);
for (int i = 0; i < A.length; i++) {
totalSum -= A[i];
}
return (int) (totalSum == 0 ? A.length + 1 : totalSum);
}
Here's another solution using JavaScript tested 100%.
function solution(A) {
let maximumNumber = A.length + 1;
let totalSum = (maximumNumber*(maximumNumber + 1))/2;
let partialSum = 0;
for(let i=0; i<A.length; i++) {
partialSum += A[i];
}
return totalSum - partialSum;
}
Golang solution:
func Solution(A []int) int {
n := len(A) + 1
total := n * (n + 1) /2
for _, e := range A {
total -= e
}
return total
}
Java solution got 100%:
public int solution(int[] A) {
Arrays.sort(A);
if (A.length == 0) {
return 1;
}
if (A[0] != 1) {
return 1;
}
for (int i = 0; i < A.length; i++) {
if (A[i] != i + 1) {
return A[i] - 1;
}
}
return A[A.length - 1] + 1;
}
While I value the math solution it's not that easy to understand.
So here's a simple solution with 100% score on codility.
import java.util.*;
public int solution(int[] A) {
int missing = 1; // missing number 1 already
Arrays.sort(A);
// check numbers one by one
for (int i = 0; i < A.length; i++) {
if (A[i] == missing) { // we found the missing number !
missing = A[i]+1; // add +1 and keep checking
}
}
return missing;
}
OBJECTIVE-C SOLUTION O(N) - SET Approach
Results given by Codility
Task Score: 100%
Correctness: 100%
Performance: 100%
Time Complexity
The worst case time complexity is O(N) or O(N * log(N))
Xcode Solution Here
+(int)SETSolution:(NSMutableArray*)array {
/******** Algorithm Explanation ********/
// FACTS
// Use of a NSSet to verify if the missing element exist or not.
// Edge case: when the array is empty [], we should return 1
// STEP 1
// validate the edge case
// STEP 2
// Generate a NSSet with the array elements in order to search an element faster
// STEP 3
// Use a for loop and find the current 'i' in the NSSset
// If an elements doesn't exist in the NSSet, that means it's the missing element.
int n = (int)[array count];
int missing = 0;
// STEP 1
if (n == 0) {
missing = 1;
return missing;
}
else {
// STEP 2
NSSet *elements = [NSSet setWithArray:array];
// STEP 3
for (int i = 1; i <= (n+1); i++) {
// O(N) or O(N * log(N)) depending of required iterations
if (![elements containsObject:[NSNumber numberWithInt:i]]) {
missing = i;
return missing;
}
}
return missing;
}
}
OBJECTIVE-C SOLUTION O(N) - XOR Approach
Results given by Codility
Task Score: 100%
Correctness: 100%
Performance: 100%
Time Complexity
The worst case time complexity is O(N) or O(N * log(N))
Xcode Solution Here
+(int)XORSolution:(NSMutableArray*)array {
/******** Algorithm Explanation ********/
// FACTS
// Use of XOR operator
// Edge case: when the array is empty [], we should return 1
// XOR of a number with itself is 0.
// XOR of a number with 0 is number itself.
// STEP 1
// XOR all the array elements, let the result of XOR be X1.
// STEP 2
// XOR all numbers from 1 to n, let XOR be X2.
// STEP 3
// XOR of X1 and X2 gives the missing number.
int n = (int)[array count];
// Edge Case
if(n==0){
return 1;
}
else {
// STEP 1
/* XOR of all the elements in array */
int x1 = 0;
for (int i=0; i<n; i++){
x1 = x1 ^ [[array objectAtIndex:i]intValue];
}
// STEP 2
/* XOR of all the elements from 1 to n+1 */
int x2 = 0;
for (int i=1; i<=(n+1); i++){
x2 = x2 ^ i;
}
// STEP 3
int missingElement = x1 ^ x2;
return missingElement;
}
}
100% solution in Swift 4:
public func solution(_ A : inout [Int]) -> Int {
// first we simply calculate the sum on the given array
var sum = 0
for element in A {
sum += element
}
// as the sum of consecutive ints is given by n(n+1)/2,
// we calculate the expected sum from 1 to n + 1
// (which is ((n+1)(n+2))/2) and substract the actual sum
// to get the missing element
return ((A.count + 1) * (A.count + 2) / 2) - sum
}
// Solution with LinQ.
// Task Score: 100%
// Correctness: 100%
// Performance: 100%
using System.Linq;
public static int GetPermMissingElem(int[] A)
{
if (A.Length <= 0)
return 1;
int size = A.Length;
System.Collections.Generic.List<int> missing = Enumerable.Range(1, A[size - 1]).Except(A.ToList()).ToList();
if (!missing.Any())
return A[size -1] + 1;
return missing.First();
}
This got 100% on Codality. It uses very basic math. For the array:
{2,3,1,5}
1,2,3,4,?
sum of all the indexes + 1 and plus the missing index + 1 to get what you total should be.
Then you can subtract the sum of the array: (1+2+3+4+5=15)-(2+3+1+5=11)=4
public int solution(int A[]) {
if (A == null) return 0;
if(A.length == 0) return 1;
int total = 0;
int max = A.length + 1;
for (int i = 0; i < A.length; i++) {
total += A[i];
max += i + 1;
}
return (max - total) < 0 ? 0 : (max - total);
}
This is one thing I had to look up though which irritates me and I don't understand.
if(A.length == 0) return 1;
This makes IMO no sense. If the array length is zero then it should be zero IMO.
I used this java code as a solution. Got 100%
class Solution {
public int solution(int[] A) {
int result = 0;
Set<Integer> set = new HashSet<>();
for (int x : A) {
set.add(x);
}
for (int x = 1; x < set.size() + 2; x++) {
if (!set.contains(x)) {
return x;
}
}
return result;
}
}
Ruby, 100% pass :
def solution(a)
n = a.length + 1
sum = n * (n + 1)/2
return sum - a.inject(0,:+)
end
I have trouble with this, but only because i did not understand all cases.
this is my solution in Java. Bit longer (i could not make it small) but score is 100%.
class Solution {
public int solution(int[] A) {
Arrays.sort(A);
if (A.length == 1) {
if (A[0] == 1) {
return A.length + 1;
} else {
return A[0] - 1;
}
}
for (int n = 0; n < A.length - 1; n++) {
if (A.length == 2) {
if (A[n] == 1) {
if (A[n] + 1 != A[n + 1]) {
return A[n] + 1;
}
return A.length + 1;
} else {
return 1;
}
} else {
if (A[0] != 1) {
return 1;
}
if (A[n] + 1 != A[n + 1]) {
return A[n] + 1;
}
}
}
return A.length + 1;
}
}
Analysis summary
The solution obtained perfect score.
Kind regards Nenad
using System;
// you can also use other imports, for example:
// using System.Collections.Generic;
// you can write to stdout for debugging purposes, e.g.
// Console.WriteLine("this is a debug message");
class Solution {
public int solution(int[] A) {
// write your code in C# 6.0 with .NET 4.5 (Mono)
int i, j = 0, n = A.Length;
if (A != null && n != 0)
{
Array.Sort(A);
for (j = A[0], i = 0; i < n; i++, j++)
{
if (j == A[i]) continue;
else return j;
}
if (i == n) return (A[0] == 2) ? 1 : ++A[--n];
}
else return 1;
return -1;
}
}
Swift solution 100% pass
import Foundation
import Glibc
public func solution(_ A : inout [Int]) -> Int {
let sortedArray = A.sorted(by: { $0 < $1 })
for i in 0..<sortedArray.count {
if sortedArray[i] != i+1 {
return i+1
}
}
return A.count + 1
}
Java Solution:
// Import Dependencies
import java.util.*;
class Solution {
public int solution(int[] A) {
// write your code in Java SE 8
long N = A.length+1;
long realSum = N*(N+1)/2;
long foundSum = 0;
for(int i=0;i<N-1;i++){
foundSum = foundSum + A[i];
}
long answer = (realSum - foundSum);
return (int)(answer);
}
}
Here is my solution.
const assert = require("assert").strict;
function solution(A) {
const n = A.length + 1;
const sum = (n * (n + 1)) / 2;
const sum2 = A.reduce((a, b) => a + b, 0);
return sum - sum2;
}
assert.strictEqual(solution([2, 3, 1, 5]), 4);
assert.strictEqual(solution([]), 1);
assert.strictEqual(solution([1]), 2);
Attaching solution written in kotlin:
fun solution(A: IntArray): Int {
val lastElement = A.size + 1
// including missing element
val arraySize = A.size + 1L
var result = (arraySize * (1 + lastElement)) / 2
A.forEach {
result -= it
}
return result.toInt()
}
P.S. Arithmetic progression sum formula was used.
P.P.S. Perform operations using Long primitive type, as you can face some Int limits.
I think the best way of doing it is via XOR which is clean, elegant and fast. No math knowledge required, just CS! This has also another advantage over the other way of summing it up where we won't get an integer overflow since we are just doing bitwise operations.
O(n) in time, O(1) in space.
This is how the code looks like (Javascript), just a single loop required:
function solution(A) {
// write your code in JavaScript (Node.js 8.9.4)
let missingNumber = A.length + 1;
// Sum up 1+2+3+...+N+(N+1) AND all of A[i] (except value not present in A[i] obviously). The value not present in A[i] is the odd one out. Note `missingNumber` starts with `A.length + 1` (i.e. N+1) because we loop N times here only...
for(let i = 0; i < A.length; ++i) {
missingNumber ^= (i + 1) ^ A[i];
}
return missingNumber;
}
https://florian.github.io/xor-trick/ has a good guide to understanding XORs.
Basically taking the idea where X ^ X equals 0, we use this to take advantage of duplicate values that cancels out the values so we get the non-duplicated value out (i.e. the missing element left).
This works because the question constraints guarantees the elements of A are all distinct. So we can just XOR them up together to take advantage of this trick. If this is a permutation where elements can be duplicated, this does not work, i.e. PermCheck
My solution tries to half the time of the summation. Detected time complexity:
O(N) or O(N * log(N))
`
int sumArray = 0;
int t = A.length-1;
for (int i=0; i<= t-i; i++) {
if(i == t-i){
sumArray += A[i];
break;
}
sumArray += (A[i] + A[t-i]);
}
int n = (A.length + 1);
int total = BigDecimal.valueOf(n).pow(2).add(BigDecimal.valueOf(n)).divide(BigDecimal.valueOf(2)).intValue();
return total - sumArray;
`
I just tried this solution which has no sorting and just sticks to the basics, got 100% result
public int solution100percent(int[] A) {
if (A.length == 0)
return 1;
int arrayCount = 0;
int iCount = 0;
for (int i = 0; i < A.length; i++) {
arrayCount += A[i];
iCount += i;
}
return iCount + A.length + (A.length + 1) - arrayCount;
}
Although knowing the total sum of consecutive integers would help get a fast solution , a fast but not memory efficient solution is possible using additional array and 2O(N) complexity without calculating the sum..
here is my solution:
class Solution {
public int findFalse(boolean [] ar){
for (int j = 0; j<ar.length; ++j){
if(ar[j]==false){
return j;
}
}
return -1;
}
public int solution(int[] A) {
// write your code in Java SE 8
boolean [] M = new boolean[A.length+1];
for (int i:A){
M[i-1] = true;
}
int missingValue = findFalse(M) +1 ;
return missingValue;
}
}
I am trying to solve a problem in which you have to count the number of possible bar codes you can make given specific parameters. I solved the problem recursively and am able to get the correct answer every time. However, my program is dreadfully slow. I tried to rectify this using a technique I read about called memoization but my program still crawls when given certain input (ex: 10, 10, 10). Here's the code in java.
Does anybody have any idea what I'm doing wrong here?
import java.util.Scanner;
//f(n, k, m) = sum (1 .. m) f(n - i, k - 1, m)
public class BarCode { public static int[][] memo;
public static int count(int units, int bars, int width) {
int sum = 0;
if (units >= 0 && memo[units][bars] != -1) //if the value has already been calculated return that value
return memo[units][bars];
for (int i = 1; i <= width; ++i) {
if (units == 0 && bars == 0)
return 1;
else if (bars == 0)
return 0;
else {
sum += count(units - i, bars - 1, width);
}
}
if (units > -1)
memo[units][bars] = sum;
return sum;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
//while (in.hasNext()) {
int num = in.nextInt();
int bars = in.nextInt();
int width = in.nextInt();
memo = new int[51][51];
for (int i = 0; i < memo.length; ++i) {
for (int j = 0; j < memo.length; ++j)
memo[i][j] = -1;
}
int sum = 0;
sum += count(num, bars, width);
System.out.println(sum);
//}
in.close();
}
}
TL:DR My memoization of a recursive search is too slow. Help!
You exclude all results from count calls with units < 0 from memoization:
if (units > -1)
memo[units][bars] = sum;
This leads to a lot of unnecessary calls to count for these values.
To include all cases, you could use a HashMap with a key generated from units and bars values. I used a string generated from units and bars like this:
//f(n, k, m) = sum (1 .. m) f(n - i, k - 1, m)
public class BarCode {
public static Map<String, Integer> memo = new HashMap<>();
public static int count(int units, int bars, int width) {
int sum = 0;
final String key = units + " " + bars;
Integer memoSum = memo.get(key);
if (memoSum != null) {
return memoSum.intValue();
}
for (int i = 1; i <= width; ++i) {
if (units == 0 && bars == 0)
return 1;
else if (bars == 0)
return 0;
else {
sum += count(units - i, bars - 1, width);
}
}
memo.put(key, Integer.valueOf(sum));
return sum;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int num = in.nextInt();
int bars = in.nextInt();
int width = in.nextInt();
memo = new HashMap<>();
int sum = 0;
sum += count(num, bars, width);
System.out.println(sum);
in.close();
}
}
For example, this brings the number of calls to count down from over 6 million to 4,150 for the input values "10 10 10" with 415 entries saved in the Map.
Your memoization implementation looks to be valid. It might help some, but the real problem here is your choice of algorithm.
From my cursory inspection of your code, on average a call to your count method will loop through width number of times. and each time it loops through, it goes a layer deeper by calling count again. It also looks like it's going to loop down bars layers deeper from the first layer. If my asymptotic analysis a few fingers of scotch in is correct, this would result in an algorithm which has a O(width^bars) runtime complexity. As you increase your input parameters, especially bars, the amount of steps your application needs to take in order to calculate your answer will increase greatly (exponentially, in the case of bars).
Your memoization will reduce the number of duplicate calculations needed, but each value being memoized will still need to be calculated at least once for the memoization to help. So with or without the memoization, you're still dealing with a non-polynomial time complexity, and that always spells bad performance.
You might want to consider looking for a more efficient approach. Instead of trying to count the number of bar code combinations, perhaps try using combinatorics to try to calculate it. For example, I could try to figure out the number of lowercase character strings (using only chars a-z) I can make for a string of length n by generating all of them and counting how many of them there are, but that will have an exponential time complexity and will not be performant. On the other hand, I know basic combinatorics tells me that the formula for the number of strings I can create is 26^n (26 choices in each position, and n positions), which the computer can easily evaluate quickly.
Look for a similar approach for computing the number of bar codes.
I want to find the Nth number of the Recurrence Equation
T(n)=T(n-1)+3T(n-2)+3T(n-3)+(n-4),T(1)=T(4)=1,T(2)=T(3)=3
so if suppose you entered 2,5,9 as input, output should be T(2)=3,T(5)=20,T(9)=695
what I did is create an array of size equal to maximum of all input value and storing solution of T(i) at index i.Then look up into the array for specific index. eg array[3] for T(3),array[5] for T(5),etc
The code worked fine till maximum number is not greater than maximum integer value system can hold i.e
Integer.MAXValue.
Because the index of array can only be integer then
if number is n=1855656959555656 what should be the best way to find the solution of
T(1855656959555656)?
as clearly I cant create an array of size=1855656959555656..
I have even tried BigInteger from java.Math but with no success.
I have to find some other approach.please suggest some ideas..
Thanks
you do not need to store every T(i), you only need to store 3 values T(i-1), T(i-2), T(i-3). While looping over i, check if the current i should be part of your output, if so put it out immediately or save it to an "output"-array.
edit: this part is quite inefficient. You check in every iteation EVERY needed output.
for (int k = 0; k < arr.length; ++k) {
if (count == arr[k])
T[k] = temp[i];
else if (arr[k] == 1)
T[k] = 1;
else if (arr[k] == 2)
T[k] = 3;
else if (arr[k] == 3)
T[k] = 3;
else if (arr[k] == 4)
T[k] = 1;
}
so your code runs in time (max*arr.length) you can reduce it to only (max). Use a HashMap with key=neededPosition (=count) value=position in arr
Init the map like this:
Map<Long, Integer> map = new HashMap<Long, Integer>();
for (int i = 0; i < arr.length; i++) {
map.put(arr[i], i);
}
if (map.containsKey(count)) {
T[map.get(count)] = temp[i]
}
check the values 1-4 just once after the whole thing!
Not possible. The array size can be a maximum of Integer.MAX_VALUE (minus something usually 5 or 8, depending on the JVM capabilities). Why?. The index for an Array should be an integer thats a limitation.
It can't be done. So you need to solve the problem by introducing a sharding mechanism. The simplest way would be to just have arrays of arrays with a fixed length.
Edit: You really do not need this much storage for your problem at hand (as pointed out in another answer; this code fragment avoids arrays altogether to avoid bounds checks / indirection):
public void t(long n) {
if (n < 5) {
return (n == 2 || n == 3) ? 3 : 1;
}
long i = 5; // Initialize variables for n == 5;
long tn_1 = 1; // T(n-1) = T(4) = 1;
long tn_2 = 3; // T(n-2) = T(3) = 3;
long tn_3 = 1; // T(n-3) = T(2) = 1;
long tn_4 = 3; // T(n-4) = T(1) = 3;
while (true) {
long tn = tn_1 + 3*tn_2 + 3*tn_3 + tn_4;
if (i++ == n) {
return tn;
}
tn_4 = tn_3;
tn_3 = tn_2;
tn_2 = tn_1;
tn_1 = tn;
}
}
To answer the question in the title anyway:
If your array is sparse, use a map (TreeMap or HashMap) of Long or BigInteger:
Map<Long,Long> t = new TreeMap<Long,Long>()
The memory consumption of sparse arrays depends on the number of elements actually stored, so you may want to delete values from the map that are no longer needed.
If your array is not sparse, use a 2-level array (memory consumption will depend on the pre-allocated size only):
public class LongArray {
static final long BLOCK_SIZE = 0x40000000;
long[][] storage;
public LongArray(long size) {
long blockCount = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
storage = new long[][(int) blockCount];
for (long i = 0; i < blockCount; i++) {
if (i == blockCount - 1) {
storage[i] = new long[(int) size - BLOCK_SIZE * (blockCount - 1)];
} else {
storage[i] = new long[(int) BLOCK_SIZE];
}
}
}
public long get(long index) {
return storage[(int) (index / BLOCK_SIZE)][(int) (index % BLOCK_SIZE)];
}
public void put(long index, long value) {
storage[(int) (index / BLOCK_SIZE)][(int) (index % BLOCK_SIZE)] = value;
}
}
In both cases, use t.get(index) and t.put(index, value) instead of t[index] to access your array (if t is the name of the array).
You can do one thing. Check if the value of n is equal to 1855656959555656 in the beginning or if its multiple. Suppose, the value of n is twice of 1855656959555656. Then you can create two arrays and link them together virtually. This should solve your problem but it will involve a lot of overhead.
Use recursive call:
int T(int n){
if (n==1 || n==4){
return 1;
} else if (n==2 || n==3){
return 3;
} else {
return T(n-1)+3*T(n-2)+3T*(n-3)+T(n-4);
}
}
Edit: Time consumming. Won't work with large numbers
The assignment is to create a method that finds the second largest even int in an array of ints. I am restricted from using any methods from any libraries.
Here is my code that works for all cases:
public static int getSecondLargestEven(int[] ary) {
int i;
aryLength = ary.length;
int largestEven = -1;
int secondLargestEven = -1;
for (i = 0; i < aryLength; i++) {
if (ary[i] % 2 == 0) {
if (ary[i] > largestEven) {
if (largestEven != -1)
secondLargestEven = largestEven;
largestEven = ary[i];
} else {
if (ary[i] != largestEven) {
if (secondLargestEven == -1 || ary[i] >= secondLargestEven) {
secondLargestEven = ary[i];
}
}
}
}
}
Prior to calling the methodI require the array to have more than one even else no method call.
So, when secondLargestEven == -1, I know there is a duplicate.
Is there a more efficient (less use of operators, less loops used, less memory allocation) way to accomplish the objective? How can I improve the logic of my code? How can I improve my code overall?
I don't like that I have to assign the magic number -1 to secondLargestEven and largestEven because they are technically named to hold EVENS. Would it be efficient to use a loop to assign a valid even integer in the array to both secondLargestEven and largestEven and THEN proceed to search? Thanks in advance.
You can make the code cleaner by not explicitly checking for the case when the largest and second variables are equal to -1.
Just set these variables to Integer.MIN_VALUE before the loop - this is the same as assuming that there were two additional values in your array that come before all the others, and they both have the value Integer.MIN_VALUE.
public static int secondLargestEven(int[] x) {
int largest = Integer.MIN_VALUE;
int second = Integer.MIN_VALUE;
for (int i = 0; i < x.length; i++) {
if (x[i] % 2 == 0) {
if (x[i] > largest) {
second = largest;
largest = x[i];
} else if (x[i] > second) {
second = x[i];
}
}
}
return second;
}
Edit -- I thought I'd throw in that you can remove one level of nesting by using a continue statement inside the loop to skip the cases where you have an odd integer, although some people would consider this more difficult to understand than the code above.
It's a tradeoff - you use explicit control flow inside the loop (bad) but you remove a nesting level (good).
public static int secondLargestEven(int[] x) {
int largest = Integer.MIN_VALUE;
int second = Integer.MIN_VALUE;
for (int i = 0; i < x.length; i++) {
if (x[i] % 2 != 0)
continue;
if (x[i] > largest) {
second = largest;
largest = x[i];
} else if (x[i] > second)
second = x[i];
}
}
return second;
}
Just a fun thought... in Haskell, this function can be written in one line
import Data.List (sort)
secondLargestEven = (!! 1) . reverse . sort . filter even
or, if you want to be more efficient
import Data.List (sortBy)
import Data.Ord (comparing)
secondLargestEven = (!! 1) . sortBy (comparing negate) . filter even
This is just-for-fun implementation:
public static int secondLargestEven(int[] array) {
Set<Integer> evenSet = new TreeSet<>(Collections.reverseOrder());
for (int n : array) if (n % 2 == 0) evenSet.add(n);
return new ArrayList<>(evenSet).get(1);
}
This method is extremely inefficient (I cant look at it) but returns second largest even number :)
Method works only if array has second largest even number.