WEBVTT

00:00:00.000 --> 00:00:01.976 align:middle line:90%
[SQUEAKING]

00:00:01.976 --> 00:00:04.446 align:middle line:90%
[RUSTLING]

00:00:04.446 --> 00:00:06.422 align:middle line:90%
[CLICKING]

00:00:06.422 --> 00:00:13.360 align:middle line:90%


00:00:13.360 --> 00:00:17.970 align:middle line:84%
JASON KU: Welcome to our
fourth problem session.

00:00:17.970 --> 00:00:21.460 align:middle line:84%
We're going to be talking about
binary trees mostly, today.

00:00:21.460 --> 00:00:24.430 align:middle line:84%
We'll talk a little bit
about binary heaps, which

00:00:24.430 --> 00:00:27.650 align:middle line:84%
is a topic we won't
cover until next Tuesday,

00:00:27.650 --> 00:00:32.710 align:middle line:84%
but it will appear
in very small ways

00:00:32.710 --> 00:00:36.460 align:middle line:84%
on your problem set 4, which
will be due next Friday.

00:00:36.460 --> 00:00:40.660 align:middle line:84%
So I'm going to go over a little
bit of that material today.

00:00:40.660 --> 00:00:43.150 align:middle line:90%
But it's mostly concerning--

00:00:43.150 --> 00:00:48.880 align:middle line:84%
the subject material for
today is mostly binary trees,

00:00:48.880 --> 00:00:52.450 align:middle line:84%
specifically, being applied
to set data structures

00:00:52.450 --> 00:00:57.400 align:middle line:84%
and sequence data structures,
as Professor Demaine talked

00:00:57.400 --> 00:01:01.340 align:middle line:90%
to you earlier this week.

00:01:01.340 --> 00:01:06.100 align:middle line:84%
But for now-- actually,
as of yesterday--

00:01:06.100 --> 00:01:08.410 align:middle line:84%
you've seen all of the data
structures that we're going

00:01:08.410 --> 00:01:10.090 align:middle line:90%
to cover to--

00:01:10.090 --> 00:01:13.180 align:middle line:84%
that will implement the set
interface and the sequence

00:01:13.180 --> 00:01:14.470 align:middle line:90%
interface.

00:01:14.470 --> 00:01:21.160 align:middle line:84%
Those nice tables that Professor
Demaine has been showing you,

00:01:21.160 --> 00:01:22.960 align:middle line:90%
those are now complete.

00:01:22.960 --> 00:01:25.210 align:middle line:84%
We have some data
structures that

00:01:25.210 --> 00:01:28.930 align:middle line:84%
are really good-- constant time
operations for some operations.

00:01:28.930 --> 00:01:32.740 align:middle line:84%
So we might use them
for some applications.

00:01:32.740 --> 00:01:36.520 align:middle line:84%
And this week, we've
been describing

00:01:36.520 --> 00:01:40.150 align:middle line:84%
to you trees, which
achieve, really, pretty

00:01:40.150 --> 00:01:43.660 align:middle line:84%
good, for any type of
query operation on my sets

00:01:43.660 --> 00:01:44.980 align:middle line:90%
or sequences--

00:01:44.980 --> 00:01:48.320 align:middle line:84%
pretty good meaning logarithmic
time, not quite constant.

00:01:48.320 --> 00:01:51.895 align:middle line:90%
But for our purposes, log n is--

00:01:51.895 --> 00:01:54.580 align:middle line:84%
I mean, on your
computer, practically--

00:01:54.580 --> 00:01:56.890 align:middle line:84%
not asymptotically,
but practically-- log

00:01:56.890 --> 00:02:00.430 align:middle line:84%
n is going to be at most
what on your computer?

00:02:00.430 --> 00:02:03.520 align:middle line:90%


00:02:03.520 --> 00:02:07.030 align:middle line:90%
Something like 64, right?

00:02:07.030 --> 00:02:11.620 align:middle line:84%
Any input that you're operating
on with, in machine words,

00:02:11.620 --> 00:02:14.000 align:middle line:90%
is your input.

00:02:14.000 --> 00:02:16.000 align:middle line:84%
You need to be able to
address all those machine

00:02:16.000 --> 00:02:18.550 align:middle line:90%
words in your input.

00:02:18.550 --> 00:02:22.840 align:middle line:84%
And on your computer, the size
of your machine word addresses

00:02:22.840 --> 00:02:25.030 align:middle line:90%
is 64 bits, right?

00:02:25.030 --> 00:02:27.760 align:middle line:84%
And we assume that the
word size is at least

00:02:27.760 --> 00:02:33.700 align:middle line:84%
log the size of your input so
that you can address the input.

00:02:33.700 --> 00:02:37.060 align:middle line:84%
So for your purposes,
on your computer,

00:02:37.060 --> 00:02:39.100 align:middle line:84%
log n is going to
be no more than 64,

00:02:39.100 --> 00:02:42.460 align:middle line:84%
which means you would get
maybe a 50 times overhead,

00:02:42.460 --> 00:02:45.670 align:middle line:84%
or for smaller instances,
it could be more like 10,

00:02:45.670 --> 00:02:49.300 align:middle line:84%
if you've got 1,000 things
that you're working on.

00:02:49.300 --> 00:02:50.620 align:middle line:90%
It's not that bad, right?

00:02:50.620 --> 00:02:53.740 align:middle line:84%
It's a constant-- it's not
a constant factor for theory

00:02:53.740 --> 00:02:57.970 align:middle line:84%
purposes, but for your purposes,
log n is much better than

00:02:57.970 --> 00:02:59.980 align:middle line:90%
a polynomial factor--

00:02:59.980 --> 00:03:03.250 align:middle line:90%
another factor of n.

00:03:03.250 --> 00:03:05.800 align:middle line:90%
You've seen all of the code.

00:03:05.800 --> 00:03:08.950 align:middle line:84%
You've seen implementations of
all of these set and sequence

00:03:08.950 --> 00:03:10.300 align:middle line:90%
interfaces, right?

00:03:10.300 --> 00:03:12.550 align:middle line:84%
So I went ahead and
wrote a little--

00:03:12.550 --> 00:03:15.490 align:middle line:84%
I compiled all of that code
from your recitation notes,

00:03:15.490 --> 00:03:18.610 align:middle line:84%
of all of the different
interface implementations.

00:03:18.610 --> 00:03:22.720 align:middle line:84%
And what I did was, I
wrote a little test program

00:03:22.720 --> 00:03:25.960 align:middle line:84%
to see how they ran
on a real machine.

00:03:25.960 --> 00:03:30.340 align:middle line:90%
I have a little test code here.

00:03:30.340 --> 00:03:35.410 align:middle line:84%
I have a little folder that
lists an array implementing

00:03:35.410 --> 00:03:37.270 align:middle line:84%
a sequence, a binary
tree implementing

00:03:37.270 --> 00:03:39.400 align:middle line:84%
a sequence, a dynamic
array implementing--

00:03:39.400 --> 00:03:41.170 align:middle line:90%
all of these kinds of things.

00:03:41.170 --> 00:03:45.250 align:middle line:84%
Then set things-- a sorted array
being a set in a binary tree,

00:03:45.250 --> 00:03:46.600 align:middle line:90%
and a hash table.

00:03:46.600 --> 00:03:48.010 align:middle line:90%
These are our implementations.

00:03:48.010 --> 00:03:50.710 align:middle line:84%
I'm not using Python
dictionaries for hash tables,

00:03:50.710 --> 00:03:55.330 align:middle line:84%
I'm using the implementations
that are in your recitation.

00:03:55.330 --> 00:03:56.980 align:middle line:84%
And I'm going to
run this little test

00:03:56.980 --> 00:03:59.440 align:middle line:84%
efficiency Python code
that basically is just

00:03:59.440 --> 00:04:00.550 align:middle line:90%
going to free each one.

00:04:00.550 --> 00:04:03.370 align:middle line:84%
It's going to do a bunch of
these different operations

00:04:03.370 --> 00:04:05.650 align:middle line:84%
and measure to see
how much time it took.

00:04:05.650 --> 00:04:07.720 align:middle line:84%
I'm just logging how
much time it took.

00:04:07.720 --> 00:04:11.380 align:middle line:84%
It's not an asymptotic
analysis, but hopefully, we

00:04:11.380 --> 00:04:13.330 align:middle line:90%
see some separation.

00:04:13.330 --> 00:04:16.390 align:middle line:84%
So when you press that,
it runs a bunch of tests.

00:04:16.390 --> 00:04:19.269 align:middle line:90%
Let's take a look.

00:04:19.269 --> 00:04:20.620 align:middle line:90%
OK.

00:04:20.620 --> 00:04:23.660 align:middle line:84%
I've got a bunch of
sequence operations.

00:04:23.660 --> 00:04:28.150 align:middle line:84%
We've got build, set_at,
get-at, insert, delete,

00:04:28.150 --> 00:04:30.880 align:middle line:90%
at the various places.

00:04:30.880 --> 00:04:36.250 align:middle line:84%
And these are the actual
timings to some scale--

00:04:36.250 --> 00:04:39.610 align:middle line:84%
to some resolution that I had
for these data structures.

00:04:39.610 --> 00:04:41.680 align:middle line:90%
And you can see build--

00:04:41.680 --> 00:04:44.170 align:middle line:84%
actually, build,
on this machine,

00:04:44.170 --> 00:04:46.270 align:middle line:84%
just allocating some
array and clearing it,

00:04:46.270 --> 00:04:49.850 align:middle line:84%
is a really efficient thing that
Python is going to do for me.

00:04:49.850 --> 00:04:54.520 align:middle line:84%
And so that's actually-- it's
mislabelling that as log n.

00:04:54.520 --> 00:04:57.970 align:middle line:84%
But these other things,
get_at and set_at--

00:04:57.970 --> 00:04:59.680 align:middle line:90%
really, really fast, right?

00:04:59.680 --> 00:05:00.910 align:middle line:90%
That's constant time.

00:05:00.910 --> 00:05:02.800 align:middle line:84%
And then these other
things, I essentially

00:05:02.800 --> 00:05:05.020 align:middle line:84%
can't do better than
loop through the thing,

00:05:05.020 --> 00:05:06.730 align:middle line:90%
and so it takes linear time.

00:05:06.730 --> 00:05:11.500 align:middle line:84%
And again, sequence stuff,
setting_at and getting_at

00:05:11.500 --> 00:05:15.250 align:middle line:84%
is slow, but deleting and
removing from the first thing,

00:05:15.250 --> 00:05:17.800 align:middle line:84%
I'm just re-linking
the pointer, right?

00:05:17.800 --> 00:05:18.910 align:middle line:90%
Dynamic arrays.

00:05:18.910 --> 00:05:23.440 align:middle line:84%
Again, set_at, get_at is
fast, because it's just

00:05:23.440 --> 00:05:24.670 align:middle line:90%
regular arrays.

00:05:24.670 --> 00:05:27.340 align:middle line:84%
And then inserting-
and deleting-last,

00:05:27.340 --> 00:05:30.010 align:middle line:84%
that's getting,
essentially, constant time.

00:05:30.010 --> 00:05:32.680 align:middle line:84%
Now, I'm actually-- when I'm
running these tests to deal

00:05:32.680 --> 00:05:34.180 align:middle line:84%
with averages, I'm
actually running

00:05:34.180 --> 00:05:36.980 align:middle line:84%
these things, a lot of times,
and testing their performance.

00:05:36.980 --> 00:05:41.500 align:middle line:84%
And so I'm not seeing the
worst case happen here, right?

00:05:41.500 --> 00:05:43.420 align:middle line:84%
I'm averaging over all
of the things, which

00:05:43.420 --> 00:05:46.630 align:middle line:84%
is exactly what
amortization means.

00:05:46.630 --> 00:05:50.560 align:middle line:84%
That's why I'm getting
good performance here.

00:05:50.560 --> 00:05:51.940 align:middle line:90%
A hash table.

00:05:51.940 --> 00:05:56.710 align:middle line:84%
Again, really--
oh, so this is what

00:05:56.710 --> 00:05:59.320 align:middle line:84%
we talked about
in problem session

00:05:59.320 --> 00:06:04.180 align:middle line:84%
last week, implementing
kind of a double-ended queue

00:06:04.180 --> 00:06:06.070 align:middle line:90%
with a hash table.

00:06:06.070 --> 00:06:07.450 align:middle line:90%
This is that implementation.

00:06:07.450 --> 00:06:09.130 align:middle line:90%
I just wanted to show it to you.

00:06:09.130 --> 00:06:10.460 align:middle line:90%
But it's actually pretty good.

00:06:10.460 --> 00:06:14.080 align:middle line:84%
This is what JavaScript
uses for arrays.

00:06:14.080 --> 00:06:19.240 align:middle line:84%
And then a binary sequence
represented as a binary tree--

00:06:19.240 --> 00:06:20.550 align:middle line:90%
a balanced binary tree.

00:06:20.550 --> 00:06:22.480 align:middle line:90%
This is our AVL code that I had.

00:06:22.480 --> 00:06:25.720 align:middle line:84%
And all of the other things
have been really pretty bad

00:06:25.720 --> 00:06:28.338 align:middle line:84%
at insert_at and
delete_at, but this one

00:06:28.338 --> 00:06:30.130 align:middle line:84%
does comparable to all
of the other things.

00:06:30.130 --> 00:06:34.060 align:middle line:84%
Now, you see these are a
little bit more machine

00:06:34.060 --> 00:06:39.230 align:middle line:84%
cycles than the other things,
but not so bad, actually.

00:06:39.230 --> 00:06:41.710 align:middle line:84%
And then, on the
set side of things,

00:06:41.710 --> 00:06:44.420 align:middle line:90%
again, we had a sorted array.

00:06:44.420 --> 00:06:46.840 align:middle line:84%
Sorry, this is a
set from an array.

00:06:46.840 --> 00:06:48.970 align:middle line:84%
Basically, it's
an unsorted array.

00:06:48.970 --> 00:06:52.480 align:middle line:84%
I'm just looking for all of the
things-- that's very bad times.

00:06:52.480 --> 00:06:54.970 align:middle line:84%
Sorted array does these
find operations great,

00:06:54.970 --> 00:06:58.040 align:middle line:84%
but inserting and
deleting is poor.

00:06:58.040 --> 00:07:00.820 align:middle line:90%
That's why we need binary trees.

00:07:00.820 --> 00:07:05.080 align:middle line:84%
Hash tables get good dictionary
operations, but really

00:07:05.080 --> 00:07:08.410 align:middle line:90%
bad order operations.

00:07:08.410 --> 00:07:13.990 align:middle line:84%
And then the binary search
tree, a set binary tree, again,

00:07:13.990 --> 00:07:16.490 align:middle line:84%
does quite good on
all of these things.

00:07:16.490 --> 00:07:20.450 align:middle line:84%
In fact, it's getting
really quite good--

00:07:20.450 --> 00:07:22.300 align:middle line:84%
it's getting better,
for some reason,

00:07:22.300 --> 00:07:26.200 align:middle line:90%
than the sorted array even did.

00:07:26.200 --> 00:07:27.730 align:middle line:90%
I don't know why.

00:07:27.730 --> 00:07:30.220 align:middle line:84%
Our implementations are
not optimized at all.

00:07:30.220 --> 00:07:31.890 align:middle line:84%
But it does pretty
well asymptotically.

00:07:31.890 --> 00:07:32.160 align:middle line:90%
Yeah?

00:07:32.160 --> 00:07:33.535 align:middle line:84%
AUDIENCE: Could
you explain again

00:07:33.535 --> 00:07:38.470 align:middle line:84%
why the first data
treasury [INAUDIBLE] log n?

00:07:38.470 --> 00:07:41.830 align:middle line:84%
JASON KU: This is just
labeled based off the timings.

00:07:41.830 --> 00:07:43.930 align:middle line:84%
It happens to be that,
probably, there's

00:07:43.930 --> 00:07:47.200 align:middle line:84%
a C intrinsic underneath Python
that allocates this thing,

00:07:47.200 --> 00:07:49.060 align:middle line:90%
and so it does it really fast.

00:07:49.060 --> 00:07:51.460 align:middle line:84%
My program that's
looking at these numbers

00:07:51.460 --> 00:07:54.350 align:middle line:84%
and trying to guess what the
asymptotic running time is,

00:07:54.350 --> 00:07:57.590 align:middle line:84%
these are just labels based
on these things, ranges.

00:07:57.590 --> 00:07:59.113 align:middle line:90%
I just-- it's mischaracterized.

00:07:59.113 --> 00:08:01.605 align:middle line:90%
AUDIENCE: [INAUDIBLE]

00:08:01.605 --> 00:08:02.230 align:middle line:90%
JASON KU: Yeah.

00:08:02.230 --> 00:08:06.940 align:middle line:84%
Well, I mean, in actuality,
if it was C code--

00:08:06.940 --> 00:08:09.730 align:middle line:84%
if all of this stuff
was in C, probably,

00:08:09.730 --> 00:08:12.820 align:middle line:84%
we would see that bar be
longer, because it's actually

00:08:12.820 --> 00:08:15.370 align:middle line:84%
having to go through and
touch all of that memory.

00:08:15.370 --> 00:08:18.250 align:middle line:84%
It's still doing that here,
but all of the Python stuff

00:08:18.250 --> 00:08:19.810 align:middle line:90%
is super crufty.

00:08:19.810 --> 00:08:23.110 align:middle line:84%
It's, like, 100 times slower
than anything that C does.

00:08:23.110 --> 00:08:26.730 align:middle line:84%
And so you're seeing
that disparity.

00:08:26.730 --> 00:08:27.920 align:middle line:90%
Does that make sense?

00:08:27.920 --> 00:08:28.420 align:middle line:90%
OK.

00:08:28.420 --> 00:08:30.610 align:middle line:90%
I just wanted to show you that.

00:08:30.610 --> 00:08:33.850 align:middle line:84%
We might release this for
you to play around with,

00:08:33.850 --> 00:08:36.309 align:middle line:84%
but just wanted to give
you a taste of that.

00:08:36.309 --> 00:08:41.010 align:middle line:84%
OK, any questions
before we move on?

00:08:41.010 --> 00:08:42.879 align:middle line:90%
How do I turn this off?

00:08:42.879 --> 00:08:46.960 align:middle line:90%
Up, and off.

00:08:46.960 --> 00:08:47.680 align:middle line:90%
Shut down.

00:08:47.680 --> 00:08:51.750 align:middle line:90%


00:08:51.750 --> 00:08:52.780 align:middle line:90%
Yes.

00:08:52.780 --> 00:08:53.280 align:middle line:90%
OK.

00:08:53.280 --> 00:08:58.440 align:middle line:90%


00:08:58.440 --> 00:09:02.640 align:middle line:84%
Moving on to problems--
working some problems.

00:09:02.640 --> 00:09:04.660 align:middle line:84%
You have your set
of problems here.

00:09:04.660 --> 00:09:09.483 align:middle line:84%
The first one is, we're going
to look at a sequence AVL tree.

00:09:09.483 --> 00:09:10.650 align:middle line:90%
This is a sequence AVL tree.

00:09:10.650 --> 00:09:11.442 align:middle line:90%
How do I know that?

00:09:11.442 --> 00:09:15.200 align:middle line:90%


00:09:15.200 --> 00:09:16.760 align:middle line:90%
You don't, necessarily.

00:09:16.760 --> 00:09:19.460 align:middle line:84%
But these things
are certainly not

00:09:19.460 --> 00:09:23.450 align:middle line:84%
in sorted order of the things
I'm storing in them, Yeah?

00:09:23.450 --> 00:09:26.420 align:middle line:84%
So it had better not
be a set AVL tree.

00:09:26.420 --> 00:09:27.530 align:middle line:90%
Is it an AVL tree?

00:09:27.530 --> 00:09:30.510 align:middle line:84%
Is it balanced--
height balanced?

00:09:30.510 --> 00:09:32.220 align:middle line:90%
Yeah, basically.

00:09:32.220 --> 00:09:36.810 align:middle line:84%
Actually, if you compute
the size of each subtree,

00:09:36.810 --> 00:09:39.120 align:middle line:84%
the left and right subtrees
on all of these-- you

00:09:39.120 --> 00:09:41.400 align:middle line:84%
can confirm for
yourself-- are balanced.

00:09:41.400 --> 00:09:43.950 align:middle line:84%
They're within plus or
minus 1 of each other.

00:09:43.950 --> 00:09:46.500 align:middle line:84%
Actually, this is about
as far away from balanced

00:09:46.500 --> 00:09:50.550 align:middle line:84%
as you could get
for this many nodes

00:09:50.550 --> 00:09:52.600 align:middle line:84%
while still maintaining
height balance--

00:09:52.600 --> 00:09:54.720 align:middle line:84%
maintaining AVL
property-- which is why

00:09:54.720 --> 00:09:56.040 align:middle line:90%
this is an instructive example.

00:09:56.040 --> 00:09:58.740 align:middle line:90%
It's kind of at the limit.

00:09:58.740 --> 00:10:02.370 align:middle line:90%
And what am I going to do?

00:10:02.370 --> 00:10:04.980 align:middle line:84%
What's missing in this
picture if I'm claiming

00:10:04.980 --> 00:10:08.790 align:middle line:90%
this is a sequence AVL tree?

00:10:08.790 --> 00:10:11.850 align:middle line:90%
Any ideas what's missing?

00:10:11.850 --> 00:10:14.700 align:middle line:84%
What does the sequence AVL
tree store that I'm not

00:10:14.700 --> 00:10:16.360 align:middle line:90%
showing in this picture?

00:10:16.360 --> 00:10:17.190 align:middle line:90%
AUDIENCE: Counts.

00:10:17.190 --> 00:10:17.490 align:middle line:90%
JASON KU: What?

00:10:17.490 --> 00:10:18.282 align:middle line:90%
AUDIENCE: Counts.

00:10:18.282 --> 00:10:18.990 align:middle line:90%
JASON KU: Counts.

00:10:18.990 --> 00:10:19.490 align:middle line:90%
And?

00:10:19.490 --> 00:10:22.520 align:middle line:90%


00:10:22.520 --> 00:10:25.360 align:middle line:90%
It's a sequence AVL tree.

00:10:25.360 --> 00:10:27.320 align:middle line:90%
Heights, right?

00:10:27.320 --> 00:10:29.470 align:middle line:84%
Sequence AVL trees,
different than set AVL trees,

00:10:29.470 --> 00:10:31.000 align:middle line:84%
are augmented by
two things, right?

00:10:31.000 --> 00:10:34.690 align:middle line:84%
Because I need to be
maintaining balance during

00:10:34.690 --> 00:10:36.910 align:middle line:84%
rotations, and so I
need to store heights.

00:10:36.910 --> 00:10:39.490 align:middle line:84%
I need to be able to tell what
the heights of these subtrees

00:10:39.490 --> 00:10:41.440 align:middle line:84%
are in constant time
when I'm walking up

00:10:41.440 --> 00:10:43.090 align:middle line:90%
the tree, fixing things.

00:10:43.090 --> 00:10:47.440 align:middle line:84%
And the sequence requires me
to store their subtree numbers

00:10:47.440 --> 00:10:50.200 align:middle line:90%
there.

00:10:50.200 --> 00:10:52.030 align:middle line:84%
I don't know-- I'm
not going to draw it

00:10:52.030 --> 00:10:55.270 align:middle line:84%
for all of these things, but
how about for number four?

00:10:55.270 --> 00:10:56.050 align:middle line:90%
What's its height?

00:10:56.050 --> 00:10:59.670 align:middle line:90%


00:10:59.670 --> 00:11:00.840 align:middle line:90%
1, 2, 3.

00:11:00.840 --> 00:11:05.200 align:middle line:84%
That's the longest path from
the root subtree of that.

00:11:05.200 --> 00:11:09.210 align:middle line:90%
So this is height equals 3.

00:11:09.210 --> 00:11:13.900 align:middle line:84%
That came from height equals
2 and height equals 1.

00:11:13.900 --> 00:11:15.000 align:middle line:90%
Does everyone see that?

00:11:15.000 --> 00:11:15.690 align:middle line:90%
Yeah?

