Une sous-séquence est une séquence qui peut être dérivée d'une autre séquence en supprimant certains éléments sans modifier l'ordre des éléments restants. Une sous-séquence strictement croissante est une sous-séquence dans laquelle chaque élément est plus grand que le précédent.
La sous-séquence croissante la plus lourde d'une séquence est la sous-séquence strictement croissante qui a la plus grande somme d'éléments.
Implémentez un programme ou une fonction dans la langue de votre choix qui trouve la somme des éléments de la sous-séquence croissante la plus lourde d'une liste donnée d'entiers non négatifs.
Exemples:
[] -> 0 ([])
[3] -> 3 ([3])
[3, 2, 1] -> 3 ([3])
[3, 2, 5, 6] -> 14 ([3, 5, 6])
[9, 3, 2, 1, 4] -> 9 ([9])
[3, 4, 1, 4, 1] -> 7 ([3, 4])
[9, 1, 2, 3, 4] -> 10 ([1, 2, 3, 4])
[1, 2, 4, 3, 4] -> 10 ([1, 2, 3, 4])
[9, 1, 2, 3, 4, 5, 10] -> 25 ([1, 2, 3, 4, 5, 10])
[3, 2, 1, 2, 3] -> 6 ([1, 2, 3])
Notez que vous n'avez qu'à donner la somme des éléments de la sous-séquence croissante la plus lourde, pas la sous-séquence elle-même.
Le code asymptotiquement le plus rapide gagne, avec une taille de code plus petite en octets comme bris d'égalité.
Réponses:
javascript (ES6)
O(n log n)
253 caractèresceci utilise des arbres de fenwick (un arbre de fenwick maximum) pour trouver les maxima de certaines sous-séquences.
Fondamentalement, dans le tableau sous-jacent du type de données, chaque place est associée à un élément de la liste d'entrée, dans le même ordre. l'arbre fenwick est initialisé avec 0 partout.
du plus petit au plus grand, nous prenons un élément de la liste d'entrée et recherchons le maximum des éléments à gauche. ce sont les éléments qui peuvent se trouver avant celui-ci dans la sous-séquence, car ils sont à gauche dans la séquence d'entrée, et sont plus petits, car ils sont entrés dans l'arbre plus tôt.
donc le maximum que nous avons trouvé est la séquence la plus lourde qui puisse arriver à cet élément, et donc nous ajoutons à cela le poids de cet élément, et le mettons dans l'arbre.
ensuite, nous retournons simplement le maximum de l'arbre entier est le résultat.
testé sur firefox
la source
Python, O (n log n)
Je n'ai pas joué au golf parce que je compétitionne principalement sur le côté code le plus rapide. Ma solution est la
heaviest_subseq
fonction, et un harnais de test est également inclus en bas.Analyse de l'exécution:
Chaque élément a sa position d'insertion recherchée une fois, est insérée une fois et peut être supprimée une fois, en plus d'un nombre constant de recherches de valeurs par boucle. Puisque j'utilise le paquetage bisect intégré et le paquet blist , chacune de ces opérations est
O(log n)
. Ainsi, le temps d'exécution global estO(n log n)
.Le programme fonctionne en maintenant une liste triée des meilleures sous-séquences croissantes possibles, représentées comme un tuple de valeur de fin et de somme de séquence. Une sous-séquence croissante est dans cette liste s'il n'y a pas d'autres sous-séquences trouvées jusqu'à présent dont la valeur de fin est plus petite et la somme est au moins aussi grande. Celles-ci sont maintenues par ordre croissant de valeur finale, et nécessairement aussi par ordre croissant de somme. Cette propriété est conservée en vérifiant le successeur de chaque sous-séquence nouvellement trouvée, en la supprimant si sa somme n'est pas suffisamment grande et en la répétant jusqu'à ce qu'une sous-séquence avec une somme plus élevée soit atteinte ou que la fin de la liste soit atteinte.
la source
Python, O (n log n)
J'ai utilisé une transformation d'index et une structure de données astucieuse (arbre indexé binaire) pour banaliser le problème.
L'arbre indexé binaire peut effectuer deux opérations dans log (n): augmenter une valeur à l'index i et obtenir la valeur maximale dans [0, i). Nous initialisons chaque valeur de l'arbre à 0. Nous indexons l'arbre en utilisant le rang des éléments, pas leur index. Cela signifie que si nous indexons l'arbre à l'indice i, tous les éléments [0, i) sont les éléments plus petits que celui de rang i. Cela signifie que nous obtenons le maximum de [0, i), y ajoutons la valeur actuelle et la mettons à jour à i. Le seul problème est que cela inclura des valeurs inférieures à la valeur actuelle, mais qui viendront plus tard dans la séquence. Mais puisque nous nous déplaçons dans la séquence de gauche à droite et que nous avons initialisé toutes les valeurs de l'arborescence à 0, celles-ci auront une valeur de 0 et n'affecteront donc pas le maximum.
la source
Python 2 -
O(n^2)
- 114 octetsla source
C ++ -
O(n log n)
- 261 octetsDevrait être corrigé maintenant:
la source
auto S=set<pair<I,I>>();
est plus long que simplementset<pair<I,I>> S;
.#define I int
est plus long queusing I=int;
. Il n'est pas nécessaire d'assignern
quoi que ce soit, vous pouvez le remplacerauto n=*prev(S.lower_bound({w,-1}));I y=n.second
parI y=prev(S.lower_bound({w,-1}))->second+w;
.S
est très compliquée, vous pouvez simplement renoncer à l'insertion et à l'utilisationstd::set<std::pair<int,int>>S{{-1,0}};
.using namespace std;using I=int;I h(vector<I>l){I W=0;set<pair<I,I>>S{{-1,0}};for(I w:l){I y=prev(S.lower_bound({w,-1}))->second+w;W=max(W,y);S.insert({w,y});}return W;}
std::max
, utilisezW=y>W?y:W;
.Matlab, O ( n 2 n ), 90 octets
Exemples:
la source
Python, O (2 n ), 91 octets
C'est plus pour le plaisir que pour être compétitif. Une solution récursive mystérieuse:
la source
max(m,l[0])
étant donné quenot(l[0]<m)
c'est justel[0]
, sûrement?