Calculate the largest best combination of denominations for a number - java

Problem Statement:
I need to get the best combination of denomination for a given number.
Example: I have three denominations {50,25,10} and given number is 30 then list should return <10,10,10>. for number 80 it should return <50,10,10,10> as remaining 30 is not completely divide by 25.
For 35 it should return <25,10>
for 75 <50,25>
for 65 <50,10>
This is somewhat similar to coin problem but I am not able to get the values of denominations.
Refence StackOverFlow Coin change DP solution to keep track of coins
Here is what I have tried so far :
public static int[] minChange(int[] denom, int changeAmount) {
int n = denom.length;
int[] count = new int[changeAmount + 1];
int[] from = new int[changeAmount + 1];
count[0] = 1;
for (int i = 0; i < changeAmount; i++ )
if (count[i] > 0)
for (int j = 0; j < n; j++ ) {
int p = i + denom[j];
if (p <= changeAmount) {
if (count[p] == 0 || count[p] > count[i] + 1) {
count[p] = count[i] + 1;
from[p] = j;
}
}
}
// No solutions:
if (count[changeAmount] == 0)
return null;
// Build answer.
int[] result = new int[count[changeAmount] - 1];
int k = changeAmount;
while (k > 0) {
result[count[k] - 2] = denom[from[k]];
k = k - denom[from[k]];
}
return result;
}
This works well if value are completely divisible by one of denomination other wise i doesn't work at all.

Once you have the solution in the 2D array for the dynamic programming solution, you can find out what denominations were optimal by backtracking through your array from the end (arr[n][n]).

Related

Find maximum triplet in an array

I have an array of numbers [1,2,6,4,105,111,1024] I want to check all possible triplets a,b,c such that b%a ==0 and c%b ==0. For such triplets get the middle element b. Now I want to return the maximum possible b for such triplets.
For this array the valid triplets are :
indices:
(0,1,2) = middle item = 2
(0,1,3) = middle item = 2
(0,1,6) = middle item = 2
(0,3,6) = middle item = 4
(1,3,6) = middle item = 4
So the maximum value is 4 is the answer.
Here is my code:
int process(List<Integer> list) {
int n = list.size();
int max = -1;
for(int i=0; i<n-2; i++) {
int a = list.get(i);
boolean valid = true;
for(int j=i+1; j<n-1; j++) {
int b = list.get(j);
valid = b % a == 0;
for(int k=j+1; valid && k<n; k++) {
int c = list.get(k);
if(c % b ==0) {
max = Math.max(max, b);
}
}
}
return max;
}
How to reduce the time complexity for this code.
constraints:
size of the input list is 1 to 10^5.
Each element in the list is also 1 to 10^5
Repetitions are allowed for input elements.
c % b = 0 and b % a = 0 means a is the lowest factor OR a possible GCD of both b and c. However, since we need to find the maximum greatest value of the middle element, we will take a different route.
We put all the elements of the array in the hashMap with a boolean falsy value by default.
For each element in arr, we check with all it's factors by iterating till square root of this number.
If any of the factor exists already in the map, we perform one more check as to whether this factor has a factor of it's own present in the array. This way, the current factor at hand makes it the middle element of the triplet.
We keep taking maximum of those and return the answer. We return -1 if no such triplet exists.
Snippet:
import java.util.*;
public class Main {
public static void main(String[] args) {
int[] arr = { 1,2,6,4,105,111,1024};
System.out.println(solve(arr));
}
private static int solve(int[] arr){
Map<Integer,Boolean> map = new HashMap<>();
int max = -1;
for(int i = 0 ; i < arr.length; ++i){
boolean factorExists = false;
for(int j = 1; j * j <= arr[i]; ++j){
if(arr[i] % j == 0 && map.getOrDefault(j, false)){
max = Math.max(max, j);
}
int cousin = arr[i] / j;
if(arr[i] % j == 0 && arr[i] % cousin == 0 && map.getOrDefault(cousin, false)){
max = Math.max(max, cousin);
}
factorExists = factorExists || arr[i] % j == 0 && map.containsKey(j) || arr[i] % j == 0 && arr[i] % cousin == 0 && map.containsKey(cousin);
}
map.putIfAbsent(arr[i], false);
map.put(arr[i], map.get(arr[i]) || factorExists);
}
return max;
}
}
Online Demo
Time Complexity: O(n1.5) since we walk through till square root of each element.
Space Complexity: O(n) since we store all the elements of the array in the map.
Here is a more efficient approach based on what #nice_dev already did. The improvement is to create a table of factors instead of checking up to the square root of each number.
If you have n numbers of size at most m, this approach is O((n+m) log(m)).
def find_max_mid(numbers):
# Find all potential factors.
max_n = max(numbers)
factors = {}
saw_n = set()
for n in numbers:
if n not in saw_n:
for m in range(n, max_n+1, n):
if m in factors:
factors[m].append(n)
else:
factors[m] = [n]
saw_n.add(n)
max_mid = -1
has_factor = set()
saw_n = set() # Reset
for n in numbers:
for f in factors[n]:
if f in saw_n:
if max_mid < f and f in has_factor:
max_mid = f
has_factor.add(n)
saw_n.add(n)
return max_mid
print(find_max_mid([1,2,6,4,105,111,1024]))
print(find_max_mid([3,9,27,32,64]))
print(find_max_mid([1,2,3]))
print(find_max_mid(list(range(1, 100000))))
Instead of using multiple for loops use single for loop and a HashMap to keep the modulo results for each position and with that you can do the same thing with O(n) time complexity

Java Sorting Even and Odd Numbers

I'm in a high school programming class right now and my instructions were to create a program that stores the random numbers in an array that's sorted by even and then odd numbers. Here's my code so far, I have no idea why it's not working. It keeps printing out 0's even though I'm supposed to generate numbers above 1. Help would be greatly appreciated, thanks! :D
Random rnd = new Random();
int randomNumArray[] = new int[10];
int evenArray[] = new int[10];
int oddArray[] = new int[10];
int countEven = 0,countOdd = 0;
for (int i = 0; i < randomNumArray.length; i++)
{
randomNumArray[i] = rnd.nextInt(100) + 1;
System.out.println(randomNumArray[i]);
if (randomNumArray[i] % 2 == 0)
{
evenArray[i] = randomNumArray[i];
countEven++;
}
else if (randomNumArray[i] % 2 == 1)
{
oddArray[i] = randomNumArray[i];
countOdd++;
}
}
for (int i = 0; i < countEven; i++)
{
System.out.println(evenArray[i]);
}
for (int i = 0; i < countOdd; i++)
{
System.out.println(oddArray[i]);
}
The problem is you are storing the values in evenArray and oddArray at index i, which is not necessarily the "next unused space" in the array you're writing to. Let's say the first number (when i = 0) is even and the second (when i = 1) is odd; when the second number is stored by oddArray[i] = randomNumArray[i];, it will be stored at index 1, but it is the first odd number so it should be in oddArray at index 0 instead.
To solve this, you can use countEven and countOdd as the correct indices to write to; for example, when countOdd is 0 then there are no odd numbers yet, so index 0 is the correct place to write the first one. So you can change these two lines:
if (randomNumArray[i] % 2 == 0)
{
// changed here
evenArray[countEven] = randomNumArray[i];
countEven++;
}
else if (randomNumArray[i] % 2 == 1)
{
// changed here
oddArray[countOdd] = randomNumArray[i];
countOdd++;
}
You should change these lines
evenArray[countEven] = randomNumArray[i];
oddArray[countOdd] = randomNumArray[i];
... instead of
evenArray[i] = randomNumArray[i];
oddArray[i] = randomNumArray[i];

Linear probing in Hashing implementation

I am trying to solve this problem where I need to implement Linear Probing.
Given an array of integers and a hash table size. Fill the array elements into a hash table using Linear Probing to handle collisions.
Example 1:
Input:
hashSize = 10
sizeOfArray = 4
Array[] = {4,14,24,44}
Output:
-1 -1 -1 -1 4 14 24 44 -1 -1
Example 2:
Input:
hashSize = 10
sizeOfArray = 4
Array[] = {9,99,999,9999}
Output:
99 999 9999 -1 -1 -1 -1 -1 -1 9
Your Task:
You don't need to read input or print anything.
Your task is to complete the function linearProbing() which takes as input a empty hash table (hash), the hash table size (hashSize), an integers array arr[] and its size N and inserts all the elements of the array arr[] into the given hash table.
The empty cells of the hash table are to be given a value of -1. Also, if there's no more space to insert a new element, just drop that element.
Expected Time Complexity: O(N).
Expected Auxiliary Space: O(1).
Constraints:
1 <= hashSize <= 100
1 <= sizeOfArray <= 100
0 <= Array[] <= 105
The code I wrote is:
static int[] linearProbing(int hash_size, int arr[], int N) {
int[] a = new int[hash_size];
for(int i = 0; i < hash_size; i++)
a[i] = -1;
for(int i = 0; i < N; i++) {
int probe = arr[i] % hash_size;
int offset = 1;
while(a[probe] != -1) {
probe = (probe + offset) % hash_size;
}
a[probe] = arr[i];
}
return a;
}
The given testcases are running. But when submitting I am getting TLE. Please help.
The driver code is given as follows =
https://i.stack.imgur.com/ULVdd.png
You missed out one single point, when the array size is bigger than the hash table, just skip the rest.
This could also be the simple point, Just replace N with hash_size and iterate. This would let you only iterate as long as arr contains elements
static int[] linearProbing(int hash_size, int arr[], int N) {
//This is what was missing from your code
int iterating_size = N>hash_size? hash_size : N;
int[] a = new int[hash_size];
for(int i = 0; i < hash_size; i++)
a[i] = -1;
int started = -1;
for(int i = 0; i < iterating_size ; i++) {
int probe = arr[i] % hash_size;
int offset = 1;
while(a[probe] != -1) {
probe = (probe + offset) % hash_size;
}
a[probe] = arr[i];
}
return a;
}

Finding all possible subset sum which is equal to 0 out of set of positive and negative numbers? [duplicate]

This question already has answers here:
given a set of n integers, return all subsets of k elements that sum to 0
(3 answers)
Closed 6 years ago.
You have an array which has a set of positive and negative numbers, print all the subset sum which is equal to 0.
I can think of approach where i can cam make all powersets of givcen array and check if their sum is 0. BUt that does not llok like optimized solution to
me.
After reading looks a bit similar problem on net , looks like it can be solved with dynamic programming like below program to find if there is combination exist
to make sum 11 just an example ?
public boolean subsetSum(int input[], int total) {
boolean T[][] = new boolean[input.length + 1][total + 1];
for (int i = 0; i <= input.length; i++) {
T[i][0] = true;
}
for (int i = 1; i <= input.length; i++) {
for (int j = 1; j <= total; j++) {
if (j - input[i - 1] >= 0) {
T[i][j] = T[i - 1][j] || T[i - 1][j - input[i - 1]];
} else {
T[i][j] = T[i-1][j];
}
}
}
return T[input.length][total];
}
public static void main(String args[]) {
TestDynamic ss = new TestDynamic();
int arr1[] = {2, 3, 7, 8};
System.out.print(ss.subsetSum(arr1, 11));
}
But i am not sure how to extend above programe to
1) Include negative number
2) find combination of elements whick makes sum as zero( Above program just finds whether its possible to make given sum but does not
find which set of numbers makes it zero)
Here is a full implementation in Javascript. You can run it with node.js.
function target_sum(a, k, x)
{
if (k == a.length) return [];
if (a[k] == x) {
return [[a[k]]];
} else {
var s = target_sum(a, k + 1, x); // not using a[k]
var t = target_sum(a, k + 1, x - a[k]); // using a[k]
for (var i = 0; i < t.length; ++i) {
t[i].unshift(a[k]); // a[k] is part of the solution
s.push(t[i]); // merge t[] into s[]
}
return s;
}
}
var s = target_sum([1,4,5,2,7,8,-3,-5,-6,9,3,-7,-1,5,6], 0, 0);
for (var i = 0; i < s.length; ++i)
console.log(s[i].join(","));
Note that this is an exponential algorithm. Don't use it on large arrays.
Erwin Rooijakkers also pointed to the right direction. In particular, this post gives another algorithm. I could be wrong about the following – I believe that algorithm trades speed for space. It avoids staging arrays into the call stack, but it has to do more recursions to achieve that.
EDIT: about the algorithm you mentioned. It is not exponential, but it only works for positive numbers if I am right. Its time complexity is also proportional to the target sum, which may not be ideal depending on input.

