Related
Recently i got a competetive programming task which i couldn't manage to complete. Just curious to know the best solution for the problem
"A" is a zero-indexed array of N integers.
Elements of A are integers within the range [−99,999,999 to 99,999,999]
The 'curry' is a string consisting of N characters such that each character is either 'P', 'Q' or 'R' and the
corresponding index of the array is the weight of each ingredient.
The curry is perfect if the sum of the total weights of 'P', 'Q' and 'R' is equal.
write a function
makeCurry(Array)
such that, given a zero-indexed array Array consisting of N integers, returns the perfect curry of this array.
The function should return the string "noLuck" if no perfect curry exists for that Array.
For example, given array Array such that
A[0] = 3 A[1] = 7 A[2] = 2 A[3] = 5 A[4] = 4
the function may return "PQRRP", as explained above. Given array A such that
A[0] = 3 A[1] = 6 A[2] = 9
the function should return "noLuck".
The approach i tried was this
import collections
class GetPerfectCurry(object):
def __init__(self):
self.curry = ''
self.curry_stats = collections.Counter({'P': 0, 'Q': 0, 'R': 0})
pass
def get_perfect_curry(self, A):
if len(A) == 0:
return "noLuck"
A.sort(reverse=True)
for i, ele in enumerate(A):
self.check_which_key_to_add_new_element_and_add_element(ele)
if self.curry_stats['P'] == self.curry_stats['Q'] == self.curry_stats['R']:
return self.curry
else:
return "noLuck"
def check_which_key_to_add_new_element_and_add_element(self, val):
# get the maximum current value
# check if addition of new value with any of the other two key equals the max value
# if yes then add that value and append the key in the curry string
current_max_key = max(self.curry_stats, key=self.curry_stats.get)
check_for_equality = False
key_to_append = None
for key, ele in enumerate(self.curry_stats):
if ele != current_max_key:
if self.curry_stats[ele] + val == self.curry_stats[current_max_key]:
check_for_equality = True
key_to_append = ele
if check_for_equality:
self.curry_stats.update(str(key_to_append) * val)
self.curry += str(key_to_append)
pass
else:
# if no value addition equals the current max
# then find the current lowest value and add it to that key
current_lowest_key = min(self.curry_stats, key=self.curry_stats.get)
self.curry_stats.update(str(current_lowest_key)*val)
self.curry += str(current_lowest_key)
if __name__ == '__main__':
perfect_curry = GetPerfectCurry()
A = [3, 7, 2, 5, 4]
# A = [3, 6, 9]
# A = [2, 9, 6, 3, 7]
res = perfect_curry.get_perfect_curry(A)
print(res)
But it was incorrect. Scratching my head for the past four hours for the best solution for this problem
A possible algorithm is as follows:
Sum the weights. If it's not a multiple of 3, no luck. If it is, divide by 3 to get the target.
Find subsets of A that add up to target. For such subsets, remove it and you get B. Find a subset of B that adds up to target.
Here's a Java implementation (I'm not a Python guy, sorry):
import java.util.Arrays;
public class Main
{
// Test if selected elements add up to target
static boolean check(int[] a, int selection, int target)
{
int sum = 0;
for(int i=0;i<a.length;i++)
{
if(((selection>>i) & 1) == 1)
sum += a[i];
}
return sum==target;
}
// Remove the selected elements
static int[] exclude(int[] a, int selection)
{
int[] res = new int[a.length];
int j = 0;
for(int i=0;i<a.length;i++)
{
if(((selection>>i) & 1) == 0)
res[j++] = a[i];
}
return Arrays.copyOf(res, j);
}
static String getCurry(int[] a)
{
int sum = 0;
for(int x : a)
sum += x;
if(sum%3 > 0)
return "noLuck";
int target = sum/3;
int max1 = 1<<a.length; // 2^length
for(int i=0;i<max1;i++)
{
if(check(a, i, target))
{
int[] b = exclude(a, i);
int max2 = 1<<b.length; // 2^length
for(int j=0;j<max2;j++)
{
if(check(b, j, target))
return formatSolution(i, j, a.length);
}
}
}
return "noLuck";
}
static String formatSolution(int p, int q, int len)
{
char[] res = new char[len];
Arrays.fill(res, 'R');
int j = 0;
for(int i=0;i<len;i++)
{
if(((p>>i) & 1) == 1)
res[i] = 'P';
else
{
if(((q>>j) & 1) == 1)
res[i] = 'Q';
j++;
}
}
return new String(res);
}
public static void main(String[] args)
{
// int[] a = new int[]{3, 7, 2, 5, 4};
// int[] a = new int[]{1, 1, 2, -1};
int[] a = new int[]{5, 4, 3, 3, 3, 3, 3, 3};
System.out.println(getCurry(a));
}
}
You can test it here.
Hereafter so many years I'm writing code for js for needed people. (TBH I took the ref of the accepted answer)
As he mentioned, A possible algorithm is as follows:
Sum the weights. If it's not a multiple of 3, no luck. If it is, divide by 3 to get the target.
Find subsets of A that add up to target. For such subsets, remove it and you get B. Find a subset of B that adds up to target.
// Test if selected elements add up to target
function check(a, selection, target)
{
let sum = 0;
for(let i=0;i<a.length;i++)
{
if(((selection>>i) & 1) == 1)
sum += a[i];
}
return sum==target;
}
// Remove the selected elements
function exclude(a, selection)
{
let res = [a.length];
let j = 0;
for(let i=0;i<a.length;i++)
{
if(((selection>>i) & 1) == 0)
res[j++] = a[i];
}
return res
}
function getCurry(a)
{
let sum = a.reduce((accumulator, currentValue) => accumulator + currentValue);
if(sum%3 > 0)
return "noLuck";
let target = sum/3;
let max1 = 1<<a.length; // 2^length
for(let i=0;i<max1;i++)
{
if(check(a, i, target))
{
let b = exclude(a, i);
let max2 = 1<<b.length; // 2^length
for(let j=0;j<max2;j++)
{
if(check(b, j, target))
return formatSolution(i, j, a.length);
}
}
}
return "noLuck";
}
function formatSolution(p, q, len)
{
let res = new Array(len)
res.fill('R')
let j = 0;
for(let i=0;i<len;i++)
{
if(((p>>i) & 1) == 1)
res[i] = 'P';
else
{
if(((q>>j) & 1) == 1)
res[i] = 'Q';
j++;
}
}
return new String(res);
}
// let a = [3, 7, 2, 5, 4]
// let a = [1, 1, 2, -1]
let a = [5, 4, 3, 3, 3, 3, 3, 3]
getCurry(a)
This was one of the interview questions in amazon.
Given a 2D array of 0's and 1's we need to find the pattern of maximum size.
Patters is as follows:
size = 1:
1
1 1 1
1
size = 2:
1
1
1 1 1
1
1
Naive Solution: Traverse each and every element of MxN matrix, and search for the index with value 1 and check if left & right entries as 1 and note the maximum length of 1's above and below the index.
Looking for a better solution. If anyone has a clue please do post.
I assume that any 1 values that surround such a pattern do not destroy it, so that also this would have size 1:
1 1 1 1
1 1 1 1
1 1 0 1
1 1 1 1
In that case I would suggest an algorithm where for each column you do the following:
Initialise size as 0
For each cell in this column:
Push the current size on a stack; it represents the number of 1 values in the upward direction starting from this cell.
If the value in this cell is a 1, then increase size, otherwise set it to 0
Initialise size as 0
For each cell in this column, but in reverse order:
Pop the last value from the stack
Call thisSize the least of the popped value and the value of size.
If thisSize is greater than the best pattern found so far and the values at both sides of the current cell are 1, then consider this the best pattern.
If the value in this cell is a 1, then increase size, otherwise set it to 0
As a further optimisation you could exit the second loop as soon as the distance between the current cell and the top of the grid becomes smaller than the size of the largest pattern we already found earlier.
Here is an implementation in JavaScript:
function findPattern(a) {
var rows = a.length,
cols = a[0].length,
maxSize = -1,
stack = [],
row, col, pos, thisSize;
for (col = 1; col < cols-1; col++) {
stack = [];
// Downward counting to store the number of 1s in upward direction
size = 0;
for (row = 0; row < rows; row++) {
stack.push(size);
size = a[row][col] == 1 ? size + 1 : 0;
}
// Reverse, but only as far as still useful given the size we already found
size = 0;
for (row = rows - 1; row > maxSize; row--) {
thisSize = Math.min(size, stack.pop());
if (thisSize >= maxSize && a[row][col-1] == 1 && a[row][col+1] == 1) {
maxSize = thisSize;
pos = [row, col];
}
size = a[row][col] == 1 ? size + 1 : 0;
}
}
return [maxSize, pos];
}
// Sample data:
var a = [
[0, 0, 1, 0, 0, 1, 0],
[0, 0, 1, 1, 0, 1, 0],
[1, 1, 1, 0, 0, 1, 1],
[1, 0, 1, 0, 1, 1, 0],
[1, 1, 1, 1, 0, 1, 0],
[0, 1, 1, 1, 1, 1, 1],
[0, 0, 1, 0, 0, 1, 0]];
var [size, pos] = findPattern(a);
console.log('Size ' + size + ' with center at row ' + (pos[0]+1)
+ ' and column ' + (pos[1]+1) + ' (first row/col is numbered 1)');
Here: gist.github.com/... is a generic Java implementation that finds the largest plus(+) pattern in a 2D matrix of any size.
The idea is to find for the biggest possible plus(+) pattern first around the central elements(initial window) of the matrix. For each element in the window find the max plus size centered at that element.
If largest is found return the largest size.
If largest possible '+' is not found, store the size of whatever smaller than that was found and repeat search from step #1 in the next outer window around the previous window for 1-size smaller '+' pattern; iteratively searching for '+' in an 'onion layer pattern' from inside towards outside.
The initial central window is chosen such that edges of matrix are equally far on all sides from this window.
Example 1 - For matrix of size {4x3}, smallest central window lies
from (1,1) to (2,1)
Example 2 - For matrix of size {3x9}, smallest
central window lies from (1,1) to (1,7)
int rows = arr.length;
int cols = arr[0].length;
int min = rows < cols ? rows : cols;
int diff = rows > cols ? rows - cols : cols - rows;
// Initializing initial window params. The center most smallest window possible
int first_r, first_c, last_r, last_c;
first_r = (min - 1) / 2;
first_c = (min - 1) / 2;
last_r = rows < cols ? (rows / 2) : (cols / 2) + diff;
last_c = rows > cols ? (cols / 2) : (rows / 2) + diff;
Full Java code:
public class PlusPattern {
/**
* Utility method to verify matrix dimensions
*
* #param a matrix to be verified
* #return true if matrix size is greater than 0;
*/
private static boolean isValid(int[][] a) {
return a.length > 0 && a[0].length > 0;
}
/**
* Finds the size of largest plus(+) pattern of given 'symbol' integer in an integer 2D matrix .
*
* The idea is to find for the biggest possible plus(+) pattern first around the central elements
* of the matrix. If largest is found return the largest size. If largest possible + is not
* found, store the size of whatever smaller than that was found and repeat search for 1 size
* smaller + in the next outer window around the previous window.
*
* #param arr matrix to be searched
* #param symbol whose + patter is sought
* #return the radius of largest + found in the matrix.
*/
static int findLargestPlusPattern(int[][] arr, int symbol) {
if (!isValid(arr)) {
throw new IllegalArgumentException("Cannot perform search on empty array");
}
int maxPlusRadius = 0;
int rows = arr.length;
int cols = arr[0].length;
int min = rows < cols ? rows : cols;
int diff = rows > cols ? rows - cols : cols - rows;
// Initializing initial window params. The center most smallest window possible
// Example - For matrix of size {4x3}, smallest central window lies from [1][1] to [2][1]
// Example - For matrix of size {3x9}, smallest central window lies from [1][1] to [1][7]
int first_r, first_c, last_r, last_c;
first_r = (min - 1) / 2;
first_c = (min - 1) / 2;
last_r = rows < cols ? (rows / 2) : (cols / 2) + diff;
last_c = rows > cols ? (cols / 2) : (rows / 2) + diff;
// Initializing with biggest possible search radius in the matrix
int searchRadius = (min - 1) / 2;
int r, c;
int found;
// Iteratively searching for + in an 'onion layer pattern' from inside to outside
while (searchRadius > maxPlusRadius) { // no need to find smaller + patterns than the one already found
// initializing r and c cursor for this window iterations.
r = first_r;
c = first_c;
// Search each of the 4 sides of the current window in a clockwise manner
// 1# Scan the top line of window
do { // do-while used to search inside initial window with width==1
found = findLargestPlusAt(r, c, arr, symbol, searchRadius);
if (found == searchRadius) {
return searchRadius; // cannot find a bigger plus(+) than this in remaining matrix
} else if (found > maxPlusRadius) {
maxPlusRadius = found;
}
c++;
} while (c < last_c);
if (c > last_c)
c--; // for initial window with width==1. Otherwise #3 condition will be true for invalid c-index
// 2# Scan the right line of window
do { // do-while used to search inside initial window with height==1
found = findLargestPlusAt(r, c, arr, symbol, searchRadius);
if (found == searchRadius) {
return searchRadius;
} else if (found > maxPlusRadius) {
maxPlusRadius = found;
}
r++;
} while (r < last_r);
if (r > last_r)
r--; // for initial window with height==1. Otherwise #4 condition will be true for invalid r-index
// 3# Scan the bottom line of window
while (c > first_c) {
found = findLargestPlusAt(r, c, arr, symbol, searchRadius);
if (found == searchRadius) {
return searchRadius;
} else if (found > maxPlusRadius) {
maxPlusRadius = found;
}
c--;
}
// 4# Scan the left line of window
while (r > first_r) {
found = findLargestPlusAt(r, c, arr, symbol, searchRadius);
if (found == searchRadius) {
return searchRadius;
} else if (found > maxPlusRadius) {
maxPlusRadius = found;
}
r--;
}
// r and c comes back at first_r and first_c.
// increasing window on all sides by 1.
first_r--;
first_c--;
last_r++;
last_c++;
// reducing search radius to avoid out of bounds error on next window.
searchRadius--;
}
return maxPlusRadius;
}
/**
* Finds, if exist, the size of largest plus around a given point a[r][c]. It grows radius
* greedily to maximise the search for + pattern returns 0 if is the point is the only symbol.
*
* #param r row coordinate of search center
* #param c column coordinate of search center
* #param a matrix
* #param symbol search symbol
* #param max_radius around the center to be searched for + pattern
* #return returns -1 if the point itself is not the symbol.
* returns n if all the next elements in E W N S directions within radius n are the symbol elements.
*/
static int findLargestPlusAt(int r, int c, int[][] a, int symbol, int max_radius) {
int largest = -1;
if (a[r][c] != symbol) { // If center coordinate itself is not the symbol
return largest;
} else {
largest = 0;
}
for (int rad = 1; rad <= max_radius; rad++) {
if (a[r + rad][c] == symbol && a[r][c + rad] == symbol && a[r - rad][c] == symbol && a[r][c - rad] == symbol) {
largest = rad; // At least a '+' of radius 'rad' is present.
} else {
break;
}
}
return largest;
}
public static void main(String[] args) {
int mat[][];
mat = new int[][]{ // max + = 3
{1, 1, 0, 1, 1, 0, 1,},
{1, 1, 0, 1, 1, 0, 1,},
{1, 1, 0, 1, 1, 0, 1,},
{1, 1, 1, 1, 1, 1, 1,},
{1, 1, 0, 1, 1, 0, 1,},
{1, 1, 0, 1, 1, 0, 1,},
{1, 1, 0, 1, 1, 0, 1,},
};
int find = findLargestPlusPattern(mat, 1);
System.out.println("# Max + size radius is : " + find);
mat = new int[][]{ // max + = 2
{1, 1, 9, 1, 1, 9, 1,},
{1, 1, 9, 1, 1, 9, 1,},
{7, 1, 1, 1, 1, 1, 1,},
{1, 1, 9, 1, 1, 9, 1,},
{1, 1, 9, 1, 1, 9, 1,},
};
find = findLargestPlusPattern(mat, 1);
System.out.println("# Max + size radius is : " + find);
mat = new int[][]{ // max + = 1
{1, 1, 0, 1, 1},
{1, 1, 0, 1, 1},
{1, 1, 0, 1, 1},
{1, 1, 1, 6, 1},
{1, 1, 0, 1, 1},
{1, 1, 0, 1, 1},
};
find = findLargestPlusPattern(mat, 1);
System.out.println("# Max + size radius is : " + find);
}
}
The following uses basically the same logic as that provided by trincot in his answer, but does the reverse scan whenever there's a break in consecutive 1's. This eliminates the need to build an explicit stack.
The running time should be approximately the same. The only advantage to my method is that this algorithm uses O(1) extra space, whereas trincot's uses O(rowCount) extra space for the stack.
The extra stack makes for shorter and more readable code, though.
Code is in C#:
class FindPatternResult
{
public int Size { get; set; }
public int Col { get; set; }
public int Row { get; set; }
}
private FindPatternResult FindPattern(int[,] a)
{
var numCols = a.GetUpperBound(0)+1;
var numRows = a.GetUpperBound(1)+1;
var maxSize = -1;
var maxCol = -1;
var maxRow = -1;
// anonymous function for checking matches when there is
// a break in consecutive 1's.
var checkForMatch = new Action<int, int, int>((height, bottomRow, col) =>
{
var topRow = bottomRow - height + 1;
for (int row = bottomRow-1; row > topRow; --row)
{
// There's a potential optimization opportunity here.
// If we get beyond the midpoint and size is decreasing,
// then if size < maxSize, we can early-out.
// For example, if maxSize is 3 and tow-topRow < 3,
// then there can't possibly be a longer match in this column.
// I didn't add that optimization because it doesn't
// really change the algorithm. But if the number of rows
// is very large, it could be meaningful.
if (a[row, col - 1] == 1 && a[row, col + 1] == 1)
{
var size = Math.Min(bottomRow-row, row-topRow);
if (size > maxSize)
{
maxSize = size;
maxCol = col;
maxRow = row;
}
}
}
});
for (int col = 1; col < numCols - 1; ++col)
{
var size = 0;
for (int row = 0; row < numRows; ++row)
{
if (a[row,col] == 1)
{
++size;
}
else
{
// If size >= 3, then go back and check for a match
if (size >= 3)
{
checkForMatch(size, row, col);
}
size = 0;
}
}
// If we end the loop with size >= 3, then check from the bottom row.
if (size >= 3)
{
checkForMatch(size, numRows - 1, col);
}
}
Test with:
private void DoIt()
{
var rslt = FindPattern(_sampleData);
Console.WriteLine($"Result: {rslt.Size}, [{rslt.Row}, {rslt.Col}]");
}
private readonly int[,] _sampleData =
{
{0, 0, 1, 0, 0, 1, 0},
{0, 0, 1, 1, 0, 1, 0},
{1, 1, 1, 0, 0, 1, 1},
{1, 0, 1, 0, 1, 1, 0},
{1, 1, 1, 1, 0, 1, 0},
{0, 1, 1, 1, 1, 1, 1},
{0, 0, 1, 0, 0, 1, 0}
};
Given an array of coin denominations coins and a total, find all possible combinations that result in the minimum number of coins summing to the total. In my solution I keep a running track of the minimum number of coins at table[i] that sum to i. I'm not sure exactly how this would be modified to store the actual coins that sum to i and make sure that both possibilities in this case are included. I've looked at other code on stack overflow, but I've only found code that will print any one of the optimal solutions.
Input: minimum_coins(10, [2,3,5,6,7,8])Output: [[5,5],[2,8]]
INT_MAX = 2 ** 63 - 1
def minimum_coins(total, coins)
table = Array.new(total + 1)
table[0] = 0
(1..total).to_a.each do |i|
table[i] = INT_MAX
end
(1..total).to_a.each do |i|
(0..coins.length-1).to_a.each do |j|
if coins[j] <= i
sub_res = table[i-coins[j]]
if sub_res != INT_MAX && sub_res + 1 < table[i]
table[i] = sub_res + 1
end
end
end
end
puts table.inspect
end
minimum_coins(10, [2,3,5,6,7,8])
let:
d[i] = minimum changes for i
So if d[i] == d[i - c] + 1, we can say if we take coin c to make exchange and we can still get a minimum coin changes for i.
Code:
def find(n, result, d, coins, changes, index):
if n == 0:
changes.append(result)
return
for i in range(index, len(coins)):
if n - coins[i] >= 0 and d[n] == d[n - coins[i]] + 1:
find(n - coins[i], result + [coins[i]], d, coins, changes, i)
def all_coin_changes(n, coins):
d = [n + 1] * (n + 1)
d[0] = 0
for i in range(1, n + 1):
for c in coins:
if i - c >= 0:
d[i] = min(d[i], d[i - c] + 1)
changes = []
find(n, [], d, coins, changes, 0)
return changes
print all_coin_changes(10, [2, 3, 5, 6, 7, 8])
# [[2, 8], [3, 7], [5, 5]]
print all_coin_changes(100, [2, 3, 5, 6, 7, 8])
# [[5, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8]]
If you still have some questions, please don't hesitate to leave a comment here.
Let's table entries contain pairs (BestCount, LastCoinList).
If sub_res + 1 < table[i].BestCount then
replace BestCount with sub_res + 1 and make LastCoinList containing coins[j] value
If sub_res + 1 = table[i].BestCount then
just add coins[j] value to LastCoinList
So in the end table[10] will contain BestValue = 2 and LastCoinList = (5,7,8)
Now recursively unroll from table[10] entry to table[10-5], to table[10-7], to table[10-8], that contain 5,3 and 2 respectively, then all recursion branches stop at the 0th entry.
I made an iterative program that can calculate the minimum number of coins required (US dollars) to get a given number of cents. It's iterative, but hope it helps!
import java.util.*;
public class CoinProblem
{
public static void main(String[] args)
{
System.out.println("----------------------------COIN PROBLEM--------------------------");
System.out.println("Denominations: \nCent - 1\nNickel - 5\nDime - 10\nQuarter - 25");
Map<Integer, Integer> map = new HashMap<Integer, Integer> ();
System.out.println("\nENTER TARGET NUMBER (CENTS): ");
Scanner sc = new Scanner(System.in);
int target = Integer.parseInt(sc.next());
int count = numCoins(target, map);
System.out.println("\nMINIMUM NUMBER OF COINS REQUIRED: " + count);
System.out.println( map.get(1) + " CENTS");
System.out.println( map.get(5) + " NICKELS");
System.out.println( map.get(10) + " DIMES");
System.out.println( map.get(25) + " QUARTERS");
System.out.println("------------------------------------------------------------------");
}
public static int numCoins(int target, Map<Integer, Integer> map)
{
int cent = 1;
int nickel = 5;
int dime = 10;
int quarter = 25;
map.put(cent, 0);
map.put(nickel, 0);
map.put(dime, 0);
map.put(quarter, 0);
int count = 0;
if (target >= 25)
{
if (target % 25 == 0)
{
count += target/25;
map.put(quarter, count);
return count;
}
else
{
count += target/25;
map.put(quarter, count);
int remtarget = target%25;
if (remtarget >= 10)
{
if (remtarget % 10 == 0)
{
count += remtarget/10;
map.put(dime, remtarget/10);
return count;
}
else
{
count += remtarget/10;
map.put(dime, remtarget/10);
int fivetarget = remtarget%10;
if (fivetarget >= 5)
{
if (fivetarget % 5 == 0)
{
count += fivetarget/5;
map.put(nickel, fivetarget/5);
}
else
{
count += fivetarget/5;
map.put(nickel, fivetarget/5);
int ones = fivetarget%5;
count+= ones;
map.put(cent, ones);
}
}
else
{
count += fivetarget;
map.put(cent, fivetarget);
return count;
}
}
}
else
{
if (remtarget >= 5)
{
if (remtarget % 5 == 0)
{
count += remtarget/5;
map.put(nickel, remtarget/5);
}
else
{
count += remtarget/5;
map.put(nickel, remtarget/5);
int ones = remtarget%5;
count+= ones;
map.put(cent, ones);
}
}
else
{
count += remtarget;
map.put(cent, remtarget);
return count;
}
}
}
}
else
{
if (target == 0)
{
return 0;
}
if (target >= 10)
{
if (target % 10 == 0)
{
count += target/10;
map.put(dime, target/10);
return count;
}
else
{
count += target/10;
map.put(dime, target/10);
int ftarget = target%10;
if (ftarget >= 5)
{
if (ftarget % 5 == 0)
{
count += ftarget/5;
map.put(nickel, ftarget/5);
}
else
{
count += ftarget/5;
map.put(nickel, ftarget/5);
int otarget = ftarget%5;
count+= otarget;
map.put(cent, otarget);
}
}
else
{
count += ftarget;
map.put(cent, ftarget);
return count;
}
}
}
else
{
if (target > 5)
{
if (target % 5 == 0)
{
count += target/5;
map.put(nickel, target/5);
}
else
{
count += target/5;
map.put(nickel, target/5);
int o = target%5;
count+= o;
map.put(cent, o);
}
}
else
{
count += target;
map.put(cent, target);
return count;
}
}
}
return count;
}
}
The problem I'm trying to solve is how do we find all the integer sets [a1, a2, ... ,am] so that
a1 + a2 + ... + am = N
and with the constraint ai >= 1
For example if M = 4, and N = 7 there are three answers
[1,1,1,4]
[1,1,2,3]
[1,2,2,2]
Since you have to print all the sets that sum to N. You can employ a complete search algorithm using recursion. In the following code, M is the number of numbers in the set and N is the sum required.
int M;
int N;
void run(){
M = 4;
N = 7;
int[] arr = new int[M];
print(arr, 0, N, 1);
}
// req holds the required sum for the numbers in the array from arr[from]
// to arr[M-1].
// "last" holds the last value that we had put in the array.
// The first call to the array will be with last=1.
void print(int[] arr, int from, int req, int last){
// Reached the end of the array and sum required 0.
if(from==M && req==0){
System.out.println(Arrays.toString(arr));
return;
}
// Either reached the end of the array but sum is not equal to N
// Or if we have not reached the end of the array but sum has already
// become more than or equal to N.
if(from==M || req<=0){
return;
}
for(int i=last; i<=req; i++){
arr[from] = i;
print(arr, from+1, req-i, i);
}
}
Output for M=4 and N=7:
[1, 1, 1, 4]
[1, 1, 2, 3]
[1, 2, 2, 2]
Output for M=3 and N=10:
[1, 1, 8]
[1, 2, 7]
[1, 3, 6]
[1, 4, 5]
[2, 2, 6]
[2, 3, 5]
[2, 4, 4]
[3, 3, 4]
Answer for the problem in the link, just got accepted.
The idea is simple, assume that we know the maximum value for each section is X, and we want to find a way to divide these cabinets to achieve that , we can greedily divide them as follow:
Starting from first cabinet, iterating through each cabinet, until the total from first to ith cabinet is greater than X. So this is the first section, similarly, we can select other sections. This greedy will always find a solution (if exists).
Finally, we can using binary search to adjust the value of X, decrease X if we can find a way to divide the cabinets, or increase X if we cannot find one.
Here is the code in Java:
public class FairWorkload {
public int getMostWork(int[] folders, int workers) {
int[] data = new int[folders.length];
data[0] = folders[0];
for (int i = 1; i < data.length; i++) {
data[i] = data[i - 1] + folders[i];
}
if (workers == 1) {
return data[data.length - 1];
}
int start = 0;
int end = data[data.length - 1];
int result = Integer.MAX_VALUE;
while (start <= end) {
int mid = (start + end) / 2;
int index = 0;
for (int k = 0; k < workers && index < data.length; k++) {
int less = index > 0 ? data[index - 1] : 0;
int temp = index;
for (int i = index; i < data.length; i++) {
if (data[i] - less <= mid) {
temp = i;
} else {
break;
}
}
// System.out.println(data[temp] - less + " " + mid);
if(data[temp] - less > mid){
index = -1;
break;
}
index = temp + 1;
}
//System.out.println(mid + " " + index);
if (index != data.length) {
start = mid + 1;
} else {
result = Math.min(result, mid);
end = mid - 1;
}
}
return result;
}
public static void main(String[] args) {
int[] data = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1000};
System.out.println(new FairWorkload().getMostWork(data, 2));
}
}
One possible solution uses a counting technique, finding the rightmost term that satisfies [i] <= [length-1] - 2, and then flattening out all other terms to the right as much as possible, keeping a[i] <= a[i+1].
import java.util.Arrays;
public class test {
public static void main(String[] args) {
test t = new test();
t.go();
}
private void go() {
int w = 3;
int sum = 10;
int[] terms = new int[w];
for (int i = 0; i < terms.length; i++) {
terms[i] = 1;
}
terms[w-1] = sum - w + 1;
System.out.println(Arrays.toString(terms));
for (int i = right_index(terms); i>=0; i = right_index(terms)) {
terms[i]++;
int a = terms[i];
int overflow = -1;
// balance all the terms to the right
for (int j = i+1; j < terms.length-1; j++) {
overflow += terms[j] - a;
terms[j] = a;
}
terms[terms.length-1] += overflow;
System.out.println(Arrays.toString(terms));
}
}
// find the rightmost index i, where [i] <= [ia.length-1] - 2
private int right_index(int[] ia) {
int max = ia[ia.length-1];
for (int i = ia.length - 1; i >= 0; i--) {
if (ia[i] <= max - 2)
return i;
}
return -1;
}
}
Let's say I have the continuous range of integers [0, 1, 2, 4, 6], in which the 3 is the first "missing" number. I need an algorithm to find this first "hole". Since the range is very large (containing perhaps 2^32 entries), efficiency is important. The range of numbers is stored on disk; space efficiency is also a main concern.
What's the best time and space efficient algorithm?
Use binary search. If a range of numbers has no hole, then the difference between the end and start of the range will also be the number of entries in the range.
You can therefore begin with the entire list of numbers, and chop off either the first or second half based on whether the first half has a gap. Eventually you will come to a range with two entries with a hole in the middle.
The time complexity of this is O(log N). Contrast to a linear scan, whose worst case is O(N).
Based on the approach suggested by #phs above, here is the C code to do that:
#include <stdio.h>
int find_missing_number(int arr[], int len) {
int first, middle, last;
first = 0;
last = len - 1;
middle = (first + last)/2;
while (first < last) {
if ((arr[middle] - arr[first]) != (middle - first)) {
/* there is a hole in the first half */
if ((middle - first) == 1 && (arr[middle] - arr[first] > 1)) {
return (arr[middle] - 1);
}
last = middle;
} else if ((arr[last] - arr[middle]) != (last - middle)) {
/* there is a hole in the second half */
if ((last - middle) == 1 && (arr[last] - arr[middle] > 1)) {
return (arr[middle] + 1);
}
first = middle;
} else {
/* there is no hole */
return -1;
}
middle = (first + last)/2;
}
/* there is no hole */
return -1;
}
int main() {
int arr[] = {3, 5, 1};
printf("%d", find_missing_number(arr, sizeof arr/(sizeof arr[0]))); /* prints 4 */
return 0;
}
Since numbers from 0 to n - 1 are sorted in an array, the first numbers should be same as their indexes. That's to say, the number 0 is located at the cell with index 0, the number 1 is located at the cell with index 1, and so on. If the missing number is denoted as m. Numbers less then m are located at cells with indexes same as values.
The number m + 1 is located at a cell with index m, The number m + 2 is located at a cell with index m + 1, and so on. We can see that, the missing number m is the first cell whose value is not identical to its value.
Therefore, it is required to search in an array to find the first cell whose value is not identical to its value. Since the array is sorted, we could find it in O(lg n) time based on the binary search algorithm as implemented below:
int getOnceNumber_sorted(int[] numbers)
{
int length = numbers.length
int left = 0;
int right = length - 1;
while(left <= right)
{
int middle = (right + left) >> 1;
if(numbers[middle] != middle)
{
if(middle == 0 || numbers[middle - 1] == middle - 1)
return middle;
right = middle - 1;
}
else
left = middle + 1;
}
return -1;
}
This solution is borrowed from my blog: http://codercareer.blogspot.com/2013/02/no-37-missing-number-in-array.html.
Based on algorithm provided by #phs
int findFirstMissing(int array[], int start , int end){
if(end<=start+1){
return start+1;
}
else{
int mid = start + (end-start)/2;
if((array[mid] - array[start]) != (mid-start))
return findFirstMissing(array, start, mid);
else
return findFirstMissing(array, mid+1, end);
}
}
Below is my solution, which I believe is simple and avoids an excess number of confusing if-statements. It also works when you don't start at 0 or have negative numbers involved! The complexity is O(lg(n)) time with O(1) space, assuming the client owns the array of numbers (otherwise it's O(n)).
The Algorithm in C Code
int missingNumber(int a[], int size) {
int lo = 0;
int hi = size - 1;
// TODO: Use this if we need to ensure we start at 0!
//if(a[0] != 0) { return 0; }
// All elements present? If so, return next largest number.
if((hi-lo) == (a[hi]-a[lo])) { return a[hi]+1; }
// While 2 or more elements to left to consider...
while((hi-lo) >= 2) {
int mid = (lo + hi) / 2;
if((mid-lo) != (a[mid]-a[lo])) { // Explore left-hand side
hi = mid;
} else { // Explore right hand side
lo = mid + 1;
}
}
// Return missing value from the two candidates remaining...
return (lo == (a[lo]-a[0])) ? hi + a[0] : lo + a[0];
}
Test Outputs
int a[] = {0}; // Returns: 1
int a[] = {1}; // Returns: 2
int a[] = {0, 1}; // Returns: 2
int a[] = {1, 2}; // Returns: 3
int a[] = {0, 2}; // Returns: 1
int a[] = {0, 2, 3, 4}; // Returns: 1
int a[] = {0, 1, 2, 4}; // Returns: 3
int a[] = {0, 1, 2, 4, 5, 6, 7, 8, 9}; // Returns: 3
int a[] = {2, 3, 5, 6, 7, 8, 9}; // Returns: 4
int a[] = {2, 3, 4, 5, 6, 8, 9}; // Returns: 7
int a[] = {-3, -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // Returns: -1
int a[] = {-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // Returns: 10
The general procedure is:
(Optional) Check if the array starts at 0. If it doesn't, return 0 as missing.
Check if the array of integers is complete with no missing integer. If it is not missing an integer, return the next largest integer.
In a binary search fashion, check for a mismatch between the difference in the indices and array values. A mismatch tells us which half a missing element is in. If there is a mismatch in the first half, move left, otherwise move right. Do this until you have two candidate elements left to consider.
Return the number that is missing based on incorrect candidate.
Note, the algorithm's assumptions are:
First and last elements are considered to never be missing. These elements establish a range.
Only one integer is ever missing in the array. This will not find more than one missing integer!
Integer in the array are expected to increase in steps of 1, not at any other rate.
Have you considered a run-length encoding? That is, you encode the first number as well as the count of numbers that follow it consecutively. Not only can you represent the numbers used very efficiently this way, the first hole will be at the end of the first run-length encoded segment.
To illustrate with your example:
[0, 1, 2, 4, 6]
Would be encoded as:
[0:3, 4:1, 6:1]
Where x:y means there is a set of numbers consecutively starting at x for y numbers in a row. This tells us immediately that the first gap is at location 3. Note, however, that this will be much more efficient when the assigned addresses are clustered together, not randomly dispersed throughout the range.
if the list is sorted, I'd iterate over the list and do something like this Python code:
missing = []
check = 0
for n in numbers:
if n > check:
# all the numbers in [check, n) were not present
missing += range(check, n)
check = n + 1
# now we account for any missing numbers after the last element of numbers
if check < MAX:
missing += range(check, MAX + 1)
if lots of numbers are missing, you might want to use #Nathan's run-length encoding suggestion for the missing list.
Missing
Number=(1/2)(n)(n+1)-(Sum of all elements in the array)
Here n is the size of array+1.
Array: [1,2,3,4,5,6,8,9]
Index: [0,1,2,3,4,5,6,7]
int findMissingEmementIndex(int a[], int start, int end)
{
int mid = (start + end)/2;
if( Math.abs(a[mid] - a[start]) != Math.abs(mid - start) ){
if( Math.abs(mid - start) == 1 && Math.abs(a[mid] - a[start])!=1 ){
return start +1;
}
else{
return findMissingElmementIndex(a,start,mid);
}
}
else if( a[mid] - a[end] != end - start){
if( Math.abs(end - mid) ==1 && Math.abs(a[end] - a[mid])!=1 ){
return mid +1;
}
else{
return findMissingElmementIndex(a,mid,end);
}
}
else{
return No_Problem;
}
}
This is an interview Question. We will have an array of more than one missing numbers and we will put all those missing numbers in an ArrayList.
public class Test4 {
public static void main(String[] args) {
int[] a = { 1, 3, 5, 7, 10 };
List<Integer> list = new ArrayList<>();
int start = 0;
for (int i = 0; i < a.length; i++) {
int ch = a[i];
if (start == ch) {
start++;
} else {
list.add(start);
start++;
i--; // a must do.
} // else
} // for
System.out.println(list);
}
}
Functional Programming solution (Scala)
Nice and elegant
Lazy evaluation
def gapFinder(sortedList: List[Int], start: Int = 0): Int = {
def withGuards: Stream[Int] =
(start - 1) +: sortedList.toStream :+ (sortedList.last + 2)
if (sortedList.isEmpty) start
else withGuards.sliding(2)
.dropWhile { p => p.head + 1 >= p.last }.next()
.headOption.getOrElse(start) + 1
} // 8-line solution
// Tests
assert(gapFinder(List()) == 0)
assert(gapFinder(List[Int](0)) == 1)
assert(gapFinder(List[Int](1)) == 0)
assert(gapFinder(List[Int](2)) == 0)
assert(gapFinder(List[Int](0, 1, 2)) == 3)
assert(gapFinder(List[Int](0, 2, 4)) == 1)
assert(gapFinder(List[Int](0, 1, 2, 4)) == 3)
assert(gapFinder(List[Int](0, 1, 2, 4, 5)) == 3)
import java.util.Scanner;
class MissingNumber {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int[] arr =new int[n];
for (int i=0;i<n;i++){
arr[i]=scan.nextInt();
}
for (int i=0;i<n;i++){
if(arr[i+1]==arr[i]+1){
}
else{
System.out.println(arr[i]+1);
break;
}
}
}
}
I was looking for a super simple way to find the first missing number in a sorted array with a max potential value in javascript and didn't have to worry about efficiency too much as I didn't plan on using a list longer 10-20 items at the most. This is the recursive function I came up with:
function findFirstMissingNumber(sortedList, index, x, maxAllowedValue){
if(sortedList[index] == x && x < maxAllowedValue){
return findFirstMissingNumber(sortedList, (index+1), (x+1), maxAllowedValue);
}else{ return x; }
}
findFirstMissingNumber([3, 4, 5, 7, 8, 9], 0, 3, 10);
//expected output: 6
Give it your array, the index you wish to start at, the value you expect it to be and the maximum value you'd like to check up to.
i got one algorithm for finding the missing number in the sorted list. its complexity is logN.
public int execute2(int[] array) {
int diff = Math.min(array[1]-array[0], array[2]-array[1]);
int min = 0, max = arr.length-1;
boolean missingNum = true;
while(min<max) {
int mid = (min + max) >>> 1;
int leftDiff = array[mid] - array[min];
if(leftDiff > diff * (mid - min)) {
if(mid-min == 1)
return (array[mid] + array[min])/2;
max = mid;
missingNum = false;
continue;
}
int rightDiff = array[max] - array[mid];
if(rightDiff > diff * (max - mid)) {
if(max-mid == 1)
return (array[max] + array[mid])/2;
min = mid;
missingNum = false;
continue;
}
if(missingNum)
break;
}
return -1;
}
Based on algorithm provided by #phs
public class Solution {
public int missing(int[] array) {
// write your solution here
if(array == null){
return -1;
}
if (array.length == 0) {
return 1;
}
int left = 0;
int right = array.length -1;
while (left < right - 1) {
int mid = left + (right - left) / 2;
if (array[mid] - array[left] != mid - left) { //there is gap in [left, mid]
right = mid;
}else if (array[right] - array[mid] != right - mid) { //there is gap in [mid, right]
left = mid;
}else{ //there is no gapin [left, right], which means the missing num is the at 0 and N
return array[0] == 1 ? array.length + 1 : 1 ;
}
}
if (array[right] - array[left] == 2){ //missing number is between array[left] and array[right]
return left + 2;
}else{
return array[0] == 1 ? -1 : 1; //when ther is only one element in array
}
}
}
public static int findFirst(int[] arr) {
int l = -1;
int r = arr.length;
while (r - l > 1) {
int middle = (r + l) / 2;
if (arr[middle] > middle) {
r = middle;
}
l = middle;
}
return r;
}