13: Introduction to Running Times
Announcements
Quiz on return Monday. Lists, Sets are fair game. No Maps on this quiz.
Homework 12
Questions / answers.
Project 6
Questions / answers.
What we’ve done
So far, we reviewed 121 material (including basic control flow, conditionals, expressions, statements, arrays, objects and classes, scope, and references).
We’ve introduced several foundational ADTs:
- lists
- sets
- maps
and covered their properties. We’ve also seen their implementations in the Java API.
We’ve seen their methods, and used them to iterate over, look up items within, and modify them.
And, guess what? For about 80% or more of the programs you’re likely to write out in the real world, this is what you need to know, at least in terms of standard data structures. Lists, sets, maps, will let you represent most problems generally, and if not, you can take 187 to learn how to define your own data structures.
There are actually two or three data types and associated implementations that 187 covers that we haven’t yet: stacks, queues, and priority queues. But they’re pretty straightforward (and we’ll get to them later this semester, the first two in more detail than the last).
What to do
So what’s left? Are we done for the semester? Of course not!
First, more practice. We’re getting you ready for 187, so there will be more programming assignments, that may start to feel more difficult in various ways. Not all of them will invoke new data structures concepts, but instead they’ll serve to give you more practice. We may also start removing some of the training wheels you’ve had so far (full sets of test cases, for example) so that you can start to get ready for the 187 experience. We’ll also do simplified versions of 187 assignments to give you a running start in that class.
Second, more exposure to other topics in computer science and informatics. This course is (or will be) a prerequisite for not just 187 but eventually for various others as well. Some of our lectures and assignments will focus on things like: working with files; simple interactions over the network (with web servers or the like); text processing and data analysis (search engine stuff); and so on.
Finally, we’re going to touch upon a few more core computer science concepts in detail. In particular, we’re going to continue our study of algorithms – how we do certain tasks – and start to develop language to describe how efficient different approaches to the same problem might be. We’ll continue to focus on “toy problems” here, things like sorting lists of numbers and searching simple graphs, but the algorithms we develop and the approaches we take will be useful to you later when tackling bigger problems. (Some of this you’ll see in later assignments, I hope.)
Thinking about efficiency
So to think about how “efficient” an algorithm, or a piece of code, is, we need a way to quantify how long it takes to run. Our rule of thumb is as follows. Things take either:
- a small, constant amount of time, which we’ll approximate as “about one unit,” or
- they take an amount of time dependent upon some variable or variables
To simplify things, we say that almost all operators and keywords evaluate in a small, constant amount of time in Java: basic arithmetic, conditionals, assignment, array access, control flow, and method invocation. So you might look at a method like:
int add(int x, int y) {
int sum = x + y;
return sum;
}
and say something like: well, when this method runs, first it adds x and y (1). Then it assigns to sum (1). Then it returns (1). So it takes “about” three units of time to execute.
OK, be that as it may, there’s something important to note here, which is that this method takes a small, fixed amount of time that doesn’t depend upon anything. Let’s look at something different:
int sum(int[] a) {
int s = 0;
for (int i: a) {
s += i;
}
return s;
}
How long does this method take to execute? Well, about one to declare and assign 0 to s.
Then about one to update i each time through the loop, and another to update s each time through the loop.
Then one for returning s.
So what’s the answer? It depends upon the length of the array, right? It depends upon the input in other words, it’s not a constant. Some parts of the runtime are (the initial setup and the return) are constant, but some are not (the loop). Here, we might say the runtime is about 2 + 2 * (a.length). In other words, the runtime here is a function (in the mathematical sense) of the length of a. It’s proportional t the length of a.
Generally, any time you see a loop, you have the possibility of a non-constant runtime, that is, of a runtime that’s a function of (some aspect of) the input.
Running time is usually a function of the input size. It might be constant, and not depend upon the input; it might also be linear (in what? in the length of an array, perhaps). Or, as we’ll see, it might quadratic (or indeed any polynomial) or sublinear (in particular, logarithmic). Usually but not always the giveaway for non-constant running time is a loop.
More after break!