Алгоритм и структура данных для случая [дубликат]

После того, как вы попробовали все здесь без каких-либо результатов, я решил проблему просто, переместив тег src скрипта из тела в голову

108
задан Cactus 12 April 2016 в 03:44
поделиться

18 ответов

257
ответ дан templatetypedef 21 August 2018 в 17:49
поделиться
public static double maxProfit(double [] stockPrices)
    {
        double initIndex = 0, finalIndex = 0;

        double tempProfit = list[1] - list[0];
        double maxSum = tempProfit;
        double maxEndPoint = tempProfit;


        for(int i = 1 ;i<list.length;i++)
        {
            tempProfit = list[ i ] - list[i - 1];;

            if(maxEndPoint < 0)
            {
                maxEndPoint = tempProfit;
                initIndex = i;
            }
            else
            {
                maxEndPoint += tempProfit;
            }

            if(maxSum <= maxEndPoint)
            {
                maxSum = maxEndPoint ;
                finalIndex = i;
            }
        }
        System.out.println(initIndex + " " + finalIndex);
        return maxSum;

    }

Вот мое решение. изменяет алгоритм максимальной подпоследовательности. Решает проблему в O (n). Я думаю, что это невозможно сделать быстрее.

1
ответ дан Afaque 21 August 2018 в 17:49
поделиться

Это максимальная разница между двумя элементами в массиве, и это мое решение:

O (N) временная сложность O (1) сложность пространства

    int[] arr   =   {5, 4, 6 ,7 ,6 ,3 ,2, 5};

    int start   =   0;
    int end     =   0;
    int max     =   0;
    for(int i=1; i<arr.length; i++){
        int currMax =   arr[i] - arr[i-1];
        if(currMax>0){
            if((arr[i] -arr[start])>=currMax && ((arr[i] -arr[start])>=(arr[end] -arr[start]))){

                 end    =   i;
            }
            else if(currMax>(arr[i] -arr[start]) && currMax >(arr[end] - arr[start])){
                start   =   i-1;
                end =   i;
            }
        }
    }
    max =   arr[end] - arr[start];
    System.out.println("max: "+max+" start: "+start+" end: "+end);
0
ответ дан Ahmed Mansy 21 August 2018 в 17:49
поделиться

Максимальная прибыль от одной продажи, O (n) -решение

function stocks_n(price_list){
    var maxDif=0, min=price_list[0]

    for (var i in price_list){
        p = price_list[i];
        if (p<min)
            min=p
        else if (p-min>maxDif)
                maxDif=p-min;
   }

    return maxDif
}

Вот проект, который проводит тестирование временной сложности на o (N) vs o (n ^ 2) на случайном наборе данных на 100k ints. O (n ^ 2) занимает 2 секунды, а O (n) принимает 0,01 с

https://github.com/gulakov/complexity.js

function stocks_n2(ps){
    for (maxDif=0,i=_i=0;p=ps[i++];i=_i++)
        for (;p2=ps[i++];)
            if (p2-p>maxDif)
                maxDif=p2-p
    return maxDif
}

Это более медленный подход o (n ^ 2), который проходит через остальные дни для каждого дня, двойной цикл.

1
ответ дан Alex G 21 August 2018 в 17:49
поделиться

Для всех ответов, отслеживающих минимальный и максимальный элементы, это решение на самом деле является решением O (n ^ 2). Это связано с тем, что в конце нужно проверить, произошло ли максимум после минимума или нет. В противном случае требуются дальнейшие итерации до тех пор, пока это условие не будет выполнено, и это оставляет худший случай O (n ^ 2). И если вы хотите пропустить дополнительные итерации, вам потребуется больше места. В любом случае, нет-нет по сравнению с решением динамического программирования

0
ответ дан Anikam 21 August 2018 в 17:49
поделиться
  • 1
    Это неправда. Проверьте принятый ответ. – adev 6 July 2017 в 19:36
def get_max_profit(stock):
    p=stock[0]
    max_profit=0
    maxp=p
    minp=p
    for i in range(1,len(stock)):
        p=min(p,stock[i])
        profit=stock[i]-p
        if profit>max_profit:
            maxp=stock[i]
            minp=p
            max_profit=profit
    return minp,maxp,max_profit



stock_prices = [310,315,275,295,260,270,290,230,255,250]
print(get_max_profit(stock_prices))

Эта программа в python3 может вернуть покупательную цену и отпускную цену, которая максимизирует прибыль, рассчитывается с учетом сложности времени O (n) и сложности пространства O (1).

0
ответ дан Arun Tom 21 August 2018 в 17:49
поделиться

Я не совсем уверен, почему это считается вопросом динамического программирования. Я видел этот вопрос в учебниках и алгоритмах, используя O (n log n), и O (log n) для пробела (например, Elements of Programming Interviews). Это кажется гораздо более простой проблемой, чем люди делают это.

Это работает, отслеживая максимальную прибыль, минимальную цену покупки и, следовательно, оптимальную цену покупки / продажи. Когда он проходит через каждый элемент массива, он проверяет, меньше ли данный элемент, чем минимальная покупательная цена. Если это так, минимальный индекс покупной цены (min) обновляется как индекс этого элемента. Кроме того, для каждого элемента алгоритм becomeABillionaire проверяет, превышает ли arr[i] - arr[min] (разница между текущим элементом и минимальной покупной ценой) больше текущей прибыли. Если это так, прибыль обновляется до этой разницы, а для покупки установлено значение arr[min], а для продажи установлено значение arr[i].

Выполняется за один проход.

static void becomeABillionaire(int arr[]) {
    int i = 0, buy = 0, sell = 0, min = 0, profit = 0;

    for (i = 0; i < arr.length; i++) {
        if (arr[i] < arr[min])
            min = i;
        else if (arr[i] - arr[min] > profit) {
            buy = min; 
            sell = i;
            profit = arr[i] - arr[min];
        }

    }

    System.out.println("We will buy at : " + arr[buy] + " sell at " + arr[sell] + 
            " and become billionaires worth " + profit );

}

Соавтор: https://stackoverflow.com/users/599402/ephraim

31
ответ дан Community 21 August 2018 в 17:49
поделиться
  • 1
    Я не думаю, что это довольно работает таким образом, поскольку, если вы покупаете акции в какой-то первоначальный день, вы не получаете преимуществ дельты с предыдущего дня. Или это не проблема в этом подходе? – templatetypedef 17 August 2011 в 06:24
  • 2
    @templatetypedef, поэтому вы отслеживаете наибольшую сумму и сумму текущей последовательности. Когда сумма текущей последовательности опускается ниже нуля, вы знаете, что вы не получите никаких денег с этой последовательностью, и вы можете начать заново. Отслеживая самую большую сумму, вы автоматически найдете лучшие даты покупки / продажи. – MSN 17 August 2011 в 07:11
  • 3

Вот мое решение

public static int maxProfit (ArrayList in) {

    int min = in.get(0), max = 0;
    for(int i=0; i<in.size()-1;i++){

        min=Math.min(min, in.get(i));

        max = Math.max(in.get(i)- min, max);
    }

    return max;
}

}

0
ответ дан Connors 21 August 2018 в 17:49
поделиться

Ответ на верхний голос не учитывает случаи, когда максимальная прибыль отрицательна и должна быть изменена, чтобы допускать такие случаи. Это можно сделать, ограничив диапазон цикла до (len (a) - 1) и изменив способ получения прибыли путем изменения индекса на единицу.

def singSellProfit(a):
profit = -max(a)
low = a[0]

for i in range(len(a) - 1):
    low = min(low, a[i])
    profit = max(profit, a[i + 1] - low)
return profit

Сравните эту версию функции с предыдущим для массива:

s = [19,11,10,8,5,2]

singSellProfit(s)
-1

DynamicProgrammingSingleSellProfit(s)
0
0
ответ дан Danny Bubb 21 August 2018 в 17:49
поделиться

здесь мое решение Java:

public static void main(String[] args) {
    int A[] = {5,10,4,6,12};

    int min = A[0]; // Lets assume first element is minimum
    int maxProfit = 0; // 0 profit, if we buy & sell on same day.
    int profit = 0;
    int minIndex = 0; // Index of buy date
    int maxIndex = 0; // Index of sell date

    //Run the loop from next element
    for (int i = 1; i < A.length; i++) {
        //Keep track of minimum buy price & index
        if (A[i] < min) {
            min = A[i];
            minIndex = i;
        }
        profit = A[i] - min;
        //If new profit is more than previous profit, keep it and update the max index
        if (profit > maxProfit) {
            maxProfit = profit;
            maxIndex = i;
        }
    }
    System.out.println("maxProfit is "+maxProfit);
    System.out.println("minIndex is "+minIndex);
    System.out.println("maxIndex is "+maxIndex);     
}
2
ответ дан Darwind 21 August 2018 в 17:49
поделиться
  • 1
    @Nitiraj, да, это решение правильно, но я бы попросил вас прочитать ответ, предоставленный templatetypedef, так как в ответе, предоставленном templatetypedef, упоминаются все возможные решения, включая сообщение, опубликованное Rohit. Решение Rohit на самом деле является реализацией последнего решения с O (n), используя динамическое программирование, упомянутое в ответе, предоставленном templatetypedef. – nits.kk 19 July 2015 в 19:28
  • 2
    Предположим, что ваш массив - это int A [] = {5, 4, 6, 7, 6, 3, 2, 5}; Затем, согласно вашей логике, вы купите по индексу 6, а затем продадите его по индексу 3. Что неправильно. Вы не можете продать в прошлом. Индекс продажи должен быть больше, чем индекс покупки. – developer747 13 August 2015 в 01:29
  • 3
    Вышеупомянутое решение является "почти" верный. но он печатает абсолютный индекс min вместо индекса «buy». цена. Чтобы исправить, вам нужна другая переменная, скажем, minBuyIndex, которую вы обновляете только внутри «if (profit & gt maxProfit)». заблокировать и распечатать это. – javabrew 9 April 2017 в 16:53

Возможность определить максимальную прибыль может состоять в том, чтобы отслеживать минимальные и правые максимальные элементы левой стороны в массиве по каждому индексу в массиве. Когда вы будете итерировать цены акций, в любой день вы будете знать самую низкую цену до этого дня, и вы также будете знать максимальную цену после (и в том числе) в тот день.