00:11:15.690 --> 00:11:18.390 align:middle line:84%
And then the size
here, how big is that?

00:11:18.390 --> 00:11:22.440 align:middle line:90%
That's 1, 2, 3, 4, 5, 6, 7.

00:11:22.440 --> 00:11:27.060 align:middle line:84%
This is-- I'm going to
put size equals 7 here.

00:11:27.060 --> 00:11:31.770 align:middle line:84%
And that's coming from
this guy, 1, 2, 3, 4.

00:11:31.770 --> 00:11:33.105 align:middle line:90%
And this guy is 2.

00:11:33.105 --> 00:11:36.300 align:middle line:90%


00:11:36.300 --> 00:11:39.700 align:middle line:84%
So how do I compute
the subtree size?

00:11:39.700 --> 00:11:43.830 align:middle line:84%
It's my left subtree size plus
my right subtree size plus 1.

00:11:43.830 --> 00:11:47.100 align:middle line:84%
And my height is taking
the max of the 2 plus 1.

00:11:47.100 --> 00:11:47.600 align:middle line:90%
All right.

00:11:47.600 --> 00:11:50.280 align:middle line:90%
So we did all that yesterday.

00:11:50.280 --> 00:11:52.860 align:middle line:90%
I'm just labeling these things.

00:11:52.860 --> 00:11:59.730 align:middle line:84%
And what I'm asking of you is
to perform a delete operation.

00:11:59.730 --> 00:12:02.250 align:middle line:90%
This is a sequence tree.

00:12:02.250 --> 00:12:06.190 align:middle line:84%
So I'm finding things by
their index in the tree.

00:12:06.190 --> 00:12:08.790 align:middle line:84%
So I'm going to ask you
to delete the eighth thing

00:12:08.790 --> 00:12:10.980 align:middle line:90%
in my sequence.

00:12:10.980 --> 00:12:14.770 align:middle line:84%
What is the 8th
thing in my sequence?

00:12:14.770 --> 00:12:15.370 align:middle line:90%
Yeah?

00:12:15.370 --> 00:12:17.890 align:middle line:84%
AUDIENCE: Just to clarify,
since delete-8 is not delete

00:12:17.890 --> 00:12:18.520 align:middle line:90%
the number.

00:12:18.520 --> 00:12:19.270 align:middle line:90%
JASON KU: Correct.

00:12:19.270 --> 00:12:21.360 align:middle line:90%
Well, delete_at 8.

00:12:21.360 --> 00:12:22.237 align:middle line:90%
Do you see that?

00:12:22.237 --> 00:12:23.320 align:middle line:90%
It's a sequence operation.

00:12:23.320 --> 00:12:23.650 align:middle line:90%
AUDIENCE: Oh, OK.

00:12:23.650 --> 00:12:24.195 align:middle line:90%
[INAUDIBLE]

00:12:24.195 --> 00:12:24.820 align:middle line:90%
JASON KU: Yeah.

00:12:24.820 --> 00:12:27.160 align:middle line:84%
So this is very
important, that you

00:12:27.160 --> 00:12:30.340 align:middle line:84%
differentiate between
sequence and set semantics.

00:12:30.340 --> 00:12:32.140 align:middle line:84%
If I'm dealing
with the sequence,

00:12:32.140 --> 00:12:35.440 align:middle line:84%
I had better not be
looking up intrinsic things

00:12:35.440 --> 00:12:38.390 align:middle line:84%
on this data structure, because
it's not an intrinsic data

00:12:38.390 --> 00:12:38.890 align:middle line:90%
structure.

00:12:38.890 --> 00:12:39.910 align:middle line:90%
It doesn't support that.

00:12:39.910 --> 00:12:46.870 align:middle line:84%
If I wanted to support find,
say, the index of key 8,

00:12:46.870 --> 00:12:50.410 align:middle line:84%
or something like that,
then all I could do

00:12:50.410 --> 00:12:51.993 align:middle line:90%
is-- it's similar to an array.

00:12:51.993 --> 00:12:54.160 align:middle line:84%
I would just have to loop
through the whole sequence

00:12:54.160 --> 00:12:56.290 align:middle line:84%
and tell me if the
thing is in it.

00:12:56.290 --> 00:12:58.165 align:middle line:84%
Can't really do better
than linear time.

00:12:58.165 --> 00:13:00.040 align:middle line:84%
This data structure is
not designed for that.

00:13:00.040 --> 00:13:01.040 align:middle line:90%
What is it designed for?

00:13:01.040 --> 00:13:05.140 align:middle line:84%
It's designed to find things
by their index in the sequence.

00:13:05.140 --> 00:13:12.130 align:middle line:90%
So how do I find the 8th index?

00:13:12.130 --> 00:13:14.110 align:middle line:84%
Well, I mean, I'm
looking at the tree,

00:13:14.110 --> 00:13:17.140 align:middle line:84%
and I can just count
along in-order traversal.

00:13:17.140 --> 00:13:19.990 align:middle line:90%
What's the in-order traversal?

00:13:19.990 --> 00:13:24.850 align:middle line:90%
0, 1, 2, 3, 4, 5, 6, 7.

00:13:24.850 --> 00:13:26.530 align:middle line:90%
OK, found 8.

00:13:26.530 --> 00:13:29.470 align:middle line:84%
But what does a
sequence AVL tree do?

00:13:29.470 --> 00:13:32.620 align:middle line:90%


00:13:32.620 --> 00:13:34.990 align:middle line:84%
I'm storing subtree
sizes, and when I'm here,

00:13:34.990 --> 00:13:38.110 align:middle line:90%
I don't know what index I'm at.

00:13:38.110 --> 00:13:40.900 align:middle line:84%
How can I find out what
index I'm at from the root?

00:13:40.900 --> 00:13:44.980 align:middle line:84%
I look at my left subtree,
see how many it is.

00:13:44.980 --> 00:13:47.990 align:middle line:90%
There are seven things here.

00:13:47.990 --> 00:13:52.910 align:middle line:90%
1, 2, 3, 4, 5, 6, 7.

00:13:52.910 --> 00:13:53.410 align:middle line:90%
Yeah.

00:13:53.410 --> 00:13:57.280 align:middle line:84%
Because I'm looking for
the 9th item by index 8.

00:13:57.280 --> 00:14:01.060 align:middle line:84%
This is saying that
I'm the 8th item.

00:14:01.060 --> 00:14:03.485 align:middle line:90%
I'm the guy at index 7.

00:14:03.485 --> 00:14:04.360 align:middle line:90%
Does that make sense?

00:14:04.360 --> 00:14:07.310 align:middle line:84%
Because I'm looking at
the subtree size here.

00:14:07.310 --> 00:14:08.930 align:middle line:90%
So what do I know?

00:14:08.930 --> 00:14:13.240 align:middle line:84%
I know that the index that I'm
looking for is to my right.

00:14:13.240 --> 00:14:17.350 align:middle line:84%
I go down over here
and I happen to know--

00:14:17.350 --> 00:14:23.470 align:middle line:84%
what index am I looking
for in this subtree?

00:14:23.470 --> 00:14:25.090 align:middle line:90%
0, right?

00:14:25.090 --> 00:14:27.490 align:middle line:84%
I want the first
thing in the subtree.

00:14:27.490 --> 00:14:32.380 align:middle line:84%
My search index has changed
now, because I essentially dealt

00:14:32.380 --> 00:14:35.740 align:middle line:90%
with all of those eight items.

00:14:35.740 --> 00:14:38.990 align:middle line:84%
Here, I'm looking for the
0th thing in my index.

00:14:38.990 --> 00:14:40.290 align:middle line:90%
I look to my left--

00:14:40.290 --> 00:14:43.930 align:middle line:84%
if I didn't have a left subtree,
I would be the 0th thing,

00:14:43.930 --> 00:14:45.010 align:middle line:90%
and I would return me.

00:14:45.010 --> 00:14:46.330 align:middle line:90%
But there is stuff in here.

00:14:46.330 --> 00:14:51.850 align:middle line:84%
So I'm looking for the 0th thing
in here, which is just him,

00:14:51.850 --> 00:14:53.560 align:middle line:90%
and I return it.

00:14:53.560 --> 00:14:56.890 align:middle line:84%
And actually, what I'm
doing is, I'm deleting it.

00:14:56.890 --> 00:15:00.190 align:middle line:90%
So I delete it.

00:15:00.190 --> 00:15:02.610 align:middle line:90%
Yuck.

00:15:02.610 --> 00:15:05.382 align:middle line:90%
What's the problem here?

00:15:05.382 --> 00:15:06.260 align:middle line:90%
AUDIENCE: [INAUDIBLE]

00:15:06.260 --> 00:15:07.920 align:middle line:90%
JASON KU: Not height balanced.

00:15:07.920 --> 00:15:10.610 align:middle line:90%
What's not height balanced here?

00:15:10.610 --> 00:15:12.510 align:middle line:90%
AUDIENCE: The left subtree is--

00:15:12.510 --> 00:15:13.150 align:middle line:90%
or, sorry.

00:15:13.150 --> 00:15:13.830 align:middle line:90%
[INAUDIBLE]

00:15:13.830 --> 00:15:15.280 align:middle line:84%
JASON KU: This guy is not
height balanced, right?

00:15:15.280 --> 00:15:17.100 align:middle line:84%
AUDIENCE: --right subtree
of the right [INAUDIBLE]..

00:15:17.100 --> 00:15:19.558 align:middle line:84%
JASON KU: This guy's subtree
is not height balanced, right?

00:15:19.558 --> 00:15:20.250 align:middle line:90%
This guy's 2.

00:15:20.250 --> 00:15:22.380 align:middle line:90%
This guy's 1.

00:15:22.380 --> 00:15:24.300 align:middle line:90%
So how do we fix it?

00:15:24.300 --> 00:15:25.740 align:middle line:90%
AUDIENCE: Rotate.

00:15:25.740 --> 00:15:27.690 align:middle line:90%
JASON KU: We do some rotations.

00:15:27.690 --> 00:15:30.470 align:middle line:84%
This is actually
the bad case that--

00:15:30.470 --> 00:15:33.570 align:middle line:84%
the third bad case that
we talked about yesterday.

00:15:33.570 --> 00:15:37.260 align:middle line:84%
If I tried to just
left-rotate this guy,

00:15:37.260 --> 00:15:38.540 align:middle line:90%
what would it look like?

00:15:38.540 --> 00:15:40.740 align:middle line:90%
It would put 12 here.

00:15:40.740 --> 00:15:42.240 align:middle line:90%
It would put 10 here.

00:15:42.240 --> 00:15:45.360 align:middle line:90%
And 8 would be attached to that.

00:15:45.360 --> 00:15:48.090 align:middle line:84%
Now it's height balanced wrong
in the other direction, right?

00:15:48.090 --> 00:15:49.950 align:middle line:90%
That's no good.

00:15:49.950 --> 00:15:53.490 align:middle line:84%
So the way to handle
this case, where

00:15:53.490 --> 00:15:59.100 align:middle line:84%
I am badly skewed to the
right but my right subtree

00:15:59.100 --> 00:16:03.900 align:middle line:84%
is skewed to the left, I
have to do a rotation here,

00:16:03.900 --> 00:16:06.810 align:middle line:84%
right rotation, and
then do a rotation.

00:16:06.810 --> 00:16:08.880 align:middle line:90%
That's the formula.

00:16:08.880 --> 00:16:10.920 align:middle line:84%
Here, we first do
a right rotation

00:16:10.920 --> 00:16:21.440 align:middle line:84%
at 10, which gives me something
that looks like 8, 10.

00:16:21.440 --> 00:16:25.150 align:middle line:84%
Now, obviously, this is not
better than what was before,

00:16:25.150 --> 00:16:28.750 align:middle line:84%
but it was an intermediate
step so that we can fix it.

00:16:28.750 --> 00:16:32.050 align:middle line:84%
We right-rotate here and
then we left-rotate here.

00:16:32.050 --> 00:16:34.290 align:middle line:84%
The default is that we
would left-rotate here,

00:16:34.290 --> 00:16:38.440 align:middle line:84%
but because this had the
skew in the wrong direction,

00:16:38.440 --> 00:16:41.390 align:middle line:84%
I need to right-rotate this one
first and then we can do it.

00:16:41.390 --> 00:16:43.570 align:middle line:84%
So now I rotate
all of these guys

00:16:43.570 --> 00:16:50.005 align:middle line:84%
over and put 12 down
here, 8 here, 10 here.

00:16:50.005 --> 00:16:53.010 align:middle line:90%


00:16:53.010 --> 00:16:56.700 align:middle line:84%
Everyone see that that's
what a rotation looks like?

00:16:56.700 --> 00:16:57.230 align:middle line:90%
OK.

00:16:57.230 --> 00:17:00.210 align:middle line:84%
It takes a little while to get
your mind wrapped around what

00:17:00.210 --> 00:17:02.970 align:middle line:84%
the transformation is, but
hopefully, you guys all

00:17:02.970 --> 00:17:04.283 align:middle line:90%
followed that transformation.

00:17:04.283 --> 00:17:06.450 align:middle line:84%
There was a little magic
while I was trying to draw.

00:17:06.450 --> 00:17:06.930 align:middle line:90%
Yeah?

00:17:06.930 --> 00:17:08.500 align:middle line:84%
AUDIENCE: I still don't
feel like this tree is

00:17:08.500 --> 00:17:09.270 align:middle line:90%
height balanced.

00:17:09.270 --> 00:17:10.980 align:middle line:90%
JASON KU: It's not.

00:17:10.980 --> 00:17:12.630 align:middle line:90%
Good observation.

00:17:12.630 --> 00:17:13.890 align:middle line:90%
Why is that?

00:17:13.890 --> 00:17:15.750 align:middle line:90%
This thing still has height 3.

00:17:15.750 --> 00:17:17.550 align:middle line:84%
What is the height
of this thing?

00:17:17.550 --> 00:17:19.020 align:middle line:90%
1, right?

00:17:19.020 --> 00:17:20.700 align:middle line:90%
This is height 1.

00:17:20.700 --> 00:17:23.400 align:middle line:84%
And actually, when I
was doing that rotation,

00:17:23.400 --> 00:17:27.318 align:middle line:84%
I needed to update all
of these augmentations.

00:17:27.318 --> 00:17:28.860 align:middle line:84%
Which augmentations
did I really need

00:17:28.860 --> 00:17:31.620 align:middle line:84%
to-- which subtrees have
changed during those things?

00:17:31.620 --> 00:17:36.380 align:middle line:90%


00:17:36.380 --> 00:17:38.810 align:middle line:84%
I don't remember what
the thing looked like.

00:17:38.810 --> 00:17:41.780 align:middle line:90%
What did the thing look like?

00:17:41.780 --> 00:17:46.860 align:middle line:84%
10 had 8 in its subtree, so
its subtree definitely changed.

00:17:46.860 --> 00:17:48.140 align:middle line:90%
8's subtree changed.

00:17:48.140 --> 00:17:49.220 align:middle line:90%
AUDIENCE: [INAUDIBLE]

00:17:49.220 --> 00:17:51.000 align:middle line:90%
JASON KU: 12 didn't change--

00:17:51.000 --> 00:17:51.500 align:middle line:90%
eventually.

00:17:51.500 --> 00:17:54.498 align:middle line:84%
AUDIENCE: These are
10 and 8 [INAUDIBLE]..

00:17:54.498 --> 00:17:55.040 align:middle line:90%
JASON KU: OK.

00:17:55.040 --> 00:17:57.920 align:middle line:84%
So there's the case analysis
that's in your lecture notes

00:17:57.920 --> 00:18:00.050 align:middle line:90%
and was done in recitation.

00:18:00.050 --> 00:18:03.800 align:middle line:84%
It tells you that
these A, B, C, D

00:18:03.800 --> 00:18:06.860 align:middle line:84%
kind of subtress,
the ones that could

00:18:06.860 --> 00:18:09.650 align:middle line:84%
change in these things,
those subtrees don't change.

00:18:09.650 --> 00:18:12.290 align:middle line:84%
The only subtree that
changed during one

00:18:12.290 --> 00:18:15.620 align:middle line:84%
of these fix operations, when
you do one or two rotations,

00:18:15.620 --> 00:18:18.860 align:middle line:84%
is either two nodes
or three nodes

00:18:18.860 --> 00:18:20.240 align:middle line:90%
whose subtree has changed.

00:18:20.240 --> 00:18:23.900 align:middle line:84%
Here, it could have been the
case that three subtrees have

00:18:23.900 --> 00:18:26.000 align:middle line:90%
changed.

00:18:26.000 --> 00:18:29.780 align:middle line:84%
But in the easy case, only
two nodes-- x and y, I think,

00:18:29.780 --> 00:18:31.130 align:middle line:90%
in the notes--

00:18:31.130 --> 00:18:32.040 align:middle line:90%
could have changed.

00:18:32.040 --> 00:18:36.710 align:middle line:84%
And so when I do that, I have
to recompute their augmentations

00:18:36.710 --> 00:18:39.200 align:middle line:84%
from their augmentations
of their children,

00:18:39.200 --> 00:18:42.110 align:middle line:84%
but it's only a constant
number of those,

00:18:42.110 --> 00:18:45.780 align:middle line:84%
so I just recompute them,
because the subtrees below me

00:18:45.780 --> 00:18:47.430 align:middle line:90%
haven't changed.

00:18:47.430 --> 00:18:47.930 align:middle line:90%
OK.

00:18:47.930 --> 00:18:50.280 align:middle line:84%
So we have a height
mismatch here.

00:18:50.280 --> 00:18:50.926 align:middle line:90%
Yeah?

00:18:50.926 --> 00:18:52.165 align:middle line:90%
AUDIENCE: [INAUDIBLE]

00:18:52.165 --> 00:18:56.743 align:middle line:90%


00:18:56.743 --> 00:18:57.410 align:middle line:90%
JASON KU: Right.

00:18:57.410 --> 00:19:01.730 align:middle line:84%
So, originally,
in the picture, 12

00:19:01.730 --> 00:19:04.010 align:middle line:84%
has a bunch of things
in its subtree--

00:19:04.010 --> 00:19:08.350 align:middle line:90%
10 and 8, and we just deleted 7.

00:19:08.350 --> 00:19:09.850 align:middle line:84%
So its subtree
definitely changed.

00:19:09.850 --> 00:19:10.980 align:middle line:90%
There used to be three--

00:19:10.980 --> 00:19:12.040 align:middle line:90%
AUDIENCE: [INAUDIBLE]

00:19:12.040 --> 00:19:14.130 align:middle line:90%
JASON KU: Oh, no, sorry, it did.

00:19:14.130 --> 00:19:14.680 align:middle line:90%
Yeah.

00:19:14.680 --> 00:19:18.040 align:middle line:84%
So here, three node
subtrees have changed.

00:19:18.040 --> 00:19:20.890 align:middle line:90%
But that's actually the most.

00:19:20.890 --> 00:19:23.620 align:middle line:90%
I'm showing you the worst case.

00:19:23.620 --> 00:19:25.870 align:middle line:84%
Only three nodes
possible in doing

00:19:25.870 --> 00:19:28.143 align:middle line:84%
one of these
double-rotation things

00:19:28.143 --> 00:19:29.560 align:middle line:84%
could have changed
their subtrees.

00:19:29.560 --> 00:19:32.740 align:middle line:84%
And so we just have to fix the
augmentation of those three

00:19:32.740 --> 00:19:33.610 align:middle line:90%
things.

00:19:33.610 --> 00:19:36.880 align:middle line:84%
In the easy case,
it's just two things.

00:19:36.880 --> 00:19:38.050 align:middle line:90%
All right.

00:19:38.050 --> 00:19:39.580 align:middle line:90%
We have unbalanced.

00:19:39.580 --> 00:19:40.600 align:middle line:90%
How can we fix this?

00:19:40.600 --> 00:19:43.520 align:middle line:90%


00:19:43.520 --> 00:19:45.890 align:middle line:90%
I could have been mean.

00:19:45.890 --> 00:19:49.070 align:middle line:84%
I want to be able to
right-rotate here,

00:19:49.070 --> 00:19:54.140 align:middle line:84%
to re-balance I could have been
mean and switched these two.

00:19:54.140 --> 00:19:56.150 align:middle line:84%
If I switched those
two, then I would

00:19:56.150 --> 00:19:58.100 align:middle line:84%
have to do two rotations
to fix this thing,

00:19:58.100 --> 00:20:01.040 align:middle line:84%
because the middle one is
heavier than the left one

00:20:01.040 --> 00:20:04.250 align:middle line:90%
against what I'm doing.

00:20:04.250 --> 00:20:09.140 align:middle line:84%
But I'm not that mean, so
I'm going to right-rotate.

00:20:09.140 --> 00:20:10.370 align:middle line:90%
How do I do that?

00:20:10.370 --> 00:20:13.130 align:middle line:84%
Well, a right-rotate
at 6 is going

00:20:13.130 --> 00:20:16.940 align:middle line:84%
to bring all of
this down below 4

00:20:16.940 --> 00:20:20.075 align:middle line:84%
and stick this subtree
as the left child of 6.

00:20:20.075 --> 00:20:21.830 align:middle line:90%
Does that makes sense?

00:20:21.830 --> 00:20:22.438 align:middle line:90%
Yuck.

00:20:22.438 --> 00:20:23.730 align:middle line:90%
That's going to be fun to draw.

00:20:23.730 --> 00:20:28.100 align:middle line:90%


00:20:28.100 --> 00:20:30.580 align:middle line:90%
I'm just going to redraw it.

00:20:30.580 --> 00:20:32.390 align:middle line:90%
That makes more sense, right?

00:20:32.390 --> 00:20:54.020 align:middle line:84%
4, 11, 3, 2, 1, and
then 6, 5, 9, 8, 12, 10.

00:20:54.020 --> 00:20:57.730 align:middle line:90%
That's the right rotation at 6.

00:20:57.730 --> 00:21:00.520 align:middle line:90%
Is everyone cool with this?

00:21:00.520 --> 00:21:05.140 align:middle line:84%
The rotation-- my
x is 6, my y is 4.

00:21:05.140 --> 00:21:09.400 align:middle line:90%
I have A, B, C subtrees.

00:21:09.400 --> 00:21:12.610 align:middle line:84%
What I'm doing is kind of
switching which of x and y

00:21:12.610 --> 00:21:15.610 align:middle line:90%
is the root here.

00:21:15.610 --> 00:21:23.080 align:middle line:84%
So now y is the root, and B
and C subtrees here now become

00:21:23.080 --> 00:21:25.480 align:middle line:90%
the children of x underneath y.

00:21:25.480 --> 00:21:29.110 align:middle line:84%
And notice that, hopefully,
through all of that process,

00:21:29.110 --> 00:21:33.150 align:middle line:84%
my in-order traversal
has not changed.

00:21:33.150 --> 00:21:35.600 align:middle line:84%
We had to update our
augmentations along the way,

00:21:35.600 --> 00:21:38.630 align:middle line:84%
but it's a constant every
time we walk up the tree.

00:21:38.630 --> 00:21:41.510 align:middle line:84%
And we walk up the tree only
a logarithmic number of times.

00:21:41.510 --> 00:21:42.460 align:middle line:90%
Yeah?

00:21:42.460 --> 00:21:42.960 align:middle line:90%
Yes.

00:21:42.960 --> 00:21:43.880 align:middle line:90%
AUDIENCE: [INAUDIBLE].

00:21:43.880 --> 00:21:46.778 align:middle line:84%
So every time we do a
rotation, do you just

00:21:46.778 --> 00:21:48.570 align:middle line:84%
update the augmentation
via the [INAUDIBLE]

00:21:48.570 --> 00:21:49.850 align:middle line:90%
before we do any other rotation?

00:21:49.850 --> 00:21:50.145 align:middle line:90%
JASON KU: Exactly.

00:21:50.145 --> 00:21:51.375 align:middle line:90%
AUDIENCE: The second part.

00:21:51.375 --> 00:21:53.870 align:middle line:84%
Updating the
augmentation just means

00:21:53.870 --> 00:21:57.380 align:middle line:84%
updating the count, and
the height, and just,

00:21:57.380 --> 00:21:58.510 align:middle line:90%
the properties that stay--

