Full download Programming Interview Problems: Dynamic Programming (with solutions in Python) 1st Edition Leonardo Rossi pdf docx
Full download Programming Interview Problems: Dynamic Programming (with solutions in Python) 1st Edition Leonardo Rossi pdf docx
com
https://textbookfull.com/product/programming-interview-
problems-dynamic-programming-with-solutions-in-python-1st-
edition-leonardo-rossi/
OR CLICK BUTTON
DOWNLOAD NOW
https://textbookfull.com/product/robust-adaptive-dynamic-
programming-1st-edition-hao-yu/
textboxfull.com
https://textbookfull.com/product/python-network-programming-cookbook-
kathiravelu/
textboxfull.com
https://textbookfull.com/product/python-gui-programming-cookbook-
meier/
textboxfull.com
https://textbookfull.com/product/abstract-dynamic-programming-second-
edition-dimitri-p-bertsekas/
textboxfull.com
1
Contents
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
General advice for the interview . . . . . . . . . . . . . . . . . . . . . . . 6
1 The Fibonacci sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Solution 1: brute force, 𝑂(2𝑛 ) time 7
Solution 2: dynamic programming, top-down 9
Solution 2: dynamic programming, bottom-up 11
2 Optimal stock market strategy . . . . . . . . . . . . . . . . . . . . . . . . 13
Solution 1: dynamic programming, top-down, 𝑂(𝑛) time 13
Solution 2: dynamic programming, bottom-up, 𝑂(𝑛) time 15
Variation: limited investment budget 16
Variation: limited number of transactions 17
3 Change-making . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Clarification questions 20
Solution 1: dynamic programming, top-down, 𝑂(𝑛𝑣) time 20
Solution 2: dynamic programming, bottom-up, 𝑂(𝑛𝑣) time 25
Solution 3: dynamic programming + BFS, bottom-up, 𝑂(𝑛𝑣) time 26
Variant: count the number of ways to pay (permutations) 29
Solution: dynamic-programming, top-down, 𝑂(𝑛𝑣) 29
Variant: count the number of ways to pay (combinations) 32
Solution: dynamic-programming, top-down, 𝑂(𝑛𝑣) 32
4 Number of expressions with a target result . . . . . . . . . . . . . . . . . . 36
Clarification questions 36
Solution 1: brute-force, 𝑂(2𝑛 ) time 36
Solution 2: dynamic programming, top-down, 𝑂(𝑛𝑆) time 38
Solution 3: dynamic programming + BFS, bottom-up, 𝑂(𝑛𝑆) time 39
Unit tests 41
5 Partitioning a set into equal-sum parts . . . . . . . . . . . . . . . . . . . . 43
Clarification questions 43
Solution 1: dynamic programming, top-down, 𝑂(𝑛𝑆) time 43
6 Splitting a string without spaces into words . . . . . . . . . . . . . . . . . . 46
Clarification questions 46
Solution 1: dynamic programming, top-down, 𝑂(𝑛𝑤) time 46
Solution 2: dynamic programming + BFS/DFS, bottom-up, 𝑂(𝑛𝑤) time 48
7 The number of binary search trees . . . . . . . . . . . . . . . . . . . . . . 50
Solution 1: dynamic programming, top-down, 𝑂(𝑛2 ) time 50
8 The maximum-sum subarray . . . . . . . . . . . . . . . . . . . . . . . . 55
Clarification questions 55
Solution 1: dynamic programming, 𝑂(𝑛) time, 𝑂(𝑛) space 55
Solution 2: dynamic programming, 𝑂(𝑛) time, 𝑂(1) space 61
Unit tests 61
9 The maximum-product subarray . . . . . . . . . . . . . . . . . . . . . . . 63
Clarification questions 63
Solution 1: greedy, two-pass, 𝑂(𝑛) time 63
Contents 3
Preface
Over the last decade, many companies have adopted the FANG-style interview process for
software engineer positions: programming questions that involve an algorithm design step,
and often require competitive programming solving techniques.
The advantages and disadvantages of this style of interview questions are highly debated, and
outside the scope of this book. What is important is that the questions that are asked pose
serious challenges to candidates, thus require thorough preparation.
The class of problems that are by far the most challenging is dynamic programming. This is
due to a combination of dynamic programming being rarely used in day-to-day work, and the
difficulty of finding a solution in a short amount of time, when not having prior experience
with this method.
This book presents 25 dynamic programming problems that are most commonly encoun-
tered in interviews, and several of their variants. For each problem, multiple solutions are
given, including a gradual walkthrough that shows how one may reach the answer. The goal
is not to memorize solutions, but to understand how they work and learn the fundamental
techniques, such that new, previously unseen problems can be solved with ease.
The solutions are very detailed, showing example walkthrougs, verbal explanations of the
solutions, and many diagrams and drawings. These were designed in a way that helps both
verbal and visual learners grasp the material with ease. The code implementation usually
comes last, accompanied by unit tests and complexity/performance analysis.
A particular focus has been put on code clarity and readability: during the interview, we are
expected to write code as we would on the job. This means that the code must be tidy, with
well-named variables, short functions that do one thing, modularity, comments describing
why we do certain things etc. This is, sadly, unlike most other material on dynamic pro-
gramming that one may find online, in competitive programming resources, or even in well-
known algorithm design textbooks. In fact, the poor state of the material on this topic is the
main reason I wrote this book.
I hope that you find this book useful for preparing to get the job you wish for. Whether you
like the book or not, I would appreciate your feedback through a book review.
Good luck with your interviews!
6 Contents
The above code is correct but too slow due to redundancies. We can see this if we add logging
to the function:
import inspect
def stack_depth():
return len(inspect.getouterframes(inspect.currentframe())) 1
def fibonacci(n):
print("{indent}fibonacci({n}) called".format(
indent=" " * stack_depth(), n=n))
if n <= 2:
return 1
return fibonacci(n 1) + fibonacci(n 2)
fibonacci(6)
We changed the code to print the argument passed to the fibonacci function. The message
is indented by the call stack depth, so that we can see better which function call is causing
which subsequent calls. Running the above code prints:
fibonacci(6) called
fibonacci(5) called
fibonacci(4) called
fibonacci(3) called
fibonacci(2) called
fibonacci(1) called
fibonacci(2) called
fibonacci(3) called
fibonacci(2) called
fibonacci(1) called
fibonacci(4) called
8 1 The Fibonacci sequence
fibonacci(3) called
fibonacci(2) called
fibonacci(1) called
fibonacci(2) called
That’s a lot of calls! If we draw the call graph, we can see that it’s an almost full binary tree:
9
Notice that the height of the binary tree is n (in this case, 6). The tree is almost full, thus
it has 𝑂(2𝑛 ) nodes. Since each node represends a call of our function, our algorithm has
exponential complexity.
It does not make sense to compute, for example, the 4-th Fibonacci number twice, since it
does not change. We should compute it only once and cache the result.
Notice how only the first call to fibonacci(n) recurses. All subsequent calls return from
the cache the value that was previously computed.
This implementation has 𝑂(𝑛) time complexity, since exactly one function call is needed to
compute each number in the series.
10 1 The Fibonacci sequence
While the above code is correct, there are some code style issues:
We can avoid adding the global variable by using instead an attribute called cache that is
attached to the function:
def fibonacci(n):
if n <= 2:
return 1
if not hasattr(fibonacci, 'cache'):
fibonacci.cache = {}
if n not in fibonacci.cache:
fibonacci.cache[n] = fibonacci(n 1) + fibonacci(n 2)
return fibonacci.cache[n]
The advantage is that the cache variable is now owned by the function, so no external code
is needed anymore to initialize it. The disadvantage is that the code has become even more
complicated, thus harder to read and modify.
A better approach is to keep the original function simple, and wrap it with a decorator that
performs the caching:
def cached(f):
cache = {}
def worker(*args):
if args not in cache:
cache[args] = f(*args)
return cache[args]
return worker
@cached
def fibonacci(n):
if n <= 2:
return 1
return fibonacci(n 1) + fibonacci(n 2)
The good news is that Python 3 has built-in support for caching decorators, so there is no
need to roll your own:
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci(n):
if n <= 2:
11
return 1
return fibonacci(n 1) + fibonacci(n 2)
By default lru_cache is limited to 128 entries, with least-recently used entries evicted when
the size limit is hit. Passing maxsize=None to lru_cache ensures that there is no memory
limit and all values are cached. In practice, it might be preferrable to set a limit instead of
letting memory usage increase without bounds.
The code has 𝑂(𝑛) time complexity, as well as 𝑂(𝑛) space complexity. In practice the perfor-
mance is better than the recursive implementation, since there is no overhead due to extra
function calls.
The space complexity can be reduced to 𝑂(1) if we notice that we do not need to store the
entire sequence, just the last two numbers:
def fibonacci(n):
previous = 1
current = 1
for i in range(n 2):
next = current + previous
previous, current = current, next
return current
We have written an algorithm that starts from the smallest subproblem (the first two numbers
in the sequence), then expands the solution to reach the original problem (the n-th number
in the sequence). This approach is called bottom-up dynamic programming. By contrast,
the previous approach of solving the problem recursively starting from the top is called top-
down dynamic programming. Both approaches are equally valid; one or the other may be
more intuitive, depending on the problem.
12 1 The Fibonacci sequence
In the rest of the book, we will look at how we can apply dynamic programming to solving
non-trivial problems. In general, we will show both top-down and bottom-up solutions. We
will see that the top-down approach is often easier to understand and implement, however it
offers less optimization opportunities compared to bottom-up.
13
Knowing this, we can model the entire problem using a state machine. In our initial state,
14 2 Optimal stock market strategy
we have some amount of cash and no shares. In the final state, we have some other amount
of cash (ideally higher), and no shares. In between, we have state transitions:
Solving the original problem can be reduced to finding a chain of transitions through this
state machine, that yields the maximum profit.
Notice how our state during any day only depends on the state from the previous day. This is
excellent: we can express our problem using a simple recurrence relation, just as we did for
the Fibonacci sequence problem.
The structure of the solution using a recursive algorithm looks like this:
def max_profit(daily_price):
def get_best_profit(day, have_stock):
"""
Returns the best profit that can be obtained by the end of the day.
At the end of the day:
* if have_stock is True, the trader must own the stock;
* if have_stock is False, the trader must not own the stock.
"""
# TODO ...
# Final state: end of last day, no shares owned.
last_day = len(daily_price) 1
no_stock = False
return get_best_profit(last_day, no_stock)
Note that we defined a helper function get_best_profit which takes as parameters the
identifiers of a state: the day number and whether we own the stock or not at the end of the
day. We use get_best_profit to compute the profit for a specific state in the state machine.
Let’s now implement the helper using a recurrence relation. We need to consider the previous
states that can transition into the current state, and choose the best one:
@lru_cache(maxsize=None)
def get_best_profit(day, have_stock):
"""
15
Returns the best profit that can be obtained by the end of the day.
At the end of the day:
* if have_stock is True, the trader must own the stock;
* if have_stock is False, the trader must not own the stock.
"""
if day < 0:
if not have_stock:
# Initial state: no stock and no profit.
return 0
else:
# We are not allowed to have initial stock.
# Add a very large penalty to eliminate this option.
return float('inf')
price = daily_price[day]
if have_stock:
# We can reach this state by buying or holding.
strategy_buy = get_best_profit(day 1, False) price
strategy_hold = get_best_profit(day 1, True)
return max(strategy_buy, strategy_hold)
else:
# We can reach this state by selling or avoiding.
strategy_sell = get_best_profit(day 1, True) + price
strategy_avoid = get_best_profit(day 1, False)
return max(strategy_sell, strategy_avoid)
The first part of the helper implements the termination condition, i.e. handling the initial
state, while the second part implements the recurrence. To simplify the logic of the recur-
rence we allow selling on any day including the first, but we ensure that selling on the first
day would yield a negative profit, so it’s an option that cannot be chosen as optimal.
Both the time and space complexity of this solution are 𝑂(𝑛). Note that it is important to
cache the results of the helper function, otherwise the time complexity becomes exponential
instead of linear.
def max_profit(daily_price):
# Initial state: start from a reference cash amount.
# It can be any value.
# We use 0 and allow our cash to go below 0 if we need to buy a share.
cash_not_owning_share = 0
# High penalty for owning a stock initially:
# ensures this option is never chosen.
cash_owning_share = float('inf')
for price in daily_price:
# Transitions to the current day, owning the stock:
strategy_buy = cash_not_owning_share price
strategy_hold = cash_owning_share
# Transitions to the current day, not owning the stock:
strategy_sell = cash_owning_share + price
strategy_avoid = cash_not_owning_share
# Compute the new states.
cash_owning_share = max(strategy_buy, strategy_hold)
cash_not_owning_share = max(strategy_sell, strategy_avoid)
# The profit is the final cash amount, since we start from
# a reference of 0.
return cash_not_owning_share
At each step, we only need to store the profit corresponding to the two states of that day. This
is due to the state machine not having any transitions between non-consecutive days: we
could say that at any time, the state machine does not “remember” anything from the days
before yesterday.
The time complexity is 𝑂(𝑛), but the space complexity has been reduced to 𝑂(1), since we
only need to store the result for the previous day.
Any time the optimal cash amount in a given state goes below zero, we replace it with negative
infinity. This ensures that this path through the state machine will not be chosen. We only
have to do this for the states where we own stock. In the states where we do not own stock,
our cash amount never decreases from the previous day, so this check is not needed.
strategy_buy,
strategy_hold)
cash_not_owning_share = cash_not_owning_share_next
cash_owning_share = cash_owning_share_next
# We have multiple final states, depending on how many times we sold.
# The transaction limit may not have been reached.
# Choose the most profitable final state.
return max(cash_not_owning_share)
3 Change-making
Given a money amount and a list of coin denominations, provide the combination of coins
adding up to that amount, that uses the fewest coins.
Example 1: Pay amount 9 using coin denominations [1, 2, 5]. The combination having
the fewest coins is [5, 2, 2]. A suboptimal combination is [5, 1, 1, 1, 1]: it adds up
to 9, but is using 5 coins instead of 3, thus it cannot be the solution.
Example 2: Pay amount 12 using coin denominations [1, 6, 10]. The combination having
the fewest coins is [6, 6]. A suboptimal combination is [10, 1, 1].
Clarification questions
Q: Is it possible that the amount cannot be paid with the given coins?
A: Yes. For example, 5 cannot be paid with coins [2, 4]. In such a situation, return None.
However, we do not know which coin to choose first optimally. In this situation, we have
no other choice but try all possible options in brute-force style. For each coin, we subtract
its value from the amount, then solve by recurrence the subproblem—this leads to a candi-
date solution for each choice of the first coin. Once we are done, we compare the candidate
solutions and choose the one using the fewest coins.
Here is an example of how we would form the optimal change for amount 9, using coins [1,
2, 5]. We represent each amount as a node in a tree. Whenever we subtract a coin value
from that amount, we add an edge to a new node with a smaller value. Please mind that the
actual solution does not use trees, at least not explicitly: they are shown here only for clarity.
21
This diagram shows that for value 9, we have three options for choosing the first coin:
• We choose coin 1. We now have to solve the subproblem for value 9 − 1 = 8. Suppose
its optimal result is [5, 2, 1]. Then we add coin 1 to create the candidate solution
[5, 2, 1, 1] for 9.
• We choose coin 2. We now have to solve the subproblem for value 9 − 2 = 7. Suppose
the optimal result is [5, 2]. We add to it coin 2 to create the candidate solution [5,
2, 2] for 9.
• We choose coin 5. We now have to solve the subproblem for value 9 − 5 = 4. The
optimal result is [2, 2]. We add to it coin 5 to create the candidate solution [5, 2,
2] for 9.
Now that we are done solving the subproblems, we compare the candidate solutions and
choose the one using the fewest coins: [5, 2, 2].
For solving the subproblems, we use the same procedure. The only difference is that we
need to pay attention to two edge cases: the terminating condition (reaching amount 0), and
avoiding choices where we are paying too much (reaching negative amounts). To understand
these better, let’s take a look at the subproblems:
22 3 Change-making
This algorithm implements the recurrence relation as explained above. Notice how we handle
the edge cases at the beginning of the function, before making any recursive calls, to avoid
infinite recursion and to keep the recursion logic as simple as possible.
This implementation has exponential time complexity, since we have not implemented
caching yet. Let’s do that now.
Unfortunately, if we try to add caching simply adding the lru_cache decorator, we will have
a nasty surprise:
from functools import lru_cache
@lru_cache(maxsize=None)
def make_change(coins, amount):
...
This code throws the exception: TypeError: unhashable type: 'list'. This is caused by
24 3 Change-making
the inability to cache the argument coins. As a list, it is mutable, and the lru_cache deco-
rator rejects it. The decorator supports caching only arguments with immutable types, such
as numbers, strings or tuples. This is for a very good reason: to prevent bugs in case mutable
arguments are changed later (in case of lists, via append, del or changing its elements), which
would require invalidating the cache.
A joke circulating in software engineering circles says that there are only two hard problems
in computer science: cache invalidation, naming things, and off-by-one errors. To address
the former, the design of the lru_cache decorator takes the easy way out: it avoids having to
implement cache invalidation at all by only allowing immutable arguments.
Still, we need to add caching one way or another. We can work around the lru_cache limi-
tation if we notice that we do not actually need to cache the coins list—that is shared among
all subproblems. We only need to pass the remaining amount to be paid. So we write a helper
function that solves the subproblem, taking as argument only the amount. The coin list is
shared between invocations.
One way to implement this is to make the helper function nested inside the make_change
function, so that it has access to the coins argument of the outer function:
def make_change(coins, amount):
@lru_cache(maxsize=None)
def helper(amount):
...
return helper(amount)
Another way is to transform the make_change function into a method of a class, that stores
the list of coins in a class member. The helper could then be written as another method of
the class, ideally a private one. I think adding classes is overkill for what we have to do, so we
will not discuss this approach.
optimal_result = None
# Consider all the possible ways to choose the last coin.
for coin in coins:
# Solve a subproblem for the rest of the amount.
partial_result = helper(amount coin)
# Skip this coin if the payment failed:
if partial_result is None:
continue
candidate = partial_result + [coin]
# Check if the candidate solution is better than the
# optimal solution known so far, and update it if needed.
if (optimal_result is None or
len(candidate) < len(optimal_result)):
optimal_result = candidate
return optimal_result
return helper(amount)
This solution is iterative, which is an advantage compared to the top-down solution, since it
avoids the overheads of recursive calls. However, for certain denominations, it wastes time
by increasing the amount very slowly, in steps of 1 unit. For example, if coins = [100,
200, 500] (suppose we use bills), it does not make sense to advance in steps of 1.
In addition, a lot of space is wasted for amounts that cannot be paid. Let’s see if we can come
up with a better solution.
Notice how we are treating the (sub)problem space as a graph, which is explored in breadth-
first order (BFS). We start from the subproblem of forming the amount 0. From there, we
keep expanding using all the possible coin choices until we reach the required amount.
Let’s look at an example showing how the problem space exploration works for paying
amount 9 with coins [1, 2, 5]. We start with amount 0 and explore by adding a coin in all
possible ways. Here is the first level of the problem space graph:
The first level contains all amounts that can be paid using a single coin. After this step, we
have [1, 2, 5] in our BFS queue, which is exactly the list of nodes on the first level—hence
the name of breadth-first search.
To fill in the second level of the problem space graph, we continue the exploration a step
further for amounts 1, 2 and 5:
28 3 Change-making
The second level contains all possible amounts that can be paid with 2 coins. After this step,
we have [3, 6, 4, 7] in our BFS queue.
Notice that we discarded nodes corresponding to already known amounts, since these can
be paid with a similar or better solution (fewer coins). We have also discarded amounts that
exceed the value we have to pay (such as 10). This ensures that the graph size is bounded and
that it contains only valid/optimal nodes.
We still have not found a way to pay our target amount, 9. Let’s explore further, adding the
third level of the problem space graph:
Note that as we reached the target amount 9, we stopped drawing the rest of the level. As
it is on the third level of the tree, the amount can be paid with 3 coins. The combination is
29
2, 2 and 5, which can be found by walking the path from 0 to 9. This is the solution to the
problem.
Note that the exploration order was important: the breadth-first order guarantees that each
time we reach a new amount, the path we followed is the shortest possible in terms of num-
ber of coins used. Had we used instead another graph search algorithm, such as depth-first
search, the solution might not have been optimal.
From this list we do not see any particular rule, other than enumerating all the permutations
of the combinations of coins that add up to 6 (1 + 5, 2 + 2 + 2, 2 + 2 + 1 + 1, 2 + 1 +
1 + 1 + 1 and 1 + 1 + 1 + 1 + 1 +1). This is not very helpful.
By C. C. FRASER-TYTLER.—Mistress Judith.
By SARAH TYTLER.
Buried Diamonds.
The Blackhall Ghosts.
The Macdonald Lass.
The Witch-Wife.
Mrs. Carmichael’s Goddesses.
Lady Bell.
Rachel Langton.
Sapphira.
A Honeymoon’s Eclipse.
By ALLEN UPWARD.
The Queen against Owen.
The Prince of Balkistan.
By EDMOND ABOUT.
The Fellah.
By HAMILTON AÏDÉ.
Carr of Carrlyon.
Confidences.
By Mrs. ALEXANDER.
Maid, Wife, or Widow?
Blind Fate.
Valerie’s Fate.
A Life Interest.
Mona’s Choice.
By Woman’s Wit.
By GRANT ALLEN.
Philistia.
Babylon.
Strange Stories.
For Mamie’s Sake.
In all Shades.
The Beckoning Hand.
The Devil’s Die.
The Tents of Shem.
The Great Taboo.
Dumaresq’s Daughter.
Duchess of Powysland.
Blood Royal.
Ivan Greet’s Masterpiece.
The Scallywag.
This Mortal Coil.
At Market Value.
Under Sealed Orders.
By E. LESTER ARNOLD.
Phra the Phœnician.
BY FRANK BARRETT.
Fettered for Life.
Little Lady Linton.
Between Life & Death.
Sin of Olga Zassoulich.
Folly Morrison.
Lieut. Barnabas.
Honest Davie.
A Prodigal’s Progress.
Found Guilty.
A Recoiling Vengeance.
For Love and Honour.
John Ford, &c.
Woman of Iron Brace’ts.
The Harding Scandal.
A Missing Witness.
By SHELSLEY BEAUCHAMP.
Grantley Grange.
By FREDERICK BOYLE.
Camp Notes.
Savage Life.
Chronicles of No-man’s Land.
By AMBROSE BIERCE.
In the Midst of Life.
BY BRET HARTE.
Californian Stories.
Gabriel Conroy.
Luck of Roaring Camp.
An Heiress of Red Dog.
Flip.
Maruja.
A Phyllis of the Sierras.
A Waif of the Plains.
Ward of Golden Gate.
By ROBERT BUCHANAN.
Shadow of the Sword.
A Child of Nature.
God and the Man.
Love Me for Ever.
Foxglove Manor.
The Master of the Mine.
Annan Water.
The Martyrdom of Madeline.
The New Abelard.
The Heir of Linne.
Woman and the Man.
Rachel Dene.
Matt.
Lady Kilpatrick.
By HALL CAINE.
The Shadow of a Crime.
A Son of Hagar.
The Deemster.
By Commander CAMERON.
The Cruise of the ‘Black Prince.’
By HAYDEN CARRUTH.
The Adventures of Jones.
By AUSTIN CLARE.
For the Love of a Lass.
By MACLAREN COBBAN.
The Cure of Souls.
The Red Sultan.
By C. ALLSTON COLLINS.
The Bar Sinister.
By WILKIE COLLINS.
Armadale.
After Dark.
No Name.
Antonina.
Basil.
Hide and Seek.
The Dead Secret.
Queen of Hearts.
Miss or Mrs.?
The New Magdalen.
The Frozen Deep.
The Law and the Lady.
The Two Destinies.
The Haunted Hotel.
A Rogue’s Life.
My Miscellanies.
The Woman in White.
The Moonstone.
Man and Wife.
Poor Miss Finch.
The Fallen Leaves.
Jezebel’s Daughter.
The Black Robe.
Heart and Science.
‘I Say No!’
The Evil Genius.
Little Novels.
Legacy of Cain.
Blind Love.
By M. J. COLQUHOUN.
Every Inch a Soldier.
By C. EGBERT CRADDOCK.
The Prophet of the Great Smoky Mountains.
By MATT CRIM.
The Adventures of a Fair Rebel.
By B. M. CROKER.
Pretty Miss Neville.
Diana Barrington.
‘To Let.’
A Bird of Passage.
Proper Pride.
A Family Likeness.
A Third Person.
Village Tales and Jungle Tragedies.
Two Masters.
Mr. Jervis.
The Real Lady Hilda.
Married or Single?
Interference.
By W. CYPLES.
Hearts of Gold.
By ALPHONSE DAUDET.
The Evangelist; or, Port Salvation.
By ERASMUS DAWSON.
The Fountain of Youth.
By JAMES DE MILLE.
A Castle in Spain.
By J. LEITH DERWENT.
Our Lady of Tears.
Circe’s Lovers.
By DICK DONOVAN.
The Man-Hunter.
Tracked and Taken.
Caught at Last!
Wanted!
Who Poisoned Hetty Duncan?
Man from Manchester.
A Detective’s Triumphs.
In the Grip of the Law.
From Information Received.
Tracked to Doom.
Link by Link.
Suspicion Aroused.
Dark Deeds.
Riddles Read.
The Mystery of Jamaica Terrace.
The Chronicles of Michael Danevitch.
By M. BETHAM-EDWARDS.
Felicia.
Kitty.
By EDWARD EGGLESTON.
Roxy.
By G. MANVILLE FENN.
The New Mistress.
Witness to the Deed.
The Tiger Lily.
The White Virgin.
By PERCY FITZGERALD.
Bella Donna.
Never Forgotten.
Polly.
Fatal Zero.
Second Mrs. Tillotson.
Seventy-five Brooke Street.
The Lady of Brantome.
By ALBANY DE FONBLANQUE.
Filthy Lucre.
By R. E. FRANCILLON.
Olympia.
One by One.
A Real Queen.
Queen Cophetua.
King or Knave?
Romances of the Law.
Ropes of Sand.
A Dog and his Shadow.
By HAROLD FREDERIC.
Seth’s Brother’s Wife.
The Lawton Girl.
By EDWARD GARRETT.
The Capel Girls.
By GILBERT GAUL.
A Strange Manuscript.
By CHARLES GIBBON.
Robin Gray.
Fancy Free.
For Lack of Gold.
What will the World Say?
In Love and War.
For the King.
In Pastures Green.
Queen of the Meadow.
A Heart’s Problem.
The Dead Heart.
In Honour Bound.
Flower of the Forest.
The Braes of Yarrow.
The Golden Shaft.
Of High Degree.
By Mead and Stream.
Loving a Dream.
A Hard Knot.
Heart’s Delight.
Blood-Money.
By WILLIAM GILBERT.
Dr. Austin’s Guests.
James Duke.
The Wizard of the Mountain.
By ERNEST GLANVILLE.
The Lost Heiress.
A Fair Colonist.
The Fossicker.
By HENRY GREVILLE.
A Noble Woman.
Nikanor.
By CECIL GRIFFITH.
Corinthia Marazion.
By SYDNEY GRUNDY.
The Days of his Vanity.
By JOHN HABBERTON.
Brueton’s Bayou.
Country Luck.
By ANDREW HALLIDAY.
Every-day Papers.
By THOMAS HARDY.
Under the Greenwood Tree.
By JULIAN HAWTHORNE.
Garth.
Ellice Quentin.
Fortune’s Fool.
Miss Cadogna.
Sebastian Strome.
Dust.
Beatrix Randolph.
Love—or a Name.
David Poindexter’s Disappearance.
The Spectre of the Camera.
By G. A. HENTY.
Rujub the Juggler.
By HENRY HERMAN.
A Leading Lady.
By HEADON HILL.
Zambra the Detective.
By JOHN HILL.
Treason Felony.
By Mrs. CASHEL HOEY.
The Lover’s Creed.
By Mrs. HUNGERFORD.
A Maiden all Forlorn.
In Durance Vile.
Marvel.
A Mental Struggle.
A Modern Circe.
April’s Lady.
Peter’s Wife.
Lady Verner’s Flight.
The Red House Mystery.
The Three Graces.
Unsatisfactory Lover.
Lady Patty.
Nora Creina.
Professor’s Experiment.
By WM. JAMESON.
My Dead Self.
By HARRIETT JAY.
The Dark Colleen.
Queen of Connaught.
By MARK KERSHAW.
Colonial Facts and Fictions.
By R. ASHE KING.
A Drawn Game.
‘The Wearing of the Green.’
Passion’s Slave.
Bell Barry.
By EDMOND LEPELLETIER.
Madame Sans Gene.
By JOHN LEYS.
The Lindsays.
By E. LYNN LINTON.
Patricia Kemball.
The World Well Lost.
Under which Lord?
Paston Carew.
‘My Love!’
Ione.
With a Silken Thread.
The Atonement of Leam Dundas.
Rebel of the Family.
Sowing the Wind.
The One Too Many.
Dulcie Everton.
By HENRY W. LUCY.
Gideon Fleyce.
By JUSTIN McCARTHY.
Dear Lady Disdain.
Waterdale Neighbours.
My Enemy’s Daughter.
A Fair Saxon.
Linley Rochford.
Miss Misanthrope.
Camiola.
Donna Quixote.
Maid of Athens.
The Comet of a Season.
The Dictator.
Red Diamonds.
The Riddle Ring.
By HUGH MACCOLL.
Mr. Stranger’s Sealed Packet.
By GEORGE MACDONALD.
Heather and Snow.
By AGNES MACDONELL.
Quaker Cousins.
By KATHARINE S. MACQUOID.
The Evil Eye.
Lost Rose.
By W. H. MALLOCK.
A Romance of the Nineteenth Century.
The New Republic.
By J. MASTERMAN.
Half-a-dozen Daughters.
By BRANDER MATTHEWS.
A Secret of the Sea.
By L. T. MEADE.
A Soldier of Fortune.
By LEONARD MERRICK.
The Man who was Good.
By JEAN MIDDLEMASS.
Touch and Go.
Mr. Dorillion.
By Mrs. MOLESWORTH.
Hathercourt Rectory.
By J. E. MUDDOCK.
Stories Weird and Wonderful.
The Dead Man’s Secret.
From the Bosom of the Deep.
By D. CHRISTIE MURRAY.
A Model Father.
Joseph’s Coat.
Coals of Fire.
Val Strange.
Hearts.
Old Blazer’s Hero.
The Way of the World.
Cynic Fortune.
A Life’s Atonement.
By the Gate of the Sea.
A Bit of Human Nature.
First Person Singular.
Bob Martin’s Little Girl.
Time’s Revenges.
A Wasted Crime.
In Direst Peril.
Mount Despair.
A Capful o’ Nails.
By HENRY MURRAY.
A Game of Bluff.
A Song of Sixpence.
By HUME NISBET.
‘Bail Up!’
Dr. Bernard St. Vincent.
By W. E. NORRIS.
Saint Ann’s.
Billy Bellew.
By ALICE O’HANLON.
The Unforeseen.
Chance? or Fate?
By GEORGES OHNET.
Dr. Rameau.
A Last Love.
A Weird Gift.
By Mrs. OLIPHANT.
Whiteladies.
The Primrose Path.
The Greatest Heiress in England.
By OUIDA.
Held in Bondage.
Strathmore.
Chandos.
Idalia.
Under Two Flags.
Cecil Castlemaine’s Gage.
Tricotrin.
Puck.
Folle Farine.
A Dog of Flanders.
Pascarel.
Signa.
Princess Napraxine.
In a Winter City.
Ariadne.
Friendship.
Two Lit. Wooden Shoes.
Moths.
Bimbi.
Pipistrello.
A Village Commune.
Wanda.
Othmar.
Frescoes.
In Maremma.
Guilderoy.
Ruffino.
Syrlin.
Santa Barbara.
Two Offenders.
Ouida’s Wisdom, Wit, and Pathos.
By EDGAR A. POE.
The Mystery of Marie Roget.
By E. C. PRICE.
Valentina.
The Foreigners.
Mrs. Lancaster’s Rival.
Gerald.
By RICHARD PRYCE.
Miss Maxwell’s Affections.
By JAMES PAYN.
Bentinck’s Tutor.
Murphy’s Master.
A County Family.
At Her Mercy.
Cecil’s Tryst.
The Clyffards of Clyffe.
The Foster Brothers.
Found Dead.
The Best of Husbands.
Walter’s Word.
Halves.
Fallen Fortunes.
Humorous Stories.
£200 Reward.
A Marine Residence.
Mirk Abbey.
By Proxy.
Under One Roof.
High Spirits.
Carlyon’s Year.
From Exile.
For Cash Only.
Kit.
The Canon’s Ward.
The Talk of the Town.
Holiday Tasks.
A Perfect Treasure.
What He Cost Her.
A Confidential Agent.
Glow-worm Tales.
The Burnt Million.
Sunny Stories.
Lost Sir Massingberd.
A Woman’s Vengeance.
The Family Scapegrace.
Gwendoline’s Harvest.
Like Father, Like Son.
Married Beneath Him.
Not Wooed, but Won.
Less Black than We’re Painted.
Some Private Views.
A Grape from a Thorn.
The Mystery of Mirbridge.
The Word and the Will.
A Prince of the Blood.
A Trying Patient.
By CHARLES READE.
It is Never Too Late to Mend.
Christie Johnstone.
The Double Marriage.
Put Yourself in His Place.
Love Me Little, Love Me Long.
The Cloister and the Hearth.
The Course of True Love.
The Jilt.
The Autobiography of a Thief.
A Terrible Temptation.
Foul Play.
The Wandering Heir.
Hard Cash.
Singleheart and Doubleface.
Good Stories of Man and other Animals.
Peg Woffington.
Griffith Gaunt.
A Perilous Secret.
A Simpleton.
Readiana.
A Woman-Hater.
By Mrs. J. H. RIDDELL.
Weird Stories.
Fairy Water.
Her Mother’s Darling.
The Prince of Wales’s Garden Party.
The Uninhabited House.
The Mystery in Palace Gardens.
The Nun’s Curse.
Idle Tales.
By AMELIE RIVES.
Barbara Dering.
By F. W. ROBINSON.
Women are Strange.
The Hands of Justice.
The Woman in the Dark.
By JAMES RUNCIMAN.
Skippers and Shellbacks.
Grace Balmaign’s Sweetheart.
Schools and Scholars.
By W. CLARK RUSSELL.
Round the Galley Fire.
On the Fo’k’sle Head.
In the Middle Watch.
A Voyage to the Cape.
A Book for the Hammock.
The Mystery of the ‘Ocean Star.’
The Romance of Jenny Harlowe.
An Ocean Tragedy.
My Shipmate Louise.
Alone on Wide Wide Sea.
Good Ship ‘Mohock.’
The Phantom Death.
Is He the Man?
Heart of Oak.
The Convict Ship.
The Tale of the Ten.
The Last Entry.
By DORA RUSSELL.
A Country Sweetheart.
By GEORGE R. SIMS.
The Ring o’ Bells.
Mary Jane’s Memoirs.
Mary Jane Married.
Tales of To-day.
Dramas of Life.
Tinkletop’s Crime.
My Two Wives.
Zeph.
Memoirs of a Landlady.
Scenes from the Show.
The 10 Commandments.
Dagonet Abroad.
Rogues and Vagabonds.
By ARTHUR SKETCHLEY.
A Match in the Dark.
By HAWLEY SMART.
Without Love or Licence.
Beatrice and Benedick.
The Master of Rathkelly.
The Plunger.
Long Odds.
By T. W. SPEIGHT.
The Mysteries of Heron Dyke.
The Golden Hoop.
Hoodwinked.
By Devious Ways.
Back to Life.
The Loudwater Tragedy.
Burgo’s Romance.
Quittance in Full.
A Husband from the Sea.
By R. A. STERNDALE.
The Afghan Knife.
By R. LOUIS STEVENSON.
New Arabian Nights.
By BERTHA THOMAS.
Cressida.
The Violin-Player.
By WALTER THORNBURY.
Tales for the Marines.
Old Stories Retold.
By T. ADOLPHUS TROLLOPE.
Diamond Cut Diamond.
By F. ELEANOR TROLLOPE.
Like Ships upon the Sea.
Anne Furness.
Mabel’s Progress.
By ANTHONY TROLLOPE.
Frau Frohmann.
Marion Fay.
Kept in the Dark.
John Caldigate.
The Way We Live Now.
The Land-Leaguers.
The American Senator.
Mr. Scarborough’s Family.
Golden Lion of Granpere.
By J. T. TROWBRIDGE.
Farnell’s Folly.
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade
Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.
textbookfull.com