Perfect shuffle algorithm implementation error

Is this code correct for perfect shuffle algorithm ? I'm always trying to generate a number from 0 to n and swapping the number with the last element in the array thereby reducing the range of n. However when the n=0, I get an exception. How do I deal with this case ?
int [] array ={1,2,3,4,5};
Random random = new Random();
int n=array.length;
while(n--!=0)
{
int number = random.nextInt(n);
int temp = array[n];
array[n] = array[number];
array[number] = temp;
}
EDIT: if I change it to --n >0 then it works correctly but am I implementing the shuffling algorithm correctly in that case because I never do anything for n=0 ?
In your code segment
while(n--!=0)
if n is 1, it will become 0 and `random.nextInt(0)` will return an error.
Refer this link
I don't think nextInt works if you pass an argument of 0.
The best way to shuffle is by using the Fisher Yates algorithm. It's fast, works in-place, and is unbiased:
int [] array = {1,2,3,4,5};
Shuffle(array, new Random());
// Fisher Yates shuffle - see http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
void Shuffle(int[] array, Random RNG)
{
for (int i = array.length - 1; i >= 1; i -= 1)
{
// get integer in range of j >= 0 && j < i + 1
int j = RNG.nextInt(i + 1);
//assert(j >= 0 && j <= i);
if (i != j)
{
// only swap if i and j are different
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}

Categories