100% found this document useful (1 vote)
13 views

Data Structures & Algorithms using Kotlin, Second Edition Hemant Jain instant download

The document provides information about the book 'Data Structures & Algorithms using Kotlin, Second Edition' by Hemant Jain, including a link for download. It also lists additional recommended ebooks related to data structures and algorithms in various programming languages. The book covers a wide range of topics including algorithms analysis, sorting, searching, and various data structures.

Uploaded by

nijasawsar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
13 views

Data Structures & Algorithms using Kotlin, Second Edition Hemant Jain instant download

The document provides information about the book 'Data Structures & Algorithms using Kotlin, Second Edition' by Hemant Jain, including a link for download. It also lists additional recommended ebooks related to data structures and algorithms in various programming languages. The book covers a wide range of topics including algorithms analysis, sorting, searching, and various data structures.

Uploaded by

nijasawsar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 76

Data Structures & Algorithms using Kotlin,

Second Edition Hemant Jain install download

https://ebookmeta.com/product/data-structures-algorithms-using-
kotlin-second-edition-hemant-jain/

Download more ebook from https://ebookmeta.com


We believe these products will be a great fit for you. Click
the link to download now, or visit ebookmeta.com
to discover even more!

Problem Solving in Data Structures Algorithms Using C


2nd Edition Hemant Jain

https://ebookmeta.com/product/problem-solving-in-data-structures-
algorithms-using-c-2nd-edition-hemant-jain/

A Common Sense Guide to Data Structures and Algorithms


Second Edition Jay Wengrow

https://ebookmeta.com/product/a-common-sense-guide-to-data-
structures-and-algorithms-second-edition-jay-wengrow/

Data Structures & Algorithms in Python John Canning

https://ebookmeta.com/product/data-structures-algorithms-in-
python-john-canning/

Working with Dynamical Systems: A Toolbox for


Scientists and Engineers (Series in Computational
Biophysics) 1st Edition Len Pismen

https://ebookmeta.com/product/working-with-dynamical-systems-a-
toolbox-for-scientists-and-engineers-series-in-computational-
biophysics-1st-edition-len-pismen/
Apostles of Transformation Anthology of Muslim Women
Trailblazers in India Akhtarul Wasey Juhi Gupta Eds

https://ebookmeta.com/product/apostles-of-transformation-
anthology-of-muslim-women-trailblazers-in-india-akhtarul-wasey-
juhi-gupta-eds/

Find Your Way Home (Small Town Dreams #1) 1st Edition
Jackie Ashenden

https://ebookmeta.com/product/find-your-way-home-small-town-
dreams-1-1st-edition-jackie-ashenden/

MrExcel 2022 Boosting Excel 6th Edition Bill Jelen

https://ebookmeta.com/product/mrexcel-2022-boosting-excel-6th-
edition-bill-jelen-2/

India–Africa Partnerships for Food Security and


Capacity Building : South–South Cooperation 1st Edition
Renu Modi

https://ebookmeta.com/product/india-africa-partnerships-for-food-
security-and-capacity-building-south-south-cooperation-1st-
edition-renu-modi/

Epicurus and the Singularity of Death 1st Edition David


B. Suits

https://ebookmeta.com/product/epicurus-and-the-singularity-of-
death-1st-edition-david-b-suits/
Digitalization and Analytics for Smart Plant
Performance Theory and Applications 1st Edition Frank
(Xin X.) Zhu

https://ebookmeta.com/product/digitalization-and-analytics-for-
smart-plant-performance-theory-and-applications-1st-edition-
frank-xin-x-zhu/
Data Structures &
Algorithms using
Kotlin
Second Edition

By Hemant Jain

Подписывайся на топовый канал по Kotlin:

https://t.me/KotlinSenior
Data Structures & Algorithms using Kotlin
Hemant Jain

Copyright © Hemant Jain, 2022. All Right Reserved.

Hemant Jain asserts the moral right to be identified as the author of this work.

All rights reserved. No part of this publication may be reproduced, stored in or


introduced into a retrieval system, or transmitted, in any form, or by any means
(electrical, mechanical, photocopying, recording or otherwise) without the prior written
permission of the author, except in the case of very brief quotations embodied in
critical reviews and certain other non-commercial uses permitted by copyright law. Any
person who does any unauthorised act in relation to this publication may be liable to
criminal prosecution and civil claims for damages.
ACKNOWLEDGMENT

The author is very grateful to GOD ALMIGHTY for his grace and blessing.

I would like to express profound gratitude to my family and friends for their invaluable
encouragement, supervision and useful suggestions throughout this book writing work.
Their support and continuous guidance enable me to complete my work successfully.

Hemant Jain
Table of Contents
CHAPTER 0: ABOUT THIS BOOK...............................................................................................................................1
CHAPTER 1: ALGORITHMS ANALYSIS.......................................................................................................................2
CHAPTER 2: APPROACH TO SOLVE PROBLEMS......................................................................................................24
CHAPTER 3: ABSTRACT DATA TYPE........................................................................................................................29
CHAPTER 4: SORTING............................................................................................................................................43
CHAPTER 5: SEARCHING........................................................................................................................................82
CHAPTER 6: LINKED LIST......................................................................................................................................153
CHAPTER 7: STACK...............................................................................................................................................206
CHAPTER 8: QUEUE.............................................................................................................................................243
CHAPTER 9: TREE.................................................................................................................................................267
CHAPTER 10: PRIORITY QUEUE / HEAPS..............................................................................................................346
CHAPTER 11: HASH TABLE...................................................................................................................................381
CHAPTER 12: GRAPHS..........................................................................................................................................396
CHAPTER 13: STRING ALGORITHMS....................................................................................................................447
CHAPTER 14: ALGORITHM DESIGN TECHNIQUES................................................................................................467
CHAPTER 15: BRUTE FORCE ALGORITHM............................................................................................................470
CHAPTER 16: GREEDY ALGORITHM.....................................................................................................................475
CHAPTER 17: DIVIDE AND CONQUER..................................................................................................................492
CHAPTER 18: DYNAMIC PROGRAMMING............................................................................................................503
CHAPTER 19: BACKTRACKING..............................................................................................................................541
CHAPTER 20: COMPLEXITY THEORY.....................................................................................................................550
APPENDIX............................................................................................................................................................559
Table of Contents
CHAPTER 0: ABOUT THIS BOOK...............................................................................................................................1
WHAT THIS BOOK IS ABOUT........................................................................................................................................1
PREREQUISITES.........................................................................................................................................................1
WHO SHOULD TAKE THIS COURSE ?..............................................................................................................................1
CODE DOWNLOADS...................................................................................................................................................1
END....................................................................................................................................................................... 1
CHAPTER 1: ALGORITHMS ANALYSIS.......................................................................................................................2
INTRODUCTION........................................................................................................................................................2
ASYMPTOTIC ANALYSIS OR ASYMPTOTIC NOTATIONS.......................................................................................................2
BIG-O NOTATION.....................................................................................................................................................2
OMEGA-Ω NOTATION...............................................................................................................................................3
THETA-Θ NOTATION.................................................................................................................................................4
COMPLEXITY ANALYSIS OF ALGORITHMS........................................................................................................................4
GROWTH OF FUNCTIONS............................................................................................................................................5
DERIVING AN ALGORITHM'S RUNTIME FUNCTION...........................................................................................................7
TIME COMPLEXITY EXAMPLES.....................................................................................................................................7
RECURSIVE FUNCTION.............................................................................................................................................13
COMPLEXITIES FROM RECURRENCE RELATION..............................................................................................................18
MASTER THEOREM.................................................................................................................................................21
EXERCISE...............................................................................................................................................................23
CHAPTER 2: APPROACH TO SOLVE PROBLEMS......................................................................................................24
INTRODUCTION.......................................................................................................................................................24
CONSTRAINTS........................................................................................................................................................24
IDEA GENERATION..................................................................................................................................................25
COMPLEXITIES........................................................................................................................................................26
CODING................................................................................................................................................................27
TESTING................................................................................................................................................................27
EXAMPLE..............................................................................................................................................................28
SUMMARY.............................................................................................................................................................28
CHAPTER 3: ABSTRACT DATA TYPE........................................................................................................................29
ABSTRACT DATA TYPE (ADT)...................................................................................................................................29
DATA-STRUCTURE...................................................................................................................................................29
KOTLIN COLLECTION FRAMEWORK.............................................................................................................................30
ARRAY..................................................................................................................................................................30
LINKED LIST...........................................................................................................................................................31
STACK..................................................................................................................................................................33
QUEUE.................................................................................................................................................................34
TREE.................................................................................................................................................................... 35
BINARY SEARCH TREE (BST).....................................................................................................................................35
HEAP / PRIORITY QUEUE.........................................................................................................................................37
HASH TABLE..........................................................................................................................................................39
ENDNOTE..............................................................................................................................................................42
CHAPTER 4: SORTING............................................................................................................................................43
INTRODUCTION.......................................................................................................................................................43
TYPES OF SORTING..................................................................................................................................................43
COMPARISON FUNCTION..........................................................................................................................................43
BUBBLE SORT........................................................................................................................................................44
INSERTION SORT.....................................................................................................................................................46
SELECTION SORT.....................................................................................................................................................47
MERGE SORT.........................................................................................................................................................49
PROS AND CONS OF MERGE-SORT ALGORITHM............................................................................................................51
EXTERNAL SORT (EXTERNAL MERGE-SORT).................................................................................................................51
QUICK SORT..........................................................................................................................................................52
QUICK SELECT........................................................................................................................................................54
COUNTING SORT....................................................................................................................................................56
RADIX SORT...........................................................................................................................................................57
HEAP SORT...........................................................................................................................................................59
TREE SORTING.......................................................................................................................................................59
SHELL SORT...........................................................................................................................................................59
BUCKET SORT........................................................................................................................................................61
GENERALISED BUCKET SORT.....................................................................................................................................62
STABLE SORTING....................................................................................................................................................63
COMPARISONS OF THE VARIOUS SORTING ALGORITHMS..................................................................................................63
SELECTION OF BEST SORTING ALGORITHM...................................................................................................................64
PROBLEMS BASED ON SORTING..................................................................................................................................65
EXERCISE...............................................................................................................................................................80
CHAPTER 5: SEARCHING........................................................................................................................................82
INTRODUCTION.......................................................................................................................................................82
WHY SEARCHING?..................................................................................................................................................82
DIFFERENT SEARCHING ALGORITHMS..........................................................................................................................82
LINEAR SEARCH OR SEQUENTIAL SEARCH – UNSORTED INPUT.........................................................................................82
LINEAR SEARCH – SORTED........................................................................................................................................83
BINARY SEARCH......................................................................................................................................................84
BINARY SEARCH IMPLEMENTATION USING RECURSION....................................................................................................85
FIBONACCI SEARCH.................................................................................................................................................86
HOW IS SORTING USEFUL IN SELECTION ALGORITHMS?..................................................................................................87
PROBLEMS IN SEARCHING........................................................................................................................................88
EXERCISE.............................................................................................................................................................151
CHAPTER 6: LINKED LIST......................................................................................................................................153
INTRODUCTION.....................................................................................................................................................153
LINKED LIST.........................................................................................................................................................153
TYPES OF LINKED LIST............................................................................................................................................153
SINGLY LINKED LIST...............................................................................................................................................154
DOUBLY LINKED LIST.............................................................................................................................................178
CIRCULAR LINKED LIST...........................................................................................................................................189
DOUBLY CIRCULAR LIST..........................................................................................................................................197
SKIP LIST.............................................................................................................................................................201
USES OF LINKED LIST.............................................................................................................................................203
EXERCISE.............................................................................................................................................................204
CHAPTER 7: STACK...............................................................................................................................................206
INTRODUCTION.....................................................................................................................................................206
THE STACK ABSTRACT DATA TYPE............................................................................................................................206
STACK USING ARRAY..............................................................................................................................................207
STACK USING ARRAY WITH MEMORY MANAGEMENT....................................................................................................209
STACK USING LINKED LIST.......................................................................................................................................210
SYSTEM STACK AND FUNCTION CALLS.......................................................................................................................213
PROBLEMS IN STACK.............................................................................................................................................214
USES OF STACK....................................................................................................................................................241
EXERCISE.............................................................................................................................................................241
CHAPTER 8: QUEUE.............................................................................................................................................243
INTRODUCTION.....................................................................................................................................................243
THE QUEUE ABSTRACT DATA TYPE..........................................................................................................................243
QUEUE USING ARRAY............................................................................................................................................244
QUEUE USING CIRCULAR LINKED LIST.......................................................................................................................245
PROBLEMS IN QUEUE............................................................................................................................................248
USES OF QUEUE...................................................................................................................................................265
EXERCISE.............................................................................................................................................................265
CHAPTER 9: TREE.................................................................................................................................................267
INTRODUCTION.....................................................................................................................................................267
TERMINOLOGY IN TREE..........................................................................................................................................267
BINARY TREE.......................................................................................................................................................269
TYPES OF BINARY TREES.........................................................................................................................................270
PROBLEMS IN BINARY TREE....................................................................................................................................272
BINARY SEARCH TREE (BST)...................................................................................................................................292
PROBLEMS IN BINARY SEARCH TREE (BST)................................................................................................................292
SEGMENT TREE....................................................................................................................................................306
BINARY INDEX TREE / FENWICK TREE.......................................................................................................................310
AVL TREE...........................................................................................................................................................313
RED-BLACK TREE..................................................................................................................................................319
SPLAY TREE.........................................................................................................................................................331
B TREE...............................................................................................................................................................336
B+ TREE.............................................................................................................................................................341
THREADED BINARY TREE........................................................................................................................................342
USES OF TREES.....................................................................................................................................................343
EXERCISE.............................................................................................................................................................343
CHAPTER 10: PRIORITY QUEUE / HEAPS..............................................................................................................346
INTRODUCTION.....................................................................................................................................................346
TYPES OF HEAP....................................................................................................................................................347
HEAP ADT OPERATIONS........................................................................................................................................348
OPERATION ON HEAP............................................................................................................................................348
HEAP SORT.........................................................................................................................................................358
PROBLEMS IN HEAP..............................................................................................................................................363
BINOMIAL HEAP...................................................................................................................................................369
FIBONACCI HEAP..................................................................................................................................................374
USES OF HEAP.....................................................................................................................................................378
EXERCISE.............................................................................................................................................................379
CHAPTER 11: HASH TABLE...................................................................................................................................381
INTRODUCTION.....................................................................................................................................................381
HASH-TABLE........................................................................................................................................................381
HASHING WITH OPEN ADDRESSING..........................................................................................................................383
HASHING WITH SEPARATE CHAINING.........................................................................................................................387
SET IMPLEMENTATION OF KOTLIN COLLECTIONS.........................................................................................................389
DICTIONARY IMPLEMENTATION IN KOTLIN COLLECTION................................................................................................389
PROBLEMS IN HASHING.........................................................................................................................................390
USES OF HASH-TABLE...........................................................................................................................................393
EXERCISE.............................................................................................................................................................393
CHAPTER 12: GRAPHS..........................................................................................................................................396
INTRODUCTION.....................................................................................................................................................396
GRAPH TERMINOLOGY...........................................................................................................................................397
GRAPH REPRESENTATION.......................................................................................................................................401
GRAPH TRAVERSALS..............................................................................................................................................404
DEPTH FIRST TRAVERSAL........................................................................................................................................405
BREADTH FIRST TRAVERSAL....................................................................................................................................407
DFS & BFS BASED PROBLEMS................................................................................................................................410
MINIMUM SPANNING TREE (MST)..........................................................................................................................426
EULER PATH AND EULER CIRCUIT.............................................................................................................................431
SHORTEST PATH ALGORITHMS IN GRAPH..................................................................................................................433
HAMILTONIAN PATH.............................................................................................................................................441
HAMILTONIAN CIRCUIT..........................................................................................................................................443
TRAVELLING SALESMAN PROBLEM (TSP)..................................................................................................................444
USES OF GRAPH ALGORITHMS.................................................................................................................................446
EXERCISE.............................................................................................................................................................446
CHAPTER 13: STRING ALGORITHMS....................................................................................................................447
INTRODUCTION.....................................................................................................................................................447
STRING MATCHING...............................................................................................................................................447
DICTIONARY / SYMBOL TABLE.................................................................................................................................451
PROBLEMS IN STRING............................................................................................................................................458
EXERCISE.............................................................................................................................................................465
CHAPTER 14: ALGORITHM DESIGN TECHNIQUES................................................................................................467
INTRODUCTION.....................................................................................................................................................467
BRUTE FORCE ALGORITHM.....................................................................................................................................467
GREEDY ALGORITHM.............................................................................................................................................468
DIVIDE AND CONQUER...........................................................................................................................................468
DYNAMIC PROGRAMMING......................................................................................................................................468
BACKTRACKING....................................................................................................................................................469
CONCLUSION.......................................................................................................................................................469
CHAPTER 15: BRUTE FORCE ALGORITHM............................................................................................................470
INTRODUCTION.....................................................................................................................................................470
PROBLEMS IN BRUTE FORCE ALGORITHM..................................................................................................................470
CONCLUSION.......................................................................................................................................................474
CHAPTER 16: GREEDY ALGORITHM.....................................................................................................................475
INTRODUCTION.....................................................................................................................................................475
PROBLEMS ON GREEDY ALGORITHM.........................................................................................................................475
CONVEX-HULL PROBLEM........................................................................................................................................489
CONCLUSION.......................................................................................................................................................491
CHAPTER 17: DIVIDE AND CONQUER..................................................................................................................492
INTRODUCTION.....................................................................................................................................................492
GENERAL DIVIDE & CONQUER RECURRENCE..............................................................................................................493
PROBLEMS ON DIVIDE & CONQUER ALGORITHM........................................................................................................493
STRASSEN’S MATRIX MULTIPLICATION......................................................................................................................499
EXERCISE.............................................................................................................................................................501
CHAPTER 18: DYNAMIC PROGRAMMING............................................................................................................503
INTRODUCTION.....................................................................................................................................................503
DYNAMIC PROGRAMMING METHODS.......................................................................................................................504
TABULATION (BOTTOM-UP)...................................................................................................................................504
MEMOIZATION (TOP-DOWN).................................................................................................................................505
DYNAMIC PROGRAMMING PATTERNS.......................................................................................................................506
TYPE 1 : MAXIMUM / MINIMUM COST TO REACH SOME STATE PROBLEMS......................................................................508
TYPE 2 : DISTINCT WAYS TO REACH SOME STATE PROBLEMS.........................................................................................513
TYPE 3 : MERGING INTERVALS TO GET OPTIMAL SOLUTION PROBLEMS............................................................................517
TYPE 4 : SUBSEQUENCE, SUBSTRINGS AND STRING MANIPULATION PROBLEMS................................................................525
TYPE 5 : STATE SELECTION KIND OF PROBLEMS..........................................................................................................534
EXERCISE.............................................................................................................................................................539
CHAPTER 19: BACKTRACKING..............................................................................................................................541
INTRODUCTION.....................................................................................................................................................541
PROBLEMS ON BACKTRACKING ALGORITHM...............................................................................................................542
EXERCISE.............................................................................................................................................................549
CHAPTER 20: COMPLEXITY THEORY.....................................................................................................................550
INTRODUCTION.....................................................................................................................................................550
DECISION PROBLEM..............................................................................................................................................550
COMPLEXITY CLASSES............................................................................................................................................550
CLASS P PROBLEMS..............................................................................................................................................551
CLASS NP PROBLEMS............................................................................................................................................552
REDUCTION.........................................................................................................................................................553
NP HARD PROBLEMS............................................................................................................................................554
NP-COMPLETE PROBLEMS.....................................................................................................................................554
CLASS CO-NP PROBLEMS.......................................................................................................................................558
END NOTE..........................................................................................................................................................558
APPENDIX............................................................................................................................................................559
CHAPTER 0: ABOUT THIS BOOK

What this book is about


This book will take you through basic to advanced data structures and algorithms. Data structures
define how data is arranged in memory for fast and efficient access. An algorithm is a finite set of
unambiguous instructions to solve problems by manipulating various data structures.

Designing an efficient algorithm is a very important skill that all software companies pursue. Most of
the interviews for software companies are focused on knowledge of data structures and algorithms.
Apart from knowing a programming language, you also need to have a good command of these key
computer fundamentals to not only crack the interview but also excel in your jobs as a software
engineer.

Prerequisites
You should have a working knowledge of Kotlin programming language. You are not an expert in the
Kotlin language, but you are well familiar with concepts of classes, functions, references, and
recursion.

Who should take this course ?


If you’re planning to pursue a career in the Kotlin language, get better at it and apply for a job, this
book is best for you. If you can put a reasonable amount of time into this book by reading various
concepts and solving the various problems on data structures, you can become an expert in data
structures and algorithms.

Code downloads
You can download the code of solved examples in the book from the author's GitHub repositories at
https://GitHub.com/Hemant-Jain-Author/. Hear the author had solved examples in various
programming languages like C, C++, C#, Java, Python, JavaScript, Swift, GoLang, Ruby, etc.

End
It is highly recommended that you should read the problem statement, try to solve the problems by
yourself and then only you should look into the solution to find the approach of this book. Practising
more and more problems will increase your thinking capacity, and you will be able to handle unseen
problems in an interview. We recommend you to practice all the problems given in this book, then
solve more and more problems from online resources like www.topcoder.com, www.careercup.com,
https://leetcode.com/ etc.

1
CHAPTER 1: ALGORITHMS ANALYSIS

Introduction
An Algorithm is a finite set of unambiguous steps or instructions to solve a given problem. Knowledge
of algorithms helps us to get desired results faster by applying the appropriate algorithm. We learn by
experience. With experience, it becomes easy to solve new problems. By looking into various problem-
solving algorithms or techniques, we begin to develop a pattern that will help us in solving similar
problems.

The properties of an algorithm are:


1. It takes zero or more inputs.
2. It should produce one or more output.
3. It should be Deterministic. It produces the same output if the same input is provided again.
4. It should be Correct. It should be correct and able to process all the given inputs and provide the
correct output.
5. It should Terminate in a finite time.
6. It should be Efficient. The algorithm should be efficient in solving problems.

The complexity of an algorithm is the amount of Time or Space required by the algorithm to process
the input and produce the output.

There are two types of Complexity:


1. First is Time-Complexity, how much time is required by an algorithm to produce output for an
input of size ‘n’.
Time-Complexity is represented by function T(n) - time required versus the input size n.
2. Second is Space-Complexity, how much RAM or memory that an algorithm is going to
consume to produce output for an input of size ‘n’.
Space-Complexity is represented by function S(n) - memory used versus the input size n.

Asymptotic Analysis or Asymptotic Notations


Calculating the running time of any algorithm in mathematical units of computation is known as
Asymptotic Analysis. The efficiency of algorithms is calculated using asymptotic analysis, independent
of the given data set or programming language.

In most cases, we are interested in the order of growth of the algorithm instead of the exact time
required for running an algorithm. This time is also known as Asymptotic Running Time.

Big-O Notation
Definition: “f(n) is big-O of g(n)” or f(n) = O(g(n)), if there are two +ve constants c and n1 such that f(n)
≤ c g(n) for all n ≥ n1,

2
Chapter 1: Algorithms Analysis Big-O Notation

In other words, c g(n) is an upper bound for f(n) for all n ≥ n0. The function f(n) growth is slower than c
g(n). For a sufficiently large value of input n, the (c.g(n)) will always be greater than f(n).

Example : n^2 + n = O(n^2)

Omega-Ω Notation
Definition: “f(n) is omega of g(n)” or f(n)=Ω(g(n)) if there are two +ve constants c and n1 such that c
g(n) ≤ f(n) for all n ≥ n1
In other words, c g(n) is the lower bound for f(n). Function f(n) growth is faster than c g(n)

Find relationship of f(n) = nc and g(n) = cn


f(n) = Ω(g(n))

3
Chapter 1: Algorithms Analysis Theta-Θ Notation

Theta-Θ Notation
Definition: “f(n) is theta of g(n).” or f(n) = Θ(g(n)) if there are three +ve constants c1, c2 and n1 such
that c1 g(n) ≤ f(n) ≤ c2 g(n) for all n ≥ n1

Function g(n) is an asymptotically tight bound on f(n). Function f(n) grows at the same rate as g(n).

Example: n^3 + n^2 + n = Ɵ(n^3)


Example: n^2 + n = Ɵ(n^2)
Find relationship of f(n) = 2n^2 + n and g(n) = n^2
f(n) = O(g(n))
f(n) = Ɵ(g(n))
f(n) = Ω(g(n))

Complexity analysis of algorithms


The complexity of an algorithm are analysed in three categories:
➢ Worst-Case Complexity: The worst-case complexity represents the maximum number of steps
required to execute an algorithm. It provides us with the upper bound of an algorithm. Usually, we
use this complexity to judge algorithm performance.
➢ Best-Case Complexity:The best-case complexity represents the minimum number of steps
required to execute an algorithm. It provides us with the lower bound of an algorithm.
➢ Average-Case Complexity:The average-case complexity represents the average number of steps
required to execute an algorithm. We take the average of the steps executed in all the cases to
calculate average-case complexity.

Note: Worst-case complexity is used to find the guarantee in how much time some particular algorithm
will finish. This is the most important time complexity. If the type of complexity is not mentioned, then
always consider Worst-Case time complexity.

4
Chapter 1: Algorithms Analysis Growth of functions

Growth of functions
Let’s look at these growth rates of various functions. The size of the input is n.

Constant Time, O(1)


An algorithm is said to run in constant time if the output is produced in constant time, regardless of the
input size.

Examples:
1 Accessing an nth element of an Array
2 Push and pop of a stack.
3 Add and remove from a queue.
4 Accessing an element of Hash-Table.

Linear Time, O(n)


An algorithm is said to run in linear time if the execution time of the algorithm is directly proportional to
the input size.

Examples:
1 Array operations like search element, find min, find max etc.
2 Linked list operations like traversal, find min, find max etc.

Note: If we need to traverse all the nodes of a data structure for some task, then complexity cant be
less than O(n)

Logarithmic Time, O(log(n))


An algorithm is said to run in logarithmic time if the execution time of the algorithm is proportional to
the logarithm of the input size. In each step of an algorithm, a significant portion (e.g. half portion) of
the input is pruned/rejected out without traversing it.

An example is the Binary search algorithm. We will read about this algorithm in this book.

n.log(n) Time, O(n.log(n))


An algorithm is said to run in n*log(n) time if the execution time of an algorithm is proportional to the
product of input size and logarithm of the input size. In these algorithms, each time the input is divided
into half (or some proportion) and each portion is processed independently.

Examples are Merge-Sort, Quick-Sort (average case), Heap-Sort etc.

5
Chapter 1: Algorithms Analysis Growth of functions

Quadratic Time, O(n^2)


An algorithm is said to run in quadratic time if the execution time of an algorithm is proportional to the
square of the input size. In these algorithms, each element is compared with all the other elements.
Examples are Bubble-Sort, Selection-Sort, Insertion-Sort

Exponential Time O(2^n)


In these algorithms, all possible subsets of elements of input data are generated. Its common example
is the power set.

Factorial Time O(n!)


In these algorithms, all possible permutations of the elements of input data are generated. Finding
permutations is a common example of factorial time.

A list of commonly occurring algorithm Time Complexity in increasing order:


Name Notation
Constant O(1)
Logarithmic O(log(n))
Linear O(n)
N.Log(N) O(n.log(n))
Quadratic O(n^2)
Polynomial O(n^c) c is a constant & c>1
Exponential O(c^m) c is a constant & c>1
Factorial O(n!)
N-Power-N O(n^n)

The time taken by certain algorithms to run varies dramatically with the size of the input. Some
algorithms take minutes or even seconds to run on huge input, whereas others may take days to
complete their execution. To understand how the rate of growth changes with the size of the input in
different functions, the following table presents the approximate number of steps required to run an
algorithm:

Function Growth Rate (Approximate)


N O(1) O(log(n)) O(n) O(n.log(n)) O(n^2) O(n^3) O(2^n)

10 1 3 10 30 102 103 103


102 1 6 102 6x102 104 106 1030
103 1 9 103 9x103 106 109 10300
104 1 13 104 13x104 108 1012 103000
105 1 16 105 16x105 1010 1015 1030000
106 1 19 106 19x106 1012 1018 10300000

6
Chapter 1: Algorithms Analysis Deriving an Algorithm's Runtime Function

Deriving an Algorithm's Runtime Function

Constants
If any line of code is a statement with basic operations, e.g., comparisons, assignments, or reading a
variable, they take constant time each. Thus, the time complexity of each statement is O(1).

Loops
In loop, a repetition of a particular code for n times, where n is the size of the loop. Every statement
inside the loop has a runtime of O(1). The running time of a loop is a product of the running time of the
statement inside a loop and the number of iterations in the loop. Time Complexity is O(n)

Nested Loops
The running time of a nested loops is a product of the running time of the statements inside the loop
multiplied by a product of the size of all the loops. Time Complexity is O(n^c). Where c is the number of
loops. For two loops, it will be O(n^2)

Consecutive Statements
In this case, we add the running time of all the consecutive lines of code.

If-Else Statement
In this case, either “if” will run or “else” will run. So, the block with larger runtime will be considered.

Logarithmic Statement
In this case, each iteration will cut the input size into b pieces and consider one of the pieces for the
next iteration. Time complexity in this situation will be O(logb(n)).

Time Complexity Examples


Example 1.1: Single loop
fun fun1(n: Int): Int {
var m = 0
for (i in 0 until n) {
m += 1
}
return m
}

// Testing code.
fun main() {
println("N = 100, Number of instructions O(n):: " + fun1(100))
}

Output:
N = 100, Number of instructions in O(n)::100

Time Complexity: O(n), single loop takes linear time.

7
Chapter 1: Algorithms Analysis Time Complexity Examples

Example 1.2: Nested loops


fun fun2(n: Int): Int {
var m = 0
for (i in 0 until n) {
for (j in 0 until n) {
m += 1
}
}
return m
}

// Testing code.
fun main() {
println("N = 100, Number of instructions O(n^2):: " + fun2(100))
}

Output:
N = 100, Number of instructions in O(n^2)::10000

Time Complexity: O(n^2), two nested for loop, takes quadratic time. Both the “for” loop is executed n
number of times, so the internal statement executed n^2 number of times.

Example 1.3: Triple nested loops


fun fun3(n: Int): Int {
var m = 0
for (i in 0 until n) {
for (j in 0 until n) {
for (k in 0 until n) {
m += 1
}
}
}
return m
}

// Testing code.
fun main() {
println("N = 100, Number of instructions O(n^3):: " + fun3(100))
}

Output:
N = 100, Number of instructions in O(n^3)::1000000

Time Complexity: O(n^3), All the three nested loops run for n number of iterations. So the statement
inside the innermost loop will run for n^3 number of times.

Example 1.4: Triple nested loops


fun fun4(n: Int): Int {
var m = 0
for (i in 0 until n) {
for (j in i until n) {
for (k in j+1 until n) {
m += 1
}
}

8
Chapter 1: Algorithms Analysis Time Complexity Examples

}
return m
}

// Testing code.
fun main() {
println("N = 100, Number of instructions O(n^3):: " + fun4(100))
}

Output:
N = 100, Number of instructions in O(n^3)::166650

Time Complexity: Three nested loops each run for n number of times. The innermost statement will
run for n^3 number of times. Time complexity is O(n^3)

Example 1.5: Arithmetic Progression


fun fun5(n: Int): Int {
var m = 0
for (i in 0 until n) {
for (j in 0 until i) {
m += 1
}
}
return m
}

// Testing code.
fun main() {
println("N = 100, Number of instructions O(n^2):: " + fun5(100))
}

Output:
N = 100, Number of instructions in O(n^2)::4950

Time Complexity: Statement inside inner loop executes for 1 time in first iteration then 2 times then 3
times and so on for n iterations. Total number of times the inner statement is executed = 1 + 2+ 3 +…..
+ n. This series is an arithmetic progression, which sums to n(n+1)/2. So the final time complexity is
O(n(n+1)/2) ignoring the constant factors, time complexity will be O(n^2).

Example 1.6: Arithmetic Progression


fun fun6(n: Int): Int {
var m = 0
for (i in 0 until n) {
for (j in i downTo 0) {
m += 1
}
}
return m
}

// Testing code.
fun main() {
println("N = 100, Number of instructions O(n^2):: " + fun6(100))
}

9
Chapter 1: Algorithms Analysis Time Complexity Examples

Output:
N = 100, Number of instructions in O(n^2)::5050

Time Complexity: The inner loop will run 1 time in the first iteration, then 2 times in the second
iteration and so on. It is an arithmetic progression, so time complexity will be O(n^2).

Example 1.7: Nested loops / Geometric Progression


fun fun7(n: Int): Int {
var m = 0
var i = n
while (i > 0) {
var j = 0
while (j < i) {
m += 1
j++
}
i /= 2
}
return m
}

// Testing code.
fun main() {
println("N = 100, Number of instructions O(n):: " + fun7(100))
}

Output:
N = 100, Number of instructions in O(n)::197

For nested loops, look for inner loop iterations. Time complexity will be calculated by looking into the
inner loop. First, it will run for n number of times then n/2 and so on. (n+n/2 +n/4+n/8+n/16 ……)
Time Complexity: O(n)

Example 1.8: Geometric Progression


fun fun8(n: Int): Int {
var m = 0
var i = 1
while (i <= n) {
var j = 0
while (j <= i) {
m += 1
j++
}
i *= 2
}
return m
}

// Testing code.
fun main() {
println("N = 100, Number of instructions O(n):: " + fun8(100))
}

10
Chapter 1: Algorithms Analysis Time Complexity Examples

Output:
N = 100, Number of instructions in O(n)::134

Time Complexity: The inner loop will run for 1, 2, 4, 8,… n times in successive iteration of the outer
loop. T(n) = O(1+ 2+ 4+ ….+n/2+n) = O(n)

Example 1.9: Double the iteration variable


fun fun9(n: Int): Int {
var m = 0
var i = 1
while (i < n) {
m += 1
i = i * 2
}
return m
}

// Testing code.
fun main() {
println("N = 100, Number of instructions O(log(n)):: " + fun9(100))
}

Output:
N = 100, Number of inst in O(log(n))::7

In each iteration, i value is doubled. So the value of i after k iterations will be 2^k.
2^k = n ...Will be the condition at the time of exit.
log(2^k) = log(n) ….Taking log both sides.
k = log(n)
Time Complexity: O(log(n))

Example 1.10: Half the iteration variable


fun fun10(n: Int): Int {
var m = 0
var i = n
while (i > 0) {
m += 1
i = i / 2
}
return m
}

// Testing code.
fun main() {
println("N = 100, Number of instructions O(log(n)):: " + fun10(100))
}

Output:
N = 100, Number of instructions in O(log(n))::7

The initial value of i is n. In each iteration, the value of “i” is halved.


So the value of i after k iterations will be n/2^k.

11
Chapter 1: Algorithms Analysis Time Complexity Examples

At the time of exit, n/ 2^k = 1


n = 2^k // At the time of exit.
log(2^k) = log(n) // Taking log both sides.
k = log(n)
Time Complexity: O(log(n))

Example 1.11: Consecutive Statements


fun fun11(n: Int): Int {
var m = 0
for (i in 0 until n) {
for (j in 0 until n) {
m += 1
}
}

for (i in 0 until n) {
for (k in 0 until n) {
m += 1
}
}
return m
}

// Testing code.
fun main() {
println("N = 100, Number of instructions O(n^2):: " + fun11(100))
}

Output:
N = 100, Number of instructions in O(n^2)::20000

These two groups of loops are consecutive, so their complexity will add up to form the final complexity
of the program.
Time Complexity: O(n^2) + O(n^2) = O(n^2)

Example 1.12:
fun fun12(n: Int): Int {
var m = 0
for (i in 0 until n) {
for (j in 0 until Math.sqrt(n.toDouble()).toInt()) {
m += 1
}
}
return m
}

// Testing code.
fun main() {
println("N = 100, Number of instructions O(n^(3/2)):: " + fun12(100))
}

Output:
N = 100, Number of instructions in O(n^(3/2))::1000

12
Chapter 1: Algorithms Analysis Time Complexity Examples

Time Complexity: Inner loop always runs for √n times. O(n * √n ) = O(n^3/2)

Example 1.13: Multiple loops in O(n)


fun fun13(n: Int): Int {
var m = 0
var i = 0
var j = 0
while (i < n) {
while (j < n) {
m += 1
j++
}
i++
}
return m
}

// Testing code.
fun main() {
println("N = 100, Number of instructions O(n):: " + fun13(100))
}

Output:
N = 100, Number of instructions in O(n)::100

Time Complexity: In this example, j is not initialised for every iteration. For i=0, the loop of j executes
completely, making the value of j as n. But for the remaining values of i, the loop of j does not execute.
So the time complexity in this case is O(n).

Recursive Function
Recursion: A recursive function is a function that calls itself, directly or indirectly. A recursive method
consists of two parts: Termination Condition and Body (which includes recursive expansion).
1 Termination Condition: A recursive method always contains one or more terminating conditions.
A condition in which a recursive method processes a simple case and does not call itself.
2 Body (including recursive expansion): The main logic of the recursive method is contained in the
body of the method. It also contains the recursion expansion statement that, in turn, calls the
method itself.

Three important properties of the recursive algorithm are:


1. A recursive algorithm must have a termination condition.
2. A recursive algorithm must change its state, and shift state towards the termination condition.
3. A recursive algorithm must be capable of calling itself.

Note: The speed of a recursive program is slower because of stack overheads. If the same problem
can be solved using an iterative solution (using loops), then we should prefer an iterative solution in
place of recursion to avoid stack overhead.

Note: Without termination conditions, the recursive method may run forever and consume full-stack
memory.

13
Chapter 1: Algorithms Analysis Recursive Function

Factorial
Problem: Given a value N find N!. Where N! = N* (N-1)…. 2*1. Use recursion to solve the problem.

Example 1. 14: Factorial Calculation.


fun factorial(i:Int):Int {
// Termination Condition
if (i <= 1) {
return 1
}
// Body, Recursive Expansion
return i * factorial(i - 1)
}

// Testing code.
fun main() {
println("Factorial:" + factorial(5))
}

Output:
Factorial:120

Analysis: We calculate factorial(i) as i*factorial(i-1) recursively.

Function F(n) calls F(n-1)


T(n) = T(n-1) + 1
T(n-1) = T(n-2) + 1
T(n-2) = T(n-3) + 1
T(n) = T(n-1) + 1 = (T(n-2) + 1) + 1 = T(n-2) + 2 = (T(n-3) + 1) + 2 = T(n-3) + 3
Similarly, for kth term T(n) = T(n-k) + k
for base case (n-k) = 1 or n – 1 = k
T(n) = T(1) + n -1 = n
Time Complexity is O(n)

Print Base 16 Integers


Problem: Given an integer in decimal form, print its hexadecimal form. Use recursion to solve the
problem.

Example 1.15: Generic print to some specific base method.


fun printInt(numberInput:Int, base:Int) {
var conversion = "0123456789ABCDEF"
var number = numberInput
var digit = conversion[number % base]

number = number / base


if (number != 0) {
printInt(number, base)
}
print(digit)
}

14
Chapter 1: Algorithms Analysis Recursive Function

// Testing code.
fun main() {
var i = 1000
printInt(i, 16)
}

Output:
3E8

Analysis:
1 The base value is provided along with the number in the function parameter.
2 The remainder of the number is calculated and stored in digits.
3 If the number is greater than the base, then the number divided by the base is passed recursively
as an argument to the print() method.
4 The number will be printed higher-ordered first, then the lower order digits.

Time Complexity is O(n), Where n is the number of digits.

Tower of Hanoi
Problem: In the Tower of Hanoi, we are given three rods and N number of disks, initially all the disks
are added to the first rod (the leftmost one) such that no smaller disk is under the larger one. The
objective is to transfer the entire stack of disks from the first tower to the third tower (the rightmost
one), moving only one disk at a time. Moving a larger disk onto a smaller one is not allowed.

Solution: If we want to transfer N disks from source to destination tower. Let's consider the bottom-
most disk, it is the largest disk so can not be placed to any other tower except the destination tower.
Also, all the disks above the largest disk need to be placed in the temporary tower, then only the
largest disk can be moved to the destination tower. So we move N-1 disks from source to temporary
tower and then move the lowest Nth disk from source to destination. Then we will move N-1 disks from
the temporary tower to the destination tower.

Example 1.16:
fun towerOfHanoi(num:Int, src:Char, dst:Char, temp:Char) {
if (num < 1) {
return
}

15
Chapter 1: Algorithms Analysis Recursive Function

towerOfHanoi(num - 1, src, temp, dst)


println("Move " + num + " disk from peg " + src + " to peg " + dst)
towerOfHanoi(num - 1, temp, dst, src)
}

// Testing code.
fun main() {
var num = 3
println("Moves involved in the Tower of Hanoi are:")
towerOfHanoi(num, 'A', 'C', 'B')
}

Output:
Moves involved in the Tower of Hanoi are:
Move 1 disk from peg A to peg C
Move 2 disk from peg A to peg B
Move 1 disk from peg C to peg B
Move 3 disk from peg A to peg C
Move 1 disk from peg B to peg A
Move 2 disk from peg B to peg C
Move 1 disk from peg A to peg C

Analysis:
Recurrence Relation: T(n) = 1 + 2T(n-1)
T(n-1) = 1 + 2*T(n-2)
T(n-2) = 1 + 2*T(n-3)
T(n) = 1 + 2*( 1 + 2*T(n-2)) = 1 + 2 + 4*T(n-2) = 1 + 2 + 4*( 1 + 2*(T(n-3)) = 1 + 2+ 22+ 23T(n-3)
= 1 + 2 + 22 …. + 2nT(0) = 1(2n+1 – 1)/2 – 1 = 2n+1 – 1 // Geometric progression sum
Time complexity will be O(2^n) ignoring the constants.

Greatest Common D ivisor (GCD)


Problem: Find the greatest common divisor of two numbers using recursion.

Solution: There are many ways to find the greatest common divisor (GCD). We are using Euclid’s
algorithm to find the GCD. The following are steps of Euclid’s algorithm:
1. If n = 0 then GCD(n, m) = m, and this is a termination condition.
2. If m = 0 then GCD(n, m) = n, and this is a termination condition.
3. Write n in the form of a quotient remainder n = mq + q. q is the quotient, and r is the remainder.
4. Since GCD(n, m) = GCD(m, r), use the Euclidean Algorithm to find GCD(m , r).

Example 1.17:
fun gcd(m:Int, n:Int):Int {
if (m == 0) {
return n
}

if (n == 0) {
return m
}

16
Chapter 1: Algorithms Analysis Recursive Function

return gcd(n, m % n)
}

// Testing code.
fun main() {
println("Gcd is:: " + gcd(5, 2));
}

Output:
Gcd is:: 1

Time-Complexity: O(Max(log(m), log(n))), Each step input is reduced by nearly half or more.

Fibonacci number
Problem: Given N, find the Nth number in the Fibonacci series.

Solution: Fibonacci numbers are calculated by adding the sum of the previous two numbers.
Example 1.18:
fun fibonacci(n:Int):Int {
if (n <= 1) {
return n
}

return fibonacci(n-1) + fibonacci(n-2)


}

// Testing code.
fun main() {
println(fibonacci(10));
}

Output:
55

Analysis: Recurrence Relation: T(n) = 1 + T(n-1) + T(n-2)


T(n) = 1 + 2T(n-1) // Approximately
T(n) = 1 + 2T(n-1)
T(n-1) = 1 + 2T(n-2)
T(n-2) = 1 + 2T(n-3)
T(n) = 1 + 2( 1 + 2T(n-2)) = 1 + 2 + 4T(n-2) = 1 + 2 + 4 ( 1 + 2(T(n-3)) = 1 + 2+ 22+ 23T(n-3)
= 1 + 2 + 22 …. + 2nT(0) = 1(2n+1 – 1)/2 – 1 = 2n+1 – 1 // Geometric progression sum
Time complexity is O(2^n), ignoring the constants.

Note: - There is an inefficiency in the solution. We will look for a better solution in the coming chapters.

17
Chapter 1: Algorithms Analysis Complexities from Recurrence Relation

Complexities from Recurrence Relation


Example 1.19: Find complexity of the function with the following recurrence relation.
T(n) =
{T (n−1 1)+1if n=0if n> 0
Solution:
T(n) = T(n-1) + 1
T(n-1) = T(n-2) + 1
T(n-2) = T(n-3) + 1
T(n) = ( T(n-2) + 1) + 1 = T(n-2) + 2 = (T(n-3) + 1) + 2 = T(n-3) + 3
T(n) = T(n-k) + k
base case when T(0) = 1, n-k = 0 => n = k
T(n) = T(0) + n = 1 + n
Time Complexity is O(n)

Example 1.20: Find complexity of the function with the following recurrence relation.

T(n) =
{T ( n−11)+nif n=0if n>0
Solution:
T(n) = T(n-1) + n
T(n-1) = T(n-2) + n
T(n-2) = T(n-3) + n
T(n) = ( T(n-2) + n) + n = T(n-2) + 2n = (T(n-3) + n) + 2n = T(n-3) + 3n
T(n) = T(n-k) + kn
base case when T(0) = 1, n-k = 0 => n = k
T(n) = T(0) + n*n = 1 + n^2
Time Complexity is O(n^2)

Example 1.21: Find complexity of the function with the following recurrence relation.

T(n) =
{1T (n− 1)+ log (n) ififn=0
n>0

Solution:
T(n) = T(n-1) + log(n)
T(n-1) = T(n-2) + log(n) // for simplicity make log(n-1) as log(n)
T(n-2) = T(n-3) + log(n)
T(n) = ( T(n-2) + log(n)) + log(n) = T(n-2) + 2log(n) = (T(n-3) + log(n)) + 2log(n) = T(n-3) + 3log(n)

18
Chapter 1: Algorithms Analysis Complexities from Recurrence Relation

T(n) = T(n-k) + klog(n)


base case when T(0) = 1, n-k = 0 => n = k
T(n) = T(0) + n*log(n) = 1 + n.log(n)
Time Complexity is O(n.log(n))

Recurrence Relation Time-Complexity


T(n) = T(n-1) + 1 O(n)
T(n) = T(n-1) + n O(n^2)
T(n) = T(n-1) + log(n) O(n.log(n))
T(n) = T(n-c) + 1 , c is a constant O(n) , complicity is not changed by c.
T(n) = T(n-c) + b , c is a constant and b is a polynomial O(n*b), generalised above 4 cases.

Example 1.22: Find complexity of the function with the following recurrence relation.

T(n) =
{T (n/12)+nif n=1if n>1
Solution:
T(n) = T(n/2) + n
T(n/2) = T(n/22) + (n/2) // substituting n as n/2
T(n/22) = T(n/23) + (n/22) // substituting n as n/22
T(n) = ( T(n/22) + (n/2) ) + n = T(n/22) + n/2 + n
T(n) = ( T(n/23) + (n/22) ) + n/2 + n = T(n/23) + n/22 + n/2 + n
T(n) = T(n/2^k) + n/2^(k-1) + …… + n/22 + n/2 + n
base case when n = 2^k,
T(n) = T(1) + n/2^k-1 + …… + n/22 + n/2 + n
T(n) = T(1) + n * ( 1/2^(k-1) + …… + 1/22 + 1/2 + 1 )
T(n) = 1 + n*2
Time Complexity is O(n)

Example 1.23: Find complexity of the function with the following recurrence relation.

T(n) =
{2∗
1 if n=1
T (n/2)+ n if n>1

Solution:
T(n) = 2 T(n/2) + n
T(n/2) = 2 T(n/22) + (n/2) // substituting n as n/2
T(n/22) = 2 T(n/23) + (n/22) // substituting n as n/22

19
Chapter 1: Algorithms Analysis Complexities from Recurrence Relation

T(n) = 2 ( 2 T(n/22) + (n/2) ) + n = 22 T(n/22) + 2n


T(n) = 22 ( 2 T(n/23) + (n/22) ) + 2n = 23T(n/23) + 3n
T(n) = 2^k.T(n/2^k) + kn
base case when n = 2^k,
k = log(n)
T(n) = n*T(1) + k*n
T(n) = n + k*n = n + n*log(n)
Time Complexity is O(n.log(n))

Example 1.24: Find complexity of the function with the following recurrence relation.

T(n) =
{12∗ T (n −1)+1 if n=0
if n>0

Solution:
T(n) = 2 T(n-1) + 1
T(n-1) = 2T(n-2) + 1
T(n-2) = 2T(n-3) + 1
T(n) = 2( 2T(n-2) + 1) + 1 = 22T(n-2) + 2 + 1 = 22 (2T(n-3) + 1) + 2 + 1 = 23T(n-3) + 22 + 2 + 1
T(n) = 2kT(n-k) + 2(k-1) + ….. + 22 + 2 + 1
base case when T(0) = 1, n-k = 0 => n = k
T(n) = 2nT(0) + 2(n-1) + ….. + 22 + 2 + 1 = 2n + 2(n-1) + ….. + 22 + 2 + 1 = 2(n+1) – 1 // GP
Time Complexity O(2^n)

Example 1.25: Find complexity of the function with the following recurrence relation.

T(n) =
{T (√1 n)+1 if n ≤2
if n>2

Solution:
T(n) = T(n1/2) + 1
T(n1/2) = T( n1/4) + 1
T(n1/4) = T( n1/8) + 1
T(n) = T(n1/2) + 1 = (T( n1/4) + 1) + 1 = T( n1/4) + 2 = (T( n1/8) + 1) + 2 = T( n1/8) + 3
T(n) = T(n1/2k) + k
for base case n,1/2k = 2
(1/(2^k) ) * log(n)= log2 = 1 // taking log.
log(n) = 2^k
log(log(n)) = k log(2) = k // taking log again.
Time Complexity is O(log(log(n)))

20
Chapter 1: Algorithms Analysis Master Theorem

Master Theorem
The master theorem solves recurrence relations of the form: T(n) = a T(n/b) + f(n), Where a≥1 and
b>1. In this relation, “n” is the size of the input. "a" is the number of sub-problems in the recursion.
“n/b” is the size of each sub-problem. "f(n)" is the cost of the division of the problem into sub-problems
and merging the individual solutions of the sub-problems into the solution.

It is possible to determine an asymptotic tight bound in these three cases:


logba-ε logba
Case 1: When f(n) = O(n ) and constant Є > 1, then the final time complexity is T(n) = O(n )

Case 2: When f(n) = Θ(n


logba.
logkn) and constant k ≥ 0, then the final time complexity is

T(n) = Θ(n
logba. k+1
log n)
logba+ε
Case 3: When f(n) = Ω(n ) and constant Є > 1, then the final time complexity is T(n) = Θ(f(n))

Master theorem flow diagram

Example 1.26: In the case of Merge Sort. Its time complexity is T(n) = 2 T(n/2) + n
Solution: In this example, a and b both equal to 2. So, logba = log22 = 1.
Which means, f(n) = n = Θ(nlog22log0n). That means case 2 is applied and T(n) = Θ(nlog22log0+1n).
So, its final time complexity will be T(n) = Θ(n.log(n))

Example 1.27: It is the case of Binary Search, Its time complexity is T(n) = T(n/2) + 1
Solution: In this example, a is equal to 1 and b is equal to 2. So, logba = log21 = 0
Which means, f(n) = 1 = Θ(nlog21log0n). That means case 2 is applied and T(n) = Θ(nlog21log0+1n).
So, its final time complexity will be T(n) = Θ(log(n))

21
Chapter 1: Algorithms Analysis Master Theorem

Example 1.28: In the case of binary tree traversal, Its time complexity is T(n) = 2T(n/2) + 1
Solution: In this example, a is equal to 2 and b is also equal to 2. So, logba = log22 = 1
Which means, f(n) =1 = O(nlog22 - 1). That means case 1 is applied and T(n) = Θ(nlog22).
So, its final time complexity will be T(n) = Θ(n)

Example 1.29: T(n) = 2 T(n/2) + n^2


Solution: In this example, a is equal to 2 and b is also equal to 2. So, logba = log22 = 1
Which means, f(n) = n^2 = Ω(nlog22 + 1). That means case 3 is applied and T(n) = Θ(f(n)).
So, its final time complexity will be T(n) = Θ(n^2)

Example 1.30: T(n) = 4 T(n/2) + n^2


Solution: In this example, a is equal to 4 and b is equal to 2. So, logba = log24 = 2.
Which means, f(n) = n^2 = Θ(nlog24log0n). That means case 2 is applied and T(n) = Θ(nlog24log0+1n).
So, its final time complexity will be T(n) = Θ(n^2 * log n)

Example 1.31: T(n) = T(n/2) + 2n


Solution: In this example, a is equal to 1 and b is equal to 2. So, logba = log21 = 0
Which means, f(n) = 2n = Ω(nlog21 + 1). That means case 3 is applied and T(n) = Θ(f(n)).
So, its final time complexity will be T(n)= Θ(n)

Example 1.32: T (n) = 16T (n/4) + n


Solution: In this example, a is equal to 16 and b is equal to 4. So, logba = log416 = 2.
Which means, f(n) = n = O(nlog416 - 1). That means case 1 is applied and T(n) = Θ(nlog416).
So, its final time complexity will be T(n)= Θ(n^2)

Example 1.33: T (n) = 2T (n/2) + n log n


Solution: In this example, a is equal to 2 and b is also equal to 2. So, logba = log22 = 1
Which means, f(n) = n.log(n) = Θ(nlog22log1n ). That means case 2 is applied and T(n) = Θ(nlog22log1+1n).
So, its final time complexity will be T(n) = Θ(n log2(n))

Example 1.34: T(n) = 2 T(n/4) + n0.5


Solution: In this example, a is equal to 2 and b is equal to 4. So, logba = log42 = 0.5
Which means, f(n) = n0.5= Θ(nlog42log0n). That means case 2 is applied and T(n) = Θ(nlog42log0+1n).
So, its final time complexity will be T(n) = Θ(n0.5 log(n))

22
Chapter 1: Algorithms Analysis Master Theorem

Example 1.35: T(n) = 2 T(n/4) + n0.49


Solution: In this example, a is equal to 2 and b is equal to 4. So, logba = log42 = 0.5
Which means, f(n) = n0.49 = O(nlog42 – 0.01). That means case 1 is applied and T(n) = Θ(nlog42).
So its final time complexity will be T(n) = Θ(n0.5)

Example 1.36: T (n) = 3T (n/3) + √ n


Solution: In this example, a is equal to 3 and b is also equal to 3. So, logba = log33 = 1
Which means, f(n) = n = O(nlog33 - 1/2). That means case 1 is applied and T(n) = Θ(f(n))
So, its final time complexity will be T(n) = Θ(n)

Example 1.37: T (n) = 3T (n/3) + n/2


Solution: In this example, a is equal to 3 and b is also equal to 3. So, logba = log33 = 1
Which means, f(n) = n = Θ(nlog33log0n). That means case 2 is applied and T(n) = Θ(nlog33log0+1n)
So, final time complexity will be T(n) = Θ(n.log(n))

Exercise
1 True or false
➢ 5 n + 10 n^2= O(n^2)
➢ n.log(n) + 4 n = O(n)
➢ log(n^2) + 4 log(log(n)) = O(log(n))
➢ 12.n1/2+ 3 = O(n^2)
➢ 3^n + 11.n^2 + n^20= O(2^n)
2 What is the best-case runtime complexity of searching an Array?
3 What is the average-case runtime complexity of searching an Array?
4 Given an array of positive numbers, you need to find the maximum sum under the constraint
that no two elements should be adjacent.

23
CHAPTER 2: APPROACH TO SOLVE PROBLEMS

Introduction
Theoretical knowledge of the algorithm is essential, but it is insufficient. When an interviewer asks the
interviewee to solve a problem, then the interviewee can use our five-step approach to solve problems.
If you master this technique, you will outperform the majority of applicants in interviews.

Five steps for solving algorithm design questions are:


1. Constraints
2. Ideas Generation
3. Complexities analysis
4. Coding
5. Testing

Constraints
Solving a technical question is not just about knowing the algorithms and designing a good software
system. The interviewer is interested in seeing your approach to any given problem. Often, people
make mistakes by failing to ask clarifying follow-up questions about a given problem. They make a lot
of assumptions at once and start working with them. Before you start solving a problem, you need to
collect a lot of missing information from your interviewer.

In this step, you will write down all the problem’s constraints. Never attempt to solve a problem that
isn’t completely defined. Interview questions are not like exam paper questions, where all the details
about a problem are well-defined. The interviewer wants you to ask questions and clarify the problem
during the interview.

Suppose, when the interviewer says to write an algorithm to sort numbers. You need to ask the
following clarifying question:
1. The first thing you need to know is what sort of data is being given. Assume the interviewer
gives you the answer Integer.
2. The size of the data is the second piece of information you need to know. If the input data is
100 integers or 1 billion integers, the algorithm is different.

The basic guideline for the Constraints for an array of numbers:


1. How many numbers of elements are there in an array?
2. What is the range of value in each element? What is the min and max value?
3. What is the kind of data in each element? Is it an integer or a floating point?
4. Does the array contain unique data or not?

24
Chapter 2: Approach to Solve Problems Constraints

The basic guideline for the Constraints for an array of strings:


1. How many total numbers of elements are there in the array?
2. What is the length of each string? What is the min and max length?
3. Does the array contain unique data or not?

The basic guideline for the Constraints for a Graph


1. How many nodes are there in the graph?
2. How many edges are there in the graph?
3. Is it a weighted graph? What is the range of weights?
4. Does the graph have directed edges, or undirected edges?
5. Does the graph have a loop?
6. Does the graph have a negative sum loop?
7. Are there any self-loops in the graph?

We will see in the graph chapter that depending upon the constraints the algorithm applied changes
and so is the complexity of the solution.

Idea Generation
We will cover a lot of theoretical knowledge in this book. It is impossible to cover all the questions, as
new questions are created every day. Therefore, you should know how to handle new problems. Even
if you know the solution to the problem asked by the interviewer, then also you need to have a
discussion with the interviewer and try to reach the solution. You need to analyse the problem also
because the interviewer may modify a question a bit, so the approach to solve it will vary.

How to solve an unseen problem? The solution to this problem is to learn a lot, and the more you
practice, the more you will be able to answer any unseen problem. When you’ve solved enough
problems, you’ll see a pattern in the questions and be able to answer unseen problems with ease.

Following is the strategy that you need to follow to solve an unknown problem:
1. Try to simplify the task at hand.
2. Try a few examples
3. Think of a suitable data structure.
4. Think about similar problems that you have already solved.

Try to simplify the task at hand


Let’s look into the following problem: Husbands and wives are standing at random in a line. Husbands
have been numbered, H1, H2, H3 and so on. Wives have been numbered, W1, W2, W3 and so on.
You need to arrange them so that H1 will stand first, followed by W1, then H2 followed by W2 and so
on.

25
Chapter 2: Approach to Solve Problems Idea Generation

At first look, it looks complicated, but it is a simple problem. Try to find a relation to the final position.
P(Hi) = i * 2 – 1 and P(Wi) = i * 2

We are leaving an exercise for you to do something like Insertion-Sort for the rest of the algorithm, and
you are done.

Try a few examples


In the above problem, if you try the above problem with an example of three husband-wife pairs then
you can get the same formula as shown in the previous section. Using more examples will also assist
in solving the problem.

Think of a suitable data-structure


It’s simple to figure out which data structure would be more appropriate for some specific problems.
Throughout this book, we will see a variety of data structures. We must determine which data structure
would best meet our requirements.

Problem 1: If we want to find the minimum and maximum of a given sequence.


Analysis: The heap is most likely the data structure we’re searching for.

Problem 2: We are given a stream of data, at any time, we can be asked to tell the median value of
the data, and maybe we can be asked to pop median data.
Analysis: We may visualise a tree, maybe a balanced tree with the median at the root. Wait a minute!
It’s not straightforward to ensure that the tree root is a median. We can’t get the median from a heap,
although it can give us the minimum or maximum. What if we use two heaps, a max-heap and a min-
heap? The max heap will hold the smaller values, while the min-heap will have the larger values.
Furthermore, we will keep track of how many elements are in the heaps. It would help if you came up
with the rest of the algorithm on your own.

For every unseen problem, think about the data structures you know, and maybe one of them or some
combination of them will solve your problem. Think about similar problems you have already solved.

Problem 3: Given head pointers of two linked lists that intersect at some point. Find the point of
intersection. However, in place of the end of the linked list to be a null pointer, there is a loop.
Analysis: You know how to find the intersection point of two intersecting linked lists, and you know
how to find if a linked list has a loop (three-pointer solution). Therefore, you can combine both solutions
to solve the problem at hand.

Complexities
Solving a problem is not just finding a correct solution. The solution should be fast and should have
reasonable memory requirements. In the previous chapters, you learned about big-O notation. You
should be able to perform Big-O analysis. If you believe the solution you have provided is not optimal
and there is a better solution, then try to figure it out.

26
Chapter 2: Approach to Solve Problems Complexities

Most interviewers expect that you should be able to find the Time and Space Complexity of the
algorithms. You should be able to calculate the Time and Space Complexity quickly. Whenever you
are solving any problem, you should find the complexity associated with it. From this, you would be
able to choose the best solutions. In some problems there are some trade-offs between Space and
Time Complexity, so you should know these trade-offs. Taking a little extra space will save you a lot of
time and make your algorithm much faster.

Coding
At this stage, you have already captured all the constraints of the problem, suggested a few solutions,
evaluated the complexities of those solutions and selected the one for final coding. Never begin coding
without first discussing with the interviewer about constraints, Idea generation and complexity.

We are used to writing code in an IDE like a Visual Studio. So several people struggle when asked to
write code on a whiteboard or some blank sheet. Therefore, you should do some practice coding on a
sheet of paper. You should think before coding because there is no back button on the sheet of paper.
Always try to write modular code. Small functions need to be created so that the code is clean and
managed. If there is a requirement for a swap function, just use this function and tell the interviewer
that you will write it later. Everybody knows that you can write a swap function.

Testing
You’re not done even if the code is written. It is essential to validate the code using a variety of small
test cases. It shows that you understand the importance of testing. It also gives the interviewer
confidence that you would not write a bug-ridden program. Once you have finished coding, you should
go over the code line-by-line for some small test cases. This is to ensure that the code is functioning as
intended.

Following are some test cases to check:


• Normal test cases: These are the positive test cases, which contain the most common
scenario, and the emphasis is on the functioning of the code’s base logic.
For example, if we are solving some problems for a linked list, then this test may contain, what
happens when a linked list with three or four nodes is given as input. Before declaring the code
complete, you should always think about these test cases.
• Edge cases: These are the test cases, which are used to test the boundaries of the code.
Edge cases can help to make your code more robust. We must add checks in the code to
handle edge cases.
For example, we can generate edge cases with the same linked list algorithm to see how the
code reacts when an empty list or only one node liar is passed.

Note: Always follow these five steps, never jump to coding before doing constraint analysis, idea
generation, and complexity analysis: At last, never miss the testing step.

27
Chapter 2: Approach to Solve Problems Example

Example
Let us suppose the interviewer asks you to give the best sorting algorithm.
Some interviewees will directly jump to Quick-Sort O(n.log(n)). Oops, mistake! You need to ask many
questions before beginning to solve this problem.

Let’s look at these questions one by one.


Question 1: What is the kind of data? Are they integers?
Answer: Yes, they are integers.

Question 2: How much data are we going to sort?


Answer: Maybe thousands.

Question 3: What exactly is this data about?


Answer: They store a person’s age

Question 4: What kind of data structure is used to hold this data?


Answer: Data are given in the form of a list

Question 5: Can we modify the given data structure? And many, many more questions…
Answer: No, you cannot modify the data structure provided

So, we are all set to use the given information to make a perfect solution. From the first answer, we will
know the type of data we are going to get is an integer. From the second answer, we can conclude that
data size is limited. It’s only in some thousands. From the next answer, we can conclude that it’s age-
related data. So we can assume that a person’s age will be between 1 to 150. And lastly, we know that
data is in the form of a list and cannot change it.

To summarise, we can use bucket sort to sort the data. Since the range is only 1-150, we only need an
integer list of 150 elements. We don’t have to think about data overflow because the data is in
thousands, and we get the solution in linear time.

Summary
At this point, you know the process of handling unseen problems very well. In the coming chapter, we
will be looking into various data structures and the problems they solve. It may be possible that the
user cannot understand some portion of this chapter as knowledge of the rest of the book is needed,
so they can reread this chapter after reading the rest of the data structures portion. A huge number of
problems are solved in this book. However, it is recommended that you first try to solve them yourself
and then look for the solution. Always think about the complexity of the problem. In the interview,
interaction is the key to get the problem described completely and discuss your approach with the
interviewer.

28
CHAPTER 3: ABSTRACT DATA TYPE

Abstract Data Type (ADT)


An abstract data type (ADT) is a logical description of the data and its operations. An ADT is known as
a user’s point of view of data. An ADT is concerned about the possible values of data and interfaces
exposed by it. An ADT is not concerned about the actual implementation of the data structure.

For example, a user wants to store some integers and find their mean value. ADT for this data
structure would have two functions, one for adding integers and another to get the mean value. ADT
for this data structure does not talk about how exactly it will be implemented.

Data-Structure
Data structures are concrete representations of data that are defined from the perspective of a
programmer. The data structure represents how data can be stored in memory. Each data structure
has its own set of advantages and disadvantages. Depending on the type of problem, we choose the
most appropriate data structure.

For example, according to the question, we can store data in arrays, stack, queue, linked list, and
many more.

Note: - In this chapter, we will be studying various data structures and their API. So that the user can
use them without knowing their internal implementation.

29
Chapter 3: Abstract Data Type Kotlin Collection Framework

Kotlin Collection Framework


Kotlin programming language provides a Kotlin Collection Framework, which is a set of high quality,
high-performance & reusable data structures and algorithms.

The following advantages of using a Kotlin collection framework:


1. Programmers do not have to implement basic data structures and algorithms repeatedly. Thereby,
it prevents the reinvention of the wheel. Thus, the programmer can devote more effort to business
logic
2. The Kotlin Collection Framework code is a well-tested, high quality, high-performance code. Using
them increases the quality of the programs.
3. Development cost is reduced as basic data structures and algorithms are implemented in the
Collections framework.
4. Easy to review and understand programs written by other developers, as most Kotlin developers
use the Collection framework. In addition, the collection framework is well documented.

Array
Arrays are the simplest data structures that store items of the same data type.

Array ADT Operations


Below is the API of an array:
1. Adds an element at the kth position. Value can be stored in an array at the kth position in O(1)
constant time. We just need to store value at arr[k].
2. Reading the value stored at the kth position. Accessing the value stored at some index in the array
is also O(1) constant time. We just need to read the value stored at arr[k].
3. Substitution of value stored in kth position with a new value.
4. Time complexity: O(1) constant time.

Example 3.1:
fun main() {
val arr = IntArray(10)
for (i in 0..9) {
arr[i] = i
}
for (i in arr){
print(" " + i)
}
}

Output:
0 1 2 3 4 5 6 7 8 9

30
Chapter 3: Abstract Data Type Array

Application of Arrays
Applications of Arrays are:
1. Storing data in tabular format.
2. Used in the creation of Matrices. Online ticket booking system in which seats are represented
in the form of Matrices.
3. Used in the creation of various higher level data structures like Stacks, Queues, Heaps,
HashTables etc.

ArrayList implementation in Kotlin Collections


ArrayList<E> in Kotlin Collections is a data structure that implements the List<E> interface, which
means that it can have duplicate elements in it. ArrayList is an implementation of a dynamic array that
can grow or shrink as needed. (Internally the array is used when it is full, a bigger array is allocated
and the old array values are copied to it.)

Example 3.2:
fun main() {
val al = ArrayList<Int>()
al.add(1) // add 1 to the end of the list
al.add(2) // add 2 to the end of the list

println("Array : $al")
println("Array Size : " + al.size)
println("Array IsEmpty : " + al.isEmpty())

al.removeAt(al.size - 1) // last element of array is removed.


println("Array : $al")

al.removeLast() // last element of array is removed.


println("Array IsEmpty : " + al.isEmpty())
}

Output:
Array : [1, 2]
Array Size : 2
Array IsEmpty : false
Array : [1]
Array IsEmpty : true

Linked List

Linked list is a dynamic data structure and memory is allocated at run time. The concept of linked list is
not to store data contiguously. Nodes of linked list contain links that point to the next elements in the
list.

31
Chapter 3: Abstract Data Type Linked List

Performance-wise, linked lists are slower than arrays because there is no direct access to linked list
elements. A linked list is a useful data structure when we do not know the number of elements to be
stored ahead of time. There are many types of linked lists: linear, circular, doubly, doubly circular etc.

Linked list ADT Operations


Below is the API of the Linked list:
1. Insert(k) will insert an element at the start of the list. Just create a new element and move
pointers. So that this new element becomes the first element of the list. This operation will take
O(1) constant time.
2. Delete() will delete an element at the start of the list. We just need to move one pointer. This
operation will also take O(1) constant time.
3. Print() will display all the elements of the list. Start with the first element and then follow the
pointers. This operation will take O(N) time.
4. Find(k) will find the position of the element with the value k. Start with the first element and
follow the pointer until we get the value we are looking for or reach the end of the list. This
operation will take O(N) time.
5. IsEmpty() will check if the number of elements in the list is zero. Just check the head pointer of
the list, if it is Null then the list is empty, otherwise not empty. This operation will take O(1) time.

LinkedList implementation in Java Collections


LinkedList<E> in by Java Collections is a data structure that also implements the List<E> interface.

Example 3.3:
import java.util.LinkedList

fun main() {
val ll = LinkedList<Int>()
ll.addFirst(2) // 2 is added to the list.
ll.addLast(10) // 10 is added to last of the list.
ll.addFirst(1) // 1 is added to first of the list.
ll.addLast(11) // 11 is added to last of the list.

println("Contents of Linked List: $ll")

ll.removeFirst()
ll.removeLast()
println("Contents of Linked List: $ll")
}

Output:
Contents of Linked List: [1, 2, 10, 11]
Contents of Linked List: [2, 10]

32
Chapter 3: Abstract Data Type Linked List

Analysis: Values are added to the back and front of the linked list. Then the values stored in the linked
list are printed. Then values are removed from the linked list from the front and back and again linked
list content is printed to the screen.

Stack
Stack is a data structure that follows the Last-In-First-Out (LIFO) principle. This means that the
element that is added last will be removed first.

Stack ADT Operations


Below is the API of the Stack:
1. Push(k) will add value k on the top of the stack.
2. Pop() will remove an element from the top of the stack and return its value.
3. Top() will return the value of the element on top of the stack.
4. Size() will return the number of elements in the stack.
5. IsEmpty() will tell us whether the stack is empty or not. It returns 1 if the stack is empty, else
return 0.

Note: All the above stack operations are implemented in O(1) time Complexity.

Stack implementation in Java Collection


Stack is implemented by calling push and pop methods of the Stack <T> class.

Example 3.4:
import java.util.Stack

fun main() {
val stack = Stack<Int>()
stack.push(1)
stack.push(2)
stack.push(3)
println("Stack : $stack")
println("Stack size : " + stack.size)
println("Stack pop : " + stack.pop())
println("Stack top : " + stack.peek())
println("Stack isEmpty : " + stack.isEmpty())
}

33
Chapter 3: Abstract Data Type Stack

Output:
Stack : [1, 2, 3]
Stack size : 3
Stack pop : 3
Stack top : 2
Stack isEmpty : false

Stack is also implemented by calling push and pop methods of the ArrayDeque<T> class.

Queue
A queue is a data structure that follows the First-In-First-Out (FIFO) principle. The first element added
to the queue first would be the first to be removed, and vice versa.

Queue ADT Operations:


Below is the API of the Queue:
1. Add(K) will add element k at the end of the queue.
2. Remove() will remove the first element at the front of the queue and return its value.
3. Front() will return the value of the element at the front of the queue.
4. Size() will return the number of elements in the queue.
5. IsEmpty() will check whether the queue is empty or not. If it is empty then return 1, else return
0.

Note: All the above queue operations are implemented in O(1) Time Complexity.

Queue implementation in Kotlin Collection


ArrayDeque<T> is the class implementation of a doubly ended queue. If we use add(), removeFirst()
and first() it will behave as a queue. (Moreover, if we use add(), removeLast() and last() it behaves as
a stack.)

Example 3.5:
fun main() {
val que = ArrayDeque<Int>()
que.add(1)
que.add(2)
que.add(3)

34
Chapter 3: Abstract Data Type Queue

println("Queue : $que")
println("Queue size : " + que.size)
println("Queue peek : " + que.first())
println("Queue remove : " + que.removeFirst())
println("Queue isEmpty : " + que.isEmpty())
}

Output:
Queue : [1, 2, 3]
Queue size : 3
Queue peek : 1
Queue remove : 1
Queue isEmpty : false

Analysis: Values are added to the queue and printed to the screen. Since the queue is first-in-first-out,
the values that are added first are the first to come out of the queue.

Tree
A tree is a data structure that is organised in a hierarchy. Each element of the tree data structure is
called a node. The top node of the tree is called the root node. Each node in a tree, except the root,
has a parent node and zero or more child nodes. In the case of the last level of nodes, they have no
child. They are called leaf nodes. Where you need to store hierarchical records, the tree is the most
appropriate data structure to use.

A binary tree is a type of tree in which each node has at most two children ( 0, 1, or 2 ) which are
referred to as left child and right child.

Binary Search Tree (BST)


A binary search tree (BST) is a binary tree in which nodes are ordered in the following way:
1. The key in the left subtree is less than or equal to the key in its parent node.
2. The key in the right subtree is greater than the key in its parent node.

35
Chapter 3: Abstract Data Type Binary Search Tree (BST)

Binary Search Tree ADT Operations


Below is the API of the BST:
1. Insert(k) will insert an element k into the tree.
2. Delete(k) will delete an element k from the tree.
3. Search(k) will search a value k into the tree if it is present or not.
4. FindMax() will find the maximum value stored in the tree.
5. FindMin() will find the minimum value stored in the tree.

The average time complexity of all the above operations on a binary search tree is O(log(n)), the case
when the tree is balanced. The worst-case time complexity is O(n) when the tree is not balanced.

TreeSet implementation in Java Collections


TreeSet<> is a class that implements the Set<> interface, which means that it stores unique elements.
TreeSet<> is implemented using a red-black balanced binary search tree in Java Collections. Since
TreeSet<> is implemented using a binary search tree, its elements are stored in sequential order.

Example 3.6:
import java.util.TreeSet

fun main() {
// Create a tree set.
val ts = TreeSet<String>()
// Add elements to the tree set.
ts.add("Banana")
ts.add("Apple")
ts.add("Mango")
println(ts)
println("Apple present : " + ts.contains("Apple"))
println("Grapes present : " + ts.contains("Grapes"))
ts.remove("Apple")
println("Apple present : " + ts.contains("Apple"))
}

Output:
[Apple, Banana, Mango]
Apple present : true
Grapes present : false
Apple present : false

Note: TreeSet is implemented using a binary search tree so add, remove, and contain methods have
logarithmic time complexity O(log(n)), where n is the number of elements in the set.

TreeMap implementation in Kotlin Collection


A Map<> is an interface that maps keys to values. A TreeMap<> is an implementation of Map<> and is
implemented using a red-black balanced binary tree so the key-value pairs are stored in sorted order.

36
Random documents with unrelated
content Scribd suggests to you:
hänen mahdoton vastata kirjeeseen. Sodan telmeen asetuttua toivoi
hän saavansa vapaahetken vastatakseen kirjallisesti valituksiin, kuten
piti.

Muutamia päiviä myöhemmin kirjoitti hän neuvostolle.

Hän tunnusti empimättä neuvoston tahdon laillisuuden, mutta


samalla lykkäsi hän kysymyksen ratkaisun määräämättömäksi ajaksi,
tai kunnes olisi saatu aikaan rauha tai aselepo Tanskan kanssa.

Nyt saapui monia kirjeitä ja viestejä.

Niinpä sai hän sanoman, etteivät taalalaiset suinkaan sallineet,


että hän, Hemming, joutuisi "kadotukseen"; he toivoivat
rukouksissaan, että hän menestyisi ja voisi hyvin.

Tuomiokapituli oli kirjoittanut valtionhoitajalle, ettei tohtori


Hemming saa enää kantaa piispankymmenyksiä, mutta valtionhoitaja
vastasi sovittelevin sanoin; hän varoitti kaikesta väkivallasta tätä
urhoollista miestä vastaan, joka pani henkensä ja verensä alttiiksi
Ruotsin vihollisia vastaan, ja pyysi tuomiokapitulia kiinnittämään
tarpeellista huomiota rahvaan ilmaisemaan tahtoon.

Sitten saapui Linköpingistä viesti, että paavillinen kirje oli naulattu


kirkon ovelle. Tuomiokapituli oli otattanut sen jälleen pois, koska se
sisälsi sanoja myös valtionhoitajaa vastaan. Mutta siellä oltiin kovin
levottomia ja peloissaan eikä tiedetty, mihin sellaisissa olosuhteissa
oli ryhdyttävä.

"Ne kurjat raukat!" jupisi Hemming. "Olisivat nyt toki suden tai
lampaan puolella!"
Mutta ainoastaan ohimennen huolehti hän omista asioistaan;
kunkin päivän huolet ja murheet täyttivät hänen mielensä alituiseen.

Viime aikoina oli lähimpien pitäjien rahvaan keskuudessa havaittu


merkillistä nurjuutta ruotsalaisia kohtaan. Nimismies kertoi, että he
olivat kieltäytyneet tekemästä uskollisuudenvalaa valtionhoitajalle, ja
valittaen kaikkea sitä hätää, mitä saivat kokea, tuumivat he, että
"olisi parempi olla Tanskan alamaisina".

Kun piispa puhui tästä Paul Kylelle, sanoi tämä: "Tanskalaiset


lupaavat kultaa ja kaikkea ihanuutta; niin tekivät he Uplannissakin
ennen Brunkebergin taistelua, sentähden se kääntyikin maan
häviöksi."

"Täytyisi tehdä jotakin!"

"Puhukaa heille!"

"Luuletteko sen auttavan?"

"Yksistään sen!"

"Kutsuttakaa siis nimismiehellä heidät kokoon!"

Mutta kun kaupungin asujamet kuulivat, että piispa aikoi lähteä


pois, nousi yleinen hälinä; he rukoilivat polvillaan, ettei hän jättäisi
heitä, koska he ja kaupunki silloin olisivat silloin hukassa.

"Kuulkaas", huusi Hemming vimmastuneena. "Jos rutto alkaa


raivota yhdessä talossa, onko minun sitouduttava, sentähden että
minun kotonani pysyttäisiin terveenä, jättämään koko muu kylä
ruton haltuun."
"Ette kai lähde yksin?"

"Yksin lähden ruton saastuttamaan paikkaan, jollette te tahdo


seurata kunniavartiona!"

Porvarit luikkivat noloina tiehensä.

Mören kirkonkylä oli valittu kokouspaikaksi, ja piispa löysi


saapuessaan suurilukuisen parven koolla. Mutta kaikkien kasvoilla
kuvastui tyytymättömyys ja uhman ilme. He olivat tulleet kuulemaan
mitä hänellä oli sanottavaa, mutta aikoivat pitää oman päänsä vielä
palatessaankin.

Kumolleen kaadettu olutsammio oli varustettu puhujan paikaksi;


sen päältä saattoi hän nähdä kuulijansa ja nämä hänet.

Tohtori jätti hevosensa majataloon ja meni kokouspaikalle.

"Täälläkö kokous on pidettävä?" kysyi hän eräältä talonpojalta.

"Niin maar se on!" vastasi tämä.

"Hänkö se aikoo puhua?" kysyi muuan toinen ja mittaili


Hemmingiä silmillään.

"Niinhän se olisi tarkoitus!"

"Tuolla on tynnyri millä seistä!"

"Mene sinä ensin!"

"Minä… ei minulla ole mitään sanottavaa!"

"Oletko sellainen raukka?"


"Eipä sitä tarvitse olla raukkakaan, vaikka on älyä pitää suunsa
kiinni."

"Jos näen sinut hukkumaisillasi, onko minulla enemmän älyä, jos


vaikenen, kuin jos huudan apua?"

"Oletpa koko veitikka", sanoi talonpoika ja raapi tuumiskellen


korvallistaan.

Nyt lähestyi muuan talonpoika, joka näytti olevan toisia ehompi,


sillä he väistyivät hänen tieltään ja myhäilivät toisilleen ikäänkuin
tahtoisivat sanoa: "Nyt tulee mies, joka voi antaa hänelle
vastauksen."

"Mistä on kysymys?" utaisi tämä.

"Tämä tässä tahtoo, että meidän pitäisi puhua."

"Mitä varten, kun olemme kaikki yksimieliset."

"Niin, niin olemme!" huusi joukko.

"Se ei ole totta!" huusi Hemming Gadd.

"Eikö ole totta?"

"Ette tiedä, mistä olette tulleet yksimielisyyteen! Olette ainoastaan


toisten tahdon välikappaleita!"

"Olemme saaneet hyviä lupauksia…"

"Joakim Trolle vakuutti minulle kättä lyöden…"


Nyt tiesi Hemming mistä aloittaa. Hän tunkeutui joukon läpi ja
hyppäsi sammion pohjalle, löi käsiään yhteen ja vaati hiljaisuutta.

Talonpoikain joukko tunkeutui taajempaan ja katseli epäluuloisesti


häneen.

"Kuulkaa!" huusi Hemming. "Ei suinkaan täällä ole ketään, joka


muistaisi Engelbrektin?"

"On kyllä"! vastasi muuan vanha ukko, joka seisoi aivan piispan
edessä. "Olen kahdeksankymmenen vuotias! Tosin olin vain pieni
pojannaskali ja riipuin äitini helmuksissa, mutta vaikkapa eläisin
satavuotiaaksi, en unhoita konsanaan sitä miestä. Jumala häntä
iankaikkisesti siunatkoon."

"Entä te muut, ovatko isänne ja äitinne puhuneet teille hänestä?"

"Ovat, ovat!" huusi koko joukko.

"No hyvä, nyt kysyn teiltä, jos hän seisoisi tässä minun sijallani ja
jos hän voisi tutkia sydämenne, mitä minä en voi tehdä, antaisitteko
ilolla hänen tehdä sen vai kääntyisittekö hänestä pois?"

Lieneekö sen vaikuttanut nimen taikavoima vaiko se


mukaansatempaava vakavuus, jolla nämä yksinkertaiset sanat
lausuttiin, mutta kuulijat katselivat toisiaan ja sitten haudanhiljaisina
ja maahan luoduin silmin odottivat jatkoa.

"Te tiedätte, että isänne, kun Tanska oli heitä äärimmilleen


rääkännyt ja sortanut, vihdoin tarttuivat aseihin. Kuinka he kärsivät
hätää ja puutetta, kuinka kodit poltettiin ja hävitettiin, kuinka naisia
raiskattiin ja rääkättiin kuoliaiksi, sen tiedätte yhtä hyvin kuin
minäkin. Engelbrekt pakoitti vihollisen antamaan perään, kansamme
sai ainakin hengähdyshetken."

"Ruotsalainen herrasmies se antoi hänelle surmaniskun", huusi


muuan ääni joukosta.

"Niin, hän oli ruotsalainen!" virkkoi Hemming jälleen. "Mutta


tiedättekö myös, että isäin pahat teot ovat siinä suhteessa menneet
lasten päälle? Voi sitä aatelismiestä tai talonpoikaa, joka ajatuksin tai
teoin seuraa sen miehen esimerkkiä!"

Joukossa huomattiin levotonta liikettä.

"Kovat ajat ovat käsissä. Me olemme kovia kokeneet, mutta


Herran käsi on ollut yllämme, ja kuinka tanskalaiset ovatkin
houkutelleet kullallaan, kuinka he ovatkin kehoittaneet vaihtamaan
pettuleipämme heidän pehmeihin vehnäpulliinsa, ei kiusaus ole
kuitenkaan saanut valtaa niin monista, että juutti olisi päässyt
maamme herraksi."

"Eikä koskaan pääsekään", huusi muuan ääni.

"Ei, Ruotsin rahvas on estävä sen!" huudahti piispa. "Se on Sten


Sturelta oppinut tuntemaan olevansa mahti valtiossa! Kun Hannu
kuningas oli viekkaudella ja petoksella pesiytynyt Tukholmaan, sanoi
hän valtionhoitajalle: 'Olette jättänyt minulle vaarallisen perinnön,
sillä olette tehnyt herroiksi ne, jotka Jumala on määrännyt orjiksi!
Tanskan talonpojat ovat järjestään kurjia orjia, joita heidän herransa
voivat vaihtaa kauniiseen koiraan tai antaa parikymmentä
talonpoikaa yhdestä hevosesta!' Sellainen ei kävisi laatuun
Ruotsissa."
"Ei, ei!" huudettiin kohti kurkkua. Nousi suunnaton melu ja
talonpojat puivat nyrkkiään.

"Hannu kuningas arveli, että meidänkin rahvaamme vähitellen


tottuisi siihen. Ja tarpeen kai se olisi ollutkin, niin että hän
herroineen olisi voinut vallita. Mutta sitten ajettiin hänet jälleen
pois."

"Oikein, oikein! Pois koko roska!"

"Olette kai kuulleet puhuttavan, kuinka kohdellaan niitä


ruotsalaisia, jotka hän on saanut käsiinsä, kuinka hän polttaa ja
hävittää rannikkoamme? Tiedätte, että kun hän vastoin lupauksiaan
otti haltuunsa Kalmarin kaupungin, peitti hän torin hirsipuilla ja
hirtätti ilman tutkintoa ja tuomiota kaikki porvarit, jotka sai käsiinsä."

"Kirottu, kirottu hän!"

"Kansa rakasti Sten Sturea, ja kuninkaan täytyi odottaa parempia


päiviä."

"Ne eivät koskaan koita hänelle!"

"Ei, ne eivät koita, jos kansa tukkii korvansa viekoituksilta. Herra


Svante Niilonpoika kulkee edeltäjänsä jälkiä. Hän tahtoo ainoastaan
Ruotsin vapautusta Tanskan ikeestä."

"Mutta sota ei lopu koskaan!"

"Ei, jos annamme myöten kädenleveydeltäkään. Hellittämättömyys


on ainoa pelastuksemme."
"Hän siellä linnassa on luvannut, että me kokonaiseksi vuodeksi
saamme verovapauden."

"Milloin on tanskalainen pitänyt lupauksensa?"

"Hannu kuningas tekee kuten rotanpyytäjä", lisäsi piispa. "Hän


panee paistetun juustopalan loukkuun, mutta vanki ei saa siitä
muuta kuin tuntea hajun vain."

"Meitä ei niin puijata!"

"Lopuksi vielä sananen, hyvät ystävät. Olonne ovat mielestänne


tukalat, ja tahtoisitte mielellänne paremmat päivät, mutta totta
puhuen on meidän kaikkien laita sellainen. Vaikka me käskemme ja
te tottelette, niin älkää luulko, että meidän osamme on siltä parempi!
Teidän puremanne leivänpala on kenties kovempi kuin meidän,
mutta teidän ruokahalunne on paljon parempi, sillä huoli
kokonaisuuden pystyssäpysymisestä vie usein meiltä pois kaiken
ruokahalun. Meillä ei siis ole mitään kadehdittavaa toisiltamme,
mutta jos pontevasti pyrimme yhteiseen maaliin, niin saavutamme
sen ennemmin tai myöhemmin, ja kun tulevat sukupolvet nauttivat
hedelmiä meidän työstämme, tunnustavat he, että heidän on meitä
kiittäminen siitä, että ovat vapaita Ruotsin miehiä."

Päästettiin jyrisevä riemuhuuto.

"No, enkö ollut oikeassa?" virkkoi piispa nauraen. "Ette olleet


selvillä mistä oli kysymys."

Näin sanoen hyppäsi hän alas maahan.

Talonpojat tunkeilivat hänen ympärilleen puristaakseen hänen


kättään. Heidät oli tenhonnut hänen puheensa yksinkertaisuus ja
kenties vielä enemmän mahtava ääni, syvä vakaumus, joka
sydämestä kuohuen löysi tien sydämiin ja vastustamattomasti teki
vaikutuksensa.

"Miksei piispa tullut tänne ennen?" kysyi muuan talonpojista.

"En tiennyt, että tarvitsette minua."

"Tulee niin varmaksi häntä kuullessaan!"

"Minä olen vain lausunut teidän omat ajatuksenne."

"Tietty se, mutta täällä puhutaan niin paljon, että väliin joutuu
ikäänkuin eksyksiin."

"Nyt kai hän jää tänne yöksi?" kysyi joku toinen.

"Minulla on siisti vierashuone, jos hän tahtoisi olla niin alava…"

"Hyvänen aika, piispa kai asuu rovastin pappilassa!"

"Rovastin, onko hän täällä?" kysyi Hemming.

"Ei, hän on enimmäkseen linnassa Joakim herran luona."

"Sitten asun jonkun teidän luonanne ja viivyn huomiseen!"

Siitäkös oltiin hyvillään. Kylän suurtalonpoika, joka ensiksi oli


häntä puhutellut, sai kunnian pitää piispaa vieraanaan, ja hän kutsui
illaksi niin suuren seuran kuin huoneihin mahtui.

Siellä Hemming Gadd päätti, mitä ennen oli aloittanut; selvin


sanoin osoitti hän unionin kestämättömyyden. "Se on samaa kuin
valjastaisi yhteen kaksi hevosta, joita ei ole koskaan koulutettu
parihevosiksi", sanoi hän.

"Ne riuhtovat itsensä erilleen!"

"Voivatpa riuhtoa toisensa vaivaisiksikin!" vastasi piispa.

"Alku on jo tehty!"

"Meidän täytyy katsoa, ettei sitä ratsastajaa, jonka olemme


valinneet varsallemme, tehdä jälleen jalkamieheksi!"

Isäntä, kunnioitettu suurtalonpoika Arvid Broderinpoika, istui


kunniasijalla piispan vieressä. Hän tarttui pikariin ja täytti sen
tervetuliaisiksi vaahtoisin olvin; sitten pyysi hän kaikkia vieraitaan
tekemään samoin, ja sitä kehoitusta noudatettiin siekailematta.

Silloin hän nousi ja sanoi: "On huonosti tehty panna kynttilänsä


vakan alle ja salata mitä tietää; ei voi kieltää, että meidät tässä
pitäjässä on eksytetty harhapoluille. Jos pahajuoniset sinua
houkuttelevat, älä heihin suostu, sanotaan, mutta juuri siten olemme
tehneet. Nyt olemme kuitenkin päässeet parempaan käsitykseen, ja
tuskinpa tarvitsee minun sanoa, ketä meidän on siitä kiittäminen."

"Piispaa!" huusi koko joukko.

"Juomme siis hänen maljansa ja kiitämme siitä, mitä hän on


tehnyt hyväksemme!"

Ja pikarit tyhjennettiin riemuiten.

"Olette antaneet sitoa silmänne!" huudahti Hemming hilpeästi.


"Olen ainoastaan temmannut pois siteet, ja nyt näette yhtä selvästi
kuin ennenkin."

"Niin teemme", virkkoi isäntä jälleen. "Ja omasta puolestani


tahdon huomenna tehdä uskollisuudenvalan jalolle Svante
Niilonpojalle."

"Me myös! Me myös!" kajahtelivat huudot.

Ja sitten he joivat ja juttelivat, ja kun erottiin, oli kaikki mieltymys


tanskalaisiin puhallettu pois kuin paksu tomukerros, ja kansallistunto
välkkyi sen alta kuin kirkkaaksi hiottu teräs ja näytti aivan loistavan
ilosta, kun oli päässyt jälleen kunniaan.

Seuraavana aamuna otti piispa vastaan uskollisuudenvalat Svante


Niilonpojalle nimismiehen ollessa läsnä, ja niin palasi hän
Kalmariin, missä kaikki oli tyyntä ja hiljaista.

Kahakoita oli vähän väliä, ja vihollisten harmi piispaa kohtaan oli


tuntuvasti lisääntynyt hänen käytyään Möressä. Ennen ei rahvas ollut
tuonut mitään tavaroita kaupunkiin, vaan ainoastaan linnaan; nyt oli
laita päinvastoin, ja piispa sai yksityisesti monia näytteitä
kansanmiesten suosiosta. Mutta turhat olivat kaikki kokeet taivuttaa
Hemming Gaddia alamaisin sanoin kirjoittamaan korkealle
esimiehelleen.

"Minä inhoan sitä kettua", sanoi hän, "enkä mene askeltakaan


häntä vastaan!"

Tavallisuuden mukaan oli jälleen ryhdytty Tanskan kanssa


neuvotteluihin. Kuningas uudisti vaatimuksensa, että niin kauan kuin
Ruotsi kieltäytyi ottamasta häntä vastaan kuninkaanaan, oli sen
suoritettava vuotuinen rahavero. Neuvosto pohti vilkkaasti tätä
kysymystä; siitä kirjoitettiin Erik Turenpojallekin, joka varoitti siitä. Ja
Hemming Gadd kirjoitti neuvostolle, ettei hänen suostumuksellaan
heitettäisi ainoaakaan lihapalaa sille koiralle, jonka verisen kidan hän
saattoi eroittaa Kalmariin saakka. Kelpo pyssyin ja tapparoin halusi
hän mieluummin maksaa.

Sellaiset sanat eivät olleet omiaan sulattamaan mieliä


leppeämmiksi piispaa kohtaan, eikä kestänyt montakaan viikkoa,
ennenkuin hän sai kutsun saapua neuvoston eteen vastaamaan
tehtyihin syytöksiin. Paul Kylen oli siksi aikaa otettava päällikkyys
huostaansa.

Hemming vastasi leimuavalla kirjeellä kutsuun. Jollei mikään vaara


uhannut, tuumi hän, lähtisi hän Kalmarista; mutta jos se tapahtuisi
nyt, saisi valtaneuvosto kenties siitä tervetulleen aiheen uuteen
syytökseen, joka sitä paitsi olisi oikeutettu. Mutta yhtä vähän kuin
hänellä oli mitään takeita, että voisi palata, yhtä vähän
kiinnitettäisiin, jos jokin onnettomuus tapahtuisi, huomiota siihen,
kenen käskystä hän oli lähtenyt matkalle.

Neuvosto viittasi kutsukirjeeseen ja lähetti hänelle sitä paitsi


sellaisen turvakirjan, "ettei hänellä enää pitänyt olla mitään vastaan
väittämistä".

Mutta silloin hänen vihansa vasta oikein kuohahti.

"Siihen turvakirjaan", kirjoitti hän, "jonka valtaneuvosto viimeksi


lähetti minulle, ei herrojen olisi tarvinnut tuhlata mustetta ja paperia,
sillä kun se ei olisi voinut kuulua toisin kuin kuului, silloin saatoin
kyllä käsittää, kuinka hyvin he suosivat minua. Mitä te sitä vastoin
kirjoitatte, että minä, jos sitä haluaisin, saisin teiltä turvakirjan
tahtoni mukaan, niin toivon teidän herruuttanne palvelleeni siten,
että voin ilman mitään vaaraa tulla huoletta luoksenne."

Kenties pelkäsi neuvosto saavansa kuulla liian tuimia totuuksia, tai


eivät syytöskohdat olleet kyllin perustellut, tai eivät he lopultakaan
uskaltaneet käydä tämän mahtavan miehen kimppuun, jonka nimi
tällä hetkellä huhun siivin liiti kautta maan; asian annettiin
toistaiseksi raueta.

Epäluuloisuus, joka oli juurtunut Hemmingin sieluun, oli kasvanut


taistelussa neuvostoa vastaan. Hän ei voinut antaa anteeksi sitä, että
Svante Niilonpoika oli pannut nimensä kutsukirjan alle.

Täällä kansan ja upseeriensa keskuudessa oli hän entisellään,


kenties vain tavallista myrskyisempi hilpeydessään. Hänen
rakkautensa ja kuolemanhalveksumisensa ei ollut koskaan esiintynyt
selvempänä. Kaikissa hankkeissa, joissa vaara oli tarjolla, esiintyi hän
etumaisena, ja hänen urhoollisuutensa oli jokapäiväisenä
puheenaineena sotamiehillä, jotka luulivat jonkin salaisen voiman
häntä suojelevan.

Mutta milloin hän oli yksin kotonaan, silloin laskeutuivat synkät


pilvet hänen otsalleen, silloin saattoi hän kävellä tunnin toisensa
jälkeen huoneessaan edestakaisin. Silloin tarkasteli hän elämäänsä:
kiittämättömyyttä oli hän kokenut, häntä oli vihattu ja vainottu ja
petetty, ja kuitenkin oli hänen ainoana määränään ollut isänmaan
pelastus!… Sellaisina hetkinä täytti hänen sydämensä rajaton
ihmisten halveksuminen. Jos hän olisi voinut, olisi hän tallannut
jalkoihinsa kaiken pikkumaisuuden, kaikki alhaiset intohimot
maailmasta. Salamoita ja ukkosta huusi hän taivaasta avukseen,
mutta ei mitään rakkautta, ei anteeksiantoa, ei sääliväisyyttä, ei
myötätuntoa!
Toisinaan saattoi hän Paul Kylelle paljastaa murtuneen mielensä.
Silloin sai sappi pursua yli äyräittensä ja hän lausui katkeria ja tuimia
totuuksia. Mutta jos toinen teki jonkun vastaväitteen, silloin malttoi
hän heti mielensä ja sanoi, että hänen käsivartensa vaivasi häntä
niin, että hänestä näytti kaikki mustalta. "Jos vapautuisin tästä
kitimestä", sanoi hän silloin, "sulkeutuisin vanhaan Rönön luostariin;
siellä parantuisin heti kaikista sekä ruumiin että sielun vammoista".
*** END OF THE PROJECT GUTENBERG EBOOK SVANTE
NIILONPOIKA STURE JA HÄNEN AIKALAISENSA I: KUOLON ENKELI
***

Updated editions will replace the previous one—the old editions will
be renamed.

Creating the works from print editions not protected by U.S.


copyright law means that no one owns a United States copyright in
these works, so the Foundation (and you!) can copy and distribute it
in the United States without permission and without paying
copyright royalties. Special rules, set forth in the General Terms of
Use part of this license, apply to copying and distributing Project
Gutenberg™ electronic works to protect the PROJECT GUTENBERG™
concept and trademark. Project Gutenberg is a registered trademark,
and may not be used if you charge for an eBook, except by following
the terms of the trademark license, including paying royalties for use
of the Project Gutenberg trademark. If you do not charge anything
for copies of this eBook, complying with the trademark license is
very easy. You may use this eBook for nearly any purpose such as
creation of derivative works, reports, performances and research.
Project Gutenberg eBooks may be modified and printed and given
away—you may do practically ANYTHING in the United States with
eBooks not protected by U.S. copyright law. Redistribution is subject
to the trademark license, especially commercial redistribution.

START: FULL LICENSE


THE FULL PROJECT GUTENBERG LICENSE
PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK

To protect the Project Gutenberg™ mission of promoting the free


distribution of electronic works, by using or distributing this work (or
any other work associated in any way with the phrase “Project
Gutenberg”), you agree to comply with all the terms of the Full
Project Gutenberg™ License available with this file or online at
www.gutenberg.org/license.

Section 1. General Terms of Use and


Redistributing Project Gutenberg™
electronic works
1.A. By reading or using any part of this Project Gutenberg™
electronic work, you indicate that you have read, understand, agree
to and accept all the terms of this license and intellectual property
(trademark/copyright) agreement. If you do not agree to abide by all
the terms of this agreement, you must cease using and return or
destroy all copies of Project Gutenberg™ electronic works in your
possession. If you paid a fee for obtaining a copy of or access to a
Project Gutenberg™ electronic work and you do not agree to be
bound by the terms of this agreement, you may obtain a refund
from the person or entity to whom you paid the fee as set forth in
paragraph 1.E.8.

1.B. “Project Gutenberg” is a registered trademark. It may only be


used on or associated in any way with an electronic work by people
who agree to be bound by the terms of this agreement. There are a
few things that you can do with most Project Gutenberg™ electronic
works even without complying with the full terms of this agreement.
See paragraph 1.C below. There are a lot of things you can do with
Project Gutenberg™ electronic works if you follow the terms of this
agreement and help preserve free future access to Project
Gutenberg™ electronic works. See paragraph 1.E below.
1.C. The Project Gutenberg Literary Archive Foundation (“the
Foundation” or PGLAF), owns a compilation copyright in the
collection of Project Gutenberg™ electronic works. Nearly all the
individual works in the collection are in the public domain in the
United States. If an individual work is unprotected by copyright law
in the United States and you are located in the United States, we do
not claim a right to prevent you from copying, distributing,
performing, displaying or creating derivative works based on the
work as long as all references to Project Gutenberg are removed. Of
course, we hope that you will support the Project Gutenberg™
mission of promoting free access to electronic works by freely
sharing Project Gutenberg™ works in compliance with the terms of
this agreement for keeping the Project Gutenberg™ name associated
with the work. You can easily comply with the terms of this
agreement by keeping this work in the same format with its attached
full Project Gutenberg™ License when you share it without charge
with others.

1.D. The copyright laws of the place where you are located also
govern what you can do with this work. Copyright laws in most
countries are in a constant state of change. If you are outside the
United States, check the laws of your country in addition to the
terms of this agreement before downloading, copying, displaying,
performing, distributing or creating derivative works based on this
work or any other Project Gutenberg™ work. The Foundation makes
no representations concerning the copyright status of any work in
any country other than the United States.

1.E. Unless you have removed all references to Project Gutenberg:

1.E.1. The following sentence, with active links to, or other


immediate access to, the full Project Gutenberg™ License must
appear prominently whenever any copy of a Project Gutenberg™
work (any work on which the phrase “Project Gutenberg” appears,
or with which the phrase “Project Gutenberg” is associated) is
accessed, displayed, performed, viewed, copied or distributed:
This eBook is for the use of anyone anywhere in the United
States and most other parts of the world at no cost and with
almost no restrictions whatsoever. You may copy it, give it away
or re-use it under the terms of the Project Gutenberg License
included with this eBook or online at www.gutenberg.org. If you
are not located in the United States, you will have to check the
laws of the country where you are located before using this
eBook.

1.E.2. If an individual Project Gutenberg™ electronic work is derived


from texts not protected by U.S. copyright law (does not contain a
notice indicating that it is posted with permission of the copyright
holder), the work can be copied and distributed to anyone in the
United States without paying any fees or charges. If you are
redistributing or providing access to a work with the phrase “Project
Gutenberg” associated with or appearing on the work, you must
comply either with the requirements of paragraphs 1.E.1 through
1.E.7 or obtain permission for the use of the work and the Project
Gutenberg™ trademark as set forth in paragraphs 1.E.8 or 1.E.9.

1.E.3. If an individual Project Gutenberg™ electronic work is posted


with the permission of the copyright holder, your use and distribution
must comply with both paragraphs 1.E.1 through 1.E.7 and any
additional terms imposed by the copyright holder. Additional terms
will be linked to the Project Gutenberg™ License for all works posted
with the permission of the copyright holder found at the beginning
of this work.

1.E.4. Do not unlink or detach or remove the full Project


Gutenberg™ License terms from this work, or any files containing a
part of this work or any other work associated with Project
Gutenberg™.

1.E.5. Do not copy, display, perform, distribute or redistribute this


electronic work, or any part of this electronic work, without
prominently displaying the sentence set forth in paragraph 1.E.1
with active links or immediate access to the full terms of the Project
Gutenberg™ License.

1.E.6. You may convert to and distribute this work in any binary,
compressed, marked up, nonproprietary or proprietary form,
including any word processing or hypertext form. However, if you
provide access to or distribute copies of a Project Gutenberg™ work
in a format other than “Plain Vanilla ASCII” or other format used in
the official version posted on the official Project Gutenberg™ website
(www.gutenberg.org), you must, at no additional cost, fee or
expense to the user, provide a copy, a means of exporting a copy, or
a means of obtaining a copy upon request, of the work in its original
“Plain Vanilla ASCII” or other form. Any alternate format must
include the full Project Gutenberg™ License as specified in
paragraph 1.E.1.

1.E.7. Do not charge a fee for access to, viewing, displaying,


performing, copying or distributing any Project Gutenberg™ works
unless you comply with paragraph 1.E.8 or 1.E.9.

1.E.8. You may charge a reasonable fee for copies of or providing


access to or distributing Project Gutenberg™ electronic works
provided that:

• You pay a royalty fee of 20% of the gross profits you derive
from the use of Project Gutenberg™ works calculated using the
method you already use to calculate your applicable taxes. The
fee is owed to the owner of the Project Gutenberg™ trademark,
but he has agreed to donate royalties under this paragraph to
the Project Gutenberg Literary Archive Foundation. Royalty
payments must be paid within 60 days following each date on
which you prepare (or are legally required to prepare) your
periodic tax returns. Royalty payments should be clearly marked
as such and sent to the Project Gutenberg Literary Archive
Foundation at the address specified in Section 4, “Information
about donations to the Project Gutenberg Literary Archive
Foundation.”

• You provide a full refund of any money paid by a user who


notifies you in writing (or by e-mail) within 30 days of receipt
that s/he does not agree to the terms of the full Project
Gutenberg™ License. You must require such a user to return or
destroy all copies of the works possessed in a physical medium
and discontinue all use of and all access to other copies of
Project Gutenberg™ works.

• You provide, in accordance with paragraph 1.F.3, a full refund of


any money paid for a work or a replacement copy, if a defect in
the electronic work is discovered and reported to you within 90
days of receipt of the work.

• You comply with all other terms of this agreement for free
distribution of Project Gutenberg™ works.

1.E.9. If you wish to charge a fee or distribute a Project Gutenberg™


electronic work or group of works on different terms than are set
forth in this agreement, you must obtain permission in writing from
the Project Gutenberg Literary Archive Foundation, the manager of
the Project Gutenberg™ trademark. Contact the Foundation as set
forth in Section 3 below.

1.F.

1.F.1. Project Gutenberg volunteers and employees expend


considerable effort to identify, do copyright research on, transcribe
and proofread works not protected by U.S. copyright law in creating
the Project Gutenberg™ collection. Despite these efforts, Project
Gutenberg™ electronic works, and the medium on which they may
be stored, may contain “Defects,” such as, but not limited to,
incomplete, inaccurate or corrupt data, transcription errors, a
copyright or other intellectual property infringement, a defective or
damaged disk or other medium, a computer virus, or computer
codes that damage or cannot be read by your equipment.

1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for


the “Right of Replacement or Refund” described in paragraph 1.F.3,
the Project Gutenberg Literary Archive Foundation, the owner of the
Project Gutenberg™ trademark, and any other party distributing a
Project Gutenberg™ electronic work under this agreement, disclaim
all liability to you for damages, costs and expenses, including legal
fees. YOU AGREE THAT YOU HAVE NO REMEDIES FOR
NEGLIGENCE, STRICT LIABILITY, BREACH OF WARRANTY OR
BREACH OF CONTRACT EXCEPT THOSE PROVIDED IN PARAGRAPH
1.F.3. YOU AGREE THAT THE FOUNDATION, THE TRADEMARK
OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL
NOT BE LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT,
CONSEQUENTIAL, PUNITIVE OR INCIDENTAL DAMAGES EVEN IF
YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH DAMAGE.

1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you


discover a defect in this electronic work within 90 days of receiving
it, you can receive a refund of the money (if any) you paid for it by
sending a written explanation to the person you received the work
from. If you received the work on a physical medium, you must
return the medium with your written explanation. The person or
entity that provided you with the defective work may elect to provide
a replacement copy in lieu of a refund. If you received the work
electronically, the person or entity providing it to you may choose to
give you a second opportunity to receive the work electronically in
lieu of a refund. If the second copy is also defective, you may
demand a refund in writing without further opportunities to fix the
problem.

1.F.4. Except for the limited right of replacement or refund set forth
in paragraph 1.F.3, this work is provided to you ‘AS-IS’, WITH NO
OTHER WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR ANY PURPOSE.

1.F.5. Some states do not allow disclaimers of certain implied


warranties or the exclusion or limitation of certain types of damages.
If any disclaimer or limitation set forth in this agreement violates the
law of the state applicable to this agreement, the agreement shall be
interpreted to make the maximum disclaimer or limitation permitted
by the applicable state law. The invalidity or unenforceability of any
provision of this agreement shall not void the remaining provisions.

1.F.6. INDEMNITY - You agree to indemnify and hold the Foundation,


the trademark owner, any agent or employee of the Foundation,
anyone providing copies of Project Gutenberg™ electronic works in
accordance with this agreement, and any volunteers associated with
the production, promotion and distribution of Project Gutenberg™
electronic works, harmless from all liability, costs and expenses,
including legal fees, that arise directly or indirectly from any of the
following which you do or cause to occur: (a) distribution of this or
any Project Gutenberg™ work, (b) alteration, modification, or
additions or deletions to any Project Gutenberg™ work, and (c) any
Defect you cause.

Section 2. Information about the Mission


of Project Gutenberg™
Project Gutenberg™ is synonymous with the free distribution of
electronic works in formats readable by the widest variety of
computers including obsolete, old, middle-aged and new computers.
It exists because of the efforts of hundreds of volunteers and
donations from people in all walks of life.

Volunteers and financial support to provide volunteers with the


assistance they need are critical to reaching Project Gutenberg™’s
goals and ensuring that the Project Gutenberg™ collection will
remain freely available for generations to come. In 2001, the Project
Gutenberg Literary Archive Foundation was created to provide a
secure and permanent future for Project Gutenberg™ and future
generations. To learn more about the Project Gutenberg Literary
Archive Foundation and how your efforts and donations can help,
see Sections 3 and 4 and the Foundation information page at
www.gutenberg.org.

Section 3. Information about the Project


Gutenberg Literary Archive Foundation
The Project Gutenberg Literary Archive Foundation is a non-profit
501(c)(3) educational corporation organized under the laws of the
state of Mississippi and granted tax exempt status by the Internal
Revenue Service. The Foundation’s EIN or federal tax identification
number is 64-6221541. Contributions to the Project Gutenberg
Literary Archive Foundation are tax deductible to the full extent
permitted by U.S. federal laws and your state’s laws.

The Foundation’s business office is located at 809 North 1500 West,


Salt Lake City, UT 84116, (801) 596-1887. Email contact links and up
to date contact information can be found at the Foundation’s website
and official page at www.gutenberg.org/contact

Section 4. Information about Donations to


the Project Gutenberg Literary Archive
Foundation
Project Gutenberg™ depends upon and cannot survive without
widespread public support and donations to carry out its mission of
increasing the number of public domain and licensed works that can
be freely distributed in machine-readable form accessible by the
widest array of equipment including outdated equipment. Many
small donations ($1 to $5,000) are particularly important to
maintaining tax exempt status with the IRS.

The Foundation is committed to complying with the laws regulating


charities and charitable donations in all 50 states of the United
States. Compliance requirements are not uniform and it takes a
considerable effort, much paperwork and many fees to meet and
keep up with these requirements. We do not solicit donations in
locations where we have not received written confirmation of
compliance. To SEND DONATIONS or determine the status of
compliance for any particular state visit www.gutenberg.org/donate.

While we cannot and do not solicit contributions from states where


we have not met the solicitation requirements, we know of no
prohibition against accepting unsolicited donations from donors in
such states who approach us with offers to donate.

International donations are gratefully accepted, but we cannot make


any statements concerning tax treatment of donations received from
outside the United States. U.S. laws alone swamp our small staff.

Please check the Project Gutenberg web pages for current donation
methods and addresses. Donations are accepted in a number of
other ways including checks, online payments and credit card
donations. To donate, please visit: www.gutenberg.org/donate.

Section 5. General Information About


Project Gutenberg™ electronic works
Professor Michael S. Hart was the originator of the Project
Gutenberg™ concept of a library of electronic works that could be
freely shared with anyone. For forty years, he produced and
distributed Project Gutenberg™ eBooks with only a loose network of
volunteer support.
Project Gutenberg™ eBooks are often created from several printed
editions, all of which are confirmed as not protected by copyright in
the U.S. unless a copyright notice is included. Thus, we do not
necessarily keep eBooks in compliance with any particular paper
edition.

Most people start at our website which has the main PG search
facility: www.gutenberg.org.

This website includes information about Project Gutenberg™,


including how to make donations to the Project Gutenberg Literary
Archive Foundation, how to help produce our new eBooks, and how
to subscribe to our email newsletter to hear about new eBooks.

You might also like