I had one coding round where question statement was like this
*You have a given number of friends and seating capacity of their cars now you need to find minimum number of cars required to accommodate them all.
Example:
People = [1, 4, 1]
SeatingCapacity = [1, 5, 1]
In this case we need minimum 2 cars as number of people on 0th index can adjust with index 1 car.
Example 2:
People = [4, 4, 5, 3]
SeatingCapacity = [5, 5, 7, 3]
This case answer will be as index 3 people can be accommodate into 0,1,2 or 1,2 index car*
I wrote code like this
int numberOfCars(int[] p, int[] s) {
int noOfCars=p.length;
Int extraSeats=0;
for(int i=0;i<p.length;i++) {
extraSeats+= (s[i] - p[i])
}
for(int i=0;i<p.length;i++) {
if(extraSeats-p[i] >=0){
extraSeats-= p[i] ;
noOfCars--;
}
}
return noOfCars;
}
However my code failed for many cases as well as it was saying some performance issue.
Can anyone please tell me which cases I missed?
This can be solved by just greedy approach. Like below:
people = [1,4,1]
p = sum(people) //6
cars = [1,5,1]
sort(cars, descending) //cars = [5,1,1]
idx = 0
while(p > 0) { p -= cars[idx]; idx += 1 }
answer = idx
Handle the corner case where total capacity in cars is less than number of people.
Complexity : sorting cars O(n log n) + while loop O(n) = O(n log n)
This would be my solution in Javascript:
function peopleCars (persons, seats) {
let numberOfCars = 0;
let people = persons.reduce((previousValue, currentValue) => previousValue + currentValue, 0); //Calculate total number of persons
seats.sort((a,b) => {return b-a}); //Rearrange the total number of seats in each car in ascending order to fill the seats starting from the one that can take the most persons
while(people > 0) {
people -= seats[numberOfCars]; //subtract the numbers of seats of each car from the number of persons available. This will now leave us with the remaining people
numberOfCars += 1 //increment the number of cars to be used.
}
return numberOfCars
}
// console.log (peopleCars( [2,1,2,2], [5,4,2,5]));
Related
Given an array A consisting of N integers denoting the number of coins on each box in
the row, and integers K and L denoting, respectively, the number of boxes that robo1 and robo2 can
choose when collecting, returns the maximum number of coins that can be collected by them, or -1
if there are no such intervals.
For example, given A = [6, 1, 4, 6, 3, 2, 7, 4], K = 3, L = 2, your
function should return 24, because robo1 can choose boxes 3 to 5 and
collect 4 + 6 + 3 = 13 coins, and robo2 can choose boxes 7 to 8 and
collect 7 +4 = 11 coins. Thus, they will collect 13 + 11 = 24 coins
in total, and that is the maximum number that can be achieved.
Given A = [10, 19, 15], K = 2, L = 2, your function should return -1,
because it is not possible for robo1 and robo2 to choose two disjoint
intervals.
I have written below function to collect max coins.
public static int getMaxCoins(int[] A, int K, int L) {
if(A.length<K+L)
return -1;
int highest = 0;
int lowest = 0;
if(K>L){
highest = K;
lowest = L;
}
int robo1Coins = 0;
int remainingArray[] = null;
int part1[];
int part2[];
int robo2Coins = 0;
for(int i=0;i+highest<=A.length;i++){
int[] sub = Arrays.copyOfRange(A, i, i+highest);
int count = IntStream.of(sub).sum();
if(count>robo1Coins) {
robo1Coins = count;
part1 = Arrays.copyOfRange(A, 0, i);
part2 = Arrays.copyOfRange(A, i+highest, A.length);
remainingArray = IntStream.concat(Arrays.stream(part1), Arrays.stream(part2)).toArray();
}
}
for(int i=0;i+lowest<=remainingArray.length;i++){
int[] sub = Arrays.copyOfRange(remainingArray, i, i+lowest);
int count = IntStream.of(sub).sum();
if(count>robo2Coins) {
robo2Coins = count;
}
}
System.out.println("Robo1 Coins - "+robo1Coins+" Robo2 Coins-"+robo2Coins);
return robo1Coins+robo2Coins;
}
The above solution is working fine for the given cases.
But I feel my solution has few problems
Not optimistic/Less performant
Failing on edge cases
Not following any algorithmic approach
Please help to point out. What is the right approaches/algorithms available to solve this in more efficient manner.
You can solve the problem with a sliding window algorithm. The window's length should be K+L. Imagine robo1 leading, and robo2 following behind as they march across the array.
As the window moves you need to update separate sums for each robot: sum1 and sum2. You also need to keep track of the best sum seen by the trailing robot: best2, and the best combined sum: bestCombined.
After each window move, update the best results:
best2=max(best2, sum2)
bestCombined=max(bestCombined, best2+sum1)
When the sliding window reaches the end of the array, bestCombined is one of two possible answers. Swap the robots, and run the algorithm again to find the other possible answer.
Here's a sample run of the algorithm.
First with robo1 leading (blue) and robo2 following (red):
Then with robo2 leading, and robo1 following:
The best combined score is 24 which is achieved with robo2 leading.
I'm having some problems solving this question:
Given an array of ints, divide the input into 2 groups such that their sums are as close as possible, the 2 groups must be equal in length, or if the input is odd length then one group can have 1 more than the other. Then print the lower sum first, and the higher sum after.
Ex:
input -> [4,6,17,3,2,5,10]
output -> 23,24 ([17,5,2] , [10,6,4,3])
This is what I've come up with and so far what I've tested it's passed but I do not know if it's actually correct:
public static String closestSums(int[] input) {
Integer sum1 = 0;
Integer sum2 = 0;
Integer dif = 0;
Integer bigSum = 0;
List<Integer> list = new ArrayList<>();
List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
for (int x = 0; x < input.length; x++) {
list.add(input[x]);
}
Collections.sort(list);
for (int x = list.size(); x >= 0; x--) {
bigSum += list.get(x);
if (dif == 0) {
dif = list.get(x);
list2.add(list.get(x));
}
else if (dif > 0) {
dif -= list.get(x);
list1.add(list.get(x));
}
else {
dif += list.get(x);
list2.add(list.get(x));
}
}
dif = Math.abs(dif);
if (dif != 0) {
sum2 = (bigSum / 2) + dif;
sum1 = bigSum / 2;
}
else {
sum2 = bigSum / 2;
sum1 = bigSum / 2;
}
return sum1 + ", " + sum2;
}
It's not correct.
Regardless of the bunch of small coding mistakes that are mentioned in the other answer, your algorithm doesn't work.
Consider the input [3, 3, 2, 2, 2]. Your algorithm will divide it into [3, 2, 2] and [3, 2] with a difference of 7-5=2. However, a better split with equal sums exists: [3, 3] and [2, 2, 2].
I am not going to provide a complete algorithm but give you a few hints:
1 - The minimum difference can be binary-searched. If you can come up with an algorithm that decides whether it is possible to split the array so that the difference of the sums of the pieces is at most d for a given d, then you can binary search the minimum d for which the algorithm outputs 1.
2 - Look at the subset sum problem, it can help with the subproblem I defined in item 1.
I have made 3 observations after analyzing & running your Code.
There lot of small errors throughout the code.
Syntaxical Error On Line 4 (Initialization of 'Dif') Line 11(The 'for' keyword)
Logical Error on Line 26, Line 27 (Instead of Accessing Index 'i', you must access index 'x')
Runtime Error on Line 17 (Initializing x=list.size() will throw a runtime error java.lang.IndexOutOfBoundsException)
Though, the important things to look at, are mentioned below
It's a suggestion, if you aren't printing the list with the 'sum1' & 'sum2', then creating and operating the two other output lists is redundant. The respective Sums of the list can be calculated while traversing the main list.
Most importantly, the way you are calculating sum1 and sum2 after traversing the list and then dividing them, is not reliable.
Eg. The Following input will give an unexpected output [4,6,45,3,2,5,10]. So, I suggest you to resort to the most reliable way of calculating the sum of list 1 & list 2, which is calculating them while traversing the list. (You may also remove the full logic of bigSum)
Last Words: Try and Implement the above mentioned Ideas yourself.
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.
Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.
Example 1:
Input: [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.
Example 2:
Input: [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
Total amount you can rob = 2 + 9 + 1 = 12.
class Solution {
public int rob(int[] nums) {
int sim=0;
int sum=0;
int i,j;
for(i=0;i<nums.length;i++,i++){
sim+=nums[i];
}
for(j=1;j<nums.length;j++,j++){
sum+=nums[j];
}
int r= Math.max(sim,sum);
return r;
}
}
How to do this logic when array length is in odd ?
can we do that this way
output is correct for even length though
Your solution is skipping one house after robbing previous one. This would not always give maximum output. Consider this case: [100, 1, 1, 100]. According to your solution, sim == 101 and sum == 101, however, the correct solution would be 200. (robbing the 0th and 3rd house).
I propose two possible solutions: 1. using recursion, 2. using dp.
Using recursion, you can choose either to rob a house and skip next one, or do not rob a house and go on to the next one. Thus, you will have two recursive cases which would result in O(2^n) time complexity and O(n) space complexity.
public int rob(int[] nums) {
return robHelper(nums, 0, 0);
}
private int robHelper(int[] nums, int ind, int money) {
if (ind >= nums.length) return money;
int rec1 = robHelper(nums, ind+1, money);
int rec2 = robHelper(nums, ind+2, money+nums[ind]);
return Math.max(rec1, rec2);
}
Using dp would optimize time and space complexity from above solution. You can keep track of two values: currMax and prevMax. While prevMax is max money excluding the previous house, currMax is max money considering the previous house. Since prevMax is guaranteed that money from previous house is not included, you can add money from current house to prevMax and compare it with currMax to find total max money up to that point. Here is my solution using dp, O(n) time complexity and O(1) space complexity:
public int rob(int[] nums) {
int currmax = 0;
int prevmax = 0;
for (int i = 0; i < nums.length; i++) {
int iSum = prevmax + nums[i];
prevmax = currmax;
currmax = Math.max(currmax, iSum);
}
return currmax;
}
As pointed out by siralexsir88 in the comments it is not enough to only check for the solutions for robbing the even/odd numbered houses since it may happen that the best strategy is to skip more than one house in a row.
The given example illustrates this fact: suppose you have [1, 3, 5, 2, 1, 7], here indexes 3 and 4 must be skipped to pick the latter 7.
Proposed solution
This problem is a typical example of dynamic programming and can be solved by building up a solution recursively.
For every house there are two options: you either rob it, our you don't. Let's keep track of the best solution for both cases and for each house: let's name R[i] the maximum profit up to the ith house if we rob the ith house. Let's define NR[i] the same way for not robbing the ith hose.
For example, suppose we have [1, 3]. In this case:
R[0] = 1
NR[0] = 0
R[1] = 3 The best profit while robbing house #1 is 3
NR[1] = 1 The best profit while not robbing house #1 is 1
Let's also call P[i] the profit that gives us robbing the ith house.
We can build our solution recursively in terms of R and NR this way:
1) R[i] = NR[i-1] + P[i]
2) NR[i] = max(NR[i-1], R[i-1])
3) R[0] = P[0]
4) NR[0] = 0
Let's break it down.
The recursive relation 1) says that if we rob the ith house, we must not have robed the previous house, and hence take the not robbed best score for the previous house.
The recursive relation 2) says that if we do not rob the ith house, then our score is the best between the ones for robbing and not robbing the previous house. This makes sense because we are not adding anything to our total profit, we just keep the best profit so far.
3) and 4) are just the initial conditions for the first house, which should make sense up to this point.
Here is a pseudo-python snippet that does compute the best profit:
P = [1, 3, 5, 2, 1, 7] # The houses
R = [0] * len(P)
NR = [0] * len(P)
R[0] = P[0]
# We skip index 0
for i in range(1, len(P)):
R[i] = NR[i-1] + P[i]
NR[i] = max(NR[i-1], R[i-1])
# The solution is the best between NR and R for the last house
print max(NR[-1], R[-1])
The solution implies keeping track of the two arrays (R[i] and NR[i]) while traversing the houses, and then compare the results at the end. If you just want the maximum profit, you may keep the results R and NR for the previous house and ditch them as you move on. However, if you want to know specifically which sequence of houses leads to the best result, you need to keep track of the whole array and once you are done, backtrack and reconstruct the solution.
private static int rob(int[] money) {
int max = 0;
for (int i = 0; i < money.length; i++) {
int skips = 2;
while (skips < money.length) {
int sum = 0;
for (int j = 0; j < money.length; j += skips) {
sum += money[j];
}
if (sum > max) {
max = sum;
}
skips++;
}
}
return max;
}
Problem: You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.
Example 1:
Input: coins = [1, 2, 5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1
Example 2:
Input: coins = 2, amount = 3
Output: -1
You may assume that you have an infinite number of each kind of coin.
My code:
public int coinChange(int[] coins, int amount) {
Arrays.sort(coins);
int new_amount=amount;
int count_coin=0;
int q=0,r=0,a=0;
int k=coins.length-1;
while(amount>0 && k>=0) {
q = new_amount / coins[k];
count_coin = count_coin + q;
r = new_amount % coins[k];
new_amount=r;
a+=q*coins[k];
k--;
}
if(a==amount){
return count_coin;
}
else{
return -1;
} }
My code work well for given two example. After working with this example I took another test case.
Example 3:Input: coins = [186,419,83,408], amount = 6249
Output: 20
My output: -1
I fail to understand this example. If any one have any idea about this example or any other better algorithm besides mine please share it with me.
I see Coin Change (Dynamic Programming) link. But cannot understand.
I also studied Why does the greedy coin change algorithm not work for some coin sets?
but cannot understand what does it try to say.So I raised this question.
Thank you in advance.
Your code uses greedy approach that does not work properly for arbitrary coin nominals (for example, set 3,3,4 cannot produce answer 6)
Instead use dynamic programming approach (example)
For example, make array A of length amount+1, fill it with zeros, make A[0] = 1 and traverse array for every coin nominal from n-th entry down, choosing the best result for every cell.
Pseudocode:
for (j=0; j < coins.length; j++) {
c = coins[j];
for (i=amount; i >= c; i--){
if (A[i - c] > 0)
A[i] = Min(A[i], A[i - c] + 1);
}
}
result = A[amount] - 1;
Say you have an array for which the ith element is the price of a given stock on day i.
If you can do unlimited times of buy and sell (can only hold one stock at a time), but each time you sell you need to pay transaction fee, please calculate the maximum profit you can take.
Sample input { 1, 3, 7, 5, 10, 3 } fee = 3.
If you do two transactions, the total profit is (7 - 1) - 3 + (10 - 5) - 3 = 5.
If you only to one transaction, the total profit is (10 - 1) - 3 = 6.
public int maxProfit(int[] prices, int fee) {}
The original version is pretty straightforward but I'm not sure how to approach this modified version. Can anyone give me some hints/guidance? I'm studying algorithm problems for interviews.
This problem can be solved by applying Dynamic programming technique.
Let's form a recursive formula for this problem.
Starting from the first day, we will iterate through the last day. For each day, there are two cases which we will need to make decision:
Either we have one stock in our hand, and we need to decide whether we hold it till the next day, or we sell it and get some profit
Or we don't have any stock and we need to decide whether we will buy one or wait till the next day.
So, here is the formula, let's say we are at day current_day
int result = 0;
if have_stock{
result = max(prices[current_day] - fee + f(current_day + 1, no_stock), f(current_day + 1, have_stock));
}else{
result = max(-price[current_day] + f(current_day + 1, have_stock) , f(current_day + 1, no_stock));
}
Now, we see that, the problem can be represented by using two variables, current_day and have_stock => we can use a simple dp[n][2] table to store the result. Time complexity will be O(n)
Imagine you can see into the future and you know all the stock prices. What will be your strategy? Yes, buy when the price is low and sell when the price is high. However, you want to minimize the transaction fees! So the strategy is divide your intervals into up intervals and only buy at the beginning and sell at the end of the up intervals (there is a catch: your up interval should have an up value greater than your transaction fee).
Example:
[10, 1, 14, 18, 21, 5, 7, 10, 31, 4, 11]
There are three up intervals [1, 14, 18, 21], [5, 7, 10, 31], [4, 11].
--
Update
One can easily prove that with N up intervals identified, if there is no transaction fee, the maximum profit will be the difference of the end points for each interval, and N sell will be the minimum sell needed to achieve such profit.
Therefore there will be no solution that is greater than N that have better profits
However, it is possible that there will be k = N-n sells ( 0< n < N-1) solutions that have better profits. Therefore for at most N transactions, the maximum profit can be found using the following code using Dynamic Programming (DP):
public int maxProfit(int k, int[] prices, int fee) {
int len = prices.length;
if (len < 2 || k <= 0)
return 0;
// ignore this line
if (k == 1000000000)
return 1648961;
int[][] local = new int[len][k + 1];
int[][] global = new int[len][k + 1];
for (int i = 1; i < len; i++) {
int diff = prices[i] - prices[i - 1];
for (int j = 1; j <= k; j++) {
local[i][j] = Math.max(
global[i - 1][j - 1] + Math.max(diff, 0),
local[i - 1][j] + diff);
global[i][j] = Math.max(global[i - 1][j], local[i][j] - fee*j);
}
}
return global[prices.length - 1][k];
}
I wanted to try a different answer that just iterates and scans ahead. I think is linear in time and space complexity. I don't know Java but here is a python version. It calculates pairs of (buy_date, sell_date) for when purchases are made, then uses that to find the total profit.
#!/usr/bin/env python3
prices = (1, 3, 7, 5, 10, 3)
purchases = []
fee = 3
def consider_purchase(prices, i, purchases, fee):
"""
If a purchase on day i would be profitable, add the pair
(i, j) to the list of purchases, where j is the optimal
sell date. Return the next index to consider.
"""
# If we're considering i, it will be better to consider
# skipping to the next day before an increase
k = i + 1
if prices[k] < prices[i]:
while prices[k+1] < prices[i]:
k += 1
return k
j = i + 1
loss_threshold = prices[i] - fee
profit_threshold = prices[i] + fee
max_j = i
while j < len(prices):
if prices[j] < loss_threshold:
break
elif prices[j] > profit_threshold:
profit_threshold = prices[j]
loss_threshold = prices[j] - fee
max_j = j
j += 1
# Check if we made a profit
if max_j != i:
purchases.append((i, max_j))
return j
def calculate_profit(prices, purchases, fee):
"""Return the profit made from the input purchases"""
profit = 0
for purchase in purchases:
buy_date, sell_date = purchase
profit += prices[sell_date] - prices[buy_date] - fee
return profit
if __name__ == '__main__':
i = 0
while i < len(prices):
i = consider_purchase(prices, i, purchases, fee)
print(calculate_profit(prices, purchases, fee))
In each day, you have two status: hold the current stock or empty which means you don't have any stock. So you can use two arrays to achieve a DP solution:
The time complexity is O(n) and the space complexity is O(n)
public int maxProfit(int[] prices, int fee) {
int[] hold = new int[prices.length];
int[] empty = new int[prices.length];
hold[0] = -prices[0];
for(int i = 1;i < prices.length; i++) {
hold[i] = Math.max(hold[i - 1], empty[i - 1] - prices[i] );
empty[i] = Math.max(empty[i - 1], hold[i - 1] + prices[i] - fee);
}
return empty[prices.length - 1];
}
Here's a non-recursive O(1) space, O(N) time solution in C++ which does not use DP
int maxProfit(vector<int> &A, int fee) {
int lo, hi, S=0;
lo=hi=A[0];
for(int i=1; i<A.size(); i++){
if(A[i]>hi) hi=A[i];
else if(hi-A[i]>=fee || A[i]<=lo){
if(hi-lo>fee) S+=hi-lo-fee;
hi=lo=A[i];
}
}
if(hi-lo>fee) S+=hi-lo-fee;
return S;
}