Some fixes

This commit is contained in:
Antti H S Laaksonen 2017-02-27 21:29:32 +02:00
parent 074134ac54
commit 98fda0b259
8 changed files with 54 additions and 48 deletions

View File

@ -849,7 +849,7 @@ $\lfloor \log_2(123)+1 \rfloor = 7$.
\subsubsection{IOI} \subsubsection{IOI}
The International Olympiad in Informatics (IOI) \cite{ioi} The International Olympiad in Informatics (IOI)
is an annual programming contest for is an annual programming contest for
secondary school students. secondary school students.
Each country is allowed to send a team of Each country is allowed to send a team of
@ -951,7 +951,7 @@ whereas the last book contains advanced material.
Of course, general algorithm books are also suitable for Of course, general algorithm books are also suitable for
competitive programmers. competitive programmers.
Some good books are: Some popular books are:
\begin{itemize} \begin{itemize}
\item T. H. Cormen, C. E. Leiserson, R. L. Rivest and C. Stein: \item T. H. Cormen, C. E. Leiserson, R. L. Rivest and C. Stein:

View File

@ -313,7 +313,7 @@ assuming a time limit of one second.
\begin{center} \begin{center}
\begin{tabular}{ll} \begin{tabular}{ll}
typical input size & required time complexity \\ input size & required time complexity \\
\hline \hline
$n \le 10$ & $O(n!)$ \\ $n \le 10$ & $O(n!)$ \\
$n \le 20$ & $O(2^n)$ \\ $n \le 20$ & $O(2^n)$ \\

View File

@ -664,7 +664,7 @@ string s = "monkey";
sort(s.begin(), s.end()); sort(s.begin(), s.end());
\end{lstlisting} \end{lstlisting}
Sorting a string means that the characters Sorting a string means that the characters
in the string are sorted. of the string are sorted.
For example, the string ''monkey'' becomes ''ekmnoy''. For example, the string ''monkey'' becomes ''ekmnoy''.
\subsubsection{Comparison operators} \subsubsection{Comparison operators}
@ -775,7 +775,7 @@ an element $x$ in the array \texttt{t}:
\begin{lstlisting} \begin{lstlisting}
for (int i = 1; i <= n; i++) { for (int i = 1; i <= n; i++) {
if (t[i] == x) // x found at index i if (t[i] == x) {} // x found at index i
} }
\end{lstlisting} \end{lstlisting}
@ -816,7 +816,7 @@ The above idea can be implemented as follows:
int a = 1, b = n; int a = 1, b = n;
while (a <= b) { while (a <= b) {
int k = (a+b)/2; int k = (a+b)/2;
if (t[k] == x) // x found at index k if (t[k] == x) {} // x found at index k
if (t[k] > x) b = k-1; if (t[k] > x) b = k-1;
else a = k+1; else a = k+1;
} }
@ -850,7 +850,7 @@ int k = 1;
for (int b = n/2; b >= 1; b /= 2) { for (int b = n/2; b >= 1; b /= 2) {
while (k+b <= n && t[k+b] <= x) k += b; while (k+b <= n && t[k+b] <= x) k += b;
} }
if (t[k] == x) // x was found at index k if (t[k] == x) {} // x was found at index k
\end{lstlisting} \end{lstlisting}
The variables $k$ and $b$ contain the position The variables $k$ and $b$ contain the position
@ -893,7 +893,7 @@ $\texttt{ok}(x)$ & \texttt{false} & \texttt{false}
\end{center} \end{center}
\noindent \noindent
Now, the value $k$ can be found using binary search: Now, the value of $k$ can be found using binary search:
\begin{lstlisting} \begin{lstlisting}
int x = -1; int x = -1;
@ -923,7 +923,7 @@ the total time complexity is $O(n \log z)$.
Binary search can also be used to find Binary search can also be used to find
the maximum value for a function that is the maximum value for a function that is
first increasing and then decreasing. first increasing and then decreasing.
Our task is to find a value $k$ such that Our task is to find a position $k$ such that
\begin{itemize} \begin{itemize}
\item \item

View File

@ -141,7 +141,7 @@ cout << c << "\n"; // tiva
A \key{set} is a data structure that A \key{set} is a data structure that
maintains a collection of elements. maintains a collection of elements.
The basic operations in a set are element The basic operations of sets are element
insertion, search and removal. insertion, search and removal.
C++ contains two set implementations: C++ contains two set implementations:
@ -149,7 +149,7 @@ C++ contains two set implementations:
The structure \texttt{set} is based on a balanced The structure \texttt{set} is based on a balanced
binary tree and the time complexity of its binary tree and the time complexity of its
operations is $O(\log n)$. operations is $O(\log n)$.
The structure \texttt{unordered\_set} uses a hash table, The structure \texttt{unordered\_set} uses hashing,
and the time complexity of its operations is $O(1)$ on average. and the time complexity of its operations is $O(1)$ on average.
The choice which set implementation to use The choice which set implementation to use
@ -262,7 +262,7 @@ the structure
binary tree and accessing elements binary tree and accessing elements
takes $O(\log n)$ time, takes $O(\log n)$ time,
while the structure while the structure
\texttt{unordered\_map} uses a hash map \texttt{unordered\_map} uses hashing
and accessing elements takes $O(1)$ time on average. and accessing elements takes $O(1)$ time on average.
The following code creates a map The following code creates a map
@ -383,7 +383,7 @@ A shorter way to write the code is as follows:
auto it = s.begin(); auto it = s.begin();
\end{lstlisting} \end{lstlisting}
The element to which an iterator points The element to which an iterator points
can be accessed through the \texttt{*} symbol. can be accessed using the \texttt{*} symbol.
For example, the following code prints For example, the following code prints
the first element in the set: the first element in the set:
@ -530,9 +530,9 @@ cout << (a^b) << "\n"; // 1001101110
A \texttt{deque} is a dynamic array A \texttt{deque} is a dynamic array
whose size can be changed at both ends of the array. whose size can be changed at both ends of the array.
Like a vector, a deque contains the functions Like a vector, a deque provides the functions
\texttt{push\_back} and \texttt{pop\_back}, but \texttt{push\_back} and \texttt{pop\_back}, but
it also contains the functions it also provides the functions
\texttt{push\_front} and \texttt{pop\_front} \texttt{push\_front} and \texttt{pop\_front}
that are not available in a vector. that are not available in a vector.
@ -610,7 +610,7 @@ either the minimum or maximum element.
The time complexity is $O(\log n)$ The time complexity is $O(\log n)$
for insertion and removal and $O(1)$ for retrieval. for insertion and removal and $O(1)$ for retrieval.
While a set structure efficiently supports While an ordered set efficiently supports
all the operations of a priority queue, all the operations of a priority queue,
the benefit in using a priority queue is the benefit in using a priority queue is
that it has smaller constant factors. that it has smaller constant factors.

View File

@ -22,6 +22,9 @@ dynamic programming, may be needed.
We first consider the problem of generating We first consider the problem of generating
all subsets of a set of $n$ elements. all subsets of a set of $n$ elements.
For example, the subsets of $\{1,2,3\}$ are
$\emptyset$, $\{1\}$, $\{2\}$, $\{3\}$, $\{1,2\}$,
$\{1,3\}$, $\{2,3\}$ and $\{1,2,3\}$.
There are two common methods for this: There are two common methods for this:
we can either implement a recursive search we can either implement a recursive search
or use bit operations of integers. or use bit operations of integers.
@ -33,7 +36,7 @@ of a set is to use recursion.
The following function The following function
generates the subsets of the set generates the subsets of the set
$\{1,2,\ldots,n\}$. $\{1,2,\ldots,n\}$.
The function maintains a vector The function maintains a vector \texttt{v}
that will contain the elements of each subset. that will contain the elements of each subset.
The search begins when the function is called The search begins when the function is called
with parameter 1. with parameter 1.
@ -164,6 +167,9 @@ for (int b = 0; b < (1<<n); b++) {
Next we will consider the problem of generating Next we will consider the problem of generating
all permutations of a set of $n$ elements. all permutations of a set of $n$ elements.
For example, the permutations of $\{1,2,3\}$ are
$(1,2,3)$, $(1,3,2)$, $(2,1,3)$, $(2,3,1)$,
$(3,1,2)$ and $(3,2,1)$.
Again, there are two approaches: Again, there are two approaches:
we can either use recursion or go through the we can either use recursion or go through the
permutations iteratively. permutations iteratively.
@ -174,7 +180,7 @@ Like subsets, permutations can be generated
using recursion. using recursion.
The following function goes The following function goes
through the permutations of the set $\{1,2,\ldots,n\}$. through the permutations of the set $\{1,2,\ldots,n\}$.
The function builds a vector that contains The function builds a vector \texttt{v} that contains
the elements in the permutation, the elements in the permutation,
and the search begins when the function is and the search begins when the function is
called without parameters. called without parameters.
@ -351,9 +357,9 @@ void search(int y) {
\end{lstlisting} \end{lstlisting}
\end{samepage} \end{samepage}
The search begins by calling \texttt{search(0)}. The search begins by calling \texttt{search(0)}.
The size of the board is in the variable $n$, The size of the board is $n$,
and the code calculates the number of solutions and the code calculates the number of solutions
to the variable $c$. to $c$.
The code assumes that the rows and columns The code assumes that the rows and columns
of the board are numbered from 0. of the board are numbered from 0.
@ -437,9 +443,9 @@ the $4 \times 4$ board are numbered as follows:
\end{center} \end{center}
Let $q(n)$ denote the number of ways Let $q(n)$ denote the number of ways
to place $n$ queens to te $n \times n$ chessboard. to place $n$ queens to an $n \times n$ chessboard.
The above backtracking The above backtracking
algorithm tells us that $q(n)=92$. algorithm tells us that, for example, $q(8)=92$.
When $n$ increases, the search quickly becomes slow, When $n$ increases, the search quickly becomes slow,
because the number of the solutions increases because the number of the solutions increases
exponentially. exponentially.
@ -460,7 +466,7 @@ to a complete solution.
Such optimizations can have a tremendous Such optimizations can have a tremendous
effect on the efficiency of the search. effect on the efficiency of the search.
Let us consider a problem Let us consider the problem
of calculating the number of paths of calculating the number of paths
in an $n \times n$ grid from the upper-left corner in an $n \times n$ grid from the upper-left corner
to the lower-right corner so that each square to the lower-right corner so that each square
@ -662,7 +668,7 @@ recursive calls: 69 millions
\end{itemize} \end{itemize}
~\\ ~\\
Now it is a good moment to stop optimizing Now is a good moment to stop optimizing
the algorithm and see what we have achieved. the algorithm and see what we have achieved.
The running time of the original algorithm The running time of the original algorithm
was 483 seconds, was 483 seconds,
@ -710,7 +716,7 @@ we can choose the numbers $[2,4,9]$ to get $2+4+9=15$.
However, if $x=10$, However, if $x=10$,
it is not possible to form the sum. it is not possible to form the sum.
A standard solution for the problem is to An easy solution to the problem is to
go through all subsets of the elements and go through all subsets of the elements and
check if the sum of any of the subsets is $x$. check if the sum of any of the subsets is $x$.
The running time of such a solution is $O(2^n)$, The running time of such a solution is $O(2^n)$,
@ -731,7 +737,7 @@ Correspondingly, the second search creates
a list $S_B$ from $B$. a list $S_B$ from $B$.
After this, it suffices to check if it is possible After this, it suffices to check if it is possible
to choose one element from $S_A$ and another to choose one element from $S_A$ and another
element from $S_B$ so that their sum is $x$. element from $S_B$ such that their sum is $x$.
This is possible exactly when there is a way to This is possible exactly when there is a way to
form the sum $x$ using the numbers in the original list. form the sum $x$ using the numbers in the original list.
@ -745,7 +751,7 @@ and the number $9$ from $S_B$,
which corresponds to the solution $[2,4,9]$. which corresponds to the solution $[2,4,9]$.
The time complexity of the algorithm is $O(2^{n/2})$, The time complexity of the algorithm is $O(2^{n/2})$,
because both lists $A$ and $B$ contain $n/2$ numbers because both lists $A$ and $B$ contain about $n/2$ numbers
and it takes $O(2^{n/2})$ time to calculate the sums of and it takes $O(2^{n/2})$ time to calculate the sums of
their subsets to lists $S_A$ and $S_B$. their subsets to lists $S_A$ and $S_B$.
After this, it is possible to check in After this, it is possible to check in

View File

@ -251,7 +251,7 @@ This algorithm selects the following events:
It turns out that this algorithm It turns out that this algorithm
\emph{always} produces an optimal solution. \emph{always} produces an optimal solution.
First, it is always an optimal choice The reason for this is that it is always an optimal choice
to first select an event that ends to first select an event that ends
as early as possible. as early as possible.
After this, it is an optimal choice After this, it is an optimal choice
@ -452,7 +452,7 @@ the average of the numbers $a_1,a_2,\ldots,a_n$.
\index{codeword} \index{codeword}
A \key{binary code} assigns for each character A \key{binary code} assigns for each character
of a given string a \key{codeword} that consists of bits. of a string a \key{codeword} that consists of bits.
We can \emph{compress} the string using the binary code We can \emph{compress} the string using the binary code
by replacing each character by the by replacing each character by the
corresponding codeword. corresponding codeword.

View File

@ -73,11 +73,11 @@ subproblems.
In the coin problem, a natural recursive In the coin problem, a natural recursive
problem is as follows: problem is as follows:
what is the smallest number of coins what is the smallest number of coins
required for constructing sum $x$? required for constructing a sum $x$?
Let $f(x)$ be a function that gives the answer Let $f(x)$ be a function that gives the answer
to the problem, i.e., $f(x)$ is the smallest to the problem, i.e., $f(x)$ is the smallest
number of coins required for constructing sum $x$. number of coins required for constructing a sum $x$.
The values of the function depend on the The values of the function depend on the
values of the coins. values of the coins.
For example, if the coin values are $\{1,3,4\}$, For example, if the coin values are $\{1,3,4\}$,
@ -142,8 +142,8 @@ we can directly implement a solution in C++:
\begin{lstlisting} \begin{lstlisting}
int f(int x) { int f(int x) {
if (x == 0) return 0;
if (x < 0) return 1e9; if (x < 0) return 1e9;
if (x == 0) return 0;
int u = 1e9; int u = 1e9;
for (int i = 1; i <= k; i++) { for (int i = 1; i <= k; i++) {
u = min(u, f(x-c[i])+1); u = min(u, f(x-c[i])+1);
@ -154,7 +154,7 @@ int f(int x) {
The code assumes that the available coins are The code assumes that the available coins are
$\texttt{c}[1], \texttt{c}[2], \ldots, \texttt{c}[k]$, $\texttt{c}[1], \texttt{c}[2], \ldots, \texttt{c}[k]$,
and the value $10^9$ denotes infinity. and $10^9$ denotes infinity.
This function works but it is not efficient yet, This function works but it is not efficient yet,
because it goes through a large number because it goes through a large number
of ways to construct the sum. of ways to construct the sum.
@ -191,8 +191,8 @@ implemented as follows:
\begin{lstlisting} \begin{lstlisting}
int f(int x) { int f(int x) {
if (x == 0) return 0;
if (x < 0) return 1e9; if (x < 0) return 1e9;
if (x == 0) return 0;
if (d[x]) return d[x]; if (d[x]) return d[x];
int u = 1e9; int u = 1e9;
for (int i = 1; i <= k; i++) { for (int i = 1; i <= k; i++) {
@ -204,9 +204,9 @@ int f(int x) {
\end{lstlisting} \end{lstlisting}
The function handles the base cases The function handles the base cases
$x=0$ and $x<0$ as previously. $x<0$ and $x=0$ as previously.
Then the function checks if Then the function checks if
$f(x)$ has already been calculated $f(x)$ has already been stored
in $\texttt{d}[x]$. in $\texttt{d}[x]$.
If the value of $f(x)$ is found in the array, If the value of $f(x)$ is found in the array,
the function directly returns it. the function directly returns it.
@ -260,7 +260,7 @@ should show how to select the coins that produce
the sum $x$ using as few coins as possible. the sum $x$ using as few coins as possible.
We can construct the solution by adding another We can construct the solution by adding another
array to the code. The array indicates for array to the code. The new array indicates for
each sum of money the first coin that should be each sum of money the first coin that should be
chosen in an optimal solution. chosen in an optimal solution.
In the following code, the array \texttt{e} In the following code, the array \texttt{e}
@ -320,7 +320,7 @@ but now we will calculate sums of numbers of solutions.
To solve the problem, we can define a function $f(x)$ To solve the problem, we can define a function $f(x)$
that gives the number of ways to construct that gives the number of ways to construct
the sum $x$ using the coins. a sum $x$ using the coins.
For example, $f(5)=6$ when the coins are $\{1,3,4\}$. For example, $f(5)=6$ when the coins are $\{1,3,4\}$.
The value of $f(x)$ can be calculated recursively The value of $f(x)$ can be calculated recursively
using the formula using the formula
@ -709,7 +709,7 @@ depends on the values of the objects.
\index{Levenshtein distance} \index{Levenshtein distance}
The \key{edit distance} or \key{Levenshtein distance}\footnote{The 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 named after V. I. Levenshtein who studied it in connection with binary codes \cite{lev66}.}
is the minimum number of editing operations is the minimum number of editing operations
needed to transform a string needed to transform a string
into another string. into another string.
@ -942,7 +942,7 @@ $\sqsubset \sqsupset \sqsubset \sqsupset \sqsubset \sqsupset \sqcup$
Let $f(k,x)$ denote the number of ways to Let $f(k,x)$ denote the number of ways to
construct a solution for rows $1 \ldots k$ construct a solution for rows $1 \ldots k$
in the grid so that string $x$ corresponds to row $k$. in the grid so that string $x$ corresponds to row $k$.
It is possible to use dynamic programing here, It is possible to use dynamic programming here,
because the state of a row is constrained because the state of a row is constrained
only by the state of the previous row. only by the state of the previous row.
@ -971,7 +971,7 @@ so that the shorter side has length $m$,
because the factor $4^{2m}$ dominates the time complexity. because the factor $4^{2m}$ dominates the time complexity.
It is possible to make the solution more efficient It is possible to make the solution more efficient
by using a better representation for the rows. by using a more compact representation for the rows.
It turns out that it is sufficient to know which It turns out that it is sufficient to know which
columns of the previous row contain the upper square columns of the previous row contain the upper square
of a vertical tile. of a vertical tile.

View File

@ -6,7 +6,7 @@ The time complexity of an algorithm
is often easy to analyze is often easy to analyze
just by examining the structure just by examining the structure
of the algorithm: of the algorithm:
what loops does the algorithm contain, what loops does the algorithm contain
and how many times the loops are performed. and how many times the loops are performed.
However, sometimes a straightforward analysis However, sometimes a straightforward analysis
does not give a true picture of the efficiency of the algorithm. does not give a true picture of the efficiency of the algorithm.
@ -95,8 +95,8 @@ contains a subarray whose sum is 8:
It turns out that the problem can be solved in It turns out that the problem can be solved in
$O(n)$ time by using the two pointers method. $O(n)$ time by using the two pointers method.
The idea is that The idea is to use
the left and right pointer indicate the left and right pointers that indicate the
first and last element of an subarray. first and last element of an subarray.
On each turn, the left pointer moves one step On each turn, the left pointer moves one step
forward, and the right pointer moves forward forward, and the right pointer moves forward
@ -235,7 +235,7 @@ where the sum of the elements is $x$.
The time complexity of the algorithm depends on The time complexity of the algorithm depends on
the number of steps the right pointer moves. the number of steps the right pointer moves.
There is no upper bound how many steps the There is no useful upper bound how many steps the
pointer can move on a single turn. pointer can move on a single turn.
However, the pointer moves \emph{a total of} However, the pointer moves \emph{a total of}
$O(n)$ steps during the algorithm, $O(n)$ steps during the algorithm,
@ -252,7 +252,7 @@ the time complexity is $O(n)$.
Another problem that can be solved using Another problem that can be solved using
the two pointers method is the following problem, the two pointers method is the following problem,
also known as the \key{2SUM problem}: also known as the \key{2SUM problem}:
We are given an array of $n$ numbers and we are given an array of $n$ numbers and
a target sum $x$, and our task is to find two numbers a target sum $x$, and our task is to find two numbers
in the array such that their sum is $x$, in the array such that their sum is $x$,
or report that no such numbers exist. or report that no such numbers exist.
@ -452,13 +452,13 @@ It turns out that the problem can be solved
in $O(n)$ time using an appropriate data structure. in $O(n)$ time using an appropriate data structure.
An efficient solution to the problem is to An efficient solution to the problem is to
iterate through the array from left to right, iterate through the array from left to right
and maintain a chain of elements where the and maintain a chain of elements where the
first element is the current element first element is the current element
and each following element is the nearest smaller and each following element is the nearest smaller
element of the previous element. element of the previous element.
If the chain only contains one element, If the chain only contains one element,
the current element does not have the nearest smaller element. the current element does not have a nearest smaller element.
At each step, elements are removed from the chain At each step, elements are removed from the chain
until the first element is smaller until the first element is smaller
than the current element, or the chain is empty. than the current element, or the chain is empty.