Need max profit.
What can I modify to get the max profit if I can only buy once and sell once?
Means if I buy at 5 and sell at 150 then its max profit.
Currently what I have done is buy when price is less than next day, and sell if price is more than next day.
As obviously we have to keep in mind we can sell only after we buy, means sell index can not be before buy index.
What I have done so far is:
package com;
public class Stock {
public static void main(String[] args) {
int[] prices = {20,10,70,80,5,150,67};
int length = prices.length-2;
int buy=0;
int sell=0;
int buyIndex=-1;
int sellIndex=-1;
int i=0;
for (i =0 ; i<=length ;i++ ){
// buy logic start
if(prices[i]<prices[i+1]){
if(i>buyIndex){
buy= prices[i];
buyIndex=i;
System.out.println("buy"+buy);
System.out.println("buyIndex"+buyIndex);
}
} // buy logic finish
// sell logic start
if(buy!=0 && i>buyIndex ){
System.out.println("inside sell logic");
if(prices[i]>prices[i+1]){
sell = prices[i];
sellIndex = i;
System.out.println("sell"+sell);
System.out.println("sellIndex"+sellIndex);
}
} // sell logic end
} // for loop end
} // main end
}
output is
buy10
buyIndex1
buy70
buyIndex2
inside sell logic
sell80
sellIndex3
buy5
buyIndex4
inside sell logic
sell150
sellIndex5
You can define 2 auxillary arrays: min and max, where:
min[0] = array[0]
min[i] = min(min[i-1], array[i] 0 < i < n
Intuitively, min[i] is the smallest number seen, that came before (or at) index i.
Similary, max:
max[0] = array[n-1]
max[i] = max(max[i+1], array[i]) 0 <= i < n-1
Intuitively, max[i] is the biggest number after or at i.
Now, once you have these arrays, max[i] - min[i] is the maximal profit achieved by a stock that can be bought at most at day i, and sold at least at date i. If you traverse over all is, which is basically the definition of valid transaction.
If you go over all 0 <= i < n, you will find the optimal solution.
(Note, optimization can eliminate the need for extra space by remembering the local min, but I'd start with the extra space solution, which in my opinion has clearer logic)
Good luck!
Related
I'm working on an old contest problem from 2019 from this page:
https://dmoj.ca/problem/ccc19s4
You are planning a trip to visit N tourist attractions. The attractions are numbered from 1 to N and must be visited in this order. You can visit at most K attractions per day, and want to plan the trip to take the fewest number of days as possible.
Under these constraints, you want to find a schedule that has a nice balance between the attractions visited each day. To be precise, we assign a score ai to attraction i. Given a schedule, each day is given a score equal to the maximum score of all attractions visited that day. Finally, the scores of each day are summed to give the total score of the schedule. What is the maximum possible total score of the schedule, using the fewest days possible?
Apparently it's a dynamic programming type of problem, which I can see how, but I can't seem to figure out how to break it down to subproblems and how each subproblem would relate to each other, especially when there are two variables N and K.
I threw together a recursive brute-force algorithm which works for smaller inputs but fails when the inputs get too large:
int daysNeeded = (int) Math.ceil((double) N / K);
// n - index of current attraction being visited
// d - days used up
public static long solve(int n, int d) {
if (d == daysNeeded) { // Base case, stop once we reach the min days required
if (n == N) // If we visited all attractions, count this answer
return 0;
else // If we didn't visit all attractions, don't count this answer
return Integer.MIN_VALUE;
}
long result = 0;
// Try to visit attractions up to K
//
// i + 1 is the number of attractions to visit in this day
for (int i = 0; i < K; i++) {
if (n + i >= N)
break;
long highestScore = attractions[n];
// Find the attraction from [n + j ... n + i] with the highest score
for (int j = 1; j <= i; j++) {
highestScore = Math.max(highestScore, attractions[n + j]);
}
long next = highestScore + solve(n + i + 1, d + 1);
// Find the attraction with the highest score out of all attractions from 0 to i
result = Math.max(result, next);
}
return result;
}
How would you find an optimized algorithm using DP? I can't seem to find any solutions or hints online for this specific problem.
Lets start out by assigning K attractions to each day, except for the last, which will be length M = N mod K. For example:
5 3
2 5 7 1 4
2 5 7|1 4 (M = 5 mod 3 = 2)
Observe that we cannot extend any of the K length days, neither can we shrink any of them, unless we first extend the smaller, M length, day. Note that the maximum amount we can extend is equal to K - M = K - (N mod K).
Now let dp[d][m] represent the the optimal score for days 1...d when day d+1 has extended m attractions into our starting dth day. Call the number of days needed D = ceil(N / K). Then:
dp[1][m] = max(attractions[0..k-m-1])
dp[D][m] = max(attractions[i-m..j]) + dp[D-1][m]
dp[d][m] = max(attractions[i-l..j-m]) + dp[d-1][l]
where (i, j) mark the starting dth day
and 0 ā¤ l ā¤ m
and the answer will be the best of dp[D][m].
We can fold into the routine our calculation of the relevant maximum in O(1): preprocess prefix maximums from left to right for each of our starting sections (meaning days) in O(n). For each loop of max(attractions[i-l..j-m]), start with the max provided at j-m in the prefix maximum, then update the maximum by comparing the current one with each attractions[i-l], as l is incremented.
Overall complexity would seem to be O(ceil(N / K) * (K - (N mod K))^2).
We can do better, time-wise, by observing that as m is incremented, we may be able to skip the iteration on l if the starting max didn't change or a max that was greater than the starting max was chosen before (meaning it came from left of i). In those cases, we only need to consider the new l, which is one greater than we checked before. We can rely on a right-to-left prefix max combined with our left-to-right prefix max to get this new max in O(1).
In the case of our simple example, we have:
2 5 7 1 4
dp[1][0] = max(2, 5, 7) = 7
dp[1][1] = max(2, 5) = 5
dp[2][0] = max(1, 4) + dp[1][0] = 11
dp[2][1] = max(7, 1, 4) + dp[1][1] = 12
I will try to give the solution as a recurrence relation.
Let m be the number of days to visit all attractions and let P[m][N] be the optimal value you obtain by visiting N attractions in m days. We don't know P yet but we will reason about it.
P[m][N]=max_{i up to k} ( P[m-1][N-i]+max_{l=0 to i-1}(a[l]) )
For example if you get the optimal score by visiting only the last two attractions on the last day then the score for that day is max(a[N],a[N-1]) and the total (optimal) score will be
P[m][N]=max(a[N],a[N-1])+optimal score to visit N-2 attractions in m-1 days
which is exactly the same as the above formula
P[m][N]=max(a[N],a[N-1]+ P[m-1][N-2]
Note that there is a constraint on i> N/k(m-1) because if you don't visit enough attractions on the last day the remaining days might not be enough to visit the rest.
I am an absolute beginner to learning programming and I was given this assignment:
Birthday problem. Suppose that people enter a room one at a time. How people must enter until two share a birthday? Counterintuitively, after 23 people enter the room, there is approximately a 50ā50 chance that two share a birthday. This phenomenon is known as the birthday problem or birthday paradox.
Write a program Birthday.java that takes two integer command-line arguments n and trials and performs the following experiment, trials times:
Choose a birthday for the next person, uniformly at random between 0 and nā1.
Have that person enter the room.
If that person shares a birthday with someone else in the room, stop; otherwise repeat.
In each experiment, count the number of people that enter the room. Print a table that summarizes the results (the count i, the number of times that exactly i people enter the room, and the fraction of times that i or fewer people enter the room) for each possible value of i from 1 until the fraction reaches (or exceeds) 50%.
For more information on the assignment
However, my code won't print. I would really appreciate if someone could help me find the problem to my assignment.
public class Birthday {
public static void main(String[] args) {
int n = Integer.parseInt(args[0]); //number of days
int trials = Integer.parseInt(args[1]);
boolean[] birthdays = new boolean[n];
int[] times = new int[n + 2]; //number of times i people entered the room
int r;
for (int t = 1; t <= trials; t++) {
for (int k = 0; k < n; k++) { //reset birthday
birthdays[k] = false;
}
for (int i = 1; i <= n; i++) { //number of times
r = (int) (Math.random() * (n - 1)); //random birthday
if (birthdays[r] = false) {
birthdays[r] = true;
continue;
}
else if (birthdays[r] = true) {
times[i]++; //number of times i people entered the room + 1
break;
}
}
}
int j = 1;
while ((double) times[j] / trials <= 0.5) {
System.out.print(j + "\t" + times[j] + "\t" + ((double) times[j] / trials));
j++;
System.out.println("");
}
}
}
I can spot two errors from your code
As Scary Wombat pointed out, you are miss double equal sign inside of your if statement.
The assignment is asking you to calculate "fraction of times that i or fewer people enter the room", meaning you need to do a summation for the first i indices and divided by trials.
For example, among 1 million trials, the fraction in which first duplicate birthday happens when 4th person enters is
(times[0] + times[1] + times[2] + times[3])/ 1000000
Here is what I got:
1 0 0.0
2 2810 0.00281
3 5428 0.008238
4 8175 0.016413
As you can see the fraction is calculated by adding the first three elements together and then divided by 1000000 (2810 + 5428 + 8175 = 16413) / 1000000 = 0.016413
The way you are calculating the fraction ((double) times[j] / trials) is not correct.
You are not adding the previous counts as shown in the example. To do so, you can create a new variable to store the sums of previous counts. and use it as your while loop condition. For instance, see below..
csum += times[j]; // this adds the previous counts into a cumulative sum.
This cumulative sum is supposed to be the one u use to divide by trials to get your probability. Cheers!
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;
Given [ (02:00, 7.5), (03:30, 7.9), (04:00, 8.0), (05:30, 6.8), (10:00, 9.01)] times and selling price we need to find the best time for buying and selling to maximize the profit.
// times are in increasing order
// Sample Output: Buy at 05:30 and sell at 10:00 for a profit of 2.21
I have written the logic to find the max profit but I also need to find the best buying and selling time, so I am bit stuck there
double profit(double prices[])
{
double maxprofit=0;
for(int i=0;i<price.length;i++)
{
double min= values[i];
for(int j=i+1;j<price.length;j++)
{
if(price[j]<price[min])
min=values[min];
}
profit=values[i]-min;
if(maxprofit<profit)
maxprofit=profit;
else
continue;
}
There is no need to use a nested loop, there is a linear time algorithm that can solve this problem.
There is a very detailed explanation of the algorithm here.
Here is how you could fix your code:
public double maxProfit(double[] prices) {
if (prices.length <= 1) return 0;
double minPrice = prices[0];
double maxSoFar = Integer.MIN_VALUE;
double profitSoFar = Integer.MIN_VALUE;
for (int i = 1; i < prices.length; i++){
profitSoFar = prices[i] - minPrice;
minPrice = Math.min(minPrice, prices[i]);
maxSoFar = Math.max(profitSoFar, maxSoFar);
}
return Math.max(maxSoFar, 0);
}