00:21:58.510 --> 00:21:59.135 align:middle line:90%
JASON KU: Yeah.

00:21:59.135 --> 00:22:00.650 align:middle line:84%
Basically what we
did, we defined--

00:22:00.650 --> 00:22:02.390 align:middle line:90%
when we augmented--

00:22:02.390 --> 00:22:04.610 align:middle line:84%
Professor Demaine
yesterday defined for you

00:22:04.610 --> 00:22:07.100 align:middle line:90%
what a subtree property is.

00:22:07.100 --> 00:22:10.490 align:middle line:84%
It meant a property
that I can compute only

00:22:10.490 --> 00:22:12.590 align:middle line:90%
by looking at my children--

00:22:12.590 --> 00:22:16.250 align:middle line:84%
the augmentations of my
children, recursively.

00:22:16.250 --> 00:22:20.570 align:middle line:84%
So here, instead of
trying to increment or try

00:22:20.570 --> 00:22:24.440 align:middle line:84%
to think about, locally, what
this augmentation should be,

00:22:24.440 --> 00:22:26.990 align:middle line:84%
I'm going to throw away
my old augmentation

00:22:26.990 --> 00:22:28.670 align:middle line:84%
and just recompute
it from my children,

00:22:28.670 --> 00:22:31.905 align:middle line:84%
because those, recursively,
had better be correct.

00:22:31.905 --> 00:22:32.780 align:middle line:90%
Does that make sense?

00:22:32.780 --> 00:22:33.463 align:middle line:90%
Yeah?

00:22:33.463 --> 00:22:35.630 align:middle line:84%
AUDIENCE: So just looking
at how the rotation works.

00:22:35.630 --> 00:22:38.420 align:middle line:84%
I'm having trouble
wrapping my head around.

00:22:38.420 --> 00:22:41.870 align:middle line:84%
So basically, you're swapping
4 and 6, and that way,

00:22:41.870 --> 00:22:47.390 align:middle line:84%
4 becomes the parent node
and 6 becomes the right node.

00:22:47.390 --> 00:22:50.480 align:middle line:84%
JASON KU: I'm going
to draw this picture.

00:22:50.480 --> 00:22:52.280 align:middle line:84%
It's just something
you've got to memorize.

00:22:52.280 --> 00:22:55.420 align:middle line:90%


00:22:55.420 --> 00:23:05.640 align:middle line:84%
This is x, B, C, and A.
Can you see that picture?

00:23:05.640 --> 00:23:07.495 align:middle line:90%
AUDIENCE: [INAUDIBLE]

00:23:07.495 --> 00:23:08.120 align:middle line:90%
JASON KU: What?

00:23:08.120 --> 00:23:09.355 align:middle line:90%
AUDIENCE: [INAUDIBLE]

00:23:09.355 --> 00:23:09.980 align:middle line:90%
JASON KU: Yeah.

00:23:09.980 --> 00:23:11.090 align:middle line:90%
It's in your notes.

00:23:11.090 --> 00:23:12.780 align:middle line:90%
It's not a big deal.

00:23:12.780 --> 00:23:15.140 align:middle line:84%
But if you've got
this structure,

00:23:15.140 --> 00:23:19.010 align:middle line:90%
where x has a left child--

00:23:19.010 --> 00:23:21.150 align:middle line:84%
and these subtrees
may be empty or not.

00:23:21.150 --> 00:23:22.100 align:middle line:90%
Doesn't really matter.

00:23:22.100 --> 00:23:25.490 align:middle line:84%
What I can do is, I can
move from here to there--

00:23:25.490 --> 00:23:30.780 align:middle line:84%
has the same in-order
traversal order,

00:23:30.780 --> 00:23:32.140 align:middle line:90%
but it's got a different shape.

00:23:32.140 --> 00:23:34.050 align:middle line:84%
And in particular,
subtree heights

00:23:34.050 --> 00:23:37.740 align:middle line:84%
have changed, which means it
can help us re-balance the tree.

00:23:37.740 --> 00:23:39.960 align:middle line:84%
And that's the
whole point of AVL.

00:23:39.960 --> 00:23:41.350 align:middle line:90%
Does that make sense?

00:23:41.350 --> 00:23:43.320 align:middle line:84%
AUDIENCE: That's
the right rotation?

00:23:43.320 --> 00:23:45.210 align:middle line:90%
JASON KU: This one is--

00:23:45.210 --> 00:23:46.680 align:middle line:90%
this is a right rotation.

00:23:46.680 --> 00:23:48.960 align:middle line:90%
This is a left rotation.

00:23:48.960 --> 00:23:50.860 align:middle line:90%
Any other questions?

00:23:50.860 --> 00:23:51.360 align:middle line:90%
Yeah?

00:23:51.360 --> 00:23:54.776 align:middle line:90%
AUDIENCE: [INAUDIBLE]

00:23:54.776 --> 00:23:58.530 align:middle line:90%


00:23:58.530 --> 00:24:00.510 align:middle line:84%
JASON KU: As I'm
walking up the tree,

00:24:00.510 --> 00:24:03.720 align:middle line:84%
every node I might have
to fix with a re-balance,

00:24:03.720 --> 00:24:07.290 align:middle line:84%
but that re-balance does
at most two rotations,

00:24:07.290 --> 00:24:11.070 align:middle line:84%
and there is at most log
n ancestors that I have,

00:24:11.070 --> 00:24:16.350 align:middle line:84%
because my tree was
height balanced at 2

00:24:16.350 --> 00:24:19.110 align:middle line:90%
log n or something like that.

00:24:19.110 --> 00:24:21.810 align:middle line:84%
Which means that,
at max, I might

00:24:21.810 --> 00:24:26.310 align:middle line:84%
have to do four log n rotations,
because each one could

00:24:26.310 --> 00:24:27.310 align:middle line:90%
do two rotations.

00:24:27.310 --> 00:24:28.230 align:middle line:90%
Does that makes sense?

00:24:28.230 --> 00:24:31.680 align:middle line:84%
Now, in actuality, you can prove
that, in a delete operation,

00:24:31.680 --> 00:24:34.050 align:middle line:84%
it's possible that you have
to do a logarithmic number

00:24:34.050 --> 00:24:35.430 align:middle line:90%
of these rotations up the tree.

00:24:35.430 --> 00:24:38.190 align:middle line:90%
This was that bad case.

00:24:38.190 --> 00:24:40.980 align:middle line:84%
The original tree I gave you
is called a Fibonacci tree.

00:24:40.980 --> 00:24:45.090 align:middle line:84%
It's the few-- it's the
highest height balanced tree

00:24:45.090 --> 00:24:47.385 align:middle line:84%
you can have on a
given number of nodes.

00:24:47.385 --> 00:24:52.620 align:middle line:90%


00:24:52.620 --> 00:24:55.440 align:middle line:84%
Yeah, the fewest nodes
for a certain height.

00:24:55.440 --> 00:24:56.820 align:middle line:90%
You can think of it either way.

00:24:56.820 --> 00:24:59.530 align:middle line:84%
And if you generalize that
to a large enough thing,

00:24:59.530 --> 00:25:01.470 align:middle line:84%
then that thing will
take a logarithmic number

00:25:01.470 --> 00:25:02.760 align:middle line:90%
of rotations going up.

00:25:02.760 --> 00:25:05.070 align:middle line:84%
Now, actually,
with an insertion,

00:25:05.070 --> 00:25:09.270 align:middle line:84%
you can actually prove-- you can
go through the case analysis.

00:25:09.270 --> 00:25:12.090 align:middle line:84%
An insertion operation will
always re-balance the tree

00:25:12.090 --> 00:25:15.668 align:middle line:84%
after one re-balance
operation, which

00:25:15.668 --> 00:25:16.835 align:middle line:90%
could include two rotations.

00:25:16.835 --> 00:25:19.350 align:middle line:90%
Does that makes sense?

00:25:19.350 --> 00:25:20.053 align:middle line:90%
Yeah?

00:25:20.053 --> 00:25:21.930 align:middle line:90%
AUDIENCE: [INAUDIBLE]

00:25:21.930 --> 00:25:27.280 align:middle line:90%


00:25:27.280 --> 00:25:27.920 align:middle line:90%
JASON KU: Yeah.

00:25:27.920 --> 00:25:30.415 align:middle line:84%
Right rotation, this guy
becomes a right child.

00:25:30.415 --> 00:25:31.040 align:middle line:90%
AUDIENCE: Yeah.

00:25:31.040 --> 00:25:33.550 align:middle line:84%
So can you not-- are there
certain rotations that you

00:25:33.550 --> 00:25:36.730 align:middle line:84%
can't perform, depending on
whether you had a child--

00:25:36.730 --> 00:25:37.390 align:middle line:90%
JASON KU: Yeah.

00:25:37.390 --> 00:25:43.070 align:middle line:84%
If I didn't have a left subtree,
can't perform a right rotation

00:25:43.070 --> 00:25:44.680 align:middle line:90%
there.

00:25:44.680 --> 00:25:47.340 align:middle line:84%
A right rotation necessitates
that I have a left child.

00:25:47.340 --> 00:25:48.520 align:middle line:90%
So if you're doing it--

00:25:48.520 --> 00:25:50.440 align:middle line:84%
and you'll see,
our code actually

00:25:50.440 --> 00:25:52.420 align:middle line:84%
checks to make sure
you have a left child.

00:25:52.420 --> 00:25:57.500 align:middle line:90%


00:25:57.500 --> 00:25:59.870 align:middle line:84%
That's an assertion
that you might

00:25:59.870 --> 00:26:02.960 align:middle line:84%
want to fire before you ever
do one of these rotations.

00:26:02.960 --> 00:26:03.700 align:middle line:90%
Anything else?

00:26:03.700 --> 00:26:04.560 align:middle line:90%
Yeah?

00:26:04.560 --> 00:26:06.393 align:middle line:84%
AUDIENCE: Just to
reiterate, so an insertion

00:26:06.393 --> 00:26:09.097 align:middle line:84%
may take two rotations
at most [INAUDIBLE]??

00:26:09.097 --> 00:26:09.680 align:middle line:90%
JASON KU: Mhm.

00:26:09.680 --> 00:26:11.680 align:middle line:84%
A constant number of
rotations, and the deletion

00:26:11.680 --> 00:26:14.540 align:middle line:84%
could take a logarithmic
number of rotations.

00:26:14.540 --> 00:26:16.490 align:middle line:84%
Now, that's not something
you need to know.

00:26:16.490 --> 00:26:19.460 align:middle line:84%
It's not something I'm
proving here to you.

00:26:19.460 --> 00:26:21.650 align:middle line:84%
Just something
that's interesting.

00:26:21.650 --> 00:26:26.390 align:middle line:84%
There are rebalancing
schemes, like in CRS.

00:26:26.390 --> 00:26:31.310 align:middle line:84%
They introduce a red-black
tree to introduce balance.

00:26:31.310 --> 00:26:34.670 align:middle line:84%
And those trees actually
have a weaker bound on--

00:26:34.670 --> 00:26:39.680 align:middle line:84%
it's not as tightly
balanced as an AVL tree is.

00:26:39.680 --> 00:26:44.030 align:middle line:90%
It allows higher than skew 2.

00:26:44.030 --> 00:26:46.400 align:middle line:84%
And because it's kind
of a weaker restriction,

00:26:46.400 --> 00:26:49.470 align:middle line:84%
they get away with only doing a
constant number of rotations--

00:26:49.470 --> 00:26:54.560 align:middle line:84%
that they can afford that
before they fix the tree.

00:26:54.560 --> 00:26:56.150 align:middle line:90%
But a little more complicated.

00:26:56.150 --> 00:26:57.680 align:middle line:90%
AUDIENCE: [INAUDIBLE]

00:26:57.680 --> 00:27:00.457 align:middle line:90%


00:27:00.457 --> 00:27:01.290 align:middle line:90%
JASON KU: Very nice.

00:27:01.290 --> 00:27:01.790 align:middle line:90%
OK.

00:27:01.790 --> 00:27:02.780 align:middle line:90%
Any questions on this?

00:27:02.780 --> 00:27:06.090 align:middle line:90%


00:27:06.090 --> 00:27:10.550 align:middle line:84%
OK, so now, this is more of
a mechanical question you'll

00:27:10.550 --> 00:27:11.750 align:middle line:90%
get on your problem sets.

00:27:11.750 --> 00:27:15.950 align:middle line:84%
And now we get more on to
the theory-type questions.

00:27:15.950 --> 00:27:19.230 align:middle line:84%
These are going to be a
reduction-type questions.

00:27:19.230 --> 00:27:19.730 align:middle line:90%
OK.

00:27:19.730 --> 00:27:25.250 align:middle line:90%
This first problem, Fick Nury.

00:27:25.250 --> 00:27:26.840 align:middle line:90%
This is-- anyone?

00:27:26.840 --> 00:27:27.650 align:middle line:90%
Nick Fury, right?

00:27:27.650 --> 00:27:31.280 align:middle line:90%
So it's an Avengers reference.

00:27:31.280 --> 00:27:33.800 align:middle line:84%
So basically, what
happens in this thing,

00:27:33.800 --> 00:27:38.210 align:middle line:84%
he's got a list of
superheroes that each

00:27:38.210 --> 00:27:41.150 align:middle line:84%
have an opinion on whether
they should go fight Sanos.

00:27:41.150 --> 00:27:43.820 align:middle line:90%


00:27:43.820 --> 00:27:49.220 align:middle line:84%
And their opinion can
be strongly positive

00:27:49.220 --> 00:27:50.730 align:middle line:90%
or strongly negative.

00:27:50.730 --> 00:27:54.320 align:middle line:84%
And so what Fick
is trying to do is

00:27:54.320 --> 00:27:59.960 align:middle line:84%
find, from among
his Revengers, what

00:27:59.960 --> 00:28:04.820 align:middle line:84%
the log n most extreme-opinion
Revengers are so

00:28:04.820 --> 00:28:05.888 align:middle line:90%
that he can talk to them.

00:28:05.888 --> 00:28:07.430 align:middle line:84%
He doesn't want to
talk to everybody.

00:28:07.430 --> 00:28:10.040 align:middle line:84%
He wants to talk to a
logarithmic number of them.

00:28:10.040 --> 00:28:11.030 align:middle line:90%
OK.

00:28:11.030 --> 00:28:14.720 align:middle line:90%
It's kind of-- whatever.

00:28:14.720 --> 00:28:18.800 align:middle line:84%
Basically, we have a
classified situation

00:28:18.800 --> 00:28:22.760 align:middle line:84%
where you're given, as a
read-only input data store

00:28:22.760 --> 00:28:23.980 align:middle line:90%
of these things in an array.

00:28:23.980 --> 00:28:26.900 align:middle line:90%


00:28:26.900 --> 00:28:31.975 align:middle line:84%
And I want to find the log
n ones with the strongest

00:28:31.975 --> 00:28:32.475 align:middle line:90%
opinions.

00:28:32.475 --> 00:28:34.138 align:middle line:90%
Does that make sense?

00:28:34.138 --> 00:28:35.930 align:middle line:84%
And I want to do it--
and the first problem

00:28:35.930 --> 00:28:39.440 align:middle line:90%
is in linear time.

00:28:39.440 --> 00:28:42.770 align:middle line:84%
You actually don't know
how to do this yet.

00:28:42.770 --> 00:28:47.810 align:middle line:84%
You'll know how to do it with
material that you cover in--

00:28:47.810 --> 00:28:50.420 align:middle line:84%
well, they teach you
one way to do it in 046,

00:28:50.420 --> 00:28:53.690 align:middle line:84%
but we're not going to
get you there right now.

00:28:53.690 --> 00:28:59.400 align:middle line:84%
We'll teach you another
way to do it on Tuesday,

00:28:59.400 --> 00:29:01.370 align:middle line:90%
which is via binary heaps.

00:29:01.370 --> 00:29:03.980 align:middle line:84%
Binary heaps are an
interesting thing.

00:29:03.980 --> 00:29:14.390 align:middle line:84%
It implements a subset
of the set interface.

00:29:14.390 --> 00:29:23.150 align:middle line:84%
Really, it just-- you can
build on some iterable x.

00:29:23.150 --> 00:29:25.270 align:middle line:90%
I collect a bunch of things.

00:29:25.270 --> 00:29:26.780 align:middle line:90%
These items have keys.

00:29:26.780 --> 00:29:29.090 align:middle line:84%
It's a key data structure
in the same way.

00:29:29.090 --> 00:29:32.100 align:middle line:84%
It's implementing what we call
a priority queue interface.

00:29:32.100 --> 00:29:33.860 align:middle line:90%
I can build these things.

00:29:33.860 --> 00:29:39.380 align:middle line:84%
I can insert things, but I'm
not going to do that here.

00:29:39.380 --> 00:29:43.490 align:middle line:84%
All I really need here,
for this situation,

00:29:43.490 --> 00:29:47.150 align:middle line:84%
is a delete_superlative
kind of operation--

00:29:47.150 --> 00:29:50.870 align:middle line:90%
in this case, probably max.

00:29:50.870 --> 00:29:52.115 align:middle line:90%
Delete_max.

00:29:52.115 --> 00:29:57.560 align:middle line:90%


00:29:57.560 --> 00:29:58.400 align:middle line:90%
So this is like--

00:29:58.400 --> 00:30:01.713 align:middle line:84%
I've got a data structure,
I'm calling these things.

00:30:01.713 --> 00:30:02.630 align:middle line:90%
Does that makes sense?

00:30:02.630 --> 00:30:02.890 align:middle line:90%
Yeah?

00:30:02.890 --> 00:30:04.190 align:middle line:84%
AUDIENCE: What's
a priority queue?

00:30:04.190 --> 00:30:04.520 align:middle line:90%
JASON KU: Yes.

00:30:04.520 --> 00:30:06.560 align:middle line:84%
A priority queue is
essentially something that

00:30:06.560 --> 00:30:08.450 align:middle line:90%
implements these two things.

00:30:08.450 --> 00:30:11.570 align:middle line:84%
Actually, there's a third one
where I can insert a new thing,

00:30:11.570 --> 00:30:13.280 align:middle line:84%
but I'm not going to
need that right now.

00:30:13.280 --> 00:30:14.738 align:middle line:84%
So that's what a
priority queue is.

00:30:14.738 --> 00:30:15.890 align:middle line:90%
And actually, a set--

00:30:15.890 --> 00:30:19.180 align:middle line:84%
this is a subset of
the set interface.

00:30:19.180 --> 00:30:20.300 align:middle line:90%
Right?

00:30:20.300 --> 00:30:22.250 align:middle line:90%
The nice thing about a heap--

00:30:22.250 --> 00:30:25.160 align:middle line:84%
which, I won't to show
you how it's done,

00:30:25.160 --> 00:30:27.380 align:middle line:90%
but what a heap can do--

00:30:27.380 --> 00:30:29.870 align:middle line:84%
if I had both of these
operations implemented

00:30:29.870 --> 00:30:34.520 align:middle line:84%
using a set AVL tree, how long
would these things take me?

00:30:34.520 --> 00:30:41.430 align:middle line:90%


00:30:41.430 --> 00:30:43.566 align:middle line:84%
How long does it take
to build a set AVL tree?

00:30:43.566 --> 00:30:46.970 align:middle line:90%


00:30:46.970 --> 00:30:48.620 align:middle line:90%
n log n, right?

00:30:48.620 --> 00:30:50.960 align:middle line:84%
Because essentially, I'm
getting a sorted order

00:30:50.960 --> 00:30:53.300 align:middle line:84%
out of this thing if I'm
inserting these things

00:30:53.300 --> 00:30:55.220 align:middle line:90%
one at a time--

00:30:55.220 --> 00:30:57.320 align:middle line:84%
or I could sort them,
and then put them

00:30:57.320 --> 00:31:00.500 align:middle line:84%
in a tree in linear time,
like you saw a couple of days

00:31:00.500 --> 00:31:03.780 align:middle line:90%
ago in recitation.

00:31:03.780 --> 00:31:05.840 align:middle line:84%
But I have to sort them
at some point, right?

00:31:05.840 --> 00:31:07.340 align:middle line:90%
I'm kind of--

00:31:07.340 --> 00:31:10.170 align:middle line:84%
I need to take at
least n log n time,

00:31:10.170 --> 00:31:14.120 align:middle line:84%
because if I'm going to be able
to return their traversal order

00:31:14.120 --> 00:31:18.110 align:middle line:84%
in linear time, and I have
this lower bound of n log

00:31:18.110 --> 00:31:21.800 align:middle line:84%
n on sorting, I kind of needed
to spend n log n time here,

00:31:21.800 --> 00:31:23.030 align:middle line:90%
right?

00:31:23.030 --> 00:31:26.524 align:middle line:84%
And how long would
this delete_max take?

00:31:26.524 --> 00:31:28.632 align:middle line:90%
AUDIENCE: It's sorted, so log n.

00:31:28.632 --> 00:31:29.590 align:middle line:90%
JASON KU: Log n, right?

00:31:29.590 --> 00:31:31.020 align:middle line:90%
So it's a set AVL tree.

00:31:31.020 --> 00:31:31.950 align:middle line:90%
Where is my max?

00:31:31.950 --> 00:31:33.180 align:middle line:90%
It's the right-most thing.

00:31:33.180 --> 00:31:35.520 align:middle line:84%
I can just walk down
the thing, take it off.

00:31:35.520 --> 00:31:37.050 align:middle line:90%
Maybe I have to re-balance.

00:31:37.050 --> 00:31:39.420 align:middle line:90%
But that's a log n operation.

00:31:39.420 --> 00:31:44.400 align:middle line:84%
It's the same as
insert-last in my subtree.

00:31:44.400 --> 00:31:46.860 align:middle line:84%
For a set AVL tree,
this is n log n.

00:31:46.860 --> 00:31:47.670 align:middle line:90%
This is log n.

00:31:47.670 --> 00:31:50.610 align:middle line:90%


00:31:50.610 --> 00:31:53.970 align:middle line:84%
Now, there's another data
structure that does better

00:31:53.970 --> 00:31:55.560 align:middle line:90%
for one of these operations.

00:31:55.560 --> 00:32:01.020 align:middle line:84%
And the same for the other one
that we've learned earlier.

00:32:01.020 --> 00:32:03.600 align:middle line:90%
Anyone remember?

00:32:03.600 --> 00:32:05.430 align:middle line:84%
Set AVL tree didn't
actually give us

00:32:05.430 --> 00:32:11.910 align:middle line:84%
anything over a sorted
array in a dynamic array.

00:32:11.910 --> 00:32:14.805 align:middle line:90%
What that did was, we have a--

00:32:14.805 --> 00:32:17.730 align:middle line:84%
we could sort it in n log n time
using merge sort or something

00:32:17.730 --> 00:32:18.790 align:middle line:90%
like that.

00:32:18.790 --> 00:32:22.500 align:middle line:84%
And then we could just pop
off the last one n times.

00:32:22.500 --> 00:32:23.790 align:middle line:90%
That would be an amortized--

00:32:23.790 --> 00:32:26.838 align:middle line:84%
I mean, if I didn't
care about taking up

00:32:26.838 --> 00:32:29.130 align:middle line:84%
that size, I could do it, in
worst case, constant time.

00:32:29.130 --> 00:32:31.380 align:middle line:84%
I just read off the
first-- the last one.

00:32:31.380 --> 00:32:33.750 align:middle line:84%
I don't need to resize
the array, ever.

00:32:33.750 --> 00:32:35.940 align:middle line:90%
I can just ignore that.

00:32:35.940 --> 00:32:37.150 align:middle line:90%
Does that makes sense?

00:32:37.150 --> 00:32:37.650 align:middle line:90%
OK.

00:32:37.650 --> 00:32:39.130 align:middle line:90%
But that's-- OK.

00:32:39.130 --> 00:32:43.230 align:middle line:84%
If I had a data structure
that implemented these two

00:32:43.230 --> 00:32:49.770 align:middle line:84%
operations, can someone
tell me an algorithm

00:32:49.770 --> 00:32:52.025 align:middle line:90%
to generate fixed lists--

00:32:52.025 --> 00:32:54.150 align:middle line:84%
don't worry about running
time right now-- but that

00:32:54.150 --> 00:32:55.800 align:middle line:90%
just uses these two operations?

00:32:55.800 --> 00:32:59.270 align:middle line:90%


00:32:59.270 --> 00:33:00.350 align:middle line:90%
Yeah?

00:33:00.350 --> 00:33:03.530 align:middle line:84%
AUDIENCE: So we build
this data structure.

00:33:03.530 --> 00:33:05.135 align:middle line:84%
It's ordered from
least to greatest

00:33:05.135 --> 00:33:07.830 align:middle line:90%
toward absolute value of x.

00:33:07.830 --> 00:33:11.880 align:middle line:84%
JASON KU: Don't worry
about where things are

00:33:11.880 --> 00:33:13.130 align:middle line:90%
ordered or anything like that.

00:33:13.130 --> 00:33:16.310 align:middle line:84%
I don't tell you how these
things are implemented, right?

00:33:16.310 --> 00:33:20.330 align:middle line:84%
All I'm saying is, I can
accept a bunch of these things,

00:33:20.330 --> 00:33:24.500 align:middle line:84%
and I can remove the
maximum and return it.

00:33:24.500 --> 00:33:25.330 align:middle line:90%
OK?

00:33:25.330 --> 00:33:26.830 align:middle line:84%
AUDIENCE: I think
we just build it--

00:33:26.830 --> 00:33:29.712 align:middle line:84%
make sure that you build it
such that the opinion levels are

00:33:29.712 --> 00:33:31.670 align:middle line:84%
the absolute value of
the opinion levels, not--

00:33:31.670 --> 00:33:32.060 align:middle line:90%
JASON KU: Sure.

00:33:32.060 --> 00:33:32.560 align:middle line:90%
OK.

00:33:32.560 --> 00:33:33.720 align:middle line:90%
So that's a nice thing.

00:33:33.720 --> 00:33:36.410 align:middle line:84%
What I'm going to do, as
your colleague is saying,

00:33:36.410 --> 00:33:39.830 align:middle line:84%
is, I'm going to look through
all of the things in my input.

00:33:39.830 --> 00:33:44.510 align:middle line:84%
I'm going to copy it over to
some writable memory store.

00:33:44.510 --> 00:33:47.150 align:middle line:84%
That read-only thing is
not relevant to this part

00:33:47.150 --> 00:33:48.808 align:middle line:90%
of the problem.

00:33:48.808 --> 00:33:49.850 align:middle line:90%
What I'm going to do is--

00:33:49.850 --> 00:33:56.950 align:middle line:90%


00:33:56.950 --> 00:33:57.550 align:middle line:90%
right.

00:33:57.550 --> 00:33:58.050 align:middle line:90%
Sorry.

00:33:58.050 --> 00:34:00.790 align:middle line:84%
I'm thinking about your
problem set that we're writing.

00:34:00.790 --> 00:34:01.750 align:middle line:90%
I'm mixing it up.

00:34:01.750 --> 00:34:09.790 align:middle line:84%
OK, so we copy it over to
our new linear-sized array.

00:34:09.790 --> 00:34:11.679 align:middle line:84%
But instead of putting
their values there,

00:34:11.679 --> 00:34:13.424 align:middle line:84%
I'm going to put the absolute
values of their values.

00:34:13.424 --> 00:34:14.170 align:middle line:90%
Does that make sense?

00:34:14.170 --> 00:34:15.420 align:middle line:90%
I just check if it's negative.

00:34:15.420 --> 00:34:17.949 align:middle line:84%
If it is, I put the
positive thing there.

00:34:17.949 --> 00:34:19.300 align:middle line:90%
OK?

00:34:19.300 --> 00:34:23.440 align:middle line:84%
And then I stick that
array in this build.

00:34:23.440 --> 00:34:26.620 align:middle line:90%
I put that there.

00:34:26.620 --> 00:34:29.199 align:middle line:84%
That will take some--
whatever this build time is.

00:34:29.199 --> 00:34:33.489 align:middle line:84%
And then I can
delete max k times.

00:34:33.489 --> 00:34:38.170 align:middle line:84%
Or I can delete max some number
of times, however many things

00:34:38.170 --> 00:34:38.739 align:middle line:90%
that I need.

00:34:38.739 --> 00:34:39.760 align:middle line:90%
Right?

00:34:39.760 --> 00:34:44.050 align:middle line:84%
If I want log n highest things,
I can just do that log n times,

00:34:44.050 --> 00:34:44.860 align:middle line:90%
right?

00:34:44.860 --> 00:34:48.219 align:middle line:84%
So for this-- if I had
such a data structure,

00:34:48.219 --> 00:34:51.580 align:middle line:84%
I could do this in one
run of this operation

00:34:51.580 --> 00:34:55.175 align:middle line:84%
and log n runs of
this operation.

00:34:55.175 --> 00:34:56.050 align:middle line:90%
Does that make sense?

00:34:56.050 --> 00:34:57.610 align:middle line:84%
I could solve this
problem reducing

00:34:57.610 --> 00:34:59.290 align:middle line:90%
to this data structure.

00:34:59.290 --> 00:35:05.980 align:middle line:84%
Now, for a sorted array
or a set AVL tree,

00:35:05.980 --> 00:35:08.155 align:middle line:84%
this operation kind
of kills me already.

00:35:08.155 --> 00:35:10.420 align:middle line:90%
It takes n log n time.

00:35:10.420 --> 00:35:13.360 align:middle line:84%
The nice thing
about a binary heap

00:35:13.360 --> 00:35:17.100 align:middle line:84%
is, it does this
operation in linear time.

00:35:17.100 --> 00:35:20.060 align:middle line:90%


00:35:20.060 --> 00:35:21.850 align:middle line:90%
You will see that on Tuesday.

00:35:21.850 --> 00:35:26.290 align:middle line:84%
And it does this
operation in log n time.

00:35:26.290 --> 00:35:30.650 align:middle line:90%


00:35:30.650 --> 00:35:34.220 align:middle line:84%
What's the running time
if I use a binary heap

00:35:34.220 --> 00:35:37.520 align:middle line:84%
to implement this
data structure?

00:35:37.520 --> 00:35:42.020 align:middle line:84%
Order of n times order
log n times log n.

00:35:42.020 --> 00:35:44.990 align:middle line:90%
How big is log n squared--

00:35:44.990 --> 00:35:48.551 align:middle line:90%
log squared n-- compared to n?

00:35:48.551 --> 00:35:49.835 align:middle line:90%
It's smaller, right?

00:35:49.835 --> 00:35:51.710 align:middle line:84%
So if I add those two
running times together,

00:35:51.710 --> 00:35:54.260 align:middle line:90%
it's still linear.

00:35:54.260 --> 00:35:57.020 align:middle line:84%
That's how you solve
the first problem.

00:35:57.020 --> 00:35:59.750 align:middle line:84%
I didn't have to tell you
what a binary heap was

00:35:59.750 --> 00:36:00.842 align:middle line:90%
or how it did what it did.

00:36:00.842 --> 00:36:02.300 align:middle line:84%
All I needed to
tell you is that it

00:36:02.300 --> 00:36:04.220 align:middle line:84%
did this operation
in linear time

00:36:04.220 --> 00:36:05.990 align:middle line:84%
and it did this
operation log n time.

00:36:05.990 --> 00:36:10.550 align:middle line:90%


00:36:10.550 --> 00:36:11.720 align:middle line:90%
All right.

00:36:11.720 --> 00:36:14.780 align:middle line:84%
The magic will be shown
to you on Tuesday.

00:36:14.780 --> 00:36:19.730 align:middle line:84%
Part B says, now, suppose
Fick's computer is only

00:36:19.730 --> 00:36:22.550 align:middle line:84%
allowed to write to,
at most, log n space.

00:36:22.550 --> 00:36:23.210 align:middle line:90%
Well, OK.

00:36:23.210 --> 00:36:24.260 align:middle line:90%
That's a problem here.

00:36:24.260 --> 00:36:29.570 align:middle line:84%
Because before, we copied
over the entire array,

00:36:29.570 --> 00:36:34.137 align:middle line:84%
filtered it out, and
then did some operations.

00:36:34.137 --> 00:36:35.720 align:middle line:84%
But we couldn't even
afford this if we

00:36:35.720 --> 00:36:40.560 align:middle line:84%
couldn't store the whole thing
externally in writable memory.

00:36:40.560 --> 00:36:42.090 align:middle line:90%
So we can't do that.

00:36:42.090 --> 00:36:46.820 align:middle line:84%
So in some sense, this is a
more restrictive environment.

00:36:46.820 --> 00:36:49.590 align:middle line:90%
I can do less things.

00:36:49.590 --> 00:36:53.540 align:middle line:84%
It's less powerful than my
previous situation, where

00:36:53.540 --> 00:36:57.500 align:middle line:84%
I had as much space
as I wanted to use.

00:36:57.500 --> 00:37:02.000 align:middle line:84%
So it kind of makes
sense that I, maybe,

00:37:02.000 --> 00:37:07.490 align:middle line:84%
couldn't get the running time
bound that we had before.

00:37:07.490 --> 00:37:10.040 align:middle line:84%
Maybe I have to
sacrifice something

00:37:10.040 --> 00:37:13.060 align:middle line:84%
because I'm in a more restricted
computational setting.

00:37:13.060 --> 00:37:17.120 align:middle line:90%


00:37:17.120 --> 00:37:19.563 align:middle line:84%
Now, this is something you
could solve with binary heaps,

00:37:19.563 --> 00:37:20.480 align:middle line:90%
but you don't have to.

00:37:20.480 --> 00:37:27.860 align:middle line:84%
You can solve it
with set AVL trees.

00:37:27.860 --> 00:37:29.960 align:middle line:84%
Does anyone have an idea
of how you could solve

00:37:29.960 --> 00:37:32.750 align:middle line:90%
this using a set AVL tree?

00:37:32.750 --> 00:37:37.430 align:middle line:84%
I'm limited by my number of--
my space is, at most, log n.

00:37:37.430 --> 00:37:40.710 align:middle line:90%


00:37:40.710 --> 00:37:43.473 align:middle line:84%
AUDIENCE: So how much space
does a set AVL tree take?

00:37:43.473 --> 00:37:44.140 align:middle line:90%
JASON KU: Right.

00:37:44.140 --> 00:37:47.080 align:middle line:84%
Space-- there's constant
number of pointers

00:37:47.080 --> 00:37:49.030 align:middle line:90%
for each one of these nodes.

00:37:49.030 --> 00:37:52.510 align:middle line:84%
And I'm storing in
notes and space.

00:37:52.510 --> 00:37:57.520 align:middle line:84%
Basically every data structure
we've shown you takes space--

00:37:57.520 --> 00:38:00.130 align:middle line:84%
the order of the things
that we're storing.

00:38:00.130 --> 00:38:02.270 align:middle line:90%
It's not using additional space.

00:38:02.270 --> 00:38:05.500 align:middle line:84%
It might take more time
to do certain things,

00:38:05.500 --> 00:38:09.457 align:middle line:84%
but the space takes
the number of items

00:38:09.457 --> 00:38:11.540 align:middle line:84%
that we're storing plus,
maybe, a constant factor.

00:38:11.540 --> 00:38:14.260 align:middle line:90%


00:38:14.260 --> 00:38:18.430 align:middle line:84%
So I'm going to draw my input
here, which I can only read--

00:38:18.430 --> 00:38:20.073 align:middle line:90%
I can't write.

00:38:20.073 --> 00:38:20.740 align:middle line:90%
Do I give it a--

00:38:20.740 --> 00:38:26.170 align:middle line:84%
I'm just going to call
it A. So this is my list

00:38:26.170 --> 00:38:29.020 align:middle line:90%
of all the Revenger opinions.

00:38:29.020 --> 00:38:31.660 align:middle line:90%
I can only read it.

00:38:31.660 --> 00:38:36.140 align:middle line:84%
But my computer can only write
to this logarithmic amount

00:38:36.140 --> 00:38:36.640 align:middle line:90%
of space.

00:38:36.640 --> 00:38:42.660 align:middle line:90%


00:38:42.660 --> 00:38:46.280 align:middle line:90%
What can I put in that space?

00:38:46.280 --> 00:38:49.500 align:middle line:90%
AUDIENCE: The log [INAUDIBLE]?

00:38:49.500 --> 00:38:53.250 align:middle line:84%
JASON KU: Well, I can certainly
put log n things in there.

00:38:53.250 --> 00:38:55.090 align:middle line:84%
So if I'm given
that restriction,

00:38:55.090 --> 00:38:58.985 align:middle line:84%
I probably want to build a
data structure of that size,

00:38:58.985 --> 00:39:00.360 align:middle line:84%
containing that
number of things.

00:39:00.360 --> 00:39:02.797 align:middle line:90%
Does that make sense?

00:39:02.797 --> 00:39:04.380 align:middle line:84%
Because what else
are you going to do?

00:39:04.380 --> 00:39:08.000 align:middle line:90%


00:39:08.000 --> 00:39:10.380 align:middle line:90%
So I gave you an idea.

00:39:10.380 --> 00:39:12.800 align:middle line:84%
Maybe we could use
a set AVL here.

00:39:12.800 --> 00:39:16.460 align:middle line:90%
I see a logarithm in my answer.

00:39:16.460 --> 00:39:21.170 align:middle line:84%
It's very possible that we
might have sorted arrays

00:39:21.170 --> 00:39:23.300 align:middle line:90%
or set AVL things.

00:39:23.300 --> 00:39:26.360 align:middle line:84%
Those things give me a log
somewhere in my running times,

00:39:26.360 --> 00:39:27.440 align:middle line:90%
right?

00:39:27.440 --> 00:39:30.930 align:middle line:84%
So kind of makes sense
that I might have,

00:39:30.930 --> 00:39:32.600 align:middle line:90%
maybe, a set AVL tree here.

00:39:32.600 --> 00:39:37.810 align:middle line:84%
Why would a set AVL
tree be helpful for me?

00:39:37.810 --> 00:39:38.310 align:middle line:90%
Yeah?

00:39:38.310 --> 00:39:39.750 align:middle line:84%
AUDIENCE: Because
it's sorted and you

00:39:39.750 --> 00:39:41.285 align:middle line:84%
don't have the
traversal order, you

00:39:41.285 --> 00:39:45.305 align:middle line:84%
can calculate the traversal
order and insert [INAUDIBLE]??

00:39:45.305 --> 00:39:45.930 align:middle line:90%
JASON KU: Sure.

00:39:45.930 --> 00:39:47.410 align:middle line:90%
I can do all of those things.

00:39:47.410 --> 00:39:49.320 align:middle line:84%
But in particular,
it's going to help

00:39:49.320 --> 00:39:54.860 align:middle line:84%
me be able to find a
large one quickly, right?

00:39:54.860 --> 00:40:00.340 align:middle line:84%
If I have a set of
things, it's going to be--

00:40:00.340 --> 00:40:02.150 align:middle line:84%
and I'm maintaining
this data structure

00:40:02.150 --> 00:40:05.960 align:middle line:84%
by adding things
incrementally to it,

00:40:05.960 --> 00:40:08.780 align:middle line:84%
I can find out what
the biggest one is--

00:40:08.780 --> 00:40:12.710 align:middle line:84%
or the smallest one--
pretty fast in log n time.

00:40:12.710 --> 00:40:17.780 align:middle line:84%
So if I have log n
things in a tree here,

00:40:17.780 --> 00:40:19.242 align:middle line:90%
what's the height of that thing?

00:40:19.242 --> 00:40:20.186 align:middle line:90%
AUDIENCE: [INAUDIBLE]

00:40:20.186 --> 00:40:21.470 align:middle line:90%
JASON KU: Log log n.

00:40:21.470 --> 00:40:23.325 align:middle line:90%
That looks familiar.

00:40:23.325 --> 00:40:24.200 align:middle line:90%
So what can I afford?

00:40:24.200 --> 00:40:31.760 align:middle line:84%
I can afford a linear number
of opt set AVL tree operations

00:40:31.760 --> 00:40:34.231 align:middle line:90%
on this data structure.

00:40:34.231 --> 00:40:35.455 align:middle line:90%
OK, you had a question?

00:40:35.455 --> 00:40:36.330 align:middle line:90%
AUDIENCE: [INAUDIBLE]

00:40:36.330 --> 00:40:37.330 align:middle line:90%
JASON KU: OK, I'm sorry.

00:40:37.330 --> 00:40:38.008 align:middle line:90%
Yeah?

00:40:38.008 --> 00:40:39.550 align:middle line:84%
AUDIENCE: For that
to be an AVL tree,

00:40:39.550 --> 00:40:42.680 align:middle line:90%
does it have to be a BTS tree?

00:40:42.680 --> 00:40:43.960 align:middle line:90%
JASON KU: Uh, BTS--

00:40:43.960 --> 00:40:45.810 align:middle line:90%
BSTs.

00:40:45.810 --> 00:40:48.110 align:middle line:90%
So when I talk about--

00:40:48.110 --> 00:40:49.760 align:middle line:90%
someone likes Korean K-Pop.

00:40:49.760 --> 00:40:50.610 align:middle line:90%
OK.

00:40:50.610 --> 00:40:55.820 align:middle line:90%
So BST-- but in natural--

00:40:55.820 --> 00:40:58.610 align:middle line:84%
kind of in the lingo
that you're probably

00:40:58.610 --> 00:41:00.860 align:middle line:84%
used to hearing
in other contexts,

00:41:00.860 --> 00:41:04.310 align:middle line:84%
what we mean, in this
class, is a set AVL tree.

00:41:04.310 --> 00:41:08.240 align:middle line:84%
Now, sometimes, what
people refer to as a

00:41:08.240 --> 00:41:12.500 align:middle line:84%
binary search tree doesn't
have balance semantics--

00:41:12.500 --> 00:41:16.190 align:middle line:84%
so what we might call, in
this class, a set binary tree.

00:41:16.190 --> 00:41:20.150 align:middle line:84%
But really, they're useful
because they're balanced.

00:41:20.150 --> 00:41:22.310 align:middle line:84%
So we're going to
usually just assume

00:41:22.310 --> 00:41:24.450 align:middle line:84%
that we're talking about
balanced things here.

00:41:24.450 --> 00:41:28.730 align:middle line:84%
Now, a set AVL tree has these
binary search tree semantics

00:41:28.730 --> 00:41:30.790 align:middle line:90%
where the keys are ordered.

00:41:30.790 --> 00:41:32.540 align:middle line:84%
These items have keys
and they're ordered.

00:41:32.540 --> 00:41:34.370 align:middle line:90%
It's a set interface.

00:41:34.370 --> 00:41:36.980 align:middle line:84%
Whereas we also presented
to you a sequence

00:41:36.980 --> 00:41:41.900 align:middle line:84%
interface, for which these
things don't even have keys.

00:41:41.900 --> 00:41:45.440 align:middle line:84%
How could I store
set semantics there?

00:41:45.440 --> 00:41:47.060 align:middle line:84%
So that's the
distinction that we

00:41:47.060 --> 00:41:53.360 align:middle line:84%
mean when we say binary search
tree versus, really, a set AVL

00:41:53.360 --> 00:41:54.660 align:middle line:90%
tree versus [INAUDIBLE].

00:41:54.660 --> 00:41:55.160 align:middle line:90%
Yeah?

00:41:55.160 --> 00:41:57.743 align:middle line:84%
AUDIENCE: So if we look at it
to make an AVL tree out of this,

00:41:57.743 --> 00:42:00.650 align:middle line:84%
would that mean that, when
we make a node, we tell it,

00:42:00.650 --> 00:42:03.830 align:middle line:84%
we are keying on the absolute
value of [INAUDIBLE]??

00:42:03.830 --> 00:42:09.350 align:middle line:84%
JASON KU: OK, when you're
making a set AVL tree,

00:42:09.350 --> 00:42:11.943 align:middle line:84%
you've got to tell us what--
if you're storing objects,

00:42:11.943 --> 00:42:13.610 align:middle line:84%
you've got to tell
me what their key is.

00:42:13.610 --> 00:42:15.170 align:middle line:84%
You're just storing
some numbers,

00:42:15.170 --> 00:42:18.110 align:middle line:90%
like what I'm doing here.

00:42:18.110 --> 00:42:19.970 align:middle line:90%
Now, this isn't a set AVL tree.

00:42:19.970 --> 00:42:21.560 align:middle line:84%
But if I'm just
storing numbers, I

00:42:21.560 --> 00:42:25.400 align:middle line:84%
have to tell you the items
that I'm storing are the keys.

00:42:25.400 --> 00:42:26.685 align:middle line:90%
And then everything follows.

00:42:26.685 --> 00:42:28.310 align:middle line:84%
But if you've got an
object that you're

00:42:28.310 --> 00:42:30.750 align:middle line:84%
trying to sort, like the
students in this room,

00:42:30.750 --> 00:42:33.130 align:middle line:90%
you've got a lot of properties.

00:42:33.130 --> 00:42:38.600 align:middle line:84%
I want all of the people
with phone number--

00:42:38.600 --> 00:42:41.300 align:middle line:84%
maybe I want to key you on
phone number for some reason.

00:42:41.300 --> 00:42:44.150 align:middle line:84%
That's going to help me
find out where you live?

00:42:44.150 --> 00:42:45.680 align:middle line:84%
I don't-- this is
getting a little--

00:42:45.680 --> 00:42:47.270 align:middle line:90%
I don't want to go there.

00:42:47.270 --> 00:42:50.283 align:middle line:84%
But if I give you
a set AVL tree,

00:42:50.283 --> 00:42:51.950 align:middle line:84%
I've got to tell you
what it's keyed on.

00:42:51.950 --> 00:42:55.790 align:middle line:84%
If I give you a
sequence AVL tree,

00:42:55.790 --> 00:42:57.920 align:middle line:84%
it's obvious what
my traversal order

00:42:57.920 --> 00:43:00.320 align:middle line:84%
is going to be because
I'm giving you a sequence.

00:43:00.320 --> 00:43:03.740 align:middle line:90%
That's what the input was.

00:43:03.740 --> 00:43:05.150 align:middle line:90%
Does that make sense?

00:43:05.150 --> 00:43:10.250 align:middle line:84%
All right, so I've got this
set AVL tree of size log n.

00:43:10.250 --> 00:43:12.678 align:middle line:90%
What should it be keyed by?

00:43:12.678 --> 00:43:13.720 align:middle line:90%
AUDIENCE: Absolute value.

00:43:13.720 --> 00:43:15.920 align:middle line:84%
JASON KU: The absolute
value of their preference--

00:43:15.920 --> 00:43:18.100 align:middle line:90%
or of their opinion.

00:43:18.100 --> 00:43:20.770 align:middle line:84%
I don't remember
what this is called.

00:43:20.770 --> 00:43:23.490 align:middle line:84%
But what log n things
do I put in here?

00:43:23.490 --> 00:43:28.240 align:middle line:90%


00:43:28.240 --> 00:43:30.550 align:middle line:90%
I don't know.

00:43:30.550 --> 00:43:32.260 align:middle line:84%
I don't know anything
about these things.

00:43:32.260 --> 00:43:35.270 align:middle line:84%
What makes one
better than another?

00:43:35.270 --> 00:43:37.900 align:middle line:84%
Let's just put the
first log n things.

00:43:37.900 --> 00:43:39.680 align:middle line:90%
Does that make sense?

00:43:39.680 --> 00:43:40.180 align:middle line:90%
All right.

00:43:40.180 --> 00:43:43.900 align:middle line:90%
What could that tell me?

00:43:43.900 --> 00:43:45.490 align:middle line:90%
Now, I've put this thing in it.

00:43:45.490 --> 00:43:47.811 align:middle line:90%
How long did that take?

00:43:47.811 --> 00:43:49.640 align:middle line:90%
AUDIENCE: [INAUDIBLE]

00:43:49.640 --> 00:43:55.760 align:middle line:84%
JASON KU: Log n times
log log n time, right?

00:43:55.760 --> 00:43:58.520 align:middle line:84%
But that's much less
than our running time

00:43:58.520 --> 00:44:01.800 align:middle line:84%
that we're looking for,
so I don't really care.

00:44:01.800 --> 00:44:04.760 align:middle line:84%
I mean, I want you to
say how long it took,

00:44:04.760 --> 00:44:06.527 align:middle line:84%
but for my purposes,
I know that it's

00:44:06.527 --> 00:44:08.360 align:middle line:84%
lower than the running
time I'm looking for.

00:44:08.360 --> 00:44:10.160 align:middle line:90%
And I did that operation once.

00:44:10.160 --> 00:44:12.140 align:middle line:84%
I don't really care
about it anymore.

00:44:12.140 --> 00:44:12.860 align:middle line:90%
Yeah?

00:44:12.860 --> 00:44:14.720 align:middle line:84%
AUDIENCE: How did you get
the log n times log log n?

00:44:14.720 --> 00:44:16.303 align:middle line:84%
JASON KU: Because
the number of things

00:44:16.303 --> 00:44:19.110 align:middle line:84%
I'm storing in this
thing is log n.

00:44:19.110 --> 00:44:24.050 align:middle line:84%
And so if I pattern match
the build time of an AVL tree

00:44:24.050 --> 00:44:29.870 align:middle line:84%
and I stick log n in there,
then it's log n times log n.

00:44:29.870 --> 00:44:31.220 align:middle line:90%
OK.

00:44:31.220 --> 00:44:33.440 align:middle line:84%
AUDIENCE: So that's
just for one iteration?

00:44:33.440 --> 00:44:36.920 align:middle line:84%
JASON KU: Well, right now,
I've just built this thing.

00:44:36.920 --> 00:44:40.460 align:middle line:90%
Maybe-- I just built it once.

00:44:40.460 --> 00:44:44.630 align:middle line:84%
I'm asserting, too, that maybe
I don't need to build it again.

00:44:44.630 --> 00:44:47.660 align:middle line:84%
What could I-- so,
by now, I know--

00:44:47.660 --> 00:44:51.290 align:middle line:84%
I haven't filtered
my data at all.

00:44:51.290 --> 00:44:55.660 align:middle line:84%
I'm just storing these things
in sorted order in some way.

00:44:55.660 --> 00:44:59.780 align:middle line:84%
What can I do to
maybe start processing

00:44:59.780 --> 00:45:01.670 align:middle line:90%
the rest of the data?

00:45:01.670 --> 00:45:02.360 align:middle line:90%
Yeah?

00:45:02.360 --> 00:45:06.490 align:middle line:84%
AUDIENCE: [INAUDIBLE] try
to scroll through the list A

00:45:06.490 --> 00:45:09.830 align:middle line:84%
and try to find someone
that's bigger than--

00:45:09.830 --> 00:45:13.430 align:middle line:84%
try to keep the
maximum [INAUDIBLE]..

00:45:13.430 --> 00:45:16.100 align:middle line:84%
JASON KU: Sweep this guy
over inserting things,

00:45:16.100 --> 00:45:18.980 align:middle line:90%
and always maintaining--

00:45:18.980 --> 00:45:20.990 align:middle line:84%
if I do that, and I
keep sticking things

00:45:20.990 --> 00:45:23.490 align:middle line:84%
n I'll have this sorted
of thing at the end.

00:45:23.490 --> 00:45:28.910 align:middle line:84%
And now I can just read
off the biggest k things.

00:45:28.910 --> 00:45:33.290 align:middle line:84%
However, as I'm inserting
things across here,

00:45:33.290 --> 00:45:34.610 align:middle line:90%
my thing's growing.

00:45:34.610 --> 00:45:35.810 align:middle line:84%
AUDIENCE: Well, just
delete the smallest one.

00:45:35.810 --> 00:45:37.185 align:middle line:84%
JASON KU: Oh,
delete small stuff.

00:45:37.185 --> 00:45:38.293 align:middle line:90%
I like that idea.

00:45:38.293 --> 00:45:39.710 align:middle line:84%
AUDIENCE: So
basically replace it.

00:45:39.710 --> 00:45:40.940 align:middle line:84%
JASON KU: Yeah,
basically replace it.

00:45:40.940 --> 00:45:41.630 align:middle line:90%
Right.

00:45:41.630 --> 00:45:43.010 align:middle line:90%
What I'm going to do--

00:45:43.010 --> 00:45:44.810 align:middle line:90%
here's a proposal.

00:45:44.810 --> 00:45:49.070 align:middle line:84%
We're going to take the
next guy, stick it in.

00:45:49.070 --> 00:45:51.520 align:middle line:90%
Awesome.

00:45:51.520 --> 00:45:54.010 align:middle line:84%
Which one don't
I care about now?

00:45:54.010 --> 00:45:55.600 align:middle line:90%
The smallest one there.

00:45:55.600 --> 00:45:57.850 align:middle line:90%
So kick the smallest one out.

00:45:57.850 --> 00:46:00.100 align:middle line:84%
Now, this one that
I stuck in may.

00:46:00.100 --> 00:46:01.550 align:middle line:90%
Be the smallest.

00:46:01.550 --> 00:46:03.580 align:middle line:84%
So I just kind of passed
it through this thing,

00:46:03.580 --> 00:46:05.300 align:middle line:90%
but how long did that take me?

00:46:05.300 --> 00:46:10.032 align:middle line:90%


00:46:10.032 --> 00:46:11.490 align:middle line:84%
It took me the
height of this tree.

00:46:11.490 --> 00:46:12.195 align:middle line:90%
What's the height of this tree?

00:46:12.195 --> 00:46:13.070 align:middle line:90%
AUDIENCE: [INAUDIBLE]

00:46:13.070 --> 00:46:15.300 align:middle line:90%
JASON KU: Log log n.

00:46:15.300 --> 00:46:18.570 align:middle line:84%
So I put one in,
I popped one out.

00:46:18.570 --> 00:46:20.638 align:middle line:90%
That's the smallest, right?

00:46:20.638 --> 00:46:22.680 align:middle line:84%
And I keep doing that all
the way down the thing.

00:46:22.680 --> 00:46:23.763 align:middle line:90%
How long did that take me?

00:46:23.763 --> 00:46:25.070 align:middle line:90%
JASON KU: [INAUDIBLE]

00:46:25.070 --> 00:46:28.415 align:middle line:90%


00:46:28.415 --> 00:46:29.040 align:middle line:90%
JASON KU: Yeah.

00:46:29.040 --> 00:46:34.890 align:middle line:84%
Processing n minus log n
things, which is basically n.

00:46:34.890 --> 00:46:37.230 align:middle line:84%
And each one of those
operations took me

00:46:37.230 --> 00:46:39.120 align:middle line:90%
height of the tree time.

00:46:39.120 --> 00:46:40.920 align:middle line:84%
That gives me the
running time that we're

00:46:40.920 --> 00:46:45.960 align:middle line:90%
looking for, n log log n.

00:46:45.960 --> 00:46:46.500 align:middle line:90%
sense?

00:46:46.500 --> 00:46:48.840 align:middle line:84%
AUDIENCE: Is this reminiscent
of a sliding window technique?

00:46:48.840 --> 00:46:48.960 align:middle line:90%
JASON KU: Yeah.

00:46:48.960 --> 00:46:50.760 align:middle line:84%
It's kind of a sliding
window technique.

00:46:50.760 --> 00:46:53.100 align:middle line:84%
You may have been
using one recently.

00:46:53.100 --> 00:46:56.470 align:middle line:90%


00:46:56.470 --> 00:46:56.970 align:middle line:90%
OK.

00:46:56.970 --> 00:46:58.322 align:middle line:90%
Everyone OK with this?

00:46:58.322 --> 00:46:58.858 align:middle line:90%
Yeah?

00:46:58.858 --> 00:47:00.900 align:middle line:84%
AUDIENCE: Could you just
remind me of the context

00:47:00.900 --> 00:47:05.170 align:middle line:84%
that we're talking about is log
log n, like tree and where--

00:47:05.170 --> 00:47:07.170 align:middle line:84%
JASON KU: So this thing--
the size of this thing

00:47:07.170 --> 00:47:08.495 align:middle line:90%
is log log n?

00:47:08.495 --> 00:47:09.120 align:middle line:90%
AUDIENCE: Yeah.

00:47:09.120 --> 00:47:10.453 align:middle line:90%
JASON KU: I mean-- sorry, log n.

00:47:10.453 --> 00:47:15.438 align:middle line:84%
And the height of this
thing is a log of the size.

00:47:15.438 --> 00:47:19.065 align:middle line:84%
AUDIENCE: I'm sorry, in relation
to our little log n size

00:47:19.065 --> 00:47:25.270 align:middle line:84%
[INAUDIBLE] small
log log n trees, or--

00:47:25.270 --> 00:47:27.150 align:middle line:90%
JASON KU: No, so-- sorry.

00:47:27.150 --> 00:47:29.790 align:middle line:90%
I'm taking this stuff--

00:47:29.790 --> 00:47:32.040 align:middle line:84%
there's no intermediate
data structure here--

00:47:32.040 --> 00:47:37.105 align:middle line:84%
I'm just sticking all of
these things into set AVL.

00:47:37.105 --> 00:47:37.605 align:middle line:90%
Yeah?

00:47:37.605 --> 00:47:39.030 align:middle line:90%
AUDIENCE: [INAUDIBLE]

00:47:39.030 --> 00:47:43.200 align:middle line:84%
JASON KU: Into one
set AVL of size log n.

00:47:43.200 --> 00:47:48.497 align:middle line:84%
I'm sticking a guy in,
popping the worst guy out.

00:47:48.497 --> 00:47:49.830 align:middle line:90%
Going through all of the things.

00:47:49.830 --> 00:47:52.410 align:middle line:84%
I need to make sure,
when I'm sticking it in,

00:47:52.410 --> 00:47:55.740 align:middle line:84%
I'm keeping track of
which Revenger it is,

00:47:55.740 --> 00:47:57.720 align:middle line:84%
and that I'm taking
the absolute value,

00:47:57.720 --> 00:48:00.450 align:middle line:84%
and all of those nitty
gritty kind of things.

00:48:00.450 --> 00:48:02.250 align:middle line:90%
But that's the basic idea.

00:48:02.250 --> 00:48:05.730 align:middle line:84%
I'm just taking this, I'm
sliding the window in,

00:48:05.730 --> 00:48:07.830 align:middle line:84%
putting something in,
taking something out

00:48:07.830 --> 00:48:11.460 align:middle line:84%
that may or may not-- probably
is not-- the same thing.

00:48:11.460 --> 00:48:14.490 align:middle line:84%
And at the end of
this procedure,

00:48:14.490 --> 00:48:17.070 align:middle line:84%
the invariant I'm
maintaining here

00:48:17.070 --> 00:48:23.730 align:middle line:84%
is that my thing always has the
k largest opinions of the ones

00:48:23.730 --> 00:48:24.925 align:middle line:90%
that I've processed so far.

00:48:24.925 --> 00:48:26.550 align:middle line:84%
That's obviously true
at the beginning,

00:48:26.550 --> 00:48:27.930 align:middle line:90%
when I build this thing.

00:48:27.930 --> 00:48:31.320 align:middle line:84%
And when I get to the end, I've
processed all of the things,

00:48:31.320 --> 00:48:38.310 align:middle line:84%
and this has size log n, and
so I have the log n largest--

00:48:38.310 --> 00:48:41.730 align:middle line:90%
highest-- extremist opinions.

00:48:41.730 --> 00:48:43.990 align:middle line:84%
And then I can just do
an in-order traversal

00:48:43.990 --> 00:48:46.140 align:middle line:90%
of this thing and return.

00:48:46.140 --> 00:48:47.290 align:middle line:90%
Does that make sense?

00:48:47.290 --> 00:48:50.130 align:middle line:84%
And I've only used
logarithmic space.

00:48:50.130 --> 00:48:53.210 align:middle line:90%


00:48:53.210 --> 00:48:53.710 align:middle line:90%
Yeah?

00:48:53.710 --> 00:48:55.002 align:middle line:90%
AUDIENCE: Wait, I don't get it.

00:48:55.002 --> 00:49:00.090 align:middle line:84%
Are all of the opinions
in that AVL tree?

00:49:00.090 --> 00:49:02.340 align:middle line:84%
JASON KU: Are all of the
opinions in that AVL tree?

00:49:02.340 --> 00:49:05.520 align:middle line:84%
All of these opinions
are in the AVL tree.

00:49:05.520 --> 00:49:12.180 align:middle line:84%
And at some point, I
will insert every opinion

00:49:12.180 --> 00:49:14.040 align:middle line:90%
into this AVL tree.

00:49:14.040 --> 00:49:17.640 align:middle line:84%
But I'll be removing the
ones that I don't care about

00:49:17.640 --> 00:49:18.223 align:middle line:90%
as I go.

00:49:18.223 --> 00:49:19.140 align:middle line:90%
Does that makes sense?

00:49:19.140 --> 00:49:22.860 align:middle line:84%
I'm always maintaining
the invariants

00:49:22.860 --> 00:49:26.010 align:middle line:84%
that this thing, before
I insert something,

00:49:26.010 --> 00:49:29.100 align:middle line:84%
has exactly log n items
in it, and then I'm

00:49:29.100 --> 00:49:31.890 align:middle line:84%
maintaining that invariant by
sticking one in, taking one

00:49:31.890 --> 00:49:32.530 align:middle line:90%
out.

00:49:32.530 --> 00:49:35.178 align:middle line:84%
AUDIENCE: Oh, OK, so then
which one are you deleting?

00:49:35.178 --> 00:49:36.720 align:middle line:84%
JASON KU: Always
the min, because I'm

00:49:36.720 --> 00:49:38.667 align:middle line:90%
wanting the largest ones.

00:49:38.667 --> 00:49:40.500 align:middle line:84%
AUDIENCE: And the min
of the absolute value.

00:49:40.500 --> 00:49:42.330 align:middle line:90%
JASON KU: Yeah.

00:49:42.330 --> 00:49:45.210 align:middle line:84%
I'm keying by the absolute
value of these opinions.

00:49:45.210 --> 00:49:45.710 align:middle line:90%
Yeah?

00:49:45.710 --> 00:49:48.510 align:middle line:90%
AUDIENCE: [INAUDIBLE]?

00:49:48.510 --> 00:49:51.390 align:middle line:90%
JASON KU: Total runtime here?

00:49:51.390 --> 00:49:52.830 align:middle line:90%
It's bookkeeping.

00:49:52.830 --> 00:50:01.470 align:middle line:84%
It took me log n
times log log n time

00:50:01.470 --> 00:50:05.430 align:middle line:84%
to build this data
structure at the beginning,

00:50:05.430 --> 00:50:11.040 align:middle line:90%
plus n times log log n.

00:50:11.040 --> 00:50:15.510 align:middle line:84%
I did, basically, n operation--
asymptotically, n operations.

00:50:15.510 --> 00:50:19.620 align:middle line:84%
This way, it's actually
n minus log n operations.

00:50:19.620 --> 00:50:22.740 align:middle line:84%
And each one of those
tree operations--

00:50:22.740 --> 00:50:25.350 align:middle line:90%
doing one insert, one delete--

00:50:25.350 --> 00:50:28.750 align:middle line:84%
each one of those took the
height of the tree time.

00:50:28.750 --> 00:50:31.440 align:middle line:90%
And so this is that.

00:50:31.440 --> 00:50:32.820 align:middle line:90%
Good?

00:50:32.820 --> 00:50:33.420 align:middle line:90%
Yeah?

00:50:33.420 --> 00:50:36.249 align:middle line:84%
AUDIENCE: If, instead of one,
we just insert and delete, can

00:50:36.249 --> 00:50:39.030 align:middle line:90%
you do a comparison and then--

00:50:39.030 --> 00:50:42.720 align:middle line:84%
JASON KU: The
inserting and deleting

00:50:42.720 --> 00:50:45.930 align:middle line:84%
a set AVL tree is
actually doing comparisons

00:50:45.930 --> 00:50:47.070 align:middle line:90%
within its data structures.

00:50:47.070 --> 00:50:47.910 align:middle line:84%
AUDIENCE: Just
compare with the min.

00:50:47.910 --> 00:50:48.410 align:middle line:90%
And then--

00:50:48.410 --> 00:50:50.490 align:middle line:84%
JASON KU: Sure,
you could do that.

00:50:50.490 --> 00:50:52.410 align:middle line:90%
I could do it the other way.

00:50:52.410 --> 00:50:56.790 align:middle line:84%
I could remove the
smallest element here,

00:50:56.790 --> 00:50:58.860 align:middle line:90%
to start with, right?

00:50:58.860 --> 00:51:00.870 align:middle line:84%
And then I compare
it with this guy,

00:51:00.870 --> 00:51:04.370 align:middle line:84%
and then whichever is
bigger, I stick it back in.

00:51:04.370 --> 00:51:06.160 align:middle line:90%
Same thing.

00:51:06.160 --> 00:51:09.260 align:middle line:84%
It's just, am I doing the delete
first and then the insertion,

00:51:09.260 --> 00:51:12.940 align:middle line:84%
or am I doing the insertion
first and then the deletion?

00:51:12.940 --> 00:51:14.830 align:middle line:90%
Any other questions?

00:51:14.830 --> 00:51:15.590 align:middle line:90%
Lots of questions.

00:51:15.590 --> 00:51:16.090 align:middle line:90%
All right.

00:51:16.090 --> 00:51:18.940 align:middle line:84%
Well, I'm probably going
to have to skip a problem.

00:51:18.940 --> 00:51:22.060 align:middle line:90%
We're going to move on to CS--

00:51:22.060 --> 00:51:23.530 align:middle line:90%
no, SCLR.

00:51:23.530 --> 00:51:27.040 align:middle line:90%


00:51:27.040 --> 00:51:28.396 align:middle line:90%
What's the reference here?

00:51:28.396 --> 00:51:30.100 align:middle line:90%
AUDIENCE: [INAUDIBLE]

00:51:30.100 --> 00:51:32.230 align:middle line:90%
JASON KU: Yeah, CLRS.

00:51:32.230 --> 00:51:34.630 align:middle line:84%
These are four academics
who wrote a popular textbook

00:51:34.630 --> 00:51:37.520 align:middle line:90%
in computer science.

00:51:37.520 --> 00:51:39.880 align:middle line:84%
This is the same kind
of k kind of thing.

00:51:39.880 --> 00:51:44.770 align:middle line:84%
They found first editions and
they want to auction them off.

00:51:44.770 --> 00:51:46.553 align:middle line:84%
People can go on
to their website.

00:51:46.553 --> 00:51:47.470 align:middle line:90%
They have a bidder ID.

00:51:47.470 --> 00:51:49.900 align:middle line:90%
It's a unique identifier.

00:51:49.900 --> 00:51:53.830 align:middle line:84%
And they can place a bid
for one of these books.

00:51:53.830 --> 00:51:57.400 align:middle line:84%
And they can change it
during the bidding period,

00:51:57.400 --> 00:52:00.640 align:middle line:84%
but at the end of
the bidding period,

00:52:00.640 --> 00:52:06.112 align:middle line:84%
the academics want
to know who the--

00:52:06.112 --> 00:52:08.080 align:middle line:84%
what is the expected
revenue I'll

00:52:08.080 --> 00:52:10.060 align:middle line:84%
get by selling to the
k highest bidders?

00:52:10.060 --> 00:52:13.470 align:middle line:90%
Does that makes sense?

00:52:13.470 --> 00:52:15.930 align:middle line:90%
Yeah?

00:52:15.930 --> 00:52:16.590 align:middle line:90%
OK.

00:52:16.590 --> 00:52:22.560 align:middle line:84%
Note that, before I build
this data structure,

00:52:22.560 --> 00:52:24.690 align:middle line:84%
I know what k is.
k is a fixed thing.

00:52:24.690 --> 00:52:27.360 align:middle line:90%


00:52:27.360 --> 00:52:31.230 align:middle line:84%
Because my running time of this
get-revenue depends on this k,

00:52:31.230 --> 00:52:34.470 align:middle line:84%
it's not an input
to that operation.

00:52:34.470 --> 00:52:37.530 align:middle line:84%
So k is kind of I don't
know what it is, a priori.

00:52:37.530 --> 00:52:39.630 align:middle line:90%
It could be n over 2.

00:52:39.630 --> 00:52:42.180 align:middle line:90%
It could be log n.

00:52:42.180 --> 00:52:43.590 align:middle line:90%
It could be 1.

00:52:43.590 --> 00:52:46.560 align:middle line:90%


00:52:46.560 --> 00:52:48.540 align:middle line:84%
But the data structure
I build needs

00:52:48.540 --> 00:52:50.940 align:middle line:84%
to satisfy these
running time properties,

00:52:50.940 --> 00:52:55.330 align:middle line:84%
no matter what choice of k
that the academics told me.

00:52:55.330 --> 00:52:57.900 align:middle line:90%
Does that make sense?

00:52:57.900 --> 00:53:03.090 align:middle line:84%
What I need to do is, as
far as time is going on,

00:53:03.090 --> 00:53:07.920 align:middle line:84%
people are placing new bids
and updating their bids.

00:53:07.920 --> 00:53:11.890 align:middle line:84%
And those updates
can take log n time.

00:53:11.890 --> 00:53:14.640 align:middle line:84%
But as soon as I
close the window,

00:53:14.640 --> 00:53:21.250 align:middle line:84%
I want to be able to tell,
in constant time, what

00:53:21.250 --> 00:53:24.670 align:middle line:90%
the k highest bidders are.

00:53:24.670 --> 00:53:26.460 align:middle line:90%
Any ideas on how to do this?

00:53:26.460 --> 00:53:28.210 align:middle line:84%
What are the operations
that I have to do?

00:53:28.210 --> 00:53:32.920 align:middle line:84%
I have to be able
to place a new bid.

00:53:32.920 --> 00:53:37.690 align:middle line:84%
Associated with a bidder
is an idea and a bid,

00:53:37.690 --> 00:53:39.440 align:middle line:90%
which is also an integer--

00:53:39.440 --> 00:53:41.440 align:middle line:84%
how many dollars I'm going
to pay for this book.

00:53:41.440 --> 00:53:44.050 align:middle line:90%


00:53:44.050 --> 00:53:45.700 align:middle line:90%
Update the bid.

00:53:45.700 --> 00:53:48.460 align:middle line:84%
In some sense, I need to find
whether that person placed

00:53:48.460 --> 00:53:51.830 align:middle line:84%
the bid before, in
my data structure.

00:53:51.830 --> 00:53:54.700 align:middle line:84%
So at some point, I'm going
to need a find on bidder ID.

00:53:54.700 --> 00:53:57.500 align:middle line:90%
Does that seem possible?

00:53:57.500 --> 00:53:59.800 align:middle line:84%
So I might want to have
some kind of dictionary

00:53:59.800 --> 00:54:01.930 align:middle line:90%
on bidder IDs.

00:54:01.930 --> 00:54:05.260 align:middle line:84%
When I say that I want to have
a dictionary on something,

00:54:05.260 --> 00:54:08.800 align:middle line:84%
right I'm not
specifying to you yet

00:54:08.800 --> 00:54:11.080 align:middle line:84%
how I'm going to
implement that dictionary.

00:54:11.080 --> 00:54:13.015 align:middle line:90%
What are my usual options?

00:54:13.015 --> 00:54:14.780 align:middle line:90%
A hash table.

00:54:14.780 --> 00:54:16.750 align:middle line:84%
But what if I need
worst-case time?

00:54:16.750 --> 00:54:19.390 align:middle line:90%


00:54:19.390 --> 00:54:21.120 align:middle line:90%
A set AVL tree, right?

00:54:21.120 --> 00:54:23.740 align:middle line:84%
That's going to be your
go-to for a dictionary,

00:54:23.740 --> 00:54:26.115 align:middle line:84%
because that's going to give
me log n time to find things

00:54:26.115 --> 00:54:28.620 align:middle line:90%
via a key.

00:54:28.620 --> 00:54:31.560 align:middle line:84%
It's the only thing--
well, except for a sorted--

00:54:31.560 --> 00:54:33.870 align:middle line:84%
you could also use
a sorted array,

00:54:33.870 --> 00:54:36.180 align:middle line:84%
but that's going
to not be dynamic.

00:54:36.180 --> 00:54:38.700 align:middle line:84%
And here, we're updating
who's in my data structure

00:54:38.700 --> 00:54:39.780 align:middle line:90%
all the time.

00:54:39.780 --> 00:54:43.850 align:middle line:84%
People are going in
and placing bids--

00:54:43.850 --> 00:54:45.120 align:middle line:90%
new people placing bids.

00:54:45.120 --> 00:54:47.280 align:middle line:84%
So my set of things
that I care about

00:54:47.280 --> 00:54:48.572 align:middle line:90%
is changing all of the time.

00:54:48.572 --> 00:54:50.280 align:middle line:84%
So that's probably
going to steer me away

00:54:50.280 --> 00:54:52.440 align:middle line:84%
from sorted arrays,
because they're not

00:54:52.440 --> 00:54:55.920 align:middle line:90%
good with dynamic operations.

00:54:55.920 --> 00:54:59.610 align:middle line:84%
So I'm going to need some kind
of dictionary on bidder IDs,

00:54:59.610 --> 00:55:06.120 align:middle line:84%
but I'm also going to need
to maintain the sum of the k

00:55:06.120 --> 00:55:06.810 align:middle line:90%
highest bidders.

00:55:06.810 --> 00:55:08.710 align:middle line:90%
Does that makes sense?

00:55:08.710 --> 00:55:10.650 align:middle line:84%
And so, in some
sense, I need to keep

00:55:10.650 --> 00:55:18.878 align:middle line:84%
track of an ordered notion of
the bidders, the bids, that

00:55:18.878 --> 00:55:19.920 align:middle line:90%
are in my data structure.

00:55:19.920 --> 00:55:22.080 align:middle line:90%
Does that make sense?

00:55:22.080 --> 00:55:24.460 align:middle line:84%
So order is going to be
important on the bids.

00:55:24.460 --> 00:55:28.410 align:middle line:84%
I'm going to need a
look-up on bidder ID.

00:55:28.410 --> 00:55:31.330 align:middle line:90%
And that's about it, right?

00:55:31.330 --> 00:55:31.830 align:middle line:90%
OK.

00:55:31.830 --> 00:55:32.100 align:middle line:90%
Yeah?

00:55:32.100 --> 00:55:32.670 align:middle line:90%
AUDIENCE: Just checking.

00:55:32.670 --> 00:55:34.045 align:middle line:84%
So if something
that's worst-case

00:55:34.045 --> 00:55:38.550 align:middle line:84%
runs at worst-case time,
runs expected [INAUDIBLE]..

00:55:38.550 --> 00:55:39.150 align:middle line:90%
JASON KU: Yes.

00:55:39.150 --> 00:55:40.260 align:middle line:90%
Correct.

00:55:40.260 --> 00:55:42.390 align:middle line:90%
Yeah.

00:55:42.390 --> 00:55:44.190 align:middle line:90%
That's a very good observation.

00:55:44.190 --> 00:55:46.590 align:middle line:84%
If it runs in worst
case time, it also

00:55:46.590 --> 00:55:47.972 align:middle line:90%
runs in expected at time, right?

00:55:47.972 --> 00:55:49.805 align:middle line:84%
Because there's essentially
no randomization

00:55:49.805 --> 00:55:51.650 align:middle line:90%
that I'm talking about here.

00:55:51.650 --> 00:55:54.620 align:middle line:90%
AUDIENCE: [INAUDIBLE]?

00:55:54.620 --> 00:55:55.450 align:middle line:90%
JASON KU: Yeah.

00:55:55.450 --> 00:55:58.890 align:middle line:84%
And so there's a stronger notion
which we want you to specify,

00:55:58.890 --> 00:56:01.770 align:middle line:84%
which is that, actually, there
is no randomization here.

00:56:01.770 --> 00:56:04.260 align:middle line:90%
We're not using a hash table.

00:56:04.260 --> 00:56:07.973 align:middle line:84%
In this class, really, that's
the only situation where

00:56:07.973 --> 00:56:09.140 align:middle line:90%
that's going to be an issue.

00:56:09.140 --> 00:56:11.880 align:middle line:90%


00:56:11.880 --> 00:56:16.450 align:middle line:84%
But if it is, what this problem
is saying for each [INAUDIBLE],,

00:56:16.450 --> 00:56:19.170 align:middle line:84%
whether your running time is
worst case expected and/or

00:56:19.170 --> 00:56:22.350 align:middle line:84%
amortized, what we're really
trying to get you to say is

00:56:22.350 --> 00:56:23.010 align:middle line:90%
what's the--

00:56:23.010 --> 00:56:26.220 align:middle line:90%


00:56:26.220 --> 00:56:28.170 align:middle line:84%
evaluate the running
time of your algorithm

00:56:28.170 --> 00:56:30.840 align:middle line:90%
with the proper qualifications.

00:56:30.840 --> 00:56:32.280 align:middle line:84%
If it took worst
case, I want you

00:56:32.280 --> 00:56:35.030 align:middle line:90%
to say that it took worst case.

00:56:35.030 --> 00:56:38.300 align:middle line:84%
If it took-- if you
used a hash table,

00:56:38.300 --> 00:56:39.620 align:middle line:90%
I want you to say expected.

00:56:39.620 --> 00:56:43.850 align:middle line:84%
And if these operations
were sometimes really bad,

00:56:43.850 --> 00:56:46.430 align:middle line:84%
but on average, they're really
good-- if I did a lot of them,

00:56:46.430 --> 00:56:49.550 align:middle line:90%
that's amortized.

00:56:49.550 --> 00:56:53.180 align:middle line:84%
Or if I reduced to
using a dynamic array,

00:56:53.180 --> 00:56:54.920 align:middle line:84%
or if I reduced to
using a hash table,

00:56:54.920 --> 00:56:59.530 align:middle line:84%
those dynamic operations
would still be amortized.

00:56:59.530 --> 00:57:00.350 align:middle line:90%
OK.

00:57:00.350 --> 00:57:01.700 align:middle line:90%
The dynamic ones.

00:57:01.700 --> 00:57:04.520 align:middle line:84%
The nice thing about
linked data structures

00:57:04.520 --> 00:57:07.148 align:middle line:84%
is that dynamic operations
aren't amortized.

00:57:07.148 --> 00:57:08.690 align:middle line:84%
So we're going to
be able to get one.

00:57:08.690 --> 00:57:12.080 align:middle line:84%
Now, for this problem, we can
actually get worst case bounds,

00:57:12.080 --> 00:57:13.860 align:middle line:90%
so we're going to try for that.

00:57:13.860 --> 00:57:16.700 align:middle line:84%
You can also do it in expected
using some hash tables

00:57:16.700 --> 00:57:20.240 align:middle line:90%
for that dictionary.

00:57:20.240 --> 00:57:21.710 align:middle line:84%
When you approach
a data structures

00:57:21.710 --> 00:57:26.630 align:middle line:84%
problem in this class,
you want to tell me

00:57:26.630 --> 00:57:30.800 align:middle line:84%
what it is you're
storing, first off.

00:57:30.800 --> 00:57:34.300 align:middle line:84%
Tell me what's supposed
to be in those things--

00:57:34.300 --> 00:57:35.970 align:middle line:84%
some invariants on
this data structure

00:57:35.970 --> 00:57:40.520 align:middle line:84%
to make sure that, when
I do queries later,

00:57:40.520 --> 00:57:42.560 align:middle line:84%
that these things
are being maintained,

00:57:42.560 --> 00:57:49.520 align:middle line:84%
so that if I'm maintaining
a sorted array,

00:57:49.520 --> 00:57:52.070 align:middle line:84%
and I'm supporting an
operation to find the maximum,

00:57:52.070 --> 00:57:52.850 align:middle line:90%
I had better--

00:57:52.850 --> 00:57:54.380 align:middle line:84%
anything I do to
this data structure

00:57:54.380 --> 00:57:56.448 align:middle line:84%
had better be maintaining
the invariants

00:57:56.448 --> 00:57:57.990 align:middle line:84%
that these things
are in sorted order

00:57:57.990 --> 00:58:00.620 align:middle line:84%
and the last thing
has the maximum item.

00:58:00.620 --> 00:58:03.770 align:middle line:84%
Because my max-return
thing is going

00:58:03.770 --> 00:58:05.540 align:middle line:90%
to look there and return that.

00:58:05.540 --> 00:58:07.290 align:middle line:90%
Does that makes sense?

00:58:07.290 --> 00:58:10.520 align:middle line:84%
So you want to tell me
what is being stored

00:58:10.520 --> 00:58:13.280 align:middle line:84%
at a generic point in
time during your data

00:58:13.280 --> 00:58:15.860 align:middle line:84%
structure, what is
being maintained-- so

00:58:15.860 --> 00:58:20.060 align:middle line:84%
that, when I support the
dynamic operation or a query,

00:58:20.060 --> 00:58:23.630 align:middle line:84%
in a dynamic operation, where
I'm inserting and leading

00:58:23.630 --> 00:58:26.180 align:middle line:84%
things from this thing, I
need to make sure that I'm

00:58:26.180 --> 00:58:28.508 align:middle line:90%
maintaining those invariants.

00:58:28.508 --> 00:58:30.050 align:middle line:84%
And when I'm querying,
I can actually

00:58:30.050 --> 00:58:34.250 align:middle line:84%
rely on those invariants
to answer my query.

00:58:34.250 --> 00:58:36.380 align:middle line:90%
Does that makes sense?

00:58:36.380 --> 00:58:40.030 align:middle line:84%
So, for this
problem-- this is 4-3.

00:58:40.030 --> 00:58:43.830 align:middle line:90%


00:58:43.830 --> 00:58:45.410 align:middle line:90%
Any ideas?

00:58:45.410 --> 00:58:50.030 align:middle line:84%
I have two kind of keys that
I might have to deal with.

00:58:50.030 --> 00:58:55.520 align:middle line:84%
One's a bid ID and
one's a bid, right?

00:58:55.520 --> 00:59:00.380 align:middle line:84%
So how could I, if I have two
keys that I might want to,

00:59:00.380 --> 00:59:03.620 align:middle line:84%
maybe, order on one
and look up on another,

00:59:03.620 --> 00:59:06.187 align:middle line:84%
how many data structures do
you think I'm going to use?

00:59:06.187 --> 00:59:06.770 align:middle line:90%
AUDIENCE: Two.

00:59:06.770 --> 00:59:07.353 align:middle line:90%
JASON KU: Two.

00:59:07.353 --> 00:59:10.130 align:middle line:90%
That's a pretty good guess.

00:59:10.130 --> 00:59:11.510 align:middle line:90%
So one of them--

00:59:11.510 --> 00:59:12.860 align:middle line:90%
let's just guess, right?

00:59:12.860 --> 00:59:15.920 align:middle line:84%
I need to be able
to look up on bid,

00:59:15.920 --> 00:59:24.110 align:middle line:84%
so let's store these bidders
in some kind of dictionary

00:59:24.110 --> 00:59:26.540 align:middle line:84%
that's going to be able to
look up those things fast.

00:59:26.540 --> 00:59:28.880 align:middle line:90%
So two data structures.

00:59:28.880 --> 00:59:41.222 align:middle line:84%
One is a dictionary
keyed on bidder ID.

00:59:41.222 --> 00:59:44.990 align:middle line:90%


00:59:44.990 --> 00:59:47.890 align:middle line:90%
What else am I going to want?

00:59:47.890 --> 00:59:48.390 align:middle line:90%
What's up?

00:59:48.390 --> 00:59:52.330 align:middle line:90%


00:59:52.330 --> 00:59:56.380 align:middle line:84%
The other way around, a
dictionary stored on the bids?

00:59:56.380 --> 00:59:57.910 align:middle line:84%
Is a dictionary
what I want here?

00:59:57.910 --> 01:00:01.480 align:middle line:84%
AUDIENCE: [INAUDIBLE] set
up AVL tree [INAUDIBLE]??

01:00:01.480 --> 01:00:03.490 align:middle line:84%
JASON KU: I want to
maintain order somehow.

01:00:03.490 --> 01:00:06.250 align:middle line:84%
Because I want to
maintain the biggest

01:00:06.250 --> 01:00:07.780 align:middle line:90%
things that I've seen so far.

01:00:07.780 --> 01:00:12.102 align:middle line:84%
Right now, if I have--
at some point in time,

01:00:12.102 --> 01:00:13.060 align:middle line:90%
what's going to happen?

01:00:13.060 --> 01:00:16.780 align:middle line:84%
If I'm maintaining the k
largest at any point in time,

01:00:16.780 --> 01:00:19.630 align:middle line:84%
it's possible that
one of those bidders

01:00:19.630 --> 01:00:24.400 align:middle line:84%
maybe decreases his bid so
it's no longer in the highest.

01:00:24.400 --> 01:00:27.310 align:middle line:84%
I'm going to also need to
keep track of the other guys

01:00:27.310 --> 01:00:31.840 align:middle line:84%
to see who I should add back
into that set, for example.

01:00:31.840 --> 01:00:33.880 align:middle line:90%
Here's an idea.

01:00:33.880 --> 01:00:37.823 align:middle line:84%
I'm going to keep not just one
other data structure, but two

01:00:37.823 --> 01:00:38.740 align:middle line:90%
other data structures.

01:00:38.740 --> 01:00:40.810 align:middle line:90%
Maybe this is a leap.

01:00:40.810 --> 01:00:42.010 align:middle line:90%
You don't have to do this.

01:00:42.010 --> 01:00:44.140 align:middle line:84%
There's a way to do it
with just one other.

01:00:44.140 --> 01:00:46.910 align:middle line:90%
But I'm going to store two more.

01:00:46.910 --> 01:00:49.900 align:middle line:90%
One is kind of an--

01:00:49.900 --> 01:01:01.100 align:middle line:84%
a data structure to
store bidders with a--

01:01:01.100 --> 01:01:14.020 align:middle line:84%
store the k highest bidders,
and a data structure

01:01:14.020 --> 01:01:22.570 align:middle line:84%
to store the n minus
k highest bidders.

01:01:22.570 --> 01:01:25.640 align:middle line:90%
Does that make sense?

01:01:25.640 --> 01:01:31.190 align:middle line:84%
This separates my problem
quite nicely, right?

01:01:31.190 --> 01:01:33.830 align:middle line:84%
Every time someone does an
interaction with this data

01:01:33.830 --> 01:01:41.360 align:middle line:84%
structure, I can check
to see whether it's

01:01:41.360 --> 01:01:44.600 align:middle line:84%
bigger than the
smallest thing in here.

01:01:44.600 --> 01:01:48.320 align:middle line:84%
If it is, I can do the same
kind of trick I did before.

01:01:48.320 --> 01:01:52.610 align:middle line:84%
I can remove it and stick
my new one in there.

01:01:52.610 --> 01:01:54.200 align:middle line:84%
And we're going--
but I removed it.

01:01:54.200 --> 01:01:56.660 align:middle line:84%
I have to maintain
this property.

01:01:56.660 --> 01:01:58.575 align:middle line:90%
So I stick it in here.

01:01:58.575 --> 01:01:59.450 align:middle line:90%
There's another case.

01:01:59.450 --> 01:02:00.367 align:middle line:90%
What's the other case?

01:02:00.367 --> 01:02:03.190 align:middle line:90%


01:02:03.190 --> 01:02:05.460 align:middle line:90%
It's smaller.

01:02:05.460 --> 01:02:07.090 align:middle line:84%
In which case, I
don't do anything

01:02:07.090 --> 01:02:09.340 align:middle line:84%
to this data structure, and
I just stick it into here.

01:02:09.340 --> 01:02:12.390 align:middle line:90%
Does that makes sense?

01:02:12.390 --> 01:02:14.460 align:middle line:84%
What are the operations
these data structures

01:02:14.460 --> 01:02:16.380 align:middle line:90%
need to maintain?

01:02:16.380 --> 01:02:19.410 align:middle line:84%
Finding the minimum or the
maximum of these two sets.

01:02:19.410 --> 01:02:20.820 align:middle line:90%
Does that make sense?

01:02:20.820 --> 01:02:25.230 align:middle line:84%
Actually, really, the--
where are those operations?

01:02:25.230 --> 01:02:26.640 align:middle line:90%
I don't have them anymore.

01:02:26.640 --> 01:02:29.070 align:middle line:84%
But they were the
priority queue operations.

01:02:29.070 --> 01:02:33.750 align:middle line:84%
They had delete_max--
and also insert--

01:02:33.750 --> 01:02:36.930 align:middle line:90%
were things that it did well on.

01:02:36.930 --> 01:02:40.200 align:middle line:84%
So any priority
queue, anything that

01:02:40.200 --> 01:02:45.270 align:middle line:84%
can deal with maxes
and mins, is good.

01:02:45.270 --> 01:02:47.610 align:middle line:84%
And what's a data
structure you know

01:02:47.610 --> 01:02:50.910 align:middle line:84%
that can deal with maxes
and mins pretty efficiently?

01:02:50.910 --> 01:02:51.870 align:middle line:90%
The set AVL, right?

01:02:51.870 --> 01:02:55.830 align:middle line:84%
So instead of data
structure here, I'm

01:02:55.830 --> 01:02:59.075 align:middle line:90%
going to say, set AVL.

01:02:59.075 --> 01:03:03.420 align:middle line:90%


01:03:03.420 --> 01:03:12.168 align:middle line:84%
And obviously, it's going
to be cheered by bid.

01:03:12.168 --> 01:03:14.460 align:middle line:84%
Because that's the thing that
I'm going to want to find

01:03:14.460 --> 01:03:15.390 align:middle line:90%
maxes and mins over.

01:03:15.390 --> 01:03:18.070 align:middle line:90%


01:03:18.070 --> 01:03:19.690 align:middle line:84%
Everyone following
the logic here

01:03:19.690 --> 01:03:23.583 align:middle line:84%
of why I'm maintaining
these things?

01:03:23.583 --> 01:03:25.000 align:middle line:84%
This is the level
of an invariants

01:03:25.000 --> 01:03:28.400 align:middle line:84%
that I want to maintain,
because when I go to,

01:03:28.400 --> 01:03:33.430 align:middle line:84%
for example, do this
query, get-revenue,

01:03:33.430 --> 01:03:36.890 align:middle line:84%
I can just run through and
sum all of these things.

01:03:36.890 --> 01:03:38.260 align:middle line:90%
Oh, wait.

01:03:38.260 --> 01:03:40.780 align:middle line:90%
How much time do I have?

01:03:40.780 --> 01:03:42.250 align:middle line:90%
Do I have k time?

01:03:42.250 --> 01:03:44.210 align:middle line:90%
No, I don't have k time.

01:03:44.210 --> 01:03:48.790 align:middle line:84%
So I don't-- I can't afford
to sum up all of these things

01:03:48.790 --> 01:03:49.880 align:middle line:90%
at the end of my thread.

01:03:49.880 --> 01:03:52.720 align:middle line:84%
I have to return it to
you in constant time.

01:03:52.720 --> 01:03:54.880 align:middle line:90%
Any ideas?

01:03:54.880 --> 01:03:59.230 align:middle line:84%
Yeah, just compute--
update a sum.

01:03:59.230 --> 01:04:02.830 align:middle line:84%
Along with this
data structure, I'm

01:04:02.830 --> 01:04:05.500 align:middle line:84%
going to keep a
fourth thing, which

01:04:05.500 --> 01:04:13.120 align:middle line:90%
is just total of their bids.

01:04:13.120 --> 01:04:14.380 align:middle line:90%
I'm going to call it t.

01:04:14.380 --> 01:04:18.670 align:middle line:90%


01:04:18.670 --> 01:04:20.380 align:middle line:84%
And that's something
I'm maintaining.

01:04:20.380 --> 01:04:22.780 align:middle line:90%
It's part of my data structure.

01:04:22.780 --> 01:04:24.370 align:middle line:84%
You can think of it
as, I'm augmenting

01:04:24.370 --> 01:04:27.310 align:middle line:90%
this thing with a number.

01:04:27.310 --> 01:04:30.130 align:middle line:84%
And the point of augmenting
this thing with a number

01:04:30.130 --> 01:04:31.510 align:middle line:90%
is that I can just--

01:04:31.510 --> 01:04:34.120 align:middle line:84%
if I need to know what the
total of this stuff is,

01:04:34.120 --> 01:04:35.800 align:middle line:90%
I can just look at that number.

01:04:35.800 --> 01:04:38.260 align:middle line:90%
Does that make sense?

01:04:38.260 --> 01:04:39.100 align:middle line:90%
All right.

01:04:39.100 --> 01:04:41.920 align:middle line:84%
So now, I think,
we're almost done.

01:04:41.920 --> 01:04:44.050 align:middle line:90%
We're basically done, right?

01:04:44.050 --> 01:04:45.860 align:middle line:90%
How do we do this?

01:04:45.860 --> 01:04:51.220 align:middle line:84%
Someone walk through to
me how I would get revenue

01:04:51.220 --> 01:04:54.270 align:middle line:90%
with this data structure.

01:04:54.270 --> 01:04:56.870 align:middle line:90%
I basically kind of told you.

01:04:56.870 --> 01:04:57.800 align:middle line:90%
Look at this number.

01:04:57.800 --> 01:04:59.240 align:middle line:90%
Return it.

01:04:59.240 --> 01:05:02.580 align:middle line:84%
Because that's the invariant
that I've maintained on my data

01:05:02.580 --> 01:05:03.080 align:middle line:90%
structure.

01:05:03.080 --> 01:05:04.760 align:middle line:90%
I'm relying on this invariant.

01:05:04.760 --> 01:05:06.860 align:middle line:84%
Now, I'd better make
sure this is good

01:05:06.860 --> 01:05:09.350 align:middle line:90%
when I do dynamic operations.

01:05:09.350 --> 01:05:11.030 align:middle line:90%
I make sure I maintain it.

01:05:11.030 --> 01:05:15.973 align:middle line:84%
But if I, by induction, I ensure
that all of this stuff is good,

01:05:15.973 --> 01:05:18.140 align:middle line:84%
and when I do a dynamic
operation, all of that stuff

01:05:18.140 --> 01:05:21.230 align:middle line:84%
is maintained,
then I'm all good.

01:05:21.230 --> 01:05:28.050 align:middle line:84%
So get-revenue, after I did all
this extra work, is very easy.

01:05:28.050 --> 01:05:31.730 align:middle line:84%
I just look at this
number and return then.

01:05:31.730 --> 01:05:33.620 align:middle line:84%
When we're grading a
data structures problem,

01:05:33.620 --> 01:05:36.710 align:middle line:84%
usually we give you some points,
first, for setting up your data

01:05:36.710 --> 01:05:39.110 align:middle line:84%
structure, separately
from the operations,

01:05:39.110 --> 01:05:42.320 align:middle line:84%
and then we give you
points per operation

01:05:42.320 --> 01:05:44.360 align:middle line:84%
that you successfully
deal with, and then

01:05:44.360 --> 01:05:47.130 align:middle line:84%
some points for correctness
and running time.

01:05:47.130 --> 01:05:49.620 align:middle line:90%
Yeah, you had a question?

01:05:49.620 --> 01:05:51.560 align:middle line:84%
AUDIENCE: So would
total be a thing

01:05:51.560 --> 01:05:54.770 align:middle line:84%
that we update
whenever we mess around

01:05:54.770 --> 01:05:58.871 align:middle line:84%
with the highest bidder tree
and then n minus k bidder tree?

01:05:58.871 --> 01:06:00.760 align:middle line:84%
JASON KU: I'm sorry,
say that again?

01:06:00.760 --> 01:06:03.790 align:middle line:84%
AUDIENCE: Are we treating
the total to an augmentation

01:06:03.790 --> 01:06:05.540 align:middle line:84%
that we update every
time we do something?

01:06:05.540 --> 01:06:05.750 align:middle line:90%
JASON KU: Yeah.

01:06:05.750 --> 01:06:06.250 align:middle line:90%
Yeah.

01:06:06.250 --> 01:06:07.885 align:middle line:90%
So it's just one number.

01:06:07.885 --> 01:06:09.260 align:middle line:84%
It's not really
a data structure,

01:06:09.260 --> 01:06:12.770 align:middle line:84%
it's just one number that
I'm storing with my database.

