Алгоритм, необходимый для этой задачи? - PullRequest
3 голосов
/ 02 декабря 2011

Входные данные: n (int) и n значения (float), которые представляют обменные курсы (разные между ними) со случайным значением между 4 и5.

Вывод: вычислить максимальное количество значений, которые можно использовать (в том же порядке) для представления восходящей и нисходящей кривой?


ex Восемь значений

4.5 4.6 4.3 4.0 4.8 4.4 4.7 4.1

должны вывести

5 (4,5 4,6 4,8 4,4 4,1)


Мой подход

  • Если я пытаюсь выполнить последовательные if с, я получаю случайный массив, который учитывает условие кривой, но не самое длинное.
  • Я не пробовал откат, потому что я не такойзнаком с ним, но что-то подсказывает мне, что я должен вычислить все решения с его помощью, а затем выбрать самое длинное.
  • И наконец: грубая сила, но так как это задание для разработки алгоритма;С таким же успехом я могу не сдавать его. :) 1036
1038 * Есть ли более простой / более эффективный / более быстрый метод?

Вот моя попытка, основанная на алгоритме Даниэля Лемира.Кажется, он не учитывает позиции 0, i и n.Я уверен, что если проблемы, как я могу их исправить?

for(int i = 0; i<n-1; i++){
            int countp=0;   // count ascending
            int countn=0;   // count descending
            for(int j=0;j<=i;j++){
                    if(currency[j]<currency[j+1]){
                        countp++;
                        System.out.print(j+" ");
                    }
                }
            System.out.print("|| ");
            for(int j=i;j<n-1;j++){
                if(currency[j]>currency[j+1]){
                    countn++;
                    System.out.print(j+" ");
                }
            }
        System.out.println();
        if(countn+countp>maxcount) maxcount=countn+countp;                   
        }

Ответы [ 2 ]

3 голосов
/ 02 декабря 2011

Во-первых, вы хотите иметь возможность вычислять самую длинную монотонную подпоследовательность из одной точки в другую.(Увеличивается или уменьшается, это не сильно влияет на проблему.) Для этого вы можете использовать динамическое программирование.Например, чтобы решить задачу с указанными индексами от 0 до i, вы начинаете с решения задачи от 0 до 0 (тривиально!), Затем от 0 до 1, затем от 0 до 2 и т. Д. При каждой записи (вмассив) ваше лучшее решение.

Например, вот код на python для вычисления самой длинной неубывающей последовательности, идущей от индекса 0 до индекса i.Мы используем массив (bbest) для хранения решения от 0 до j для всех j от 0 до i: длина самой длинной неубывающей подпоследовательности от 0 до j.(Используется стратегия динамического программирования.)

def countasc(array,i):
  mmin = array[0] # must start with mmin
  mmax= array[i] # must end with mmax
  bbest=[1] # going from 0 to 0 the best we can do is length 1
  for j in range(1,i+1): # j goes from 1 to i
    if(array[j]>mmax):
      bbest.append(0) # can't be used
      continue
    best = 0 # store best result
    for k in range(j-1,-1,-1): # count backward from j-1 to 0
      if(array[k]>array[j]) :
        continue # can't be used
      if(bbest[k]+1>best):
          best = bbest[k]+1
    bbest.append(best)
  return bbest[-1] # return last value of array bbest

или эквивалентно в Java (предоставляется по запросу):

int countasc(float[] array,int i) {
    float mmin = array[0];
    float mmax = array[i];
    ArrayList<Integer> bbest= new ArrayList<Integer>();
    bbest.add(1);
    for (int j = 1; j<=i;++j) {
        if(array[j]>mmax){
            bbest.add(0);
            continue;
        }
        int best = 0;
        for(int k = j-1; k>=0;--k) {
            if(array[k]>array[j]) 
                continue;
            if(bbest.get(k).intValue()+1>best)
                best = bbest.get(k).intValue()+1;
        }
        bbest.add(best);
    }
    return bbest.get(bbest.size()-1);
}

Вы можете написать функцию такого же типа, чтобы найти самую длинную не- возрастающая последовательность от i до n-1 (оставлено как упражнение).

Обратите внимание, что countasc работает за линейное время.

Теперь мы можем решить актуальную проблему:

Start with S, an empty array
For i an index that goes from 0 to n-1 :
  compute the length of the longest increasing subsequence from 0 to i (see function countasc above)
  compute the length of the longest decreasing subsequence from n-1 to i
  add these two numbers, add the sum to S
return the max of S

Имеет квадратичную сложность.Я уверен, что вы можете улучшить это решение.В этом подходе много избыточности.Например, для скорости вам, вероятно, не следует повторно вызывать countasc с неинициализированным массивом bbest: его можно вычислить один раз.Возможно, вы сможете снизить сложность до O (n log n), проделав еще больше работы.

1 голос
/ 02 декабря 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...