Discrete Math Lec410!22!21
Discrete Math Lec410!22!21
• Determinants of a matrix
• Inverse of a matrix
• Analysis of Algorithms
Note the difference in the matrix
Determinants and the determinant of the
matrix!
1 3
• Every square matrix has
a determinant. -½ 0
• The determinant of a
matrix is a number.
• We will consider the -3 8 ¼
determinants only of
2x2 and 3x3 matrices. 2 0 -¾
4 180 11
Why do we need the determinant
• It is used to help us calculate
the inverse of a matrix and it
is used when finding the area
of a triangle
Finding Determinants of Matrices
3 2
= (3 * 4) - (-5 * 2)
5 4
= 12 - (-10)
= 22
Finding Determinants of Matrices
2 0 3 2 0
1 2 5 1 -2
1 4 2 -1 4
1 0 2 x 2 identity matrix
0 1
1 0 0
0 1 0
3 x 3 identity matrix
0 0 1
1 0 5 2 5 2
3 4 =
3
4
0 1
5 2 1 0 5 2
=
3 4 0 1 3 4
Mathematically, IA = A and AI = A !!
Using matrix equations
Inverse Matrix: 2 x 2
a b
A
c d
1 1 d b
A ad bc c a
In words:
•Take the original matrix.
•Switch a and d.
•Change the signs of b and c.
•Multiply the new matrix by 1 over the determinant of the original matrix.
Using matrix equations
2 4
A
4 10
1 1 10 4
A (2)( 10) ( 4)( 4) 4 2
5 1
1 1 10 4
A 4 4 2 =
2
1
1
2
Find the inverse matrix.
8 3
1 Matrix
Inverse =
5 2 det Reloaded
Matrix A
1 2 3 2 3
=
1 =
5 8 5 8
What happens when you multiply a matrix by its inverse?
1
1st: What happens when you multiply a number by its inverse? 7
7
8 3 2 3 1 0
=
5 2 5 8 0 1
So, AA-1 = I
Algorithms
•What is an algorithm?
12
Algorithms
• Properties of algorithms:
13
Algorithm Examples
•We will use a pseudocode to specify algorithms, which
slightly reminds us of Basic and Pascal.
•Example: an algorithm that finds the maximum element in
a finite sequence
14
Algorithm Examples
•Another example: a linear search algorithm, that is, an
algorithm that linearly searches a sequence for a particular
element.
procedure linear_search(x: integer; a1, a2, …, an:
integers)
i := 1
while (i n and x ai)
i := i + 1
if i n then location := i
else location := 0
{location is the subscript of the term that equals x, or is
zero if x is not found}
15
Algorithm Examples
16
Algorithm Examples
search interval
a c d f g h j l m o p r s u v x z
center element
17
Algorithm Examples
search interval
a c d f g h j l m o p r s u v x z
center element
18
Algorithm Examples
search interval
a c d f g h j l m o p r s u v x z
center element
19
Algorithm Examples
search interval
a c d f g h j l m o p r s u v x z
center element
20
Algorithm Examples
search interval
a c d f g h j l m o p r s u v x z
center element
found !
21
Algorithm Examples
procedure binary_search(x: integer; a1, a2, …, an:
integers)
i := 1 {i is left endpoint of search interval}
j := n {j is right endpoint of search interval}
while (i < j)
begin
m := (i + j)/2
if x > am then i := m + 1
else j := m
end
if x = ai then location := i
else location := 0
{location is the subscript of the term that equals x, or is
zero if x is not found}
22
Bubble Sort
• The bubble sort is one of the simplest sorting algorithms,
but not one of the most efficient.
• It puts a list into increasing order by successively
comparing adjacent elements, interchanging them if they
are in the wrong order.
Bubble Sort
• To carry out the bubble sort, we perform the basic
operation, that is, interchanging a larger element with a
smaller one following it, starting at the beginning of the list,
for a full pass.
• We iterate this procedure until the sort is complete.
Bubble Sort
• Pseudocode for the bubble sort is given as Algorithm 4.
• We can imagine the elements in the list placed in a column.
• In the bubble sort, the smaller elements “bubble” to the top
as they are interchanged with larger elements.
• The larger elements “sink” to the bottom.
Bubble Sort
Bubble Sort
Bubble Sort
Insertion sort
• The insertion sort is a simple sorting algorithm, but it is
usually not the most efficient.
• To sort a list with n elements, the insertion sort begins with
the second element.
• The insertion sort compares this second element with the
first element and inserts it before the first element if it does
not exceed the first element and after the first element if it
exceeds the first element.
Insertion sort
• At this point, the first two elements are in the correct order.
• The third element is then compared with the first element,
and if it is larger than the first element, it is compared with
the second element; it is inserted into the correct position
among the first three elements.
Insertion sort
• In general, in the j th step of the insertion sort, the j th
element of the list is inserted into the correct position in the
list of the previously sorted j − 1 elements.
• To insert the j th element in the list, a linear search
technique is used; the j th element is successively compared
with the already sorted j − 1 elements at the start of the list
until the first element that is not less than this element is
found or until it has been compared with all j − 1 elements;
the j th element is inserted in the correct position so that the
first j elements are sorted.
Insertion sort
• The algorithm continues until the last element is placed in
the correct position relative to the already sorted list of the
first n − 1 elements. The insertion sort is described in
pseudocode in Algorithm 5.
Insertion sort
• Use the insertion sort to put the elements of the list 3, 2, 4,
1, 5 in increasing order.
• Solution: The insertion sort first compares 2 and 3. Because
3 > 2, it places 2 in the first position, producing the list 2, 3,
4, 1, 5 (the sorted part of the list is shown in color). At this
point, 2 and 3 are in the correct order.
Insertion sort
• Next, it inserts the third element, 4, into the already sorted
part of the list by making the comparisons 4 > 2 and 4 > 3.
• Because 4 > 3, 4 remains in the third position.
• At this point, the list is 2, 3, 4, 1, 5 and we know that the
ordering of the first three elements is correct.
• Next, we find the correct place for the fourth element, 1,
among the already sorted elements, 2, 3, 4.
• Because 1 < 2, we obtain the list 1, 2, 3, 4, 5.
Insertion sort
• Finally, we insert 5 into the correct position by successively
comparing it to 1, 2, 3, and 4.
• Because 5 > 4, it stays at the end of the list, producing the
correct order for the entire list
Insertion sort
What’s next?
• The growth of functions
• Complexity of Algorithms
• Big-O notation
Growth of functions
Objectives:
• study the number of operations used by these algorithms.
• estimate the number of comparisons used by the linear and
binary search algorithms to find an element in a sequence of
n elements.
Growth of functions
• The time required to solve a problem depends on more than
the number of operations it uses.
• The time also depends on the hardware and software used to
run the program that implements the algorithm.
• However, when we change the hardware and software used
to implement an algorithm, we can closely approximate the
time required to solve a problem of size n by multiplying
the previous time required by a constant.
Growth of functions
• One of the advantages of using big-O notation is that we
can estimate the growth of a function without worrying
about constant multipliers or smaller order terms.
• This means that, using big-O notation, we do not have to
worry about the hardware and software used to implement
an algorithm.
• Furthermore, using big-O notation, we can assume that the
different operations used in an algorithm take the same
time, which simplifies the analysis considerably
Growth of functions
• Big-O notation is used extensively to estimate the number
of operations an algorithm uses as its input grows.
• With the help of this notation, we can determine whether it
is practical to use a particular algorithm to solve a problem
as the size of the input increases.
Growth of functions
• Furthermore, using big-O notation, we can compare two
algorithms to determine which is more efficient as the size
of the input grows.
• For instance, if we have two algorithms for solving a
problem, one using 100n2 + 17n + 4 operations and the
other using n3 operations, big-O notation can help us see
that the first algorithm uses far fewer operations when n is
large, even though it uses more operations for small values
of n, such as n = 10.
Complexity
43
Complexity
44
Complexity
45
Complexity
• Comparison: time complexity of algorithms A and B
n 5,000n 1.1n
10 50,000 3
46
Complexity
47
The Growth of Functions
•The growth of functions is usually described using the
big-O notation.
48
The Growth of Functions
49
The Growth of Functions
•The idea behind the big-O notation is to establish an
upper boundary for the growth of a function f(x) for
large x.
•This boundary is specified by a function g(x) that is
usually much simpler than f(x).
•We accept the constant C in the requirement
•f(x) Cg(x) whenever x > k,
•because C does not grow with x.
•We are only interested in large x, so it is OK if
f(x) > Cg(x) for x k.
50
The Growth of Functions
•Example:
•Show that f(x) = x2 + 2x + 1 is O(x2).
• f(x) is O(x2).
51
The Growth of Functions
•Example:
•Show that 7x2 is O(x3).
•For x > 7 we have:
•7x2 x3
•Therefore, for C = 1 and k = 7:
•f(x) Cx2 whenever x > k.
• f(x) is O(x3).
52
The Growth of Functions
53
The Growth of Functions
“Popular” functions g(n) are
n log n, 1, 2n, n2, n!, n, n3, log n
54
The Growth of Functions
55
Useful Rules for Big-O
For any polynomial f(x) = anxn + an-1xn-1 + … + a0, where
a0, a1, …, an are real numbers,
f(x) is O(xn).
58
Analysis of Algorithms
Running Time
80
with the input size.
60
Average case time is often
difficult to determine. 40
running time. 0
1000 2000 3000 4000
Easier to analyze Input Size
Crucial to applications such as
games, finance and robotics
algorithm 7000
Time (ms)
inputs of varying size and 5000
composition 4000
Use a method like 3000
System.currentTimeMillis() to 2000
get an accurate measure
1000
of the actual running time
0
Plot the results 0 50 100
Input Size
An potentially unbounded
bank of memory cells, 1
2
each of which can hold an 0
arbitrary number or
character
Memory cells are numbered and accessing
any cell in memory takes unit time.
© 2004 Goodrich, Tamassia Analysis of Algorithms 66
Primitive Operations
Basic computations
Examples:
performed by an algorithm
Evaluating an
Identifiable in pseudocode expression
Largely independent from the Assigning a value
to a variable
programming language
Indexing into an
Exact definition not important array
(we will see why later) Calling a method
Returning from a
Assumed to take a constant
method
amount of time in the RAM
model
Constant 1 1E+25
Quadratic
1E+23
Logarithmic log n 1E+21 Linear
Linear n 1E+19
N-Log-N n log n 1E+17
T(n)
1E+15
Quadratic n2 1E+13
Cubic n3 1E+11
Exponential 2n 1E+9
1E+7
1E+5
In a log-log chart, the 1E+3
slope of the line 1E+1
T(n)
1E+13
Examples 1E+11
102n + 105 is a linear 1E+9
1E+7
function 1E+5
105n2 + 108n is a 1E+3
quadratic function 1E+1
1E-1
1E-1 1E+1 1E+3 1E+5 1E+7 1E+9
n2 cn 10,000 n
nc
The above inequality 1,000
cannot be satisfied
since c must be a 100
constant
10
1
1 10 100 1,000
n
3n3 + 20n2 + 5
3n3 + 20n2 + 5 is O(n3)
need c > 0 and n0 1 such that 3n3 + 20n2 + 5 c•n3 for n n0
this is true for c = 4 and n0 = 21
3 log n + 5
3 log n + 5 is O(log n)
need c > 0 and n0 1 such that 3 log n + 5 c•log n for n n0
this is true for c = 8 and n0 = 2
© 2004 Goodrich, Tamassia Analysis of Algorithms 75
Big-Oh and Growth Rate
The big-Oh notation gives an upper bound on the
growth rate of a function
The statement “f(n) is O(g(n))” means that the growth
rate of f(n) is not more than the growth rate of g(n)
We can use the big-Oh notation to rank functions
according to their growth rate
big-Theta
f(n) is (g(n)) if there are constants c’ > 0 and c’’
> 0 and an integer constant n0 1 such that
c’•g(n) f(n) c’’•g(n) for n n0
87
What does “size of the input” mean?
If we are searching an array, the “size” of the input could be the size of the
array
If we are merging two arrays, the “size” could be the sum of the two array
sizes
If we are computing the nth Fibonacci number, or the nth factorial, the
“size” is n
We choose the “size” to be the parameter that most influences the actual
time/space required
It is usually obvious what this parameter is
Sometimes we need two or more parameters
88
Characteristic operations
In computing time complexity, one good approach
is to count characteristic operations
What a “characteristic operation” is depends on the
particular problem
If searching, it might be comparing two values
If sorting an array, it might be:
comparing two values
swapping the contents of two array locations
both of the above
Sometimes we just look at how many times the
innermost loop is executed
89
Exact values
It is sometimes possible, in assembly language, to
compute exact time and space requirements
We know exactly how many bytes and how many cycles
each machine instruction takes
For a problem with a known sequence of steps (factorial,
Fibonacci), we can determine how many instructions of
each type are required
However, often the exact sequence of steps cannot
be known in advance
The steps required to sort an array depend on the actual
numbers in the array (which we do not know in advance)
90
Higher-level languages
In a higher-level language (such as Java), we do not
know how long each operation takes
Which is faster, x < 10 or x <= 9 ?
We don’t know exactly what the compiler does with this
The compiler probably optimizes the test anyway
(replacing the slower version with the faster one)
In a higher-level language we cannot do an exact
analysis
Our timing analyses will use major oversimplifications
Nevertheless, we can get some very useful results
91
Average, best, and worst cases
Usually we would like to find the average time to perform an algorithm
However,
Sometimes the “average” isn’t well defined
Example: Sorting an “average” array
Time typically depends on how out of order the array is
92
Constant time
Constant time means there is some constant k such
that this operation always takes k nanoseconds
A Java statement takes constant time if:
It does not include a loop
93
Linear time
We may not be able to predict to the nanosecond how long a
Java program will take, but do know some things about
timing:
for (i = 0, j = 1; i < n; i++) {
j = j * i;
}
This loop takes time k*n + c, for some constants k and c
k : How long it takes to go through the loop once
(the time for j = j * i, plus loop overhead)
n : The number of times through the loop
(we can use this as the “size” of the problem)
c : The time it takes to initialize the loop
The total time k*n + c is linear in n
94
Constant time is (usually)
better than linear time
Suppose we have two algorithms to solve a task:
Algorithm A takes 5000 time units
Algorithm B takes 100*n time units
Which is better?
Clearly, algorithm B is better if our problem size is small,
that is, if n < 50
Algorithm A is better for larger problems, with n > 50
So B is better on small problems that are quick anyway
But A is better for large problems, where it matters more
We usually care most about very large problems
But not always!
95
The array subset problem
Suppose you have two sets, represented as unsorted arrays:
int[] sub = { 7, 1, 3, 2, 5 };
int[] super = { 8, 4, 7, 1, 2, 3, 9 };
and you want to test whether every element of the first set
(sub) also occurs in the second set (super):
System.out.println(subset(sub, super));
(The answer in this case should be false, because sub
contains the integer 5, and super doesn’t)
We are going to write method subset and compute its time
complexity (how fast it is)
Let’s start with a helper function, member, to test whether
one number is in an array
96
member
static boolean member(int x, int[] a) {
int n = a.length;
for (int i = 0; i < n; i++) {
if (x == a[i]) return true;
}
return false;
}
If x is not in a, the loop executes n times, where
n = a.length
This is the worst case
If x is in a, the loop executes n/2 times on average
Either way, linear time is required: k*n+c
97
subset
static boolean subset(int[] sub, int[] super) {
int m = sub.length;
for (int i = 0; i < m; i++)
if (!member(sub[i], super) return false;
return true;
}
The loop (and the call to member) will execute:
m = sub.length times, if sub is a subset of super
This is the worst case, and therefore the one we are most interested in
99
What about the constants?
Forget the constants!
An added constant, f(n)+c, becomes less and less
important as n gets larger
A constant multiplier, k*f(n), does not get less
important, but...
Improving k gives a linear speedup (cutting k in half cuts the
time required in half)
Improving k is usually accomplished by careful code
optimization, not by better algorithms
We aren’t that concerned with only linear speedups!
100
Simplifying the formulae
Throwing out the constants is one of two things we
do in analysis of algorithms
By throwing out constants, we simplify 12n2 + 35 to
just n2
Our timing formula is a polynomial, and may have
terms of various orders (constant, linear, quadratic,
cubic, etc.)
We usually discard all but the highest-order term
We simplify n2 + 3n + 5 to just n2
101
Big O notation
When we have a polynomial that describes the time requirements of an
algorithm, we simplify it by:
Throwing out all but the highest-order term
Throwing out all the constants
If an algorithm takes 12n3+4n2+8n+35 time, we simplify this formula
to just n3
We say the algorithm requires O(n3) time
We call this Big O notation
(More accurately, it’s Big , but we’ll talk about that later)
102
Big O for subset algorithm
Recall that, if n is the size of the set, and m is the size of the (possible)
subset:
We go through the loop in subset m times, calling member each time
We go through the loop in member n times
Hence, the actual running time should be k*(m*n) + c, for some constants k
and c
We say that subset takes O(m*n) time
103
Can we justify Big O notation?
Big O notation is a huge simplification; can we
justify it?
It only makes sense for large problem sizes
For sufficiently large problem sizes, the
highest-order term swamps all the rest!
Consider R = x2 + 3x + 5 as x varies:
x= 0 x2 = 0 3x =0 5 =5 R= 5
x= 10 x2 = 100 3x = 30 5 =5 R= 135
x= 100 x2 = 10000 3x = 300 5 =5 R= 10,305
x= 1000 x2 = 1000000 3x = 3000 5 =5 R= 1,003,005
x= 10,000 x2 = 108 3x = 3*104 5 =5 R= 100,030,005
x= 100,000 x2 = 1010 3x = 3*105 5 =5 R= 10,000,300,005
104
y = x2 + 3x + 5, for x=1..10
105
y = x2 + 3x + 5, for x=1..20
106
Common time complexities
BETTER O(1) constant time
O(log n) log time
O(n) linear time
O(n log n) log linear time
O(n2) quadratic time
O(n3) cubic time
O(2n) exponential time
WORSE
107
FINDING RUNNING TIME OF AN ALGORITHM /
ANALYZING AN ALGORITHM
Running time is measured by number of steps/primitive
operations performed
108
SIMPLE EXAMPLE (1)
N = 10 => 53 steps
N = 100 => 503 steps
N = 1,000 => 5003 steps
N = 1,000,000 => 5,000,003 steps
111
WHAT DOMINATES IN PREVIOUS
EXAMPLE?
112
ASYMPTOTIC COMPLEXITY
113
COMPARING FUNCTIONS:
ASYMPTOTIC NOTATION
Big Oh Notation: Upper bound
114
BIG OH NOTATION [1]
f(N) = O(g(N))
115
BIG OH NOTATION [2]
116
O(F(N))
117
EXAMPLE (2): COMPARING FUNCTIONS
10 n2 Vs n3 3500
3000
2500
10 n^2
2000
n^3
1500
1000
500
0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
118
COMPARING FUNCTIONS
0.05 N2 = O(N2)
Time (steps)
3N = O(N)
Input (size)
N = 60
119
BIG-OH NOTATION
Simple Rule:
Drop lower order terms and constant factors
7n-3 is O(n)
8n2log n + 5n2 + n is O(n2log n)
120
BIG OMEGA NOTATION
If we wanted to say “running time is at least…” we use Ω
If f(n) and g(n) are two complexity functions then we can say:
f(n) is Ω(g(n)) if there exist positive numbers c and n0 such that 0<=f(n)>=cΩ (n) for all n>=n0
121
BIG THETA NOTATION
If we wish to express tight bounds we use the theta notation, Θ
122
WHAT DOES THIS ALL MEAN?
If f(n) = Θ(g(n)) we say that f(n) and g(n) grow at the same
rate, asymptotically
123
WHICH NOTATION DO WE USE?
To express the efficiency of our algorithms which of the
three notations should we use?
Why?
log n Logarithmic: when n increases, so does run time, but much slower. Common in programs which
solve large problems by transforming them into smaller problems. Exp : binary Search
n Linear: run time varies directly with n. Typically, a small amount of processing is done on each
element. Exp: Linear Search
n log n When n doubles, run time slightly more than doubles. Common in programs which break a problem
down into smaller sub-problems, solves them independently, then combines solutions. Exp: Merge
n2 Quadratic: when n doubles, runtime increases fourfold. Practical only for small problems; typically
the program processes all pairs of input (e.g. in a double nested loop). Exp: Insertion Search
2n Exponential: when n doubles, run time squares. This is often the result of a natural, “brute force”
solution. Exp: Brute Force.
Note: logn, n, nlogn, n2>> less Input>>Polynomial
n3, 2n>>high input>> non polynomial
125
SIZE DOES MATTER[1]
N log2N 5N N log2N N2 2N
8 3 40 24 64 256
16 4 80 64 256 65536
32 5 160 160 1024 ~109
64 6 320 384 4096 ~1019
128 7 640 896 16384 ~1038
256 8 1280 2048 65536 ~1076
126
COMPLEXITY CLASSES
Time (steps)
127
SIZE DOES MATTER[2]
Suppose a program has run time O(n!) and the run time for
n = 10 is 1 second
Analyzing Loops
Arithmetic operations:
x = 5 * y + 4 - z;
Array referencing:
A[j] = 5;
Array assignment:
j, A[j] = 5;
130
Most conditional tests:
if (x < 12) ...
ANALYZING LOOPS[1]
Any loop has two parts:
How many iterations are performed?
How many steps per iteration?
int j,k;
for (j=0; j<N; j++)
for (k=N; k>0; k--)
sum += k+j;
int j,k;
for (j=0; j < N; j++)
for (k=0; k < j; k++)
sum += k+j;
Gauss figured out that the sum of the first n numbers is always:
136
SEQUENCE OF STATEMENTS
For a sequence of statements, compute their complexity
functions individually and add them up
137
CONDITIONAL STATEMENTS
What about conditional statements such as
if (condition)
statement1;
else
statement2;
However if N ≥ 2, then running time T(N) is the cost of each step taken plus time
required to compute power(x,n-1). (i.e. T(N) = 2+T(N-1) for N ≥ 2)
139