Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Martin Mareš
prm2
Commits
f4fce2fd
Commit
f4fce2fd
authored
Apr 15, 2020
by
Martin Mareš
Browse files
Rekurze: Příklady
parent
97d5a67e
Changes
3
Hide whitespace changes
Inline
Side-by-side
07-rekurze/fib.py
0 → 100755
View file @
f4fce2fd
#!/usr/bin/python3
# Různé způsoby výpočtu Fibonacciho čísel
### Čistá rekurzivní verze, exponenciálně pomalá
def
fib
(
n
):
if
n
<
2
:
return
n
else
:
return
fib
(
n
-
1
)
+
fib
(
n
-
2
)
### Rekurze s pamětí na už spočítané výsledky, složitost O(n)
pamet
=
{
0
:
0
,
1
:
1
}
def
fib1
(
n
):
if
n
not
in
pamet
:
pamet
[
n
]
=
fib
(
n
-
1
)
+
fib
(
n
-
2
)
return
pamet
[
n
]
### Iterativní řešení
def
fib2
(
n
):
p
=
[
0
]
*
(
n
+
1
)
p
[
1
]
=
1
for
i
in
range
(
2
,
n
+
1
):
p
[
i
]
=
p
[
i
-
1
]
+
p
[
i
-
2
]
return
p
[
n
]
07-rekurze/gen-01.py
0 → 100755
View file @
f4fce2fd
#!/usr/bin/python3
# Generování všech posloupností 0 a 1 délky n
# Posloupnosti vypisujeme v lexikografickém pořadí
### První řešení: rekurzivní funkce, která vygeneruje všechny posloupnosti
### začínající zadaným prefixem. Parametr "p" je prefix, "n" říká, kolik ještě
### potřebujeme přidat prvků.
def
gen01
(
n
,
p
=
[]):
if
n
==
0
:
print
(
""
.
join
(
map
(
str
,
p
)))
else
:
gen01
(
n
-
1
,
p
+
[
0
])
gen01
(
n
-
1
,
p
+
[
1
])
### V předchozím řešení se v každém volání funkce kopíruje seznam až n prvků,
### takže i vnitřní vrcholy stromu rekurze mají linearní složitost. Toho se můžeme
### zbavit, když prefix místo v argumentu funkce předáváme v proměnné sdílené
### všemi instancemi funkce.
def
gen01b
(
n
):
def
g
(
n
):
if
n
==
0
:
print
(
""
.
join
(
map
(
str
,
p
)))
else
:
for
i
in
[
0
,
1
]:
p
.
append
(
i
)
g
(
n
-
1
)
p
.
pop
()
p
=
[]
g
(
n
)
### Funkci gen01 můžeme také upravit, aby místo vygenerování všech posloupností
### jenom spočítala, kolik jich je. Na prefixu nezáleží, tak ho nemusíme předávat.
### Díky tomu stačí jen jedno rekurzivní volání a výsledek znásobit dvěma,
### takže funkce má celkově složitost O(n).
def
count01
(
n
):
if
n
==
0
:
return
1
else
:
return
2
*
count01
(
n
-
1
)
07-rekurze/gen-k1.py
0 → 100755
View file @
f4fce2fd
#!/usr/bin/python3
# Generování všech posloupností 0 a 1 délky n, ve kterých je právě k jedniček
# Posloupnosti vypisujeme v lexikografickém pořadí
### Rekurzivní řešení: generujeme všechny posloupnosti délky s prefixem p,
### do kterých potřebujeme přidat n cifer, z nichž k jsou jedničky.
def
genk1
(
n
,
k
,
p
=
[]):
if
n
==
0
:
print
(
""
.
join
(
map
(
str
,
p
)))
else
:
# 0 můžeme přidat, pokud zbude dost pozic na to, aby se do nich
# vešly všechny zbývající 1.
if
k
<
n
:
genk1
(
n
-
1
,
k
,
p
+
[
0
])
# 1 můžeme přidat, pokud jsme ještě všechny nespotřebovali.
if
k
>
0
:
genk1
(
n
-
1
,
k
-
1
,
p
+
[
1
])
### A opět můžeme podobným způsobem počítat, kolik takových posloupností existuje:
def
countk1
(
n
,
k
):
if
n
==
0
:
return
1
else
:
result
=
0
if
k
<
n
:
result
+=
countk1
(
n
-
1
,
k
)
if
k
>
0
:
result
+=
countk1
(
n
-
1
,
k
-
1
)
return
result
### Počítačí funkce je ovšem pomalá: výsledek je kombinační číslo (poznáváte
### v naší funkci součtový vzorec z Pascalova trojúhelníku?) a nasčítáme ho
### postupně z jedniček. Přitom "n nad n/2" je řádově 2^n / √n. Stejně jako
### u příkladu s Fibonacciho čísly si můžeme mezivýsledky pamatovat a tím
### výpočet zrychlit na O(n^2). Mimochodem, uměli byste to rychleji, aniž
### byste potřebovali mezivýsledky řádově větší než výsledek?
mem
=
{}
# Slovník, kde klíče jsou tuply (n,k)
def
countk1b
(
n
,
k
):
if
(
n
,
k
)
not
in
mem
:
if
n
==
0
:
result
=
1
else
:
result
=
0
if
k
<
n
:
result
+=
countk1b
(
n
-
1
,
k
)
if
k
>
0
:
result
+=
countk1b
(
n
-
1
,
k
-
1
)
mem
[(
n
,
k
)]
=
result
return
mem
[(
n
,
k
)]
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment