Some fixes
This commit is contained in:
parent
074134ac54
commit
98fda0b259
|
@ -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:
|
||||||
|
|
|
@ -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)$ \\
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue