## Are you sure?

This action might not be possible to undo. Are you sure you want to continue?

Ratings:

924 pages5 hours

Part I Algorithms and Data Structures

1 Fundamentals:

Approximating the square root of a number

Generating Permutation Efficiently

Unique 5-bit Sequences

Select Kth Smallest Element

The Non-Crooks Problem

Is this (almost) sorted?

Sorting an almost sorted list

The Longest Upsequence Problem

Fixed size generic array in C++

Seating Problem

Segment Problems

Exponentiation

Searching two-dimensional sorted array

Hamming Problem

Constant Time Range Query

Linear Time Sorting

Writing a Value as the Sum of Squares

The Celebrity Problem

Transport Problem

Find Length of the rope

Switch Bulb Problem

In, On or Out

The problem of the balanced seg

The problem of the most isolated villages

2 Arrays

The Plateau Problem

Searching in Two Dimensional Sequence

The Welfare Crook Problem

2D Array Rotation

A Queuing Problem in A Post Office

Interpolation Search

Robot Walk

Linear Time Sorting

Write as sum of consecutive positive numbers

Print 2D Array in Spiral Order

The Problem of the Circular Racecourse

Sparse Array Trick

Bulterman’s Reshuffling Problem

Finding the majority

Mode of a Multiset

Circular Array

Find Median of two sorted arrays

Finding the missing integer

Finding the missing number with sorted columns

Re-arranging an array

Switch and Bulb Problem

Compute sum of sub-array

Find a number not sum of subsets of array

Kth Smallest Element in Two Sorted Arrays

Sort a sequence of sub-sequences

Find missing integer

Inplace Reversing

Find the number not occurring twice in an array

3 Trees

Lowest Common Ancestor(LCA) Problem

..

4 Dynamic Programming

5 Graphs

6 Miscellaneous

Compute Next Higher Number

Searching in Possibly Empty Two Dimensional Sequence

Matching Nuts and Bolts Optimally

Random-number generation

Weighted Median

Compute a^n

Compute a^n revisited

Compute the product a × b

Compute the quotient and remainder

Compute GCD

Computed Constrained GCD

Alternative Euclid’ Algorithm

Revisit Constrained GCD

Compute Square using only addition and subtraction

Factorization

Factorization Revisited

Decimal Representation

Reverse Decimal Representation

Solve Inequality

Solve Inequality Revisited

Print Decimal Representation

Decimal Period Length

Sequence Periodicity Problem

Compute Function

Emulate Division and Modulus Operations

Sorting Array of Strings : Linear Time

LRU data structure

Exchange Prefix and Suffix

7 Parallel Algorithms

8 Low Level Algorithms

Manipulating Rightmost Bits

Counting 1-Bits

Counting the 1-bits in an Array

Computing Parity of a word

Counting Leading/Trailing 0’s

Bit Reversal

Bit Shuffling

Integer Square Root

Newton’s Method

Integer Exponentiation

LRU Algorithm

Shortest String of 1-Bits

Fibonacci words

Computation of Power of 2

Round to a known power of 2

Round to Next Power of 2

Efficient Multiplication by Constants

Bit-wise Rotation

Gray Code Conversion

Average of Integers without Overflow

Least/Most Significant 1 Bit

Next bit Permutation

Modulus Division

Part II C++

Publisher: Sergei NakariakovReleased: Dec 15, 2014ISBN: 9781311977861Format: book

*sergei.nakariakov.5@gmail.com *

This book contains **500 **programming questions most frequently asked in technical interviews in top technical companies including Facebook, Microsoft, Google, Apple, Yahoo and others. Detailed solutions are provided for all of these including tips and techniques for solving similar problems.

For suggestions, feedback and comments, please contact :

*sergei.nakariakov.5@gmail.com *

Sergei Nakariakov

Senior Scientist(Defence Lab)

USA

January 4, 2015

**Preface **

**I Algorithms and Data Structures **

**Fundamentals **

1.1 **Approximating the square root of a number **

1.2 **Generating Permutation Efficiently **

1.3 **Unique 5-bit Sequences **

1.4 **Select Kth Smallest Element **

1.5 **The Non-Crooks Problem **

1.6 **Is this (almost) sorted? **

1.7 Sorting an almost sorted list

1.8 The Longest Upsequence Problem

1.9 **Fixed size generic array in C++ **

1.10 Seating Problem

1.11 Segment Problems

1.12 **Exponentiation **

1.13 **Searching two-dimensional sorted array **

1.14 **Hamming Problem **

1.15 **Constant Time Range Query **

1.16 **Linear Time Sorting **

1.17 **Writing a Value as the Sum of Squares **

1.18 **The Celebrity Problem **

1.19 Transport Problem

1.20 **Find Length of the rope **

1.21 **Switch Bulb Problem **

1.22 **In, On or Out **

1.23 The problem of the balanced segments

1.24 **The problem of the most isolated villages **

**Arrays **

2.1 **The Plateau Problem **

2.2 **Searching in Two Dimensional Sequence **

2.3 **The Welfare Crook Problem **

2.4 **2D Array Rotation **

2.5 **A Queuing Problem in A Post Office **

2.6 **Interpolation Search **

2.7 **Robot Walk **

2.8 **Linear Time Sorting **

2.9 Write as sum of consecutive positive numbers

2.10 **Print 2D Array in Spiral Order **

2.11 **The Problem of the Circular Racecourse **

2.12 **Sparse Array Trick **

2.13 **Bulterman’s Reshuffling Problem **

2.14 **Finding the majority **

2.15 **Mode of a Multiset **

2.16 **Circular Array **

2.17 **Find Median of two sorted arrays **

2.18 **Finding the missing integer **

2.19 Finding the missing number with sorted columns

2.20 **Re-arranging an array **

2.21 **Switch and Bulb Problem **

2.22 **Compute sum of sub-array **

2.23 Find a number not sum of subsets of array

2.24 **Kth Smallest Element in Two Sorted Arrays **

2.25 Sort a sequence of sub-sequences

2.26 **Find missing integer **

2.27 **Inplace Reversing **

2.28 **Find the number not occurring twice in an array **

**Trees **

3.1 **Lowest Common Ancestor(LCA) Problem **

3.2 **Spying Campaign **

**Dynamic Programming **

4.1 **Stage Coach Problem **

4.2 **Matrix Multiplication **

4.3 **TSP Problem **

4.4 A Simple Path Problem

4.5 **String Edit Distance **

4.6 **Music recognition **

4.7 **Max Sub-Array Problem **

**Graphs **

5.1 **Reliable distribution **

5.2 **Independent Set **

5.3 **Party Problem **

**Miscellaneous **

6.1 **Compute Next Higher Number **

6.2 **Searching in Possibly Empty Two Dimensional Sequence **

6.3 **Matching Nuts and Bolts Optimally **

6.4 **Random-number generation **

6.5 **Weighted Median **

6.6 Compute *an *

6.7 **Compute an revisited **

6.8 **Compute the product a × b **

6.9 **Compute the quotient and remainder **

6.10 **Compute GCD **

6.11 **Computed Constrained GCD **

6.12 **Alternative Euclid’ Algorithm **

6.13 **Revisit Constrained GCD **

6.14 **Compute Square using only addition and subtraction **

6.15 **Factorization **

6.16 **Factorization Revisited **

6.17 **Decimal Representation **

6.18 **Reverse Decimal Representation **

6.19 **Solve Inequality **

6.20 **Solve Inequality Revisited **

6.21 **Print Decimal Representation **

6.22 **Decimal Period Length **

6.23 **Sequence Periodicity Problem **

6.24 **Compute Function **

6.25 **Emulate Division and Modulus Operations **

6.26 **Sorting Array of Strings : Linear Time **

6.27 **LRU data structure **

6.28 **Exchange Prefix and Suffix **

**Parallel Algorithms **

7.1 **Parallel Addition **

7.2 Find Maximum

7.3 **The Parallel Prefix Problem **

7.4 **Finding Ranks in Linked Lists **

7.5 **Finding the kth Smallest Element on a Tree **

**Low Level Algorithms **

8.1 **Introduction **

8.1.1 **Manipulating Rightmost Bits **

8.1.1.1 Extending De Morgan’s Laws

8.1.1.2 **Compute Next higher number with same number of 1-bits **

8.2 Bit Counting Algorithms

8.2.1 Counting 1-Bits

8.2.1.1 Counting the 1-bits in an Array

8.2.2 Computing Parity of a word

8.2.3 Counting Leading 0’s

8.2.4 Counting Trailing 0’s

8.3 Rearranging Algorithms

8.3.1 Bit Reversal

8.3.2 **Bit Shuffling **

8.4 Computing Functions

8.4.1 Integer Square Root

8.4.1.1 **Newtons Method **

8.4.2 **Integer Exponentiation : Compute xn **

8.5 **Miscellaneous **

8.5.1 **LRU Algorithm : Reference Matrix **

8.5.2 **Find Shortest String of 1-Bits **

8.5.3 **Fibonacci words **

8.5.4 Computation of Power of 2

8.5.4.1 Round to a known power of 2

8.5.4.2 **Round to Next Power of 2 **

8.5.5 Efficient Multiplication by Constants

8.5.6 **Bit-wise Rotation **

8.5.7 Gray Code Conversion

8.5.8 Average of Integers without Overflow

8.5.9 **Double Linked List with One Pointer Field **

8.5.10 **Least Significant 1 Bit **

8.5.11 **Most Significant 1 Bit **

8.5.12 Swap Values Without a Temporary

8.5.13 Next bit Permutation

8.5.14 Compute Modulus Division

8.5.15 **Conditionally set or clear bits without branching **

8.5.16 Conditionally negate a value without branching

**II C++ **

**General **

**Constant Expression **

**Type Specifier **

**Namespaces **

**Misc **

**Classes **

**Templates **

**Standard Library **

*

1 Computing Square Root Program

2 Unique 5-bit Sequence Program

3 Maximum of a sequence

4 Generic Kth Select Minimum

5 Partitioning a sequence

6 Randomized Partition Algorithm

7 Randomized Quicksort Algorithm

8 Randomized Kth Min Select Algorithm

9 Iterative Version of Quick Select Algorithm

10 The Non-Crooks Program

11 Binary Search on unsorted list

12 is almost sorted

13 Sort Almost Sorted Algorithm

14 The Longest Upsequence Program

15 Seat Algorithm

16 ReSeat Algorithm

17 ReSeat Linear Time Algorithm

18 All Zeros Program

19 Exponentiation

20 Exponentiation Revisited

21 Efficient Exponentiation

22 Saddleback Search Algorithm

23 Saddleback Search Algorithm in practice

24 Saddleback Search Algorithm : Find First Occurrence

25 Saddleback Search Algorithm : Find All Occurrences

26 Saddleback Count Algorithm : Initial Approach

27 Saddleback Count : Correct Algorithm

28 Hamming Problem

29 Counting Sort Algorithm

30 Radix Sort Algorithm

31 Writing a Value as the Sum of Squares

32 Writing a Value as the Sum of Squares

33 Celebrity Algorithm

34 Celebrity Algorithm Brute Force

35 Celebrity Algorithm Optimized

36 Transport Algorithm

37 triangle analysis

38 The Plateau Problem

39 The Plateau Problem Revisited

40 Searching in a 2D Array

41 Searching in a 2D Array : Another Program

42 Searching in a 2D Array : Another Program(Simplified)

43 The Welfare Crook Program

44 The Welfare Crook Program Simplified

45 Interpolation Search Algorithm

46 Robot Walk Algorithm

47 Write as sum of consecutive positive numbers

48 Circular Racecourse Program

49 Bulterman’s Reshuffling Problem

50 Find Majority Simple Algorithm

51 Find Majority Algorithm Revisited

52 Find Majority Algorithm Simplified

53 Find Majority Algorithm Final

54 Circular Array Algorithm

55 Find Median of two sorted array

56 Median Search

57 Re-arranging an array

58 Re-arranging an array revisited

59 Switches and Bulbs

60 Find a number not sum of subsets of array

61 *Kth *Smallest Element in Two Sorted Arrays

62 Reversing an array inplace

63 Kadane’s 1D Algorithm

64 Kadane’s 1D Algorithm : Find Indices

65 Maximum sub-array sum using prefix array

66 K-Maximum sub-array sum using prefix array

67 Independent Set on trees

68 Searching in a possibly empty 2D Array

69 Partitioning a sequence

70 Quicksort to sort a sequence

71 Randomized Partition Algorithm

72 Randomized Quicksort Algorithm

73 Selecting a c-approximate median of X with O(n) complexity

74 Back-Tracking

75 Finding Misplaced Nuts and Bolts

76 Random number generation using binary search

77 Random number generation : Preprocess

78 Random number generation

79 Weighted Median

80 Linear Time Weighted Median

81 Compute *an *program

82 Compute *an *alternative program

83 Compute *an *program revisited

84 Compute the product *a *× *b *

85 Compute the quotient and remainder

86 Compute GCD

87 Compute GCD : Euclid’s Algorithm

88 Computed Constrained GCD

89 Alternative Euclid’ Algorithm

90 Compute Square using only addition and subtraction

91 Factorization Program

92 Factorization Alternative Program

93 Factorization Program Revisited

94 Decimal Representation

95 Reverse Decimal Representation

96 Solve Inequality Program

97 Solve Inequality Revisited

98 Print Decimal Representation

99 Decimal Period Length

100 Sequence Periodicity Problem

101 Compute Function

102 Emulate Division and Modulus Operations

103 LRU Data Structure : Drop program

104 LRU Data Structure : Use program

105 LRU Data Structure : Insert program

106 Exchange Prefix and Suffix

107 Parallel Prefix Algorithm

108 Parallel Prefix : Efficient Algorithm

109 List Rank Algorithm

**Preface **

**I Algorithms and Data Structures **

**Fundamentals **

1.1 **Approximating the square root of a number **

1.2 **Generating Permutation Efficiently **

1.3 **Unique 5-bit Sequences **

1.4 **Select Kth Smallest Element **

1.5 **The Non-Crooks Problem **

1.6 **Is this (almost) sorted? **

1.7 Sorting an almost sorted list

1.8 The Longest Upsequence Problem

1.9 **Fixed size generic array in C++ **

1.10 Seating Problem

1.11 Segment Problems

1.12 **Exponentiation **

1.13 **Searching two-dimensional sorted array **

1.14 **Hamming Problem **

1.15 **Constant Time Range Query **

1.16 **Linear Time Sorting **

1.17 **Writing a Value as the Sum of Squares **

1.18 **The Celebrity Problem **

1.19 Transport Problem

1.20 **Find Length of the rope **

1.21 **Switch Bulb Problem **

1.22 **In, On or Out **

1.23 The problem of the balanced segments

1.24 **The problem of the most isolated villages **

**Arrays **

2.1 **The Plateau Problem **

2.2 **Searching in Two Dimensional Sequence **

2.3 **The Welfare Crook Problem **

2.4 **2D Array Rotation **

2.5 **A Queuing Problem in A Post Office **

2.6 **Interpolation Search **

2.7 **Robot Walk **

2.8 **Linear Time Sorting **

2.9 Write as sum of consecutive positive numbers

2.10 **Print 2D Array in Spiral Order **

2.11 **The Problem of the Circular Racecourse **

2.12 **Sparse Array Trick **

2.13 **Bulterman’s Reshuffling Problem **

2.14 **Finding the majority **

2.15 **Mode of a Multiset **

2.16 **Circular Array **

2.17 **Find Median of two sorted arrays **

2.18 **Finding the missing integer **

2.19 Finding the missing number with sorted columns

2.20 **Re-arranging an array **

2.21 **Switch and Bulb Problem **

2.22 **Compute sum of sub-array **

2.23 Find a number not sum of subsets of array

2.24 **Kth Smallest Element in Two Sorted Arrays **

2.25 Sort a sequence of sub-sequences

2.26 **Find missing integer **

2.27 **Inplace Reversing **

2.28 **Find the number not occurring twice in an array **

**Trees **

3.1 **Lowest Common Ancestor(LCA) Problem **

3.2 **Spying Campaign **

**Dynamic Programming **

4.1 **Stage Coach Problem **

4.2 **Matrix Multiplication **

4.3 **TSP Problem **

4.4 A Simple Path Problem

4.5 **String Edit Distance **

4.6 **Music recognition **

4.7 **Max Sub-Array Problem **

**Graphs **

5.1 **Reliable distribution **

5.2 **Independent Set **

5.3 **Party Problem **

**Miscellaneous **

6.1 **Compute Next Higher Number **

6.2 **Searching in Possibly Empty Two Dimensional Sequence **

6.3 **Matching Nuts and Bolts Optimally **

6.4 **Random-number generation **

6.5 **Weighted Median **

6.6 Compute *an *

6.7 **Compute an revisited **

6.8 **Compute the product a × b **

6.9 **Compute the quotient and remainder **

6.10 **Compute GCD **

6.11 **Computed Constrained GCD **

6.12 **Alternative Euclid’ Algorithm **

6.13 **Revisit Constrained GCD **

6.14 **Compute Square using only addition and subtraction **

6.15 **Factorization **

6.16 **Factorization Revisited **

6.17 **Decimal Representation **

6.18 **Reverse Decimal Representation **

6.19 **Solve Inequality **

6.20 **Solve Inequality Revisited **

6.21 **Print Decimal Representation **

6.22 **Decimal Period Length **

6.23 **Sequence Periodicity Problem **

6.24 **Compute Function **

6.25 **Emulate Division and Modulus Operations **

6.26 **Sorting Array of Strings : Linear Time **

6.27 **LRU data structure **

6.28 **Exchange Prefix and Suffix **

**Parallel Algorithms **

7.1 **Parallel Addition **

7.2 Find Maximum

7.3 **The Parallel Prefix Problem **

7.4 **Finding Ranks in Linked Lists **

7.5 **Finding the kth Smallest Element on a Tree **

**Low Level Algorithms **

8.1 **Introduction **

8.1.1 **Manipulating Rightmost Bits **

8.1.1.1 Extending De Morgan’s Laws

8.1.1.2 **Compute Next higher number with same number of 1-bits **

8.2 Bit Counting Algorithms

8.2.1 Counting 1-Bits

8.2.1.1 Counting the 1-bits in an Array

8.2.2 Computing Parity of a word

8.2.3 Counting Leading 0’s

8.2.4 Counting Trailing 0’s

8.3 Rearranging Algorithms

8.3.1 Bit Reversal

8.3.2 **Bit Shuffling **

8.4 Computing Functions

8.4.1 Integer Square Root

8.4.1.1 **Newtons Method **

8.4.2 **Integer Exponentiation : Compute xn **

8.5 **Miscellaneous **

8.5.1 **LRU Algorithm : Reference Matrix **

8.5.2 **Find Shortest String of 1-Bits **

8.5.3 **Fibonacci words **

8.5.4 Computation of Power of 2

8.5.4.1 Round to a known power of 2

8.5.4.2 **Round to Next Power of 2 **

8.5.5 Efficient Multiplication by Constants

8.5.6 **Bit-wise Rotation **

8.5.7 Gray Code Conversion

8.5.8 Average of Integers without Overflow

8.5.9 **Double Linked List with One Pointer Field **

8.5.10 **Least Significant 1 Bit **

8.5.11 **Most Significant 1 Bit **

8.5.12 Swap Values Without a Temporary

8.5.13 Next bit Permutation

8.5.14 Compute Modulus Division

8.5.15 **Conditionally set or clear bits without branching **

8.5.16 Conditionally negate a value without branching

**II C++ **

**General **

**Constant Expression **

**Type Specifier **

**Namespaces **

**Misc **

**Classes **

**Templates **

**Standard Library **

**Problem Description **

Write a program that, given a fixed integer *n *≥ 0, establishes the truth of

*R *: 0 ≤ *a*2 ≤ *n < *(*a *+ 1)2

**Solution **

Taking the square root of all terms in *R*, we find that *R *is equivalent to 0 ≤ *a **< a *+ 1. Hence, *a *. The first step is to rewrite *R *as a set of conjuncts:

*R *: 0 ≤ *a*2 ∧ *a*2 ≤ *n *∧ *n < *(*a *+ 1)2

Deleting the third conjunct of *R *yields a possible invariant:

*P *: 0 ≤ *a*2 ≤ *n*.

Because *n *≥ 0, *P *can be established by the assignment *a *← 0. For the condition of the loop, use the complement of the deleted conjunct, so that when the loop terminates because the condition is false, the deleted conjunct is true. This yields the almost completed program :

1: *a *← 0

2: **while** (*a *+ 1)2 ≤ *n* **do **

3: ?

4: **end** **while **

The purpose of the command of the loop is to progress towards termination. Clearly, if the condition of the loop is true then *a *is too small, so that progress can be made by increasing *a*. Since *a *, a possible bound function is *t *⌉- *a*. Using the easiest way to increase *a*, incrementing by 1, yields the program

1: *a *← 0

2: **while** (*a *+ 1)2 ≤ *n* **do **

3: *a *← *a *+ 1

4: **end** **while **

We show that *P *is indeed an invariant of the loop:

*P *∧ *B *= 0 ≤ *a*2 ≤ *n *∧ (*a *+ 1)2 ≤ *n *= 0 ≤ (*a *+ 1)2 ≤ *n *

. This program is developed by deleting the conjunct *n < *(*a *+ 1)2. Now let us try using the method of replacing a constant by a variable.

First try replacing the expression *a *+ 1 by a fresh variable *b *to yield

*a*2 ≤ *n < b*2

Clearly, *b *must be greater than *a *if this predicate is to be true. Moreover, the predicate can be established by executing *a *← 0 and *b *← *n *+ 1. Hence, *b *is bounded by *a *+ 1 and *n *+ 1, and the invariant is

*P *: *a < b *≤ *n *+ 1 ∧ *a*2 ≤ *n < b*2

The condition *B *for the loop, obtained by investigating *P *∧¬*B **R*, is *a *+ 1≠*b*. Thus far, the program is

1: *a *← 0

2: *b *← *n *+ 1

3: **while** *a *+ 1≠*b* **do **

4: ?

5: **end** **while **

Since *P *indicates that *a *+ 1 ≤ *b *and the loop should terminate with *a *+ 1 = *b*, the task of each iteration is to bring *a *and *b *closer together, i. e. to decrease the value of *b*-*a*. Execution should continue until *b*-*a *= 1. Hence a possible bound function *t *is *b *- *a *- 1.

The size of the interval (*a,b*) could be decreased by one at each iteration, but perhaps a faster technique exists. Perhaps the interval could be halved, by setting either *a *or *b *. If so, the command of the loop could have the form

1: **if** ? **then **

2: *a *

3: **else** **if** ? **then **

4: *b *

5: **end** **if **

Each command must maintain the invariant *P*. To find a suitable condition for the first command, first calculate

*< b *≤ *n *)2 ≤ *n *∧ *b*2 *> n *

The precondition will be the invariant together with the condition of the loop

*P *∧ *a *+ 1≠*b *

)2 ≤ *n*)2 *> n*. Introducing a fresh variable *d *to save local calculations, we arrive at the program

1: *a *← 0

2: *b *← *n *+ 1

3: *Invariant *: *P *: *a < b *≤ *n *+ 1 ∧ *a*2 ≤ *n < b*2

4: *bound t *: *b *- *a *+ 1

5: **while** *a *+ 1≠*b* **do **

6: *d *

7: **if** *d *× *d *≤ *n* **then **

8: *a *← *d *

9: **else** **if** *d *× *d > n* **then **

10: *b *← *d *

11: **end** **if **

12: **end** **while ***a*2 ≤ *n < *(*a *+ 1)2

It may seem that the technique of halving the interval was pulled out of a hat. It is simply one of the useful techniques that programmers must know about, for its use often speeds up programs considerably. The execution time of this program is proportional to log *n*.

This program illustrates another reason to introduce a variable : *d *has been introduced to make a local optimization. The introduction of *d *is evaluated, it also makes the program more readable.

Note that no definition is given for *d*. Variable *d *is essentially a constant of the loop body. It is assigned a value upon entrance to the loop body, and this values is used throughout the body. It carries no value from iteration to iteration. Moreover, *d *is used only in two adjacent lines, and its use is obvious from these two lines. A definition of *d *would belabor the obvious and is therefore omitted.

If the difference *b *- *a *is always even, then *d *can be calculated using

*d *← *a *

Therefore, let us attempt to deal with the difference, say *c*, between *b *and *a *and to keep this difference even. This will be easiest if *c *is always a power of 2. Thus we have:

*b *= *a *+ *c *

*d *= *a *+ *c∕*2

*p *: 1 ≤ *p *: *c *= 2*p *c is even.

Because *b *and *d *are defined in terms of *a *and *c*, we may be able to write the program using only *a *and *c*. Thus, we try the loop invariant and bound function

*P *: *a*2 ≤ *n < *(*a *+ *c*)2 ∧ (*p *: 1 ≤ *p *: *c *= 2*p*)

*t *: *c *+ 1

The initialization will require a loop to establish *P*, since *c *must be a power of 2. The rest of the program is derived from the previous program. essentially by deleting the assignments to *b *and *d *and transforming the other commands into commands involving *c*:

Algorithm 1: Computing Square Root Program

1: *a *← 0

2: *c *← 1

3: **while** *c*2 ≤ *n* **do **

4: *c *← 2 × *c *

5: **end** **while ***P *

6: **while** *c*≠1 **do **

7: *c *

8: **if** (*a *+ *c*)2 ≤ *n* **then **

9: *a *← *a *+ *c *

10: **else** **if** (*a *+ *c*)2 *> n* **then **

11: *skip *

12: **end** **if **

13: **end** **while ***a*2 ≤ *n < *(*a *+ 1)2

**Problem Description **

Design a program that will generate the n! permutations of the values from 0 through n-1 in such an order that the transition from one permutation to the next is always performed by exactly one swap of two neighbors.

**Solution **

**Reduction Approach( to inversion) **

In a permutation each pair of values such that the larger value precedes the smaller one, presents a so-called *inversion*. In particular: the one and only permutation with zero inversions is the one in which the values are placed in monotonically increasing order.

The notion of inversions can be expected to be relevant here because the swapping of two neighbors changes the total number of inversions : i.e. the number of pairs in the wrong order: by (plus or minus) 1, and it is, therefore, suggested to

*characterize each permutation by its inversions*.

This can be done by introducing n inversion counters inversion[i] for 0 ≤ *i < n*, where inversion[i] equals the number of inversions between the value i and the values smaller than i.

In other words, inversion[i] equals the number of numbers ¡ i , that are placed at *the wrong side *of i, so we can say that

*inversion[i] = the number of inversions between the value i and smaller values. *

From this definition

0 ≤ *inversion*[*i*] ≤ *i *

follows;

*the total number of inversions of a permutation is the sum of the corresponding inversion[i] values. *

i.e., The total number of inversions of the permutation is the sum of all the inversion[i] values.

So it is obvious that:

1.

Each permutation defines the inversion[i] values uniquely, and

2.

The inverse[i] define the permutation uniquely.

The second point above is easily seen by considering the algorithm constructing the permutation from the inversion[i] values, thus processing these values in the order of increasing i.

So there is a one-to-one correspondence between the n! possible inversion values and the n! permutations. With this insight, the original problem is reduced to the following problem :

*which modifications of the inversion value correspond to a swap of neighbors *

Each swap of two neighbors changes exactly one inversion[i] value by 1, viz. with i = the larger of the two values swapped. The value of inversion[i] is to be increased if the swap increases the number of inversions; otherwise it is to be decreased.

A feasible sequence of inversion values to be generated is now reasonably obvious: it is the generalization of the Grey-code. For n = 4 it would begin

**Algorithm **

The logic is simple: a number is changeable when

1.

if the sum of the numbers to its left is even and it has not reached its maximum value.

2.

if the sum of the numbers to its left is odd and it has not reached its minimum value zero.

Please note that at each step, always the right-most changeable number is changed. It is not difficult to see that in the permutation, the value i is, indeed, swapped with a smaller value.

After having established the value i, such that inversion[i] has to be changed, and, also, whether the value i has to be swapped with its predecessor in the permutation (corresponding to an increase of inversion[i]) or with its successor in the permutation (corresponding to a decrease of inversion[i]), we have to establish the place c in the permutation, where the value i is located, because ∀*j > i*, inversion[j] has an extreme value, c is given by:

*c *= *i *- *inversion*[*i*]+(the number of values j ∣*j > i* && *inversion*[*j*] = *j*)

Reason is simple : i is its original position, inversion[i] is the number of smaller elements to the right of it; we have to add to it the number of larger elements in front of the section with *elements *≤ *i *.

**C++ Implementation **

Putting this algorithm in C++ code is easy now:

Program 1.1: generate efficient permutation

1**#include** *<*iostream*> *

2**#include** *<***algorithm***> *

3

4**bool** odd(**int** i)

5{

6 **return** i & 1;

7}

8

9**bool** even(**int** i)

10{

11 **return** !odd(i);

12}

13

14**int** main()

15{

16 **const** **int** n = 4;

17

18 **int** permuted_array[n], inversion[n];

19 **bool** ready;

20 **int** total_inversion, i, c, sum_left_inversion;

21 i = 0;

22

23 **while** (i *<* n)

24 {

25 permuted_array[i] = i;

26 inversion[i] = 0;

27 ++i;

28 }

29

30 inversion[0] = -2;

31

32 ready = **false**;

33 total_inversion = 0;

34

35 **while** (!ready)

36 {

37 **for**(**auto** e : permuted_array)

38 **std**::**cout** *<<* e *<<* ’\t’;

39

40 **std**::**cout** *<<* **std**::**endl**;

41

42 i = n - 1;

43 c = 0;

44 sum_left_inversion = total_inversion - inversion[i];

45

46 **while** ((inversion[i] == i) && even(sum_left_inversion))

47 {

48 c = c + 1;

49 i = i - 1;

50 sum_left_inversion = sum_left_inversion - inversion[i];

51 }

52

53 **while** ((inversion[i] == 0) && odd(sum_left_inversion))

54 {

55 i = i - 1;

56 sum_left_inversion = sum_left_inversion - inversion[i];

57 }

58

59 c = c + i - inversion[i];

60

61 **if** (even(sum_left_inversion) && i *>* 0)

62 {

63 inversion[i] = inversion[i] + 1;

64 total_inversion = total_inversion + 1;

65 **std**::**swap**(permuted_array[c-1], permuted_array[c]);

66 }

67 **else** **if**(odd(sum_left_inversion) && i *>* 0)

68 {

69 inversion[i] = inversion[i] - 1;

70 total_inversion = total_inversion - 1;

71 **std**::**swap**(permuted_array[c], permuted_array[c + 1]);

72 }

73 **else** **if**(i == 0)

74 {

75 ready = **true**;

76 }

77 }

78}

In the program given above, inversion[0], which should be constantly 0, has been assigned the funny value -2; this is the usual, mean, little coding trick, in order to let the search for the right-most changeable inversion[i] value terminate artificially when there is no more such an inversion[i] value. The value *total_inversion *records the total number of inversions in the array *permuted_array*, that is used to record the permutation; the variable *sum_left_inversion *records the sum of the (non-funny) inversion[j] values to the left of inversion[i] (i.e. with j ¡ i).

**Problem Description **

Consider sequences of 36 bits. Each such sequence has 32 5 - *bit *sequences consisting of *adjacent bits*. For example, the sequence 1101011... contains the 5 -*bit *sequences 11010*, *10101*, *01011*,*.... Write a program that prints all 36 -*bit *sequences with the two properties:

1.

The first 5 bits of the sequence are 00000.

2.

No two 5 - *bit *subsequences are the same.

Call a sequence of zeros and ones that begins with 0000, i.e. 4 zeros, and satisfy property (2) a *good sequence*. Call a sequence with *k *bits a *k-sequence*.

Define an ordering among good sequences as follows:

Sequence *s*1 is less than sequence *s*2, written as

*s*1*. < .s*2, if, when viewed as decimal numbers with the decimal point to the extreme left, *s*1 is less than *s*2.

For example, 101*. < .*1011 because *.*101 *< .*1011.

In a similar manner, we write 101*. *= *.*101000, because *.*101 = *.*101000. Appending a *zero *to a sequence yields an equal sequence; appending a *one *yields a larger sequence.

Any *good *sequence *s *to be printed satisfies 0*. < .s. < .*00001, and must begin with 00000.

The program below iteratively generates, in order, all *good *sequences satisfying 0*. *≤ *.s. *≤ *.*00001, printing the 36 - *bit *ones as they are generated. The sequence currently under consideration will be called *s*. There will be no variable *s*; it is just a name for the sequence currently under consideration. *s *always contains at least 5 bits. Further, to eliminate problems with equal sequences, we will always be sure that *s *is the longest *good *sequence equal to itself.

*P*1 : *good*(*s*) ∧¬*good*(*s*∣0) ∧ 5 ≤∣*s*∣∧ 0*. *≤ *.s. *≤ *.*00001∧ *All good sequences . < .s *are printed.

Sequence *s *with *n *bits could be represented by a bit array. However, it is better to represent *s *by an integer array *c*[4*..n*- 1], where *c*[*i*] is the decimal representation of the 5 - *bit *subsequence of *s *ending in bit *i*. Thus, we will maintain as part of the invariant of the main loop the assertion

*P*2 : 5 ≤ *n *= ∣*s*∣≤ 36 ∧ *c*[*i*] = *s*[*i *- 4] × 24 + *s*[*i *- 3] × 23 + *s*[*i *- 2] × 22 + *s*[*i *- 1] × 2 + *s*[*i*], for 4 ≤ *i < n *

Further, in order to keep track of which 5 - *bit *subsequence *s *contains, we use a Boolean array *in*[0*..*31]:

*P*3 : *i *: 0 ≤ *i < *32 : *in*[*i*] = (*i *∈ *c*[4*..n *- 1])

With this introduction, the program should be easy to follow.

Algorithm 2: Unique 5-bit Sequence Program

1: *n *← 5

2: *c*[4] ← 0

3: *in*[0] ← *T *

4: *in*[1*..*31] ← *F *s = (0, 0, 0, 0, 0)

5: *invariant *: *P*1 ∧ *P*2 ∧ *P*3 ∧¬*good*(*s*∣0)

6: **while** *c*[4]≠1 **do **

7: **if** *n *== 36 **then **

8: *Print sequence s *

9: **else** **if** *n*≠36 **then **

10: *skip *

11: **end** **if **

12: *Change s to next higher good sequence: *

13: **while** *in*[(*c*[*n *- 1] × 2 + 1) mod32] **do **i.e. ¬*good*(*s*∣1)