Например , давайте определим min_arr и max_arr, причем данный массив будет arr. Индекс i в min_arr будет минимальным элементом в arr для всех индексов <= i (слева от i и включает i). Индекс i в max_arr будет максимальным элементом в arr для всех индексов >= i (справа и в том числе i). Затем вы можете найти максимальную разницу между соответствующими элементами в max_arr и `min_arr ':

def max_profit(arr)
   min_arr = []
   min_el = arr.first
   arr.each do |el|
       if el < min_el
           min_el = el
           min_arr << min_el
       else
           min_arr << min_el
       end
   end

   max_arr = []
   max_el = arr.last
   arr.reverse.each do |el|
       if el > max_el
           max_el = el
           max_arr.unshift(max_el)
       else
           max_arr.unshift(max_el)
       end

   end

   max_difference = max_arr.first - min_arr.first
   1.upto(arr.length-1) do |i|
        max_difference = max_arr[i] - min_arr[i] if max_difference < max_arr[i] - min_arr[i]  
   end

   return max_difference 
end

Это должно выполняться в O (n) времени, но я считаю, что он использует много пространство.

0
ответ дан fibono 21 August 2018 в 17:49
поделиться

После того, как это произошло в текущем экзамене по кодированию для инженера-конструктора FB, мне пришлось решить его в спокойной прохладной атмосфере, так что вот мои 2 цента:

var max_profit = 0;
var stockPrices = [23,40,21,67,1,50,22,38,2,62];

var currentBestBuy = 0; 
var currentBestSell = 0;
var min = 0;

for(var i = 0;i < (stockPrices.length - 1) ; i++){
    if(( stockPrices[i + 1] - stockPrices[currentBestBuy] > max_profit) ){
        max_profit = stockPrices[i + 1] - stockPrices[currentBestBuy];
        currentBestSell = i + 1;  
    }
    if(stockPrices[i] < stockPrices[currentBestBuy]){
            min = i;
        }
    if( max_profit < stockPrices[i + 1] - stockPrices[min] ){
        max_profit = stockPrices[i + 1] - stockPrices[min];
        currentBestSell = i + 1;
        currentBestBuy = min;
    }
}

console.log(currentBestBuy);
console.log(currentBestSell);
console.log(max_profit);
0
ответ дан Ido Weinstein 21 August 2018 в 17:49
поделиться
static void findmaxprofit(int[] stockvalues){
    int buy=0,sell=0,buyingpoint=0,sellingpoint=0,profit=0,currentprofit=0;
    int finalbuy=0,finalsell=0;
    if(stockvalues.length!=0){
        buy=stockvalues[0];
    }           
    for(int i=1;i<stockvalues.length;i++){  
        if(stockvalues[i]<buy&&i!=stockvalues.length-1){                
            buy=stockvalues[i];
            buyingpoint=i;
        }               
        else if(stockvalues[i]>buy){                
            sell=stockvalues[i];
            sellingpoint=i;
        }
        currentprofit=sell-buy;         
        if(profit<currentprofit&&sellingpoint>buyingpoint){             
            finalbuy=buy;
            finalsell=sell;
            profit=currentprofit;
        }

    }
    if(profit>0)
    System.out.println("Buy shares at "+finalbuy+" INR and Sell Shares "+finalsell+" INR and Profit of "+profit+" INR");
    else
        System.out.println("Don't do Share transacations today");
}
0
ответ дан Mohan Raj 21 August 2018 в 17:49
поделиться

Единственный ответ, действительно отвечающий на вопрос, - это вопрос @akash_magoon (и таким простым способом!), но он не возвращает точный объект, указанный в вопросе. Я немного реорганизовал и получил ответ в PHP, возвращающий только то, что задано:

function maximizeProfit(array $dailyPrices)
{
    $buyDay = $sellDay = $cheaperDay = $profit = 0;

    for ($today = 0; $today < count($dailyPrices); $today++) {
        if ($dailyPrices[$today] < $dailyPrices[$cheaperDay]) {
            $cheaperDay = $today;
        } elseif ($dailyPrices[$today] - $dailyPrices[$cheaperDay] > $profit) {
            $buyDay  = $cheaperDay;
            $sellDay = $today;
            $profit   = $dailyPrices[$today] - $dailyPrices[$cheaperDay];
        }
    }
    return [$buyDay, $sellDay];
}
0
ответ дан Natxet 21 August 2018 в 17:49
поделиться

Оптимальное решение:

+ (int)maxProfit:(NSArray *)prices {
    int maxProfit = 0;

    int bestBuy = 0;
    int bestSell = 0;
    int currentBestBuy = 0;

    for (int i= 1; i < prices.count; i++) {
        int todayPrice = [prices[i] intValue];
        int bestBuyPrice = [prices[currentBestBuy] intValue];
        if (todayPrice < bestBuyPrice) {
            currentBestBuy = i;
            bestBuyPrice = todayPrice;
        }

        if (maxProfit < (todayPrice - bestBuyPrice)) {
            bestSell = i;
            bestBuy = currentBestBuy;
            maxProfit = (todayPrice - bestBuyPrice);
        }
    }

    NSLog(@"Buy Day : %d", bestBuy);
    NSLog(@"Sell Day : %d", bestSell);

    return maxProfit;
}
0
ответ дан Naveen Shan 21 August 2018 в 17:49
поделиться

Это интересная проблема, потому что она кажется трудной, но тщательная мысль дает элегантное, исправленное решение.

Как уже отмечалось, его можно решить грубо -force в O (N ^ 2) времени. Для каждой записи в массиве (или списке), итерации по всем предыдущим записям, чтобы получить min или max в зависимости от того, найти ли проблему наибольший коэффициент усиления или потери.

Вот как думать о решении в O (N): каждая запись представляет собой новый возможный максимум (или мин). Затем все, что нам нужно сделать, это сохранить предыдущий мин (или максимум) и сравнить diff с током и предыдущим мин (или max). Легкий peasy.

Вот код, в Java как тест JUnit:

import org.junit.Test;

public class MaxDiffOverSeriesProblem {

    @Test
    public void test1() {
        int[] testArr = new int[]{100, 80, 70, 65, 95, 120, 150, 75, 95, 100, 110, 120, 90, 80, 85, 90};

        System.out.println("maxLoss: " + calculateMaxLossOverSeries(testArr) + ", maxGain: " + calculateMaxGainOverSeries(testArr));
    }

    private int calculateMaxLossOverSeries(int[] arr) {
        int maxLoss = 0;

        int idxMax = 0;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] > arr[idxMax]) {
                idxMax = i;
            }

            if (arr[idxMax] - arr[i] > maxLoss) {
                maxLoss = arr[idxMax] - arr[i];
            }           
        }

        return maxLoss;
    }

    private int calculateMaxGainOverSeries(int[] arr) {
        int maxGain = 0;

        int idxMin = 0;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] < arr[idxMin]) {
                idxMin = i;
            }

            if (arr[i] - arr[idxMin] > maxGain) {
                maxGain = arr[i] - arr[idxMin];
            }           
        }

        return maxGain;
    }

}

В случае вычисления наибольшей потери мы отслеживаем максимальное количество в списке (цена покупки) до текущей записи. Затем мы вычисляем разницу между максимальным и текущим. Если max - current> maxLoss, то мы сохраняем этот diff как новый maxLoss. Так как индекс max гарантированно меньше индекса тока, мы гарантируем, что дата «buy» меньше даты «sell».

В случае вычисления наибольшего выигрыша все обращается вспять. Мы отслеживаем мин в списке до текущей записи. Мы вычисляем разность между минимумом и током (изменяем порядок в вычитании). Если current - min> maxGain, то мы сохраняем этот diff как новый maxGain. Опять же, индекс «buy» (min) приходит перед индексом текущего («продавать»).

Нам остается только отслеживать maxGain (или maxLoss), а индекс min или макс, но не оба, и нам не нужно сравнивать индексы, чтобы подтвердить, что «покупка» меньше, чем «продать», поскольку мы получаем это естественно.

1
ответ дан Steven Solomon 21 August 2018 в 17:49
поделиться

Я придумал простое решение - код более понятен. Это один из вопросов динамического программирования.

Код не заботится об ошибках и краях. Его просто образец, чтобы дать идею базовой логики решить проблему.

namespace MaxProfitForSharePrice
{
    class MaxProfitForSharePrice
    {
        private static int findMax(int a, int b)
        {
            return a > b ? a : b;
        }

        private static void GetMaxProfit(int[] sharePrices)
        {
            int minSharePrice = sharePrices[0], maxSharePrice = 0, MaxProft = 0;
            int shareBuyValue = sharePrices[0], shareSellValue = sharePrices[0];

            for (int i = 0; i < sharePrices.Length; i++)
            {
                if (sharePrices[i] < minSharePrice )
                {
                    minSharePrice = sharePrices[i];
                    // if we update the min value of share, we need to reset the Max value as 
                    // we can only do this transaction in-sequence. We need to buy first and then only we can sell.
                    maxSharePrice = 0; 
                }
                else 
                {
                    maxSharePrice = sharePrices[i];
                }

                // We are checking if max and min share value of stock are going to
                // give us better profit compare to the previously stored one, then store those share values.
                if (MaxProft < (maxSharePrice - minSharePrice))
                {
                    shareBuyValue = minSharePrice;
                    shareSellValue = maxSharePrice;
                }

                MaxProft = findMax(MaxProft, maxSharePrice - minSharePrice);
            }

            Console.WriteLine("Buy stock at ${0} and sell at ${1}, maximum profit can be earned ${2}.", shareBuyValue, shareSellValue, MaxProft);
        }

        static void Main(string[] args)
        {
           int[] sampleArray = new int[] { 1, 3, 4, 1, 1, 2, 11 };
           GetMaxProfit(sampleArray);
            Console.ReadLine();
        }
    }
}
1
ответ дан Templar 21 August 2018 в 17:49
поделиться

Проблема идентична максимальной подпоследовательности, которую я решил использовать с помощью динамического программирования. Следите за текущей и предыдущей (прибыль, день продажи и дата продажи) Если ток выше предыдущего, замените предыдущий на текущий.

    int prices[] = { 38, 37, 35, 31, 20, 24, 35, 21, 24, 21, 23, 20, 23, 25, 27 };

    int buyDate = 0, tempbuyDate = 0;
    int sellDate = 0, tempsellDate = 0; 

    int profit = 0, tempProfit =0;
    int i ,x = prices.length;
    int previousDayPrice = prices[0], currentDayprice=0;

    for(i=1 ; i<x; i++ ) {

        currentDayprice = prices[i];

        if(currentDayprice > previousDayPrice ) {  // price went up

            tempProfit = tempProfit + currentDayprice - previousDayPrice;
            tempsellDate = i;
        }
        else { // price went down 

            if(tempProfit>profit) { // check if the current Profit is higher than previous profit....

                profit = tempProfit;
                sellDate = tempsellDate;
                buyDate = tempbuyDate;
            } 
                                     // re-intialized buy&sell date, profit....
                tempsellDate = i;
                tempbuyDate = i;
                tempProfit =0;
        }
        previousDayPrice = currentDayprice;
    }

    // if the profit is highest till the last date....
    if(tempProfit>profit) {
        System.out.println("buydate " + tempbuyDate + " selldate " + tempsellDate + " profit " + tempProfit );
    }
    else {
        System.out.println("buydate " + buyDate + " selldate " + sellDate + " profit " + profit );
    }   
1
ответ дан Vikas 21 August 2018 в 17:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: