Hackerrank – Popis problému
Celý popis zadania sa nacháza – Hackerrank.
Riešenie
Máme zadané pravidlá, ako sa mení zadané číslo cez Collatzovú postupnosť:
- ak je
n
párne, urobímn/2
- ak je
n
nepárne, urobím3n + 1
Zadanie problému obsahuje mnoho čísel, teda počítať každý samostatne nám zaberie množstvo času.
Moje riešenie spočíva v predvýpočítaní si hodnôt sekvencie, ako keby boli zadané čísla od 1
po 5 000 000
a prepoužití už vypočítaných Collatzových sekvencii pre už vypočítané čísla.
Začneme si určením počiatočných hodnôt.
Pre 1
je Collatz sekvencia veľká 1
jednotku.
Pre 2
použijem pravidlo a vydelím ho 2
lebo je párne. Sekvencia už bude dlhá 2
. Výsledok po delení je 1
. Pozriem sa do cache a zistím, že mám už dĺžku sekvencie pre 1
a to je 1
. Teda pre 2
je sekvencia dlhá 2
.
Pre 3
podobne: Nemám nič v cache, musím násobiť. Dostanem 10
(už mám dĺžku 1
). 10
nie je v cache, musím deliť. Dostanem 5
(už mám dĺžku 2
). 5
nie je v cache, musím násobiť, dostanem 16
(dĺžka sekvencie 3
). 16
nie je v cache vydelím 2
, dostanem 8
(dĺžka 4
). 8
nie je v cache, musím deliť, dostanem 4
(dĺžka 5
). 4
nie je v cache, delím 2
, dostanem 2
(dlžka 6
). 2
už je v cache. Jej dlžka je 2
. Teda pripočítam: 6 + 2
. Dĺžka sekvencie pre 3
bude 8
.
Pre 4
: Nie je v cache, delím 2
, dostanem 2
(dĺžka 1
). 2
už je v cache s hodnotou 2
. Pripočítam 1 + 2
. Dostanem dĺžku 3
.
atď…
Súčasne si pamätám, aká je najdlšia sekvencia od 1
po dané číslo.
- pre
1
: od1
po1
je najdlhšia sekvencia1
- pre
2
: od1
po2
je najdlhšia sekvencia2
(1
má sekvenciu dlhú1
) - pre
3
: od1
po3
je najdlhšia sekvencia8
- pre
4
: od1
po4
je najdlhšia sekvencia8
(1
má1
,2
má2
,3
má8
a4
má3
)
Vytvoril som riešenie v týchto programovacích jazykoch:
Všetky riešenia sú dostupné aj na mojom GitHub profile.
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
import java.util.Scanner; public class LongestCollatzSequence { private static final int CACHE_SIZE = 5_000_000; // stores collatz sequence for number at index private static int[] cache = new int[CACHE_SIZE + 1]; // stores number with max collatz sequence at index private static int[] collatzCache = new int[CACHE_SIZE + 1]; public static void main(String[] args) { precomputeCache(); Scanner scanner = new Scanner(System.in); int tests = Integer.parseInt(scanner.nextLine()); for (int i = 0; i < tests; i++) { int n = Integer.parseInt(scanner.nextLine()); System.out.println(collatzCache[n]); } scanner.close(); } private static void precomputeCache() { cache[0] = 1; cache[1] = 1; collatzCache[0] = 1; collatzCache[1] = 1; int maxSeq = 0; int maxNum = 0; for (int j = 2; j <= CACHE_SIZE; j++) { int collatzSeq = 0; long number = j; while (number > 1) { if(cache[j] > 0) { collatzSeq += cache[j]; break; } collatzSeq++; if(number % 2 == 0) { number >>= 1; } else { number = 3 * number + 1; } } cache[j] = collatzSeq; if(collatzSeq >= maxSeq) { maxSeq = collatzSeq; maxNum = j; } collatzCache[j] = maxNum; } } } |