01:06:12.770 --> 01:06:16.820 align:middle line:90%


01:06:16.820 --> 01:06:17.420 align:middle line:90%
All right.

01:06:17.420 --> 01:06:23.010 align:middle line:84%
How do I implement
a new bid operation?

01:06:23.010 --> 01:06:23.510 align:middle line:90%
Yeah?

01:06:23.510 --> 01:06:24.677 align:middle line:90%
AUDIENCE: I have a question.

01:06:24.677 --> 01:06:27.302 align:middle line:84%
Can we assume that the
bids will also be unique?

01:06:27.302 --> 01:06:29.510 align:middle line:84%
JASON KU: Can you assume
that the bids may be unique?

01:06:29.510 --> 01:06:30.010 align:middle line:90%
No.

01:06:30.010 --> 01:06:32.420 align:middle line:90%


01:06:32.420 --> 01:06:39.050 align:middle line:84%
That's actually something that
is a really useful observation.

01:06:39.050 --> 01:06:42.290 align:middle line:84%
We've been talking about
set data structures

01:06:42.290 --> 01:06:47.390 align:middle line:90%
as requiring unique keys.

01:06:47.390 --> 01:06:48.890 align:middle line:84%
How can I deal with
non-unique keys?

01:06:48.890 --> 01:06:51.140 align:middle line:84%
It actually turns
out that, hash table,

01:06:51.140 --> 01:06:54.650 align:middle line:84%
it's really important
that these be unique keys.

01:06:54.650 --> 01:06:56.930 align:middle line:84%
Because I need to check
whether it's in there.

01:06:56.930 --> 01:06:59.110 align:middle line:90%
I'm looking for that single key.

01:06:59.110 --> 01:07:01.340 align:middle line:84%
When I find it,
I have to return.

01:07:01.340 --> 01:07:03.230 align:middle line:84%
If I had multiple
things with that key,

01:07:03.230 --> 01:07:05.450 align:middle line:84%
I might not return the
one that I'm looking for.

01:07:05.450 --> 01:07:08.240 align:middle line:90%
Doesn't even make sense.

01:07:08.240 --> 01:07:17.240 align:middle line:84%
But you can generalize
the set infrastructure

01:07:17.240 --> 01:07:19.230 align:middle line:90%
to deal with multi-sets.

01:07:19.230 --> 01:07:21.420 align:middle line:90%
How can I do that?

01:07:21.420 --> 01:07:24.860 align:middle line:90%
Well, with each key--

01:07:24.860 --> 01:07:26.720 align:middle line:90%
again, I'm storing unique keys.

01:07:26.720 --> 01:07:30.110 align:middle line:84%
With each key, I can link it
to a sequence set of structure,

01:07:30.110 --> 01:07:32.258 align:middle line:90%
or any other data structure.

01:07:32.258 --> 01:07:34.550 align:middle line:84%
And what I'm going to do is,
I'm going to do-- anything

01:07:34.550 --> 01:07:36.440 align:middle line:84%
that has that key,
I'm going to stick it

01:07:36.440 --> 01:07:38.558 align:middle line:90%
in that data structure.

01:07:38.558 --> 01:07:40.100 align:middle line:84%
So instead of storing
one item there,

01:07:40.100 --> 01:07:42.267 align:middle line:84%
I have the possibility of
storing many things there.

01:07:42.267 --> 01:07:44.700 align:middle line:84%
Now, I have to change
the semantics here.

01:07:44.700 --> 01:07:48.800 align:middle line:84%
If I'm saying, find on this
key, well, now, I could say,

01:07:48.800 --> 01:07:51.800 align:middle line:84%
I'm going to return all of
the things with that key,

01:07:51.800 --> 01:07:55.010 align:middle line:84%
or I'm going to store
some thing with that key.

01:07:55.010 --> 01:07:56.150 align:middle line:90%
But you get the idea.

01:07:56.150 --> 01:07:59.970 align:middle line:84%
All I have to do is map it
to some other data structure

01:07:59.970 --> 01:08:01.160 align:middle line:90%
to maintain [INAUDIBLE].

01:08:01.160 --> 01:08:06.380 align:middle line:84%
Like, maybe, I want all of
the things with that key.

01:08:06.380 --> 01:08:09.440 align:middle line:84%
I want to find the one
with this other key.

01:08:09.440 --> 01:08:11.475 align:middle line:84%
So maybe I link to
a set data structure

01:08:11.475 --> 01:08:13.100 align:middle line:84%
that can search on
other things, right?

01:08:13.100 --> 01:08:15.410 align:middle line:84%
But the idea here
is, we maintain

01:08:15.410 --> 01:08:18.109 align:middle line:90%
this uniqueness key property.

01:08:18.109 --> 01:08:20.810 align:middle line:84%
I have to relax my
semantics so that I'm

01:08:20.810 --> 01:08:23.609 align:middle line:84%
storing multiple things
at that key location.

01:08:23.609 --> 01:08:24.550 align:middle line:90%
Does that makes sense?

01:08:24.550 --> 01:08:25.250 align:middle line:90%
Yeah?

01:08:25.250 --> 01:08:27.250 align:middle line:84%
AUDIENCE: Why does it
matter whether the set AVL

01:08:27.250 --> 01:08:28.512 align:middle line:90%
tree has unique keys or not?

01:08:28.512 --> 01:08:31.220 align:middle line:90%


01:08:31.220 --> 01:08:35.750 align:middle line:84%
JASON KU: It's going to matter
here because I have bids.

01:08:35.750 --> 01:08:38.899 align:middle line:84%
And the bids could
be non-unique.

01:08:38.899 --> 01:08:43.580 align:middle line:84%
Two people could
have the same bid.

01:08:43.580 --> 01:08:46.850 align:middle line:84%
And by our definition
of a set data structure,

01:08:46.850 --> 01:08:48.149 align:middle line:90%
it had to have unique keys.

01:08:48.149 --> 01:08:50.870 align:middle line:84%
So if I stuck in all of
these things keyed by bidder,

01:08:50.870 --> 01:08:53.510 align:middle line:90%
you've got a problem.

01:08:53.510 --> 01:08:54.979 align:middle line:84%
Now, in actuality,
we can get away

01:08:54.979 --> 01:08:57.439 align:middle line:84%
with that by storing,
basically, a linked

01:08:57.439 --> 01:09:00.529 align:middle line:84%
list of all of the things with
that key, and we would be fine.

01:09:00.529 --> 01:09:03.109 align:middle line:90%


01:09:03.109 --> 01:09:06.260 align:middle line:84%
And then, whenever I want to
return one, I could just do it.

01:09:06.260 --> 01:09:10.550 align:middle line:84%
But actually, a
binary tree actually

01:09:10.550 --> 01:09:12.950 align:middle line:84%
is flexible enough that,
in most implementations,

01:09:12.950 --> 01:09:15.920 align:middle line:84%
you can just store a
bunch of those things.

01:09:15.920 --> 01:09:20.840 align:middle line:84%
But, actually, our
run times do worse.

01:09:20.840 --> 01:09:24.439 align:middle line:84%
What does it mean to
find-next in my sequence?

01:09:24.439 --> 01:09:29.750 align:middle line:84%
What does it mean to
return the next larger

01:09:29.750 --> 01:09:32.029 align:middle line:90%
thing above this key?

01:09:32.029 --> 01:09:33.859 align:middle line:84%
Doesn't really make
sense, because there

01:09:33.859 --> 01:09:34.819 align:middle line:90%
could be multiple ones.

01:09:34.819 --> 01:09:36.200 align:middle line:90%
Which one do I return?

01:09:36.200 --> 01:09:41.270 align:middle line:84%
And if I repeatedly do find-next
on this data structure,

01:09:41.270 --> 01:09:44.720 align:middle line:84%
I might not loop through
all of the things.

01:09:44.720 --> 01:09:49.170 align:middle line:84%
So some stuff breaks
down in our interface.

01:09:49.170 --> 01:09:54.980 align:middle line:84%
So I would prefer you use unique
keys in this kind of situation.

01:09:54.980 --> 01:09:58.580 align:middle line:84%
Next Tuesday, I think,
with binary heaps,

01:09:58.580 --> 01:10:02.720 align:middle line:90%
we'll deal with non-unique keys.

01:10:02.720 --> 01:10:04.230 align:middle line:90%
That's fine.

01:10:04.230 --> 01:10:09.440 align:middle line:84%
But if you're going to use
non-unique keys in here,

01:10:09.440 --> 01:10:11.480 align:middle line:84%
you've just got
to be a little bit

01:10:11.480 --> 01:10:13.920 align:middle line:90%
careful about the semantics.

01:10:13.920 --> 01:10:14.420 align:middle line:90%
Yeah?

01:10:14.420 --> 01:10:15.410 align:middle line:90%
AUDIENCE: [INAUDIBLE]?

01:10:15.410 --> 01:10:24.500 align:middle line:90%


01:10:24.500 --> 01:10:27.620 align:middle line:84%
JASON KU: You would
get the same running

01:10:27.620 --> 01:10:29.960 align:middle line:84%
time-- you have to
change the semantics

01:10:29.960 --> 01:10:32.510 align:middle line:84%
on what you mean by
"find something."

01:10:32.510 --> 01:10:35.570 align:middle line:84%
I just want to return
anything with this key.

01:10:35.570 --> 01:10:37.490 align:middle line:84%
AUDIENCE: What if
everything has the same key.

01:10:37.490 --> 01:10:38.190 align:middle line:90%
Then--

01:10:38.190 --> 01:10:39.900 align:middle line:84%
JASON KU: Then it
takes constant time.

01:10:39.900 --> 01:10:41.150 align:middle line:90%
I just return the first thing.

01:10:41.150 --> 01:10:45.110 align:middle line:90%


01:10:45.110 --> 01:10:48.410 align:middle line:84%
I mean, these are
special cases that you

01:10:48.410 --> 01:10:51.140 align:middle line:90%
have to think about, right?

01:10:51.140 --> 01:10:52.920 align:middle line:84%
I don't like
thinking about them.

01:10:52.920 --> 01:10:55.460 align:middle line:84%
So I just like
having unique keys.

01:10:55.460 --> 01:10:59.570 align:middle line:84%
And if I want a situation
where I have non-unique keys,

01:10:59.570 --> 01:11:02.870 align:middle line:84%
I'm going to basically
put collisions at that key

01:11:02.870 --> 01:11:04.910 align:middle line:90%
into a new data structure.

01:11:04.910 --> 01:11:06.540 align:middle line:84%
It's just easier for
me to separate out

01:11:06.540 --> 01:11:08.300 align:middle line:90%
in my head on what's happening.

01:11:08.300 --> 01:11:11.030 align:middle line:84%
Because, all of the running
times that we proposed,

01:11:11.030 --> 01:11:14.540 align:middle line:84%
there's very strong
definitions for unique key.

01:11:14.540 --> 01:11:16.970 align:middle line:84%
When you're dealing
with a multi-set,

01:11:16.970 --> 01:11:20.150 align:middle line:84%
it's a little bit
more prevalent.

01:11:20.150 --> 01:11:21.890 align:middle line:90%
Any other questions?

01:11:21.890 --> 01:11:25.910 align:middle line:84%
We really need to kind
of move on here, right?

01:11:25.910 --> 01:11:27.650 align:middle line:90%
Dictionary keyed on bidder.

01:11:27.650 --> 01:11:31.670 align:middle line:84%
We still haven't implemented
any dynamic operations.

01:11:31.670 --> 01:11:32.360 align:middle line:90%
New bid.

01:11:32.360 --> 01:11:34.890 align:middle line:90%
What do I do?

01:11:34.890 --> 01:11:38.030 align:middle line:84%
What am I going to
need for my update?

01:11:38.030 --> 01:11:42.020 align:middle line:84%
I'm going to be able to
need to essentially find,

01:11:42.020 --> 01:11:44.120 align:middle line:84%
in each of these
data structures,

01:11:44.120 --> 01:11:47.510 align:middle line:90%
where that bidder is.

01:11:47.510 --> 01:11:51.890 align:middle line:84%
And if I just have a
thing keyed on their bid,

01:11:51.890 --> 01:11:54.770 align:middle line:84%
the interface doesn't tell
me what their old bid was.

01:11:54.770 --> 01:11:57.200 align:middle line:84%
It just tells me what
their bidder ID is.

01:11:57.200 --> 01:12:02.030 align:middle line:84%
So if I just had their bidder ID
and their new bid, how the heck

01:12:02.030 --> 01:12:04.430 align:middle line:84%
am I going to find out
which of these data-- where

01:12:04.430 --> 01:12:07.190 align:middle line:84%
in these data
structures they are?

01:12:07.190 --> 01:12:11.630 align:middle line:84%
What I can do is, I can
store, in this dictionary--

01:12:11.630 --> 01:12:15.680 align:middle line:84%
which I can look up in
some amount of time--

01:12:15.680 --> 01:12:18.050 align:middle line:84%
a pointer to where it
exists in these things.

01:12:18.050 --> 01:12:20.690 align:middle line:90%
Does that make sense?

01:12:20.690 --> 01:12:21.920 align:middle line:90%
This is called cross-linking.

01:12:21.920 --> 01:12:24.800 align:middle line:84%
You may have done that
a little bit in problem

01:12:24.800 --> 01:12:26.940 align:middle line:90%
set 2, or something like that.

01:12:26.940 --> 01:12:27.440 align:middle line:90%
Yeah?

01:12:27.440 --> 01:12:30.590 align:middle line:84%
AUDIENCE: Restoring a
pointer to a specific bidder?

01:12:30.590 --> 01:12:32.780 align:middle line:90%
JASON KU: Yeah, exactly.

01:12:32.780 --> 01:12:34.178 align:middle line:84%
The invariant we
have is that all

01:12:34.178 --> 01:12:35.720 align:middle line:84%
of the bidders we've
processed so far

01:12:35.720 --> 01:12:38.420 align:middle line:90%
exist in these data structures--

01:12:38.420 --> 01:12:41.060 align:middle line:84%
in one of these
data structures--

01:12:41.060 --> 01:12:43.850 align:middle line:84%
because we've used
a set AVL tree.

01:12:43.850 --> 01:12:45.800 align:middle line:84%
In particular, it
exists in a node of one

01:12:45.800 --> 01:12:47.660 align:middle line:90%
of these data structures.

01:12:47.660 --> 01:12:50.780 align:middle line:84%
What we can do
is, in this thing,

01:12:50.780 --> 01:12:56.480 align:middle line:84%
maintain pointers mapping
each of the bidder IDs

01:12:56.480 --> 01:12:58.910 align:middle line:84%
to their location in
these data structures.

01:12:58.910 --> 01:13:00.920 align:middle line:84%
And why is that going
to be a useful thing?

01:13:00.920 --> 01:13:04.220 align:middle line:90%


01:13:04.220 --> 01:13:06.290 align:middle line:90%
Say I map this dictionary.

01:13:06.290 --> 01:13:07.790 align:middle line:84%
What could I use
for this dictionary

01:13:07.790 --> 01:13:10.580 align:middle line:84%
to get the running
time we're looking for?

01:13:10.580 --> 01:13:13.340 align:middle line:84%
I could use a hash
table or a set AVL.

01:13:13.340 --> 01:13:16.520 align:middle line:84%
If it's a set AVL, I'm going
to get logarithmic time, worst

01:13:16.520 --> 01:13:17.705 align:middle line:90%
case.

01:13:17.705 --> 01:13:19.580 align:middle line:84%
With a hash table, I'm
getting constant time,

01:13:19.580 --> 01:13:21.120 align:middle line:90%
but it's expected.

01:13:21.120 --> 01:13:24.920 align:middle line:84%
So it could be linear
time in the worst case.

01:13:24.920 --> 01:13:27.020 align:middle line:84%
We're going to use a set
AVL tree, because that's

01:13:27.020 --> 01:13:30.330 align:middle line:90%
what we do right now.

01:13:30.330 --> 01:13:32.810 align:middle line:84%
And that's going to
give us worst case.

01:13:32.810 --> 01:13:35.060 align:middle line:84%
What I'm going to do is, for
each one of these things,

01:13:35.060 --> 01:13:36.393 align:middle line:90%
I'm going to store that pointer.

01:13:36.393 --> 01:13:39.683 align:middle line:84%
What I'm going to
do is, first, I'm

01:13:39.683 --> 01:13:41.100 align:middle line:84%
going to do that
operation we had.

01:13:41.100 --> 01:13:49.100 align:middle line:84%
If I'm adding a new bidder,
I'm going to take the D and B--

01:13:49.100 --> 01:13:53.840 align:middle line:84%
these two values, that
object, that bidder object,

01:13:53.840 --> 01:13:54.820 align:middle line:90%
or whatever--

01:13:54.820 --> 01:13:58.040 align:middle line:84%
I'm going to look at the
smallest thing in this data

01:13:58.040 --> 01:14:06.470 align:middle line:84%
structure, see if its bid
is bigger than the thing

01:14:06.470 --> 01:14:07.683 align:middle line:90%
I'm inserting.

01:14:07.683 --> 01:14:10.100 align:middle line:84%
If it is, then I'm not going
to touch this data structure.

01:14:10.100 --> 01:14:11.840 align:middle line:84%
I'm just going to
insert it in here.

01:14:11.840 --> 01:14:13.992 align:middle line:84%
And now, after I
insert in here, I

01:14:13.992 --> 01:14:15.950 align:middle line:84%
know exactly where it is
in the data structure.

01:14:15.950 --> 01:14:19.370 align:middle line:90%
I just inserted it.

01:14:19.370 --> 01:14:22.010 align:middle line:84%
So now, holding
that in my hand--

01:14:22.010 --> 01:14:27.680 align:middle line:84%
the node-- I can go and
insert that bidder into here

01:14:27.680 --> 01:14:29.990 align:middle line:90%
by bid ID.

01:14:29.990 --> 01:14:31.820 align:middle line:84%
So it's going to
take logarithm time.

01:14:31.820 --> 01:14:36.410 align:middle line:84%
And now I can store, with
that node, my pointer

01:14:36.410 --> 01:14:37.565 align:middle line:90%
to this data structure.

01:14:37.565 --> 01:14:38.820 align:middle line:90%
Does that makes sense?

01:14:38.820 --> 01:14:41.780 align:middle line:84%
And in the other case, I
kind of do the same thing.

01:14:41.780 --> 01:14:45.050 align:middle line:84%
If it's bigger than the smallest
thing here, I pop that smaller

01:14:45.050 --> 01:14:48.620 align:middle line:84%
thing out, stick it in there,
and I stick my new guy in here,

01:14:48.620 --> 01:14:52.860 align:middle line:84%
cross-linking each of those
pointers along the way.

01:14:52.860 --> 01:14:57.470 align:middle line:90%
Does that make sense, hopefully?

01:14:57.470 --> 01:14:59.280 align:middle line:90%
Kind of?

01:14:59.280 --> 01:14:59.780 align:middle line:90%
Kind of?

01:14:59.780 --> 01:15:00.860 align:middle line:90%
OK.

01:15:00.860 --> 01:15:03.470 align:middle line:90%
And for update, very similar.

01:15:03.470 --> 01:15:06.050 align:middle line:84%
If I want to update
a certain bidder,

01:15:06.050 --> 01:15:11.550 align:middle line:84%
I look in this data
structure, find the bidder,

01:15:11.550 --> 01:15:13.440 align:middle line:84%
traverse that
pointer to wherever

01:15:13.440 --> 01:15:16.980 align:middle line:84%
it is in one of these
AVL trees, right?

01:15:16.980 --> 01:15:22.050 align:middle line:84%
If it's in this one, I just
remove it from the tree,

01:15:22.050 --> 01:15:23.790 align:middle line:84%
or I remove it from
the tree and then

01:15:23.790 --> 01:15:29.070 align:middle line:84%
I re-insert with
whatever the new bid is.

01:15:29.070 --> 01:15:32.010 align:middle line:84%
And if it's in
this one, again, I

01:15:32.010 --> 01:15:35.190 align:middle line:84%
remove it from the tree,
re-insert in whichever

01:15:35.190 --> 01:15:36.840 align:middle line:84%
of these things is,
and then I might

01:15:36.840 --> 01:15:39.720 align:middle line:84%
have to swap a constant
number of things back

01:15:39.720 --> 01:15:43.020 align:middle line:84%
and forth here to maintain
that this has the k highest.

01:15:43.020 --> 01:15:47.610 align:middle line:84%
And when I do those
dynamic operations,

01:15:47.610 --> 01:15:50.370 align:middle line:84%
I'm always removing
some constant number

01:15:50.370 --> 01:15:53.340 align:middle line:84%
of nodes in each of these
trees and adding back

01:15:53.340 --> 01:15:55.213 align:middle line:90%
in a constant number of things.

01:15:55.213 --> 01:15:57.630 align:middle line:84%
And while I do that, I just
make sure to update this total

01:15:57.630 --> 01:15:58.980 align:middle line:90%
as I go.

01:15:58.980 --> 01:16:04.680 align:middle line:84%
This total was the sum of
all of the bids in here.

01:16:04.680 --> 01:16:07.320 align:middle line:84%
And if I insert a
new bid in here,

01:16:07.320 --> 01:16:09.520 align:middle line:90%
I have to add to that total.

01:16:09.520 --> 01:16:11.858 align:middle line:84%
And if I remove one, I have
to remove from that total.

01:16:11.858 --> 01:16:13.650 align:middle line:84%
But again, it's a
constant number of things

01:16:13.650 --> 01:16:15.900 align:middle line:84%
I'm moving in and out of
these data structures,

01:16:15.900 --> 01:16:18.060 align:middle line:84%
and so it can update
this in constant time.

01:16:18.060 --> 01:16:19.800 align:middle line:90%
Does that makes sense?

01:16:19.800 --> 01:16:23.760 align:middle line:84%
Now, the lookup here, and
the insertion and deletion

01:16:23.760 --> 01:16:29.130 align:middle line:84%
in here, those each took
logarithmic time, worst case.

01:16:29.130 --> 01:16:30.850 align:middle line:84%
But I did a constant
number of them.

01:16:30.850 --> 01:16:32.780 align:middle line:90%
So again, logarithm time.

01:16:32.780 --> 01:16:33.930 align:middle line:90%
Does that makes sense?

01:16:33.930 --> 01:16:37.680 align:middle line:84%
That's, essentially,
this problem.

01:16:37.680 --> 01:16:39.280 align:middle line:90%
It's difficult, right?

01:16:39.280 --> 01:16:41.470 align:middle line:84%
There's a lot of
moving parts here.

01:16:41.470 --> 01:16:44.610 align:middle line:84%
But if you just break it
up and to describe to me--

01:16:44.610 --> 01:16:47.280 align:middle line:84%
like, you really do a
good job on this part,

01:16:47.280 --> 01:16:50.790 align:middle line:84%
describe well to me what
your data structure has, then

01:16:50.790 --> 01:16:52.380 align:middle line:84%
those descriptions
of those algorithms

01:16:52.380 --> 01:16:53.920 align:middle line:90%
can be pretty brief, actually.

01:16:53.920 --> 01:16:57.120 align:middle line:90%


01:16:57.120 --> 01:16:59.940 align:middle line:84%
In this one, you tell me
these three data structures,

01:16:59.940 --> 01:17:03.630 align:middle line:84%
you tell me this guy's
mapping to its location

01:17:03.630 --> 01:17:07.770 align:middle line:84%
and these things, I'm
maintaining this guy,

01:17:07.770 --> 01:17:11.520 align:middle line:84%
and then you just maintain those
things with dynamic operations

01:17:11.520 --> 01:17:14.910 align:middle line:84%
and then use those things
for query operations.

01:17:14.910 --> 01:17:15.900 align:middle line:90%
Does that make sense?

01:17:15.900 --> 01:17:19.630 align:middle line:90%


01:17:19.630 --> 01:17:20.960 align:middle line:90%
Wow, we have 10 more minutes?

01:17:20.960 --> 01:17:25.810 align:middle line:90%


01:17:25.810 --> 01:17:32.830 align:middle line:84%
I'm going to briefly
do 4-4 for you.

01:17:32.830 --> 01:17:33.700 align:middle line:90%
Receiver roster.

01:17:33.700 --> 01:17:36.880 align:middle line:90%
We've got a coach.

01:17:36.880 --> 01:17:38.980 align:middle line:84%
She's got a bunch of
football players--

01:17:38.980 --> 01:17:41.650 align:middle line:90%
receivers.

01:17:41.650 --> 01:17:45.790 align:middle line:84%
And wanting to
start on her team,

01:17:45.790 --> 01:17:50.380 align:middle line:84%
some number of players that
have the highest performance.

01:17:50.380 --> 01:17:52.930 align:middle line:84%
And by performance, we
mean the average number

01:17:52.930 --> 01:17:54.970 align:middle line:84%
of points they've played
in games that they

01:17:54.970 --> 01:17:56.980 align:middle line:90%
have logged in their system.

01:17:56.980 --> 01:18:00.280 align:middle line:84%
But actually, their
data is incomplete.

01:18:00.280 --> 01:18:02.680 align:middle line:84%
They don't know which games,
and how much they scored,

01:18:02.680 --> 01:18:03.680 align:middle line:90%
and all of these things.

01:18:03.680 --> 01:18:05.090 align:middle line:90%
There could be errors.

01:18:05.090 --> 01:18:08.320 align:middle line:84%
And so these interns,
they're constantly

01:18:08.320 --> 01:18:15.370 align:middle line:84%
updating this database with
queries like, oh, never mind,

01:18:15.370 --> 01:18:17.980 align:middle line:84%
this person didn't
play in this game,

01:18:17.980 --> 01:18:21.850 align:middle line:84%
or actually, they did, and they
scored this number of points.

01:18:21.850 --> 01:18:25.780 align:middle line:84%
That's the-- clear
and record things.

01:18:25.780 --> 01:18:28.360 align:middle line:84%
And then, at some
point in time, like

01:18:28.360 --> 01:18:31.870 align:middle line:84%
when we want to
play a game, I want

01:18:31.870 --> 01:18:36.760 align:middle line:84%
to be able to return the
jersey with the kth highest

01:18:36.760 --> 01:18:40.270 align:middle line:90%
performance in log n time.

01:18:40.270 --> 01:18:45.370 align:middle line:84%
This is kind of a
rank query, right?

01:18:45.370 --> 01:18:46.135 align:middle line:90%
The kth highest.

01:18:46.135 --> 01:18:48.670 align:middle line:90%


01:18:48.670 --> 01:18:53.500 align:middle line:84%
Now, in actuality, I might want
to return all k highest players

01:18:53.500 --> 01:18:56.050 align:middle line:90%
so that that might be my roster.

01:18:56.050 --> 01:19:00.070 align:middle line:84%
But this is a more
generalized query.

01:19:00.070 --> 01:19:02.000 align:middle line:90%
It's more specific, more--

01:19:02.000 --> 01:19:04.030 align:middle line:90%
it's not really comparable.

01:19:04.030 --> 01:19:07.358 align:middle line:84%
But you get an idea for why that
might be useful to the coach.

01:19:07.358 --> 01:19:07.900 align:middle line:90%
I don't know.

01:19:07.900 --> 01:19:10.090 align:middle line:90%
Maybe not.

01:19:10.090 --> 01:19:11.667 align:middle line:90%
So what's the idea here?

01:19:11.667 --> 01:19:13.750 align:middle line:84%
We have a lot of different
things floating around.

01:19:13.750 --> 01:19:15.280 align:middle line:90%
We've got games.

01:19:15.280 --> 01:19:17.180 align:middle line:90%
They have IDs-- unique IDs.

01:19:17.180 --> 01:19:18.040 align:middle line:90%
We've got receivers.

01:19:18.040 --> 01:19:19.630 align:middle line:90%
They have unique IDs.

01:19:19.630 --> 01:19:23.890 align:middle line:84%
And each receiver could
play in many games.

01:19:23.890 --> 01:19:26.590 align:middle line:90%
Oh, that's kind of worrisome.

01:19:26.590 --> 01:19:30.990 align:middle line:84%
And many receivers could
play in the same game.

01:19:30.990 --> 01:19:32.680 align:middle line:84%
These kind of
many-to-one mappings

01:19:32.680 --> 01:19:34.490 align:middle line:90%
are a little confusing.

01:19:34.490 --> 01:19:39.110 align:middle line:90%
And then we've got each player--

01:19:39.110 --> 01:19:42.200 align:middle line:84%
receiver-- having a certain
number of points per game.

01:19:42.200 --> 01:19:45.930 align:middle line:84%
And we're trying to sort them,
kind of, by their performance,

01:19:45.930 --> 01:19:47.944 align:middle line:90%
which is a rational number.

01:19:47.944 --> 01:19:50.480 align:middle line:90%
Ugh, right?

01:19:50.480 --> 01:19:52.880 align:middle line:84%
Which has to do with the
number of games they've played

01:19:52.880 --> 01:19:55.880 align:middle line:90%
and the total number of points.

01:19:55.880 --> 01:19:59.420 align:middle line:84%
Now, I see rational number,
I can't compute that.

01:19:59.420 --> 01:20:02.990 align:middle line:84%
That's what we're talking about
last problem session, right?

01:20:02.990 --> 01:20:04.448 align:middle line:84%
But what I can do
is, I could store

01:20:04.448 --> 01:20:05.990 align:middle line:84%
the total number of
games they played

01:20:05.990 --> 01:20:07.730 align:middle line:84%
and the total number
of points they have.

01:20:07.730 --> 01:20:09.830 align:middle line:84%
And you can imagine,
by augmentation

01:20:09.830 --> 01:20:14.690 align:middle line:84%
similar to this, every
time I add a game, one

01:20:14.690 --> 01:20:18.980 align:middle line:84%
of these small operations, I
can update that information

01:20:18.980 --> 01:20:19.700 align:middle line:90%
for each player.

01:20:19.700 --> 01:20:22.850 align:middle line:90%


01:20:22.850 --> 01:20:25.040 align:middle line:84%
If one of these
dynamic operations

01:20:25.040 --> 01:20:27.440 align:middle line:84%
is affecting only
one receiver, I

01:20:27.440 --> 01:20:31.550 align:middle line:84%
can update whatever it
is in constant time,

01:20:31.550 --> 01:20:35.060 align:middle line:84%
probably, if I just store
with the player what

01:20:35.060 --> 01:20:38.732 align:middle line:84%
their total number of games
is as recorded by the database

01:20:38.732 --> 01:20:40.190 align:middle line:84%
and how many points
they've scored.

01:20:40.190 --> 01:20:43.070 align:middle line:84%
Then, if I have a
data structure that

01:20:43.070 --> 01:20:47.790 align:middle line:84%
needs to sort the receivers
by their performance

01:20:47.790 --> 01:20:50.210 align:middle line:84%
so I might be able
to find the kth one--

01:20:50.210 --> 01:20:56.740 align:middle line:84%
the kth largest-- then I can't
compute that performance.

01:20:56.740 --> 01:20:59.290 align:middle line:90%
But what can I do?

01:20:59.290 --> 01:21:02.820 align:middle line:84%
I can compare two players based
on their performance using

01:21:02.820 --> 01:21:05.430 align:middle line:90%
cross-multiplication.

01:21:05.430 --> 01:21:07.740 align:middle line:84%
Because I have the
numerator and denominator

01:21:07.740 --> 01:21:09.240 align:middle line:84%
of each of these
rationals and I can

01:21:09.240 --> 01:21:11.910 align:middle line:84%
cross-multiply and
figure out whether one's

01:21:11.910 --> 01:21:13.330 align:middle line:90%
bigger or smaller.

01:21:13.330 --> 01:21:15.030 align:middle line:84%
And as long as I
have a comparitor,

01:21:15.030 --> 01:21:17.850 align:middle line:90%
I can do set AVL stuff.

01:21:17.850 --> 01:21:19.120 align:middle line:90%
Does that makes sense?

01:21:19.120 --> 01:21:20.610 align:middle line:90%
OK.

01:21:20.610 --> 01:21:25.440 align:middle line:84%
I'm just going to outline kind
of the components of this data

01:21:25.440 --> 01:21:26.240 align:middle line:90%
structure.

01:21:26.240 --> 01:21:28.770 align:middle line:90%


01:21:28.770 --> 01:21:32.730 align:middle line:84%
Well, first off, I'm going
to need to record a receiver.

01:21:32.730 --> 01:21:34.780 align:middle line:84%
And a receiver could
have a lot of games.

01:21:34.780 --> 01:21:37.650 align:middle line:84%
But the important-- this is
kind of a receiver-centric kind

01:21:37.650 --> 01:21:38.230 align:middle line:90%
of problem.

01:21:38.230 --> 01:21:39.930 align:middle line:84%
Does that makes
sense to you guys?

01:21:39.930 --> 01:21:42.960 align:middle line:84%
I'm not ever wanting to
filter on all of the receivers

01:21:42.960 --> 01:21:44.490 align:middle line:90%
playing a game.

01:21:44.490 --> 01:21:50.490 align:middle line:84%
I'm never removing a
game from the system,

01:21:50.490 --> 01:21:53.040 align:middle line:84%
I'm removing a
receiver from ever

01:21:53.040 --> 01:21:54.420 align:middle line:90%
playing in a specific game.

01:21:54.420 --> 01:21:55.630 align:middle line:90%
Does that makes sense?

01:21:55.630 --> 01:21:59.430 align:middle line:84%
So if I'm storing a
receiver, and each receiver

01:21:59.430 --> 01:22:01.980 align:middle line:84%
has some games
associated with them,

01:22:01.980 --> 01:22:05.370 align:middle line:84%
kind of makes sense I might
want to have a nested data

01:22:05.370 --> 01:22:08.160 align:middle line:90%
structure where with--

01:22:08.160 --> 01:22:11.550 align:middle line:84%
maybe I have a
dictionary on receivers.

01:22:11.550 --> 01:22:14.400 align:middle line:84%
And for each one, I
store all the games

01:22:14.400 --> 01:22:17.220 align:middle line:84%
that they've played in
some other data structure.

01:22:17.220 --> 01:22:20.347 align:middle line:84%
With each receiver, I store
another-- its own data

01:22:20.347 --> 01:22:21.930 align:middle line:84%
structure containing
all of its games.

01:22:21.930 --> 01:22:23.640 align:middle line:90%
Does that makes sense?

01:22:23.640 --> 01:22:26.280 align:middle line:90%
OK, so that's the idea.

01:22:26.280 --> 01:22:27.540 align:middle line:90%
We have some kind of--

01:22:27.540 --> 01:22:31.590 align:middle line:84%
I need to be able to
look up receivers,

01:22:31.590 --> 01:22:35.970 align:middle line:84%
because I'm clearing them
or I'm recording them.

01:22:35.970 --> 01:22:40.320 align:middle line:84%
So I'm going to have
a dictionary or--

01:22:40.320 --> 01:22:42.970 align:middle line:84%
here, I'm looking for
worst-case log n time.

01:22:42.970 --> 01:22:45.870 align:middle line:84%
So I'm going to skip the
dictionary abstraction

01:22:45.870 --> 01:22:49.260 align:middle line:90%
and go straight for the set AVL.

01:22:49.260 --> 01:23:00.150 align:middle line:90%
AVL keyed on receivers.

01:23:00.150 --> 01:23:06.730 align:middle line:84%
I before E, except
after C. It is I--

01:23:06.730 --> 01:23:07.230 align:middle line:90%
E-I?

01:23:07.230 --> 01:23:10.650 align:middle line:90%


01:23:10.650 --> 01:23:11.850 align:middle line:90%
That rule never works.

01:23:11.850 --> 01:23:13.200 align:middle line:90%
OK.

01:23:13.200 --> 01:23:17.940 align:middle line:84%
Set AVL tree on receivers,
and each one of those nodes

01:23:17.940 --> 01:23:23.010 align:middle line:84%
with each one of those
receivers, I'm going to store--

01:23:23.010 --> 01:23:32.250 align:middle line:84%
for each, store a
set AVL on games.

01:23:32.250 --> 01:23:36.330 align:middle line:90%


01:23:36.330 --> 01:23:38.460 align:middle line:84%
Why do I store a
set AVL on games?

01:23:38.460 --> 01:23:42.480 align:middle line:84%
Why don't I just store a
list of all of the games?

01:23:42.480 --> 01:23:45.360 align:middle line:84%
Because if I want to remove
this game from a receiver,

01:23:45.360 --> 01:23:47.250 align:middle line:90%
I need to do that in log n time.

01:23:47.250 --> 01:23:51.520 align:middle line:84%
And here, what we're saying is
that n is the number of games,

01:23:51.520 --> 01:23:54.000 align:middle line:84%
but that the number of
receivers on the team

01:23:54.000 --> 01:23:56.760 align:middle line:84%
is always less than
the number of games.

01:23:56.760 --> 01:24:02.040 align:middle line:84%
If I search in this AVL tree
and I search in its AVL tree,

01:24:02.040 --> 01:24:07.050 align:middle line:84%
I can be assured that those two
searches was only log n time.

01:24:07.050 --> 01:24:08.840 align:middle line:84%
Because I need to
remove game, right?

01:24:08.840 --> 01:24:11.710 align:middle line:90%
So there you go.

01:24:11.710 --> 01:24:13.290 align:middle line:90%
Then what am I doing?

01:24:13.290 --> 01:24:15.550 align:middle line:84%
I'm returning the kth
highest performance.

01:24:15.550 --> 01:24:21.100 align:middle line:84%
Well, I need-- with each one
of these guys, I also store--

01:24:21.100 --> 01:24:22.630 align:middle line:90%
what was this augmentation?

01:24:22.630 --> 01:24:28.030 align:middle line:84%
The sum of the points
stored in these games.

01:24:28.030 --> 01:24:32.755 align:middle line:90%
Sum of points and--

01:24:32.755 --> 01:24:35.350 align:middle line:90%


01:24:35.350 --> 01:24:40.000 align:middle line:90%
what was it-- number games.

01:24:40.000 --> 01:24:43.130 align:middle line:84%
Because if I store both of
those things in constant time,

01:24:43.130 --> 01:24:46.450 align:middle line:84%
I'm going to be able to
compute their performance,

01:24:46.450 --> 01:24:49.000 align:middle line:84%
where I'm going to be
able to have the data

01:24:49.000 --> 01:24:51.290 align:middle line:90%
I need to compare performances.

01:24:51.290 --> 01:24:52.600 align:middle line:90%
AUDIENCE: [INAUDIBLE]?

01:24:52.600 --> 01:24:53.530 align:middle line:90%
JASON KU: Yeah, it is.

01:24:53.530 --> 01:24:54.970 align:middle line:90%
Just numbers.

01:24:54.970 --> 01:24:56.090 align:middle line:90%
These are data structures.

01:24:56.090 --> 01:24:56.970 align:middle line:90%
This is a data structure.

01:24:56.970 --> 01:24:57.928 align:middle line:90%
These are just numbers.

01:24:57.928 --> 01:25:00.400 align:middle line:90%


01:25:00.400 --> 01:25:02.190 align:middle line:84%
And I'm storing that
with each receiver.

01:25:02.190 --> 01:25:05.110 align:middle line:90%


01:25:05.110 --> 01:25:08.860 align:middle line:84%
But that's not going to help
me find the kth highest player.

01:25:08.860 --> 01:25:13.580 align:middle line:84%
None of these things are
sorted by performance.

01:25:13.580 --> 01:25:15.635 align:middle line:90%
So I need a last data structure.

01:25:15.635 --> 01:25:22.760 align:middle line:90%


01:25:22.760 --> 01:25:31.130 align:middle line:84%
Five, I need to store
something dynamically sorted

01:25:31.130 --> 01:25:32.970 align:middle line:90%
by performance.

01:25:32.970 --> 01:25:33.720 align:middle line:90%
AUDIENCE: Set AVL?

01:25:33.720 --> 01:25:35.810 align:middle line:90%
JASON KU: Set AVL, yeah.

01:25:35.810 --> 01:25:50.940 align:middle line:84%
Set AVL storing receivers
keyed on performance.

01:25:50.940 --> 01:25:55.580 align:middle line:84%
Now, when I say
keyed on performance,

01:25:55.580 --> 01:25:57.200 align:middle line:84%
you want to mention
something about

01:25:57.200 --> 01:25:58.910 align:middle line:90%
the cross-pot multiplication.

01:25:58.910 --> 01:26:01.220 align:middle line:84%
Like, I'm storing, with
each one of these things,

01:26:01.220 --> 01:26:04.070 align:middle line:84%
this augmentation, and when
I'm comparing two things,

01:26:04.070 --> 01:26:05.900 align:middle line:90%
I'm using cross-multiplication.

01:26:05.900 --> 01:26:08.840 align:middle line:84%
But other than that, then we
can abstract it away, right?

01:26:08.840 --> 01:26:10.700 align:middle line:84%
We've abstracted
that function call.

01:26:10.700 --> 01:26:13.700 align:middle line:84%
And I can imagine
comparing two keys.

01:26:13.700 --> 01:26:14.992 align:middle line:90%
I can do this.

01:26:14.992 --> 01:26:15.950 align:middle line:90%
This is a theory thing.

01:26:15.950 --> 01:26:18.200 align:middle line:84%
I'm not asking you
to implement that.

01:26:18.200 --> 01:26:22.280 align:middle line:84%
But that's sufficient for me,
as a reader of your solution,

01:26:22.280 --> 01:26:26.810 align:middle line:84%
to be able to say, yeah, you
know what you're talking about.

01:26:26.810 --> 01:26:28.100 align:middle line:90%
All right.

01:26:28.100 --> 01:26:30.050 align:middle line:90%
How do I connect these things?

01:26:30.050 --> 01:26:32.480 align:middle line:84%
The thing is, I'm
going to need to be--

01:26:32.480 --> 01:26:38.800 align:middle line:84%
I need to update these things
when I insert or remove a game.

01:26:38.800 --> 01:26:41.360 align:middle line:90%


01:26:41.360 --> 01:26:47.600 align:middle line:84%
So how do I know where are these
receivers are in this thing?

01:26:47.600 --> 01:26:50.690 align:middle line:84%
I store a pointer into
this data structure, right?

01:26:50.690 --> 01:26:57.710 align:middle line:84%
So up here, I store
a pointer to where

01:26:57.710 --> 01:26:59.570 align:middle line:90%
it is in the data structure.

01:26:59.570 --> 01:27:01.280 align:middle line:84%
Again, I'm storing
all of the receivers.

01:27:01.280 --> 01:27:04.070 align:middle line:84%
This has the same size
as the number 1 data

01:27:04.070 --> 01:27:06.530 align:middle line:84%
structure up there-- has the
same number of receivers.

01:27:06.530 --> 01:27:09.590 align:middle line:90%


01:27:09.590 --> 01:27:13.220 align:middle line:84%
But we're not quite done
yet, because I'm not

01:27:13.220 --> 01:27:21.350 align:middle line:84%
wanting to know who has
the best performance.

01:27:21.350 --> 01:27:25.170 align:middle line:84%
I want to know who has
the kth best performance.

01:27:25.170 --> 01:27:27.410 align:middle line:90%
Ugh.

01:27:27.410 --> 01:27:30.450 align:middle line:84%
How do I find the kth
best thing in this tree?

01:27:30.450 --> 01:27:31.220 align:middle line:90%
I've got a tree.

01:27:31.220 --> 01:27:34.070 align:middle line:90%


01:27:34.070 --> 01:27:35.030 align:middle line:90%
Set AVL tree.

01:27:35.030 --> 01:27:37.130 align:middle line:90%
It's mapped on performance.

01:27:37.130 --> 01:27:38.990 align:middle line:90%
I know where the last one is.

01:27:38.990 --> 01:27:41.390 align:middle line:84%
But if I want to find
the kth one from the end,

01:27:41.390 --> 01:27:44.360 align:middle line:90%
how do I do that?

01:27:44.360 --> 01:27:45.890 align:middle line:90%
It's an AVL tree--

01:27:45.890 --> 01:27:47.300 align:middle line:90%
a set AVL tree.

01:27:47.300 --> 01:27:50.070 align:middle line:90%
All I'm storing is heights.

01:27:50.070 --> 01:27:54.690 align:middle line:84%
Is there an operation
that you've thought about?

01:27:54.690 --> 01:27:58.790 align:middle line:84%
AUDIENCE: [INAUDIBLE] you're
not storing the size of each.

01:27:58.790 --> 01:28:00.770 align:middle line:84%
JASON KU: A set AVL
tree, by default,

01:28:00.770 --> 01:28:02.300 align:middle line:90%
does not store sizes, right?

01:28:02.300 --> 01:28:04.220 align:middle line:90%
That's what a sequence does.

01:28:04.220 --> 01:28:08.370 align:middle line:84%
But you think maybe that would
be helpful in this situation?

01:28:08.370 --> 01:28:08.870 align:middle line:90%
Yeah.

01:28:08.870 --> 01:28:12.500 align:middle line:84%
So, actually, if I decided
to augment by sizes also,

01:28:12.500 --> 01:28:17.240 align:middle line:84%
I could do the exact same kind
of sequence find_at operation,

01:28:17.240 --> 01:28:22.670 align:middle line:84%
and I could be able to look
up the n minus kth item

01:28:22.670 --> 01:28:28.190 align:middle line:84%
in here using the exact same
function for subtree at that I

01:28:28.190 --> 01:28:32.000 align:middle line:84%
had in the sequence
AVL tree stuff.

01:28:32.000 --> 01:28:33.920 align:middle line:84%
Actually, in CLRS,
they don't even

01:28:33.920 --> 01:28:35.930 align:middle line:90%
bother with sequence AVL trees.

01:28:35.930 --> 01:28:39.710 align:middle line:84%
They go straight to, if I wanted
this rank-find functionality

01:28:39.710 --> 01:28:44.180 align:middle line:84%
on a sorted order
of things, then

01:28:44.180 --> 01:28:47.330 align:middle line:84%
I could augment
the subtree sizes.

01:28:47.330 --> 01:28:51.320 align:middle line:84%
But it's actually a much
more useful general property,

01:28:51.320 --> 01:28:54.500 align:middle line:84%
so we decided to present it to
you in the context of sequence

01:28:54.500 --> 01:28:56.780 align:middle line:84%
AVL trees, because then I
can just basically reduce

01:28:56.780 --> 01:28:58.520 align:middle line:90%
to it when I get to here.

01:28:58.520 --> 01:29:01.130 align:middle line:84%
So that's kind of a
structure of a data structure

01:29:01.130 --> 01:29:02.420 align:middle line:90%
that work on this problem.

01:29:02.420 --> 01:29:04.820 align:middle line:84%
I leave it to you as an
exercise to implement

01:29:04.820 --> 01:29:06.920 align:middle line:84%
all of these operations
for yourself,

01:29:06.920 --> 01:29:08.790 align:middle line:90%
or take a look at the solutions.

01:29:08.790 --> 01:29:13.460 align:middle line:84%
The last one is going
to be put online--

01:29:13.460 --> 01:29:15.140 align:middle line:90%
the solution.

01:29:15.140 --> 01:29:16.500 align:middle line:90%
It's pretty complicated.

01:29:16.500 --> 01:29:19.490 align:middle line:84%
It's what's called-- you can
think of the size augmentation

01:29:19.490 --> 01:29:22.370 align:middle line:84%
finding-rank as a
one-sided range query.

01:29:22.370 --> 01:29:27.410 align:middle line:84%
It's basically, how many things
are to the right of this value?

01:29:27.410 --> 01:29:29.780 align:middle line:84%
What the last problem
does is walks you

01:29:29.780 --> 01:29:32.330 align:middle line:84%
through a two-sided
range query, where

01:29:32.330 --> 01:29:37.070 align:middle line:84%
I want to know how many nodes
are between these two values.

01:29:37.070 --> 01:29:39.150 align:middle line:90%
So it's a walkthrough.

01:29:39.150 --> 01:29:39.650 align:middle line:90%
All right.

01:29:39.650 --> 01:29:40.550 align:middle line:90%
Thanks, guys.

01:29:40.550 --> 01:29:42.100 align:middle line:90%
AUDIENCE: Thank you.

01:29:42.100 --> 01:29:47.000 align:middle line:90%