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.
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
that solves the problem.
The following table contains some useful estimates
@ -325,7 +325,7 @@ $n$ is large & $O(1)$ or $O(\log n)$ \\
\end{center}
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)$.
This information makes it easier to design the algorithm,
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
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
may perform $n/2$ or $5n$ operations.
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,
our task is to calculate the
\key{maximum subarray sum}, i.e.,
the largest possible sum of numbers
in a contiguous region in the array\footnote{J. Bentley's
the largest possible sum of
a sequence of consecutive numbers
in the array\footnote{J. Bentley's
book \emph{Programming Pearls} \cite{ben86} made the problem popular.}.
The problem is interesting when there may be
negative numbers in the array.
@ -398,8 +399,8 @@ the following subarray produces the maximum sum $10$:
\subsubsection{Algorithm 1}
Let us assume that the numbers are stored in
an array \texttt{x}.
Assume that the numbers are stored in
an array \texttt{t}.
A straightforward way to solve the problem
is to go through all possible ways of
selecting a subarray, calculate the sum of
@ -408,23 +409,23 @@ the maximum sum.
The following code implements this algorithm:
\begin{lstlisting}
int p = 0;
int best = 0;
for (int a = 0; a < n; a++) {
for (int b = a; b < n; b++) {
int s = 0;
for (int c = a; c <= b; c++) {
s += x[c];
int sum = 0;
for (int k = a; k <= b; k++) {
sum += t[k];
}
p = max(p,s);
best = max(best,sum);
}
}
cout << p << "\n";
cout << best << "\n";
\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,
and the sum of the numbers is calculated to the variable $s$.
The variable $p$ contains the maximum sum found during the search.
and the sum of the numbers is calculated to the variable \texttt{sum}.
The variable \texttt{best} contains the maximum sum found during the search.
The time complexity of the algorithm is $O(n^3)$,
because it consists of three nested loops
@ -432,22 +433,22 @@ that go through the input.
\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.
This is possible by calculating the sum at the same
time when the right end of the subarray moves.
The result is the following code:
\begin{lstlisting}
int p = 0;
int best = 0;
for (int a = 0; a < n; a++) {
int s = 0;
int sum = 0;
for (int b = a; b < n; b++) {
s += x[b];
p = max(p,s);
sum += t[b];
best = max(best,sum);
}
}
cout << p << "\n";
cout << best << "\n";
\end{lstlisting}
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
in $O(n)$ time\footnote{In \cite{ben86}, this linear-time 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.
called \index{Kadene's algorithm} \key{Kadene's algorithm}.}, which means
that just one loop is enough.
The idea is to calculate, for each array position,
the maximum sum of a subarray that ends at that position.
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$.
\end{enumerate}
Our goal is to find a subarray with maximum sum,
so in case 2 the subarray that ends at position $k-1$
In the latter case, since we want to
find a subarray with maximum sum,
the subarray that ends at position $k-1$
should also have the maximum sum.
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.
The following code implements the algorithm:
\begin{lstlisting}
int p = 0, s = 0;
int best = 0, sum = 0;
for (int k = 0; k < n; k++) {
s = max(x[k],s+x[k]);
p = max(p,s);
sum = max(t[k],sum+t[k]);
best = max(best,sum);
}
cout << p << "\n";
cout << best << "\n";
\end{lstlisting}
The algorithm only contains one loop
@ -510,7 +512,7 @@ measured.
\begin{center}
\begin{tabular}{rrrr}
array size $n$ & algorithm 1 & algorithm 2 & algorithm 3 \\
array size $n$ & Algorithm 1 & Algorithm 2 & Algorithm 3 \\
\hline
$10^2$ & $0{,}0$ s & $0{,}0$ s & $0{,}0$ s \\
$10^3$ & $0{,}1$ s & $0{,}0$ s & $0{,}0$ s \\