New references etc.
This commit is contained in:
parent
702f5ac9c3
commit
c18f6a808f
|
@ -778,7 +778,7 @@ n! & = & n \cdot (n-1)! \\
|
|||
|
||||
\index{Fibonacci number}
|
||||
|
||||
The \key{Fibonacci numbers} arise in many situations.
|
||||
The \key{Fibonacci numbers}\footnote{Fibonacci (c. 1175--1250) was an Italian mathematician.} arise in many situations.
|
||||
They can be defined recursively as follows:
|
||||
\[
|
||||
\begin{array}{lcl}
|
||||
|
@ -790,7 +790,8 @@ f(n) & = & f(n-1)+f(n-2) \\
|
|||
The first Fibonacci numbers are
|
||||
\[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, \ldots\]
|
||||
There is also a closed-form formula
|
||||
for calculating Fibonacci numbers:
|
||||
for calculating Fibonacci numbers\footnote{This formula is sometimes called
|
||||
\index{Binet's formula} \key{Binet's formula}.}:
|
||||
\[f(n)=\frac{(1 + \sqrt{5})^n - (1-\sqrt{5})^n}{2^n \sqrt{5}}.\]
|
||||
|
||||
\subsubsection{Logarithms}
|
||||
|
|
|
@ -281,7 +281,11 @@ Still, there are many important problems for which
|
|||
no polynomial algorithm is known, i.e.,
|
||||
nobody knows how to solve them efficiently.
|
||||
\key{NP-hard} problems are an important set
|
||||
of problems for which no polynomial algorithm is known \cite{gar79}.
|
||||
of problems for which no polynomial algorithm
|
||||
is known\footnote{A classic book on this topic is
|
||||
M. R. Garey's and D. S. Johnson's
|
||||
\emph{Computers and Intractability: A Guide to the Theory
|
||||
of NP-Completeness} \cite{gar79}.}.
|
||||
|
||||
\section{Estimating efficiency}
|
||||
|
||||
|
@ -352,7 +356,7 @@ time and even in $O(n)$ time.
|
|||
|
||||
Given an array of $n$ integers $x_1,x_2,\ldots,x_n$,
|
||||
our task is to find the
|
||||
\key{maximum subarray sum}\footnote{Bentley's
|
||||
\key{maximum subarray sum}\footnote{J. Bentley's
|
||||
book \emph{Programming Pearls} \cite{ben86} made this problem popular.}, i.e.,
|
||||
the largest possible sum of numbers
|
||||
in a contiguous region in the array.
|
||||
|
@ -470,7 +474,9 @@ After this change, the time complexity is $O(n^2)$.
|
|||
\subsubsection{Algorithm 3}
|
||||
|
||||
Surprisingly, it is possible to solve the problem
|
||||
in $O(n)$ time, which means that we can remove
|
||||
in $O(n)$ time\footnote{In \cite{ben86}, this linear algorithm
|
||||
is attributed to J. B. Kadene, and the algorithm is sometimes
|
||||
called \index{Kadene's algorithm} \key{Kadene's algorithm}.}, which means that we can remove
|
||||
one more loop.
|
||||
The idea is to calculate for each array position
|
||||
the maximum sum of a subarray that ends at that position.
|
||||
|
|
|
@ -326,7 +326,8 @@ of the algorithm is at least $O(n^2)$.
|
|||
It is possible to sort an array efficiently
|
||||
in $O(n \log n)$ time using algorithms
|
||||
that are not limited to swapping consecutive elements.
|
||||
One such algorithm is \key{mergesort}
|
||||
One such algorithm is \key{mergesort}\footnote{According to \cite{knu98},
|
||||
mergesort was invented by J. von Neumann in 1945.}
|
||||
that is based on recursion.
|
||||
|
||||
Mergesort sorts a subarray \texttt{t}$[a,b]$ as follows:
|
||||
|
|
|
@ -196,7 +196,7 @@ for (auto x : s) {
|
|||
}
|
||||
\end{lstlisting}
|
||||
|
||||
An important property of sets
|
||||
An important property of sets is
|
||||
that all the elements are \emph{distinct}.
|
||||
Thus, the function \texttt{count} always returns
|
||||
either 0 (the element is not in the set)
|
||||
|
@ -723,7 +723,7 @@ $5 \cdot 10^6$ & $10{,}0$ s & $2{,}3$ s & $0{,}9$ s \\
|
|||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
Algorithm 1 and 2 are equal except that
|
||||
Algorithms 1 and 2 are equal except that
|
||||
they use different set structures.
|
||||
In this problem, this choice has an important effect on
|
||||
the running time, because algorithm 2
|
||||
|
|
|
@ -436,18 +436,18 @@ the $4 \times 4$ board are numbered as follows:
|
|||
\end{tikzpicture}
|
||||
\end{center}
|
||||
|
||||
Let $q(n)$ denote the number of ways
|
||||
to place $n$ queens to te $n \times n$ chessboard.
|
||||
The above backtracking
|
||||
algorithm tells us that
|
||||
there are 92 ways to place 8
|
||||
queens to the $8 \times 8$ chessboard.
|
||||
algorithm tells us that $q(n)=92$.
|
||||
When $n$ increases, the search quickly becomes slow,
|
||||
because the number of the solutions increases
|
||||
exponentially.
|
||||
For example, calculating the ways to
|
||||
place 16 queens to the $16 \times 16$
|
||||
chessboard already takes about a minute
|
||||
on a modern computer
|
||||
(there are 14772512 solutions).
|
||||
For example, calculating $q(16)=14772512$
|
||||
using the above algorithm already takes about a minute
|
||||
on a modern computer\footnote{There is no known way to efficiently
|
||||
calculate larger values of $q(n)$. The current record is
|
||||
$q(27)=234907967154122528$, calculated in 2016 \cite{q27}.}.
|
||||
|
||||
\section{Pruning the search}
|
||||
|
||||
|
@ -716,7 +716,8 @@ check if the sum of any of the subsets is $x$.
|
|||
The running time of such a solution is $O(2^n)$,
|
||||
because there are $2^n$ subsets.
|
||||
However, using the meet in the middle technique,
|
||||
we can achieve a more efficient $O(2^{n/2})$ time solution.
|
||||
we can achieve a more efficient $O(2^{n/2})$ time solution\footnote{This
|
||||
technique was introduced in 1974 by E. Horowitz and S. Sahni \cite{hor74}.}.
|
||||
Note that $O(2^n)$ and $O(2^{n/2})$ are different
|
||||
complexities because $2^{n/2}$ equals $\sqrt{2^n}$.
|
||||
|
||||
|
|
114
chapter06.tex
114
chapter06.tex
|
@ -530,7 +530,9 @@ the string \texttt{AB} or the string \texttt{C}.
|
|||
|
||||
\subsubsection{Huffman coding}
|
||||
|
||||
\key{Huffman coding} \cite{huf52} is a greedy algorithm
|
||||
\key{Huffman coding}\footnote{D. A. Huffman discovered this method
|
||||
when solving a university course assignment
|
||||
and published the algorithm in 1952 \cite{huf52}.} is a greedy algorithm
|
||||
that constructs an optimal code for
|
||||
compressing a given string.
|
||||
The algorithm builds a binary tree
|
||||
|
@ -672,113 +674,3 @@ character & codeword \\
|
|||
\texttt{D} & 111 \\
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
% \subsubsection{Miksi algoritmi toimii?}
|
||||
%
|
||||
% Huffmanin koodaus on ahne algoritmi, koska se
|
||||
% yhdistää aina kaksi solmua, joiden painot ovat
|
||||
% pienimmät.
|
||||
% Miksi on varmaa, että tämä menetelmä tuottaa
|
||||
% aina optimaalisen koodin?
|
||||
%
|
||||
% Merkitään $c(x)$ merkin $x$ esiintymiskertojen
|
||||
% määrää merkkijonossa sekä $s(x)$
|
||||
% merkkiä $x$ vastaavan koodisanan pituutta.
|
||||
% Näitä merkintöjä käyttäen merkkijonon
|
||||
% bittiesityksen pituus on
|
||||
% \[\sum_x c(x) \cdot s(x),\]
|
||||
% missä summa käy läpi kaikki merkkijonon merkit.
|
||||
% Esimerkiksi äskeisessä esimerkissä
|
||||
% bittiesityksen pituus on
|
||||
% \[5 \cdot 1 + 1 \cdot 3 + 2 \cdot 2 + 1 \cdot 3 = 15.\]
|
||||
% Hyödyllinen havainto on, että $s(x)$ on yhtä suuri kuin
|
||||
% merkkiä $x$ vastaavan solmun \emph{syvyys} puussa
|
||||
% eli matka puun huipulta solmuun.
|
||||
%
|
||||
% Perustellaan ensin, miksi optimaalista koodia vastaa
|
||||
% aina binääripuu, jossa jokaisesta solmusta lähtee
|
||||
% alaspäin joko kaksi haaraa tai ei yhtään haaraa.
|
||||
% Tehdään vastaoletus, että jostain solmusta lähtisi
|
||||
% alaspäin vain yksi haara.
|
||||
% Esimerkiksi seuraavassa puussa tällainen tilanne on solmussa $a$:
|
||||
% \begin{center}
|
||||
% \begin{tikzpicture}[scale=0.9]
|
||||
% \node[draw, circle, minimum size=20pt] (3) at (3,1) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (2) at (4,0) {$b$};
|
||||
% \node[draw, circle, minimum size=20pt] (5) at (5,1) {$a$};
|
||||
% \node[draw, circle, minimum size=20pt] (6) at (4,2) {\phantom{$a$}};
|
||||
%
|
||||
% \path[draw,thick,-] (2) -- (5);
|
||||
% \path[draw,thick,-] (3) -- (6);
|
||||
% \path[draw,thick,-] (5) -- (6);
|
||||
% \end{tikzpicture}
|
||||
% \end{center}
|
||||
% Tällainen solmu $a$ on kuitenkin aina turha, koska se
|
||||
% tuo vain yhden bitin lisää polkuihin, jotka kulkevat
|
||||
% solmun kautta, eikä sen avulla voi erottaa kahta
|
||||
% koodisanaa toisistaan. Niinpä kyseisen solmun voi poistaa
|
||||
% puusta, minkä seurauksena syntyy parempi koodi,
|
||||
% eli optimaalista koodia vastaavassa puussa ei voi olla
|
||||
% solmua, josta lähtee vain yksi haara.
|
||||
%
|
||||
% Perustellaan sitten, miksi on joka vaiheessa optimaalista
|
||||
% yhdistää kaksi solmua, joiden painot ovat pienimmät.
|
||||
% Tehdään vastaoletus, että solmun $a$ paino on pienin,
|
||||
% mutta sitä ei saisi yhdistää aluksi toiseen solmuun,
|
||||
% vaan sen sijasta tulisi yhdistää solmu $b$
|
||||
% ja jokin toinen solmu:
|
||||
% \begin{center}
|
||||
% \begin{tikzpicture}[scale=0.9]
|
||||
% \node[draw, circle, minimum size=20pt] (1) at (0,0) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (2) at (-2,-1) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (3) at (2,-1) {$a$};
|
||||
% \node[draw, circle, minimum size=20pt] (4) at (-3,-2) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (5) at (-1,-2) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (8) at (-2,-3) {$b$};
|
||||
% \node[draw, circle, minimum size=20pt] (9) at (0,-3) {\phantom{$a$}};
|
||||
%
|
||||
% \path[draw,thick,-] (1) -- (2);
|
||||
% \path[draw,thick,-] (1) -- (3);
|
||||
% \path[draw,thick,-] (2) -- (4);
|
||||
% \path[draw,thick,-] (2) -- (5);
|
||||
% \path[draw,thick,-] (5) -- (8);
|
||||
% \path[draw,thick,-] (5) -- (9);
|
||||
% \end{tikzpicture}
|
||||
% \end{center}
|
||||
% Solmuille $a$ ja $b$ pätee
|
||||
% $c(a) \le c(b)$ ja $s(a) \le s(b)$.
|
||||
% Solmut aiheuttavat bittiesityksen pituuteen lisäyksen
|
||||
% \[c(a) \cdot s(a) + c(b) \cdot s(b).\]
|
||||
% Tarkastellaan sitten toista tilannetta,
|
||||
% joka on muuten samanlainen kuin ennen,
|
||||
% mutta solmut $a$ ja $b$ on vaihdettu keskenään:
|
||||
% \begin{center}
|
||||
% \begin{tikzpicture}[scale=0.9]
|
||||
% \node[draw, circle, minimum size=20pt] (1) at (0,0) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (2) at (-2,-1) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (3) at (2,-1) {$b$};
|
||||
% \node[draw, circle, minimum size=20pt] (4) at (-3,-2) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (5) at (-1,-2) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (8) at (-2,-3) {$a$};
|
||||
% \node[draw, circle, minimum size=20pt] (9) at (0,-3) {\phantom{$a$}};
|
||||
%
|
||||
% \path[draw,thick,-] (1) -- (2);
|
||||
% \path[draw,thick,-] (1) -- (3);
|
||||
% \path[draw,thick,-] (2) -- (4);
|
||||
% \path[draw,thick,-] (2) -- (5);
|
||||
% \path[draw,thick,-] (5) -- (8);
|
||||
% \path[draw,thick,-] (5) -- (9);
|
||||
% \end{tikzpicture}
|
||||
% \end{center}
|
||||
% Osoittautuu, että tätä puuta vastaava koodi on
|
||||
% \emph{yhtä hyvä tai parempi} kuin alkuperäinen koodi, joten vastaoletus
|
||||
% on väärin ja Huffmanin koodaus
|
||||
% toimiikin oikein, jos se yhdistää aluksi solmun $a$
|
||||
% jonkin solmun kanssa.
|
||||
% Tämän perustelee seuraava epäyhtälöketju:
|
||||
% \[\begin{array}{rcl}
|
||||
% c(b) & \ge & c(a) \\
|
||||
% c(b)\cdot(s(b)-s(a)) & \ge & c(a)\cdot (s(b)-s(a)) \\
|
||||
% c(b)\cdot s(b)-c(b)\cdot s(a) & \ge & c(a)\cdot s(b)-c(a)\cdot s(a) \\
|
||||
% c(a)\cdot s(a)+c(b)\cdot s(b) & \ge & c(a)\cdot s(b)+c(b)\cdot s(a) \\
|
||||
% \end{array}\]
|
|
@ -708,7 +708,8 @@ depends on the values of the objects.
|
|||
\index{edit distance}
|
||||
\index{Levenshtein distance}
|
||||
|
||||
The \key{edit distance} or \key{Levenshtein distance}
|
||||
The \key{edit distance} or \key{Levenshtein distance}\footnote{The distance
|
||||
is named after V. I. Levenshtein who discussed it in connection with binary codes \cite{lev66}.}
|
||||
is the minimum number of editing operations
|
||||
needed to transform a string
|
||||
into another string.
|
||||
|
|
|
@ -440,7 +440,8 @@ we can conclude that $\textrm{rmq}(2,7)=1$.
|
|||
\index{binary indexed tree}
|
||||
\index{Fenwick tree}
|
||||
|
||||
A \key{binary indexed tree} or \key{Fenwick tree} \cite{fen94}
|
||||
A \key{binary indexed tree} or \key{Fenwick tree}\footnote{The
|
||||
binary indexed tree structure was presented by P. M. Fenwick in 1994 \cite{fen94}.}
|
||||
can be seen as a dynamic version of a prefix sum array.
|
||||
This data structure supports two $O(\log n)$ time operations:
|
||||
calculating the sum of elements in a range
|
||||
|
@ -738,7 +739,9 @@ takes $O(1)$ time using bit operations.
|
|||
|
||||
\index{segment tree}
|
||||
|
||||
A \key{segment tree} is a data structure
|
||||
A \key{segment tree}\footnote{The origin of this structure is unknown.
|
||||
The bottom-up-implementation in this chapter corresponds to
|
||||
the implementation in \cite{sta06}.} is a data structure
|
||||
that supports two operations:
|
||||
processing a range query and
|
||||
modifying an element in the array.
|
||||
|
|
24
list.tex
24
list.tex
|
@ -107,7 +107,13 @@
|
|||
Computer Science and Computational Biology},
|
||||
Cambridge University Press, 1997.
|
||||
|
||||
\bibitem{hor74}
|
||||
E. Horowitz and S. Sahni.
|
||||
Computing partitions with applications to the knapsack problem.
|
||||
\emph{Journal of the ACM}, 21(2):277--292, 1974.
|
||||
|
||||
\bibitem{huf52}
|
||||
D. A. Huffman.
|
||||
A method for the construction of minimum-redundancy codes.
|
||||
\emph{Proceedings of the IRE}, 40(9):1098--1101, 1952.
|
||||
|
||||
|
@ -125,11 +131,20 @@
|
|||
The statistics of dimers on a lattice: I. The number of dimer arrangements on a quadratic lattice.
|
||||
\emph{Physica}, 27(12):1209--1225, 1961.
|
||||
|
||||
\bibitem{knu98}
|
||||
D. E. Knuth.
|
||||
\emph{The Art of Computer Programming. Volume 3: Sorting and Searching}, Addison–Wesley, 1998 (2nd edition).
|
||||
|
||||
\bibitem{kru56}
|
||||
J. B. Kruskal.
|
||||
On the shortest spanning subtree of a graph and the traveling salesman problem.
|
||||
\emph{Proceedings of the American Mathematical Society}, 7(1):48--50, 1956.
|
||||
|
||||
\bibitem{lev66}
|
||||
V. I. Levenshtein.
|
||||
Binary codes capable of correcting deletions, insertions, and reversals.
|
||||
\emph{Soviet physics doklady}, 10(8):707--710, 1966.
|
||||
|
||||
\bibitem{mai84}
|
||||
M. G. Main and R. J. Lorentz.
|
||||
An $O(n \log n)$ algorithm for finding all repetitions in a string.
|
||||
|
@ -145,11 +160,20 @@
|
|||
Shortest connection networks and some generalizations.
|
||||
\emph{Bell System Technical Journal}, 36(6):1389--1401, 1957.
|
||||
|
||||
\bibitem{q27}
|
||||
27-Queens Puzzle: Massively Parallel Enumeration and Solution Counting.
|
||||
\url{https://github.com/preusser/q27}
|
||||
|
||||
\bibitem{sha81}
|
||||
M. Sharir.
|
||||
A strong-connectivity algorithm and its applications in data flow analysis.
|
||||
\emph{Computers \& Mathematics with Applications}, 7(1):67--72, 1981.
|
||||
|
||||
\bibitem{sta06}
|
||||
P. Stańczyk.
|
||||
\emph{Algorytmika praktyczna w konkursach Informatycznych},
|
||||
MSc thesis, University of Warsaw, 2006.
|
||||
|
||||
\bibitem{str69}
|
||||
V. Strassen.
|
||||
Gaussian elimination is not optimal.
|
||||
|
|
Loading…
Reference in New Issue