Ну, конкретно эта задачка еще ничего, корявый O(n) вариант можно придумать не зная истории с профессором, проверено. Другое дело, что не получится сразу выдать код такой же чистоты и компактности, рабочий O(n) можно упрощать гораздо дольше, чем придумывать. Она есть (без решения) в одной из начальных глав CLRS (которая Комен в народе), оттого и на интервью должна встречаться довольно часто.АццкоМото wrote: ↑12 May 2017 00:32Блдж, как меня такие вопросы выбешивают. Решение за линейное время было придумано "вскорости после" формулировки задачи, всего через примерно 7 лет, профессором Карнеги Меллона. А ты, нигра, давай мне на интервью за 40 минут сообрази
-
- Уже с Приветом
- Posts: 998
- Joined: 23 Feb 2005 07:28
- Location: Los Angeles
Re: facebook
-
- Уже с Приветом
- Posts: 382
- Joined: 16 Jan 2013 21:35
Re: facebook
вот задачка -
Чтобы время зря не терять - если в циклах текущий элемент больше (или равен) какому либо из предыдущих, то
1 - добавляем эту пару в increasing subsequence
2 - добавляем все ранее накопленные subsequences для меньшего из той самой пары СПЛЮСОВАННЫЕ с текущим элементом.
что-то типа
Как нетрудно видеть сложность O(N^3)(хоть и максимальная) - 2 петли, да еще и накопленные элементы плюсовать с текущим, еще петля
В интернете полно задачек где нужно вернуть лишь максильмальный subsequence, что легко решается в O(N^2) и посложнее решается в O(N Log N)
Можно ли данную задачку решить в O(N^2) или даже в O(N Log N) ?
Предлагаю постить псевдокод) там меньше лишнего
Code: Select all
Given an integer array, find all the different possible increasing subsequences of the given array, and the length of an increasing subsequence should be at least 2 .
Example:
Input: [4, 6, 7, 7]
Output: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]
input: [2,1,3]
output: [2, 3] [1, 3]
1 - добавляем эту пару в increasing subsequence
2 - добавляем все ранее накопленные subsequences для меньшего из той самой пары СПЛЮСОВАННЫЕ с текущим элементом.
что-то типа
Code: Select all
//начинаем со второго элемента
for (i=1;i<sizeof(ary);i++) {
for(j=0;j<i;j++) {
if(ary[i]>=ary[j]) {
if(isset(hash[j])){
// собираем все что было в hash[j] + ary[i]
//Loop through hash[j]
}
}
hash[i][]=array(ary[j],ary[i]);
}
}
}
В интернете полно задачек где нужно вернуть лишь максильмальный subsequence, что легко решается в O(N^2) и посложнее решается в O(N Log N)
Можно ли данную задачку решить в O(N^2) или даже в O(N Log N) ?
Предлагаю постить псевдокод) там меньше лишнего
-
- Уже с Приветом
- Posts: 12257
- Joined: 20 Dec 2000 10:01
- Location: Bellevue, WA
Re: facebook
Чтобы время не терять - генерировать (и записывать в output каждую в отдельности) все такие subsequences это уже практически O(N!) даже в самом простом случае когда 1,2,3,4,5,6,7,i+1
Так что n*log(n) точно не получится
Максильмальный subsequence в n*lon(n) решается с помощью TreeMap
Так что n*log(n) точно не получится
Максильмальный subsequence в n*lon(n) решается с помощью TreeMap
-
- Уже с Приветом
- Posts: 382
- Joined: 16 Jan 2013 21:35
Re: facebook
должно быть O(n^3)-две петли и внутри ко всем hash(i) добавляем ary(i) откуда же там O(N!)
если бы нужно было вернуть только максимальный сиквенс или сосчитать кол-во сиквенсов (не составляя все секвенсы) то O(n^2) и O(n log n) точно делается. Полно решений в интернете.
подозреваю что данную задачу можно сделать с O(n^2 log N)
если бы нужно было вернуть только максимальный сиквенс или сосчитать кол-во сиквенсов (не составляя все секвенсы) то O(n^2) и O(n log n) точно делается. Полно решений в интернете.
подозреваю что данную задачу можно сделать с O(n^2 log N)
-
- Уже с Приветом
- Posts: 15242
- Joined: 01 Mar 2007 05:18
- Location: VVO->ORD->DFW->SFO->DFW->PDX
Re: facebook
да где же вы факториал-то увидели? долбаный стыдDweller wrote: ↑25 May 2017 07:49 Чтобы время не терять - генерировать (и записывать в output каждую в отдельности) все такие subsequences это уже практически O(N!) даже в самом простом случае когда 1,2,3,4,5,6,7,i+1
Так что n*log(n) точно не получится
Максильмальный subsequence в n*lon(n) решается с помощью TreeMap
Мат на форуме запрещен, блдж!
-
- Уже с Приветом
- Posts: 4435
- Joined: 13 Feb 2002 10:01
- Location: Bay Area
Re: facebook
Число подпоследовательностей длины к : n!/k!/(n-k)!АццкоМото wrote: ↑25 May 2017 21:59да где же вы факториал-то увидели? долбаный стыдDweller wrote: ↑25 May 2017 07:49 Чтобы время не терять - генерировать (и записывать в output каждую в отдельности) все такие subsequences это уже практически O(N!) даже в самом простом случае когда 1,2,3,4,5,6,7,i+1
Так что n*log(n) точно не получится
Максильмальный subsequence в n*lon(n) решается с помощью TreeMap
-
- Уже с Приветом
- Posts: 1860
- Joined: 02 Sep 2016 20:26
Re: facebook
Ну, не знаю. Видел решение на http://e-maxx.ru/algo/maximum_average_segment . Там два решения, и оба за линейное время. Первое названо очевидным, но я в нём пытался разобраться минут десять. А второе объявлено более сложным для понимания (как раз которое решил чувак из Карнеги 7 лет спустя), но я его как раз придумал сам за несколько минут. Наверно, хороший алгоритмист видит какие-то тонкости и хочет обосновать какие-то слабые места, а я как неалгоритмист даже не заметил этих трудностей и без должной скрупулезности нашел алгоритм, недостаточно убедительно доказав его корректность. Но алгоритм оказался правильным, а для меня - и более простым, чем тот, который "практически очевиден".АццкоМото wrote: ↑12 May 2017 00:32Блдж, как меня такие вопросы выбешивают. Решение за линейное время было придумано "вскорости после" формулировки задачи, всего через примерно 7 лет, профессором Карнеги Меллона. А ты, нигра, давай мне на интервью за 40 минут сообрази
-
- Уже с Приветом
- Posts: 15242
- Joined: 01 Mar 2007 05:18
- Location: VVO->ORD->DFW->SFO->DFW->PDX
Re: facebook
Во-первых, при чём тут длина к, если нужно любой длины больше единицы. Во-вторых, последовательность должна возрастать. Ну и переставлять местами элементы нельзя.oshibka_residenta wrote: ↑26 May 2017 00:45Число подпоследовательностей длины к : n!/k!/(n-k)!АццкоМото wrote: ↑25 May 2017 21:59да где же вы факториал-то увидели? долбаный стыдDweller wrote: ↑25 May 2017 07:49 Чтобы время не терять - генерировать (и записывать в output каждую в отдельности) все такие subsequences это уже практически O(N!) даже в самом простом случае когда 1,2,3,4,5,6,7,i+1
Так что n*log(n) точно не получится
Максильмальный subsequence в n*lon(n) решается с помощью TreeMap
Так что для 1, 2, 3 ... N будет ровно 2^N - N - 1.
Иными словами: каждый элемент можно либо включить в результат, либо нет (2^N), но не подходят последовательности из ровно одного элемента (-N) и пустая (-1)
Факториалы же появляются, когда возможны перестановки
Мат на форуме запрещен, блдж!
-
- Уже с Приветом
- Posts: 4435
- Joined: 13 Feb 2002 10:01
- Location: Bay Area
Re: facebook
Факториалы появляются когда есть выборка. И, конечно, нужно просто о k просуммировать и получится 2^n, как вы точно заметили. Пойнт в том, что это сильно больше n^3АццкоМото wrote: ↑26 May 2017 05:57Во-первых, при чём тут длина к, если нужно любой длины больше единицы. Во-вторых, последовательность должна возрастать. Ну и переставлять местами элементы нельзя.oshibka_residenta wrote: ↑26 May 2017 00:45Число подпоследовательностей длины к : n!/k!/(n-k)!АццкоМото wrote: ↑25 May 2017 21:59да где же вы факториал-то увидели? долбаный стыдDweller wrote: ↑25 May 2017 07:49 Чтобы время не терять - генерировать (и записывать в output каждую в отдельности) все такие subsequences это уже практически O(N!) даже в самом простом случае когда 1,2,3,4,5,6,7,i+1
Так что n*log(n) точно не получится
Максильмальный subsequence в n*lon(n) решается с помощью TreeMap
Так что для 1, 2, 3 ... N будет ровно 2^N - N - 1.
Иными словами: каждый элемент можно либо включить в результат, либо нет (2^N), но не подходят последовательности из ровно одного элемента (-N) и пустая (-1)
Факториалы же появляются, когда возможны перестановки
Google: binomial coefficients
-
- Уже с Приветом
- Posts: 15242
- Joined: 01 Mar 2007 05:18
- Location: VVO->ORD->DFW->SFO->DFW->PDX
Re: facebook
Это называется "мы не ищем легких путей" Получить не самую простую формулу для выборки к из н, потом просуммировать по к 1..н и сообразить, что на выхлопе получается 2**н.... при том что любая выборка из н однозначно описывается последовательностью из н бит и, следовательно, уши 2**н торчат просто со всей очевидностью и не требуют уаще ни одного даже самого простейшего вычисленияoshibka_residenta wrote: ↑26 May 2017 16:08 И, конечно, нужно просто о k просуммировать и получится 2^n, как вы точно заметили.
вообще не бином ньютона чай. ну, или он самый. в любом случае, это еще в школе проходили. я уж как-нибудь без гуглаoshibka_residenta wrote: ↑26 May 2017 16:08Пойнт в том, что это сильно больше n^3
Google: binomial coefficients
Мат на форуме запрещен, блдж!
-
- Уже с Приветом
- Posts: 4435
- Joined: 13 Feb 2002 10:01
- Location: Bay Area
Re: facebook
Видимо я больше математик чем программист. формулу для выборки к из н я помню с 7(?) класса. Свел задачу к предыдущей.АццкоМото wrote: ↑26 May 2017 21:43Это называется "мы не ищем легких путей" Получить не самую простую формулу для выборки к из н, потом просуммировать по к 1..н и сообразить, что на выхлопе получается 2**н.... при том что любая выборка из н однозначно описывается последовательностью из н бит и, следовательно, уши 2**н торчат просто со всей очевидностью и не требуют уаще ни одного даже самого простейшего вычисленияoshibka_residenta wrote: ↑26 May 2017 16:08 И, конечно, нужно просто о k просуммировать и получится 2^n, как вы точно заметили.
-
- Уже с Приветом
- Posts: 12257
- Joined: 20 Dec 2000 10:01
- Location: Bellevue, WA
Re: facebook
Согласитесь что 2^N это ближе к факториалу чем к n^2
Экспонента против полинома
Экспонента против полинома
-
- Уже с Приветом
- Posts: 15242
- Joined: 01 Mar 2007 05:18
- Location: VVO->ORD->DFW->SFO->DFW->PDX
Re: facebook
Оно, конечно, ближе, но какая разница?
Вообще интересно, вроде выше приводилось решение за кубическое время. Правда, я его не читал. Типа неверное чоле?
Вообще интересно, вроде выше приводилось решение за кубическое время. Правда, я его не читал. Типа неверное чоле?
Мат на форуме запрещен, блдж!
-
- Уже с Приветом
- Posts: 4435
- Joined: 13 Feb 2002 10:01
- Location: Bay Area
Re: facebook
Так о чем и речь. Правильное решение- рекурсия. Где в функцию в качестве параметров передается текущая подпоследовательность (слева) и остаток последовательности справа, который надо перебрать. И внутри для каждого элемента справа опять эту же функцию вызываем
-
- Уже с Приветом
- Posts: 15242
- Joined: 01 Mar 2007 05:18
- Location: VVO->ORD->DFW->SFO->DFW->PDX
Re: facebook
Да, как-то так, и подход тащемта стандартный, тривиальный и давно надоевший.oshibka_residenta wrote: ↑27 May 2017 05:50Так о чем и речь. Правильное решение- рекурсия. Где в функцию в качестве параметров передается текущая подпоследовательность (слева) и остаток последовательности справа, который надо перебрать. И внутри для каждого элемента справа опять эту же функцию вызываем
Единственное, что напрягает, это что в рамках блабла на привете можно с лёгкостью найти не только ассимптотическую сложность, но и worst case scenario output size с точностью до единицы практически не задействовав остатки мозга. А вот на интервью можно обосраться как с биг-о комплексити правильного решения, так и не суметь доказать, что быстрее никак. Проблеять нечто невразумительное, выйти на улицу и через 5 минут понять все до конца
У кого как, а у меня подобное было неоднократно.
Мат на форуме запрещен, блдж!
-
- Уже с Приветом
- Posts: 12257
- Joined: 20 Dec 2000 10:01
- Location: Bellevue, WA
-
- Уже с Приветом
- Posts: 232
- Joined: 18 Nov 2014 22:55
- Location: SFBA
Re: facebook
Я утверждаю что по скольку размер memo зависит от длины списка то сложность этого алгоритма O(n) поскольку максимум требуется заполнить только n ключей, после этого будет O(1) lookup. Хз как это называется, amortized complexity может быть или как то так
Code: Select all
def compute(input: Seq[Int]): Seq[Seq[Int]] = {
val memo = mutable.Map.empty[Seq[Int], Seq[Seq[Int]]]
def run(seq: Seq[Int]): Seq[Seq[Int]] = memo.getOrElseUpdate(seq, seq match {
case Nil => Seq(Seq.empty)
case x :: Nil => Seq(Seq(x))
case x :: xs =>
val candidates = seq.zipWithIndex.tail.filter { case (value, idx) => value >= x }
val res = candidates.map { case (value, idx) => run(seq.drop(idx)).map(x +: _) }
res.flatten
})
val res = for (i <- 0 to input.length) yield run(input.drop(i))
res.flatten.filter(_.length >= 2)
}
Last edited by _reality on 27 May 2017 07:00, edited 1 time in total.
-
- Уже с Приветом
- Posts: 15242
- Joined: 01 Mar 2007 05:18
- Location: VVO->ORD->DFW->SFO->DFW->PDX
-
- Уже с Приветом
- Posts: 382
- Joined: 16 Jan 2013 21:35
Re: facebook
что то в O(n) слабо верится. А можно псевдокод или любой С-подобный синтаксис вашего решения._reality wrote: ↑27 May 2017 06:58 Я утверждаю что по скольку размер memo зависит от длины списка то сложность этого алгоритма O(n) поскольку максимум требуется заполнить только n ключей, после этого будет O(1) lookup. Хз как это называется, amortized complexity может быть или как то так
Code: Select all
def compute(input: Seq[Int]): Seq[Seq[Int]] = { val memo = mutable.Map.empty[Seq[Int], Seq[Seq[Int]]] def run(seq: Seq[Int]): Seq[Seq[Int]] = memo.getOrElseUpdate(seq, seq match { case Nil => Seq(Seq.empty) case x :: Nil => Seq(Seq(x)) case x :: xs => val candidates = seq.zipWithIndex.tail.filter { case (value, idx) => value >= x } val res = candidates.map { case (value, idx) => run(seq.drop(idx)).map(x +: _) } res.flatten }) val res = for (i <- 0 to input.length) yield run(input.drop(i)) res.flatten.filter(_.length >= 2) }
Я уверен что можно добиться O(N LogN) хотя знаю только как решить O(N^2) (используя hash) и O(N^3)
-
- Уже с Приветом
- Posts: 15242
- Joined: 01 Mar 2007 05:18
- Location: VVO->ORD->DFW->SFO->DFW->PDX
Re: facebook
Потрясающие дела. Даже после того, как выяснилось, что worst case output size is 2^N - N -1 идея решить быстрее не умерла.
Мат на форуме запрещен, блдж!
-
- Уже с Приветом
- Posts: 382
- Joined: 16 Jan 2013 21:35
Re: facebook
когда же это выяснилось...? Опровергните что это не решается в N^3 (для простоты, на самом деле можно свести к N^2 и скорее всего к N log N)
Перебираем 1...N элементы через i, внутри перебираем от 2...i через j и сравниваем ary(i) vs ary (j) если ary(i) >ary(j) то ary(i),ary(j) это уже increasing subsequence из двух элементов, добавляем в копилочку result(i) этот маленький сабсиквенс . Да еще и добавляем накопленные subsequnces которые уже лежает в result(j) предварительно добавив элемент ary(i) к каждому из накопленных в result(j) и все это в копилочку result(i). Максимум таких добавлений будет N-1.
O(N^3)
Опровергайте
Перебираем 1...N элементы через i, внутри перебираем от 2...i через j и сравниваем ary(i) vs ary (j) если ary(i) >ary(j) то ary(i),ary(j) это уже increasing subsequence из двух элементов, добавляем в копилочку result(i) этот маленький сабсиквенс . Да еще и добавляем накопленные subsequnces которые уже лежает в result(j) предварительно добавив элемент ary(i) к каждому из накопленных в result(j) и все это в копилочку result(i). Максимум таких добавлений будет N-1.
O(N^3)
Опровергайте
Last edited by alex-IT on 02 Jun 2017 06:37, edited 1 time in total.
-
- Уже с Приветом
- Posts: 232
- Joined: 18 Nov 2014 22:55
- Location: SFBA
Re: facebook
Вот решение на Java
Code: Select all
public class IncreasingSubList {
static class Solution {
final List<Integer> input;
final Map<Integer, List<List<Integer>>> memo = new HashMap<>();
int runCnt = 0;
int computeCnt = 0;
public Solution(List<Integer> input) {
this.input = input;
}
public List<List<Integer>> run(Integer idx) {
runCnt += 1;
return memo.computeIfAbsent(idx, notUsed -> {
computeCnt += 1;
List<Integer> list = input.subList(idx, input.size());
List<List<Integer>> out = new ArrayList<>();
// empty list has zero increasing sublists
if (list.isEmpty()) {
out.add(new ArrayList<>());
} else
// single element list hast only one increasing sublist
if (list.size() == 1) {
out.add(list);
} else
// prepend head element to all other solutions
{
Integer head = list.get(0);
for (int i = 1; i <= list.size(); i++) {
if (i == list.size() || list.get(i) >= head) run(idx + i).forEach(sol -> {
List<Integer> l = new ArrayList<>();
l.add(head);
l.addAll(sol);
out.add(l);
});
}
}
return out;
});
}
Set<List<Integer>> solution() {
List<List<Integer>> solutions = new ArrayList<>();
for (int i = 0; i < input.size(); i++) {
solutions.addAll(run(i));
}
Set<List<Integer>> out = solutions.stream()
.filter(l -> l.size() >= 2)
.collect(Collectors.toSet());
System.out.println(
"n = " + input.size() +
" run = " + runCnt +
" compute = " + computeCnt);
return out;
}
}
public static void main(String[] args) {
for (int i = 1; i < 20; i ++) {
List<Integer> input = Stream.iterate(0, n -> n + 1)
.limit(i)
.collect(Collectors.toList());
new Solution(input).solution();
}
//Solution s = new Solution(Stream.of(4, 6, 7, 7).collect(Collectors.toList()));
//s.solution().forEach(System.out::println);
}
}
Code: Select all
n = 1 run = 1 compute = 1
n = 2 run = 4 compute = 3
n = 3 run = 8 compute = 4
n = 4 run = 13 compute = 5
n = 5 run = 19 compute = 6
n = 6 run = 26 compute = 7
n = 7 run = 34 compute = 8
n = 8 run = 43 compute = 9
n = 9 run = 53 compute = 10
n = 10 run = 64 compute = 11
n = 11 run = 76 compute = 12
n = 12 run = 89 compute = 13
n = 13 run = 103 compute = 14
n = 14 run = 131 compute = 16
n = 15 run = 161 compute = 18
n = 16 run = 193 compute = 20
n = 17 run = 227 compute = 22
n = 18 run = 263 compute = 24
n = 19 run = 301 compute = 26
и это кстати для худшего случая когда список идет от 1 то n то есть там точно 2^n-1 возрастающих подпоследовательностей
-
- Уже с Приветом
- Posts: 382
- Joined: 16 Jan 2013 21:35
Re: facebook
что-то сомнительно на счет O(n), хотя бы потому что количество сиквенсов может быть больше n, как их все можно составить и уложиться в n не понятно. Хоть раз но будет же итерация на каждый сиквенс, тот же последний элемент добавляем. Вот - уже больше N. Если не так, то поясните как это O(n) получается. Если конечно мы одно и то же имеем ввиду
-
- Уже с Приветом
- Posts: 4435
- Joined: 13 Feb 2002 10:01
- Location: Bay Area