Improve language

This commit is contained in:
Antti H S Laaksonen 2017-05-17 21:38:50 +03:00
parent c6a24af52d
commit 9d61b10876
1 changed files with 34 additions and 32 deletions

View File

@ -305,7 +305,7 @@ This should take at least some tens of seconds,
so the algorithm seems to be too slow for solving the problem. so the algorithm seems to be too slow for solving the problem.
On the other hand, given the input size, On the other hand, given the input size,
we can try to guess we can try to \emph{guess}
the required time complexity of the algorithm the required time complexity of the algorithm
that solves the problem. that solves the problem.
The following table contains some useful estimates The following table contains some useful estimates
@ -325,7 +325,7 @@ $n$ is large & $O(1)$ or $O(\log n)$ \\
\end{center} \end{center}
For example, if the input size is $n=10^5$, For example, if the input size is $n=10^5$,
it should probably be expected that the time it is probably expected that the time
complexity of the algorithm is $O(n)$ or $O(n \log n)$. complexity of the algorithm is $O(n)$ or $O(n \log n)$.
This information makes it easier to design the algorithm, This information makes it easier to design the algorithm,
because it rules out approaches that would yield because it rules out approaches that would yield
@ -335,7 +335,7 @@ an algorithm with a worse time complexity.
Still, it is important to remember that a Still, it is important to remember that a
time complexity is only an estimate of efficiency, time complexity is only an estimate of efficiency,
because it hides the \key{constant factors}. because it hides the \emph{constant factors}.
For example, an algorithm that runs in $O(n)$ time For example, an algorithm that runs in $O(n)$ time
may perform $n/2$ or $5n$ operations. may perform $n/2$ or $5n$ operations.
This has an important effect on the actual This has an important effect on the actual
@ -357,8 +357,9 @@ time and even in $O(n)$ time.
Given an array of $n$ numbers, Given an array of $n$ numbers,
our task is to calculate the our task is to calculate the
\key{maximum subarray sum}, i.e., \key{maximum subarray sum}, i.e.,
the largest possible sum of numbers the largest possible sum of
in a contiguous region in the array\footnote{J. Bentley's a sequence of consecutive numbers
in the array\footnote{J. Bentley's
book \emph{Programming Pearls} \cite{ben86} made the problem popular.}. book \emph{Programming Pearls} \cite{ben86} made the problem popular.}.
The problem is interesting when there may be The problem is interesting when there may be
negative numbers in the array. negative numbers in the array.
@ -398,8 +399,8 @@ the following subarray produces the maximum sum $10$:
\subsubsection{Algorithm 1} \subsubsection{Algorithm 1}
Let us assume that the numbers are stored in Assume that the numbers are stored in
an array \texttt{x}. an array \texttt{t}.
A straightforward way to solve the problem A straightforward way to solve the problem
is to go through all possible ways of is to go through all possible ways of
selecting a subarray, calculate the sum of selecting a subarray, calculate the sum of
@ -408,23 +409,23 @@ the maximum sum.
The following code implements this algorithm: The following code implements this algorithm:
\begin{lstlisting} \begin{lstlisting}
int p = 0; int best = 0;
for (int a = 0; a < n; a++) { for (int a = 0; a < n; a++) {
for (int b = a; b < n; b++) { for (int b = a; b < n; b++) {
int s = 0; int sum = 0;
for (int c = a; c <= b; c++) { for (int k = a; k <= b; k++) {
s += x[c]; sum += t[k];
} }
p = max(p,s); best = max(best,sum);
} }
} }
cout << p << "\n"; cout << best << "\n";
\end{lstlisting} \end{lstlisting}
The variables $a$ and $b$ determine the first and last The variables \texttt{a} and \texttt{b} determine the first and last
number in the subarray, number in the subarray,
and the sum of the numbers is calculated to the variable $s$. and the sum of the numbers is calculated to the variable \texttt{sum}.
The variable $p$ contains the maximum sum found during the search. The variable \texttt{best} contains the maximum sum found during the search.
The time complexity of the algorithm is $O(n^3)$, The time complexity of the algorithm is $O(n^3)$,
because it consists of three nested loops because it consists of three nested loops
@ -432,22 +433,22 @@ that go through the input.
\subsubsection{Algorithm 2} \subsubsection{Algorithm 2}
It is easy to make the first algorithm more efficient It is easy to make Algorithm 1 more efficient
by removing one loop from it. by removing one loop from it.
This is possible by calculating the sum at the same This is possible by calculating the sum at the same
time when the right end of the subarray moves. time when the right end of the subarray moves.
The result is the following code: The result is the following code:
\begin{lstlisting} \begin{lstlisting}
int p = 0; int best = 0;
for (int a = 0; a < n; a++) { for (int a = 0; a < n; a++) {
int s = 0; int sum = 0;
for (int b = a; b < n; b++) { for (int b = a; b < n; b++) {
s += x[b]; sum += t[b];
p = max(p,s); best = max(best,sum);
} }
} }
cout << p << "\n"; cout << best << "\n";
\end{lstlisting} \end{lstlisting}
After this change, the time complexity is $O(n^2)$. After this change, the time complexity is $O(n^2)$.
@ -456,8 +457,8 @@ After this change, the time complexity is $O(n^2)$.
Surprisingly, it is possible to solve the problem Surprisingly, it is possible to solve the problem
in $O(n)$ time\footnote{In \cite{ben86}, this linear-time algorithm in $O(n)$ time\footnote{In \cite{ben86}, this linear-time algorithm
is attributed to J. B. Kadene, and the algorithm is sometimes 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 called \index{Kadene's algorithm} \key{Kadene's algorithm}.}, which means
one more loop. that just one loop is enough.
The idea is to calculate, for each array position, The idea is to calculate, for each array position,
the maximum sum of a subarray that ends at that position. the maximum sum of a subarray that ends at that position.
After this, the answer for the problem is the After this, the answer for the problem is the
@ -472,21 +473,22 @@ There are two possibilities:
at position $k-1$, followed by the element at position $k$. at position $k-1$, followed by the element at position $k$.
\end{enumerate} \end{enumerate}
Our goal is to find a subarray with maximum sum, In the latter case, since we want to
so in case 2 the subarray that ends at position $k-1$ find a subarray with maximum sum,
the subarray that ends at position $k-1$
should also have the maximum sum. should also have the maximum sum.
Thus, we can solve the problem efficiently Thus, we can solve the problem efficiently
when we calculate the maximum subarray sum by calculating the maximum subarray sum
for each ending position from left to right. for each ending position from left to right.
The following code implements the algorithm: The following code implements the algorithm:
\begin{lstlisting} \begin{lstlisting}
int p = 0, s = 0; int best = 0, sum = 0;
for (int k = 0; k < n; k++) { for (int k = 0; k < n; k++) {
s = max(x[k],s+x[k]); sum = max(t[k],sum+t[k]);
p = max(p,s); best = max(best,sum);
} }
cout << p << "\n"; cout << best << "\n";
\end{lstlisting} \end{lstlisting}
The algorithm only contains one loop The algorithm only contains one loop
@ -510,7 +512,7 @@ measured.
\begin{center} \begin{center}
\begin{tabular}{rrrr} \begin{tabular}{rrrr}
array size $n$ & algorithm 1 & algorithm 2 & algorithm 3 \\ array size $n$ & Algorithm 1 & Algorithm 2 & Algorithm 3 \\
\hline \hline
$10^2$ & $0{,}0$ s & $0{,}0$ s & $0{,}0$ s \\ $10^2$ & $0{,}0$ s & $0{,}0$ s & $0{,}0$ s \\
$10^3$ & $0{,}1$ s & $0{,}0$ s & $0{,}0$ s \\ $10^3$ & $0{,}1$ s & $0{,}0$ s & $0{,}0$ s \\