14: *Delete ending 1’s from s: *

15: **while** *odd*(*c*[*n *- 1]) **do **

16: *n *← *n *- 1

17: *in*[*c*[*n*]] ← *F *

18: **end** **while **

19: *Delete ending 0: *

20: *n *← *n *- 1

21: *in*[*c*[*n*]] ← *F *

22: **end** **while **

23: *Append 1 to s: *

24: *c*[*n*] ← (*c*[*n *- 1] × 2 + 1) mod32

25: *in*[*c*[*n*]] ← *T *

26: *n *← *n *+ 1

27: **end** **while **

**Problem **

Design and implement an efficient algorithm to select the *Kth *Smallest Element of an array.

**Basic Analysis **

**Simultaneous Min-Max Algorithm **

Before embarking on this selection problem, let us work out a general scheme of finding maximum and minimum of the input sequence. Min-max algorithms are ubiquitous in various applications specially geometric ones. In this section we will revisit several versions with primary focus being finding the most efficient one.

*Design an efficient algorithm to find the minimum and maximum of an integer sequence simultaneously. *

Let us revisit a typical set-up for finding the maximum of an integer sequence where we end up examine each element of the sequence in turn along with keeping track of the largest element seen so far.

Algorithm 3: Maximum of a sequence

1: **function** maxval(a, l, r)

2: 0 ≤ *n *

3: *a*[*k*] ≥ *a*[0*..n *- 1]

4: *i *← 1

5: *k *← 0

6: **while** 0 ≤ *n* **do **

7: **if** *a*[*i*] ≤ *a*[*k*] **then **

8: *do nothing *

9: **else** **if** *a*[*i*] ≥ *a*[*k*] **then **

10: *k *← *i *

11: **end** **if **

12: *i *← *i *+ 1

13: **end** **while **

14: **return ***k *

15: **end** **function **

––––––––

Program 1.2: Finding Maximum in an integer array

1**#include** *<***vector***> *

2**#include** *<***algorithm***> *

3**#include** *<***cassert***> *

4

5**template** *<***typename** T*> *

6**size_t** maxValArray(**std**::**vector***<*T*>* & v)

7{

8 **size_t** i = 1, k = 0;

9 **size_t** n = v.size();

10

11 **while**(i *<*= n)

12 {

13 **if**(v[i] *>*= v[k]) k = i;

14 ++i;

15 }

16

17 **assert**(v[k] == ***std**::max_element(v.**begin**(),

18 v.**end**()));

19 **return** k;

20}

21

22**int** main()

23{

24 **std**::**vector***<***int***>* v {10, 12, 2, 8, 5, 20, 7};

25 maxValArray(v);

26}

As can be seen that this doesn’t address the scenario in presence of multiple occurrences. Let us put forth obvious solutions.

Program 1.3: Finding First Maximum in an integer array

1**template** *<***typename** ForwardIterator*> *

2ForwardIterator first_max_element(

3 ForwardIter first, ForwardIter last)

4{

5 **if** (first == last) **return** last;

6 ForwardIter max_result = first;

7 **while** (++first != last)

8 {

9 **if** (*max_result *<* *first)

10 max_result = first;

11 }

12 **return** max_result;

13}

Program 1.4: Finding First Maximum Satisfying Predicate

1**#include** *<*boost/iterator_adaptors.hpp*> *

2

3**template** *<***typename** ForwardIterator,

4 **typename** Predicate*> *

5ForwardIterator

6first_max_element_if(ForwardIter first,

7 ForwardIter last,

8 Predicate pred)

9{

10 **return** first_max_element(

11 boost::make_filter_iterator(first, last,

12 pred),

13 boost::make_filter_iterator(last, last,

14 pred)

15 );

16}

Program 1.5: Finding First Minimum in an integer array

1**template** *<***typename** ForwardIterator*> *

2ForwardIterator first_min_element(

3 ForwardIter first, ForwardIter last)

4{

5 **if** (first == last) **return** last;

6 ForwardIter min_result = first;

7 **while** (++first != last)

8 {

9 **if** (*first *<* *min_result)

10 min_result = first;

11 }

12 **return** min_result;

13}

Please note that :

Program 1.6: Ordering Equivalence

1**std**::min_element(v.**begin**(), v.**end**(),

2 **std**::**less***<***int***>*())

3==

4**std**::max_element(v.**begin**(), v.**end**(),

5 **std**::greater*<***int***>*())

Program 1.7: Finding Last Maximum in an integer array

1**template** *<***typename** ForwardIterator*> *

2ForwardIterator last_max_element(

3 ForwardIter first, ForwardIter last)

4{

5 **if** (first == last) **return** last;

6 ForwardIter max_result = first;

7 **while** (++first != last)

8 {

9 **if** (*first *<* *max_result)

10 max_result = first;

11 }

12 **return** max_result;

13}

Program 1.8: Finding Last Minimum in an integer array

1**template** *<***typename** ForwardIterator*> *

2ForwardIterator last_min_element(

3 ForwardIter first, ForwardIter last)

4{

5 **if** (first == last) **return** last;

6 ForwardIter min_result = first;

7 **while** (++first != last)

8 {

9 **if** (*min_result *<* *first)

10 min_result = first;

11 }

12 **return** min_result;

13}

Please note that:

Program 1.9: Another Ordering Equivalence

1**std**::reverse_iterator(

2 first_min_element(v.**begin**(), v.**end**(),

3 **std**::**less***<***int***>*()))

4==

5last_max_element(v.rbegin(), v.rend(),

6 **std**::greater*<***int***>*())

All of these algorithms work in similar way requiring *n - 1 *comparisons in worst case.

How about simultaneously finding maximum and minimum of the sequence?

Naively, we can get this done in two passes : once for finding maximum and another for finding minimum : total of *2n - 2 *comparisons. But we can definitely do better if we confine ourselves to a single pass and reply on maintaining maximum and minimum elements seen so far. Instead of picking one element and probing it against the current maximum or minimum, we can rather examine two elements at a time treating them as pairs. The process goes like this:

1.

Maintain the minimum and maximum of elements seen so far.

2.

Don’t compare each element to the minimum and maximum separately, which requires two comparisons per element.

3.

Pick up the elements in pairs.

4.

Compare the elements of a pair to each other.

5.

Then compare the larger element to the maximum so far, and compare the smaller element to the minimum so far.

The above requires only three comparisons per two elements. Setting up the initial values for the min and max depends on whether n is odd or even.

If n is even, compare the first two elements and assign the larger to max and the smaller to min.

more comparisons. Thus total number of comparisons =

- 3

- 2.

Then process the rest of the elements in pairs.

comparisons.

Program 1.10: C++ Implementation of first min and first max

1**template** *<***typename** ForwardIterator*> *

2**std**::pair*<*ForwardIterator, ForwardIterator*> *

3first_min_first_max_element(

4 ForwardIterator first,

5 ForwardIterator last)

6{

7 **if** (first == last)

8 **return** **std**::make_pair(last,last);

9

10 ForwardIterator min_result,

11 max_result = first;

12

13 *//* *if* *only* *one* *element *

14 ForwardIterator second = first; ++second;

15

16 **if** (second == last)

17 **return** **std**::make_pair(min_result,

18 max_result);

19

20 *//* *treat* *first* *pair* *separately *

21 *//(only* *one* *comparison* *for *

22 *//first* *two* *elements) *

23 ForwardIterator

24 potential_min_result = last;

25

26 **if** (*first *<* *second) max_result = second;

27 **else **

28 {

29 min_result = second;

30 potential_min_result = first;

31 }

32

33 *//* *then* *each* *element* *by* *pairs, *

34 *//* *with* *at* *most* *3* *comparisons* *per* *pair *

35 first = ++second;

36

37 **if** (first != last) ++second;

38

39 **while** (second != last)

40 {

41 **if** (*first *<* *second)

42 {

43 **if** (*first *<* *min_result)

44 {

45 min_result = first;

46 potential_min_result = last;

47 }

48

49 **if** (*max_result *<* *second)

50 max_result = second;

51 }

52 **else **

53 {

54 **if** (*second *<* *min_result)

55 {

56 min_result = second;

57 potential_min_result = first;

58 }

59

60 **if** (*max_result *<* *first)

61 max_result = first;

62 }

63

64 first = ++second;

65

66 **if** (first != last) ++second;

67 }

68

69 *//* *if* *odd* *number* *of* *elements, *

70 *//treat* *last* *element *

71 **if** (first != last)

72 { *//* *odd* *number* *of* *elements *

73 **if** (*first *<* *min_result)

74 {

75 min_result = first;

76 potential_min_result = last;

77 }

78 **else** **if** (*max_result *<* *first)

79 max_result = first;

80 }

81

82 *//* *resolve* *min_result* *being* *incorrect *

83 *//* *with* *one* *extra* *comparison *

84 *//* *(in* *which* *case* *potential_min_result *

85 *//* *is* *necessarily* *the *

86 *//* *correct* *result) *

87 **if** (potential_min_result != last &&

88 !(*min_result *<* *potential_min_result))

89 min_result = potential_min_result;

90

91 **return **

92 **std**::make_pair(min_result,max_result);

93}

Please note that only one comparison is required for first two elements(aka first pair). The above requires at most three comparisons per pair.

In similar spirit, there are multiple combinations possible like:

first_min_first_max_element

first_min_last_max_element

last_min_first_max_element

last_min_last_max_element

Let us look at the implementation of

first_min_last_max_element as inspiration.

Program 1.11: first_min_last_max_element

1**template** *<***typename** ForwardIterator*> *

2**std**::pair*<*ForwardIterator,ForwardIterator*> *

3first_min_last_max_element(

4 ForwardIterator first,

5 ForwardIterator last)

6{

7 **if** (first == last)

8 **return** **std**::make_pair(last,last);

9

10 ForwardIterator min_result,

11 max_result = first;

12

13 ForwardIterator second = ++first;

14

15 **if** (second == last)

16 **return** **std**::make_pair(min_result,

17 max_result);

18

19 **if** (*second *<* *min_result)

20 min_result = second;

21 **else** max_result = second;

22

23 first = ++second;

24

25 **if** (first != last) ++second;

26

27 **while** (second != last)

28 {

29 **if** (!(*second *<* *first))

30 {

31 **if** (*first *<* *min_result)

32 min_result = first;

33 **if** (!(*second *<* *max_result))

34 max_result = second;

35 }

36 **else **

37 {

38 **if** (*second *<* *min_result)

39 min_result = second;

40 **if** (!(*first *<* *max_result))

41 max_result = first;

42 }

43

44 first = ++second;

45

46 **if** (first != last) ++second;

47 }

48

49 **if** (first != last)

50 {

51 **if** (*first *<* *min_result)

52 min_result = first;

53 **else** **if** (!(*first *<* *max_result))

54 max_result = first;

55 }

56 **return** **std**::make_pair(min_result, max_result);

57}

**Generic Select **

Selection can be reduced to sorting by sorting the sequence and then extracting the sought after element. This method is more efficient when many selections need to be made from a sequence, in which case only one initial, so-called expensive sort is needed, followed by many relatively less expensive extraction operations, usually in amortized constant time. In general, this method requires *O*(*n *log *n*) time, where *n *is the length of the sequence.

Let us try using similar ideas as in finding minimum and maximum of a given sequence for finding the *kth *smallest or *kth *largest element in a sequence.

Algorithm 4: Generic Kth Select Minimum

1: **function** generic-kth-min-select(a, l, r, k)

2: *numElements *← *r *- *l *+ 1

3: **for** *i *

You've reached the end of this preview. Sign up to read more!

Page 1 of 1

Close Dialog## Are you sure?

This action might not be possible to undo. Are you sure you want to continue?

Loading