26 terms

A program consists of an O(n) loop followed by another O(n) loop. What is the Big O of the program?

A: O(n) + O(n)

B: 2 O(n)

C: O(2 n)

D: O(n)

E: O(n2)

A: O(n) + O(n)

B: 2 O(n)

C: O(2 n)

D: O(n)

E: O(n2)

Answer: D

If there is a section of sequential code:

{ s1;

s2;

...

}

the Big O is the max of the Big O of the statements.

Constants are not included in Big O, which means answers A, B, C should be reduced to O(n).

If there is a section of sequential code:

{ s1;

s2;

...

}

the Big O is the max of the Big O of the statements.

Constants are not included in Big O, which means answers A, B, C should be reduced to O(n).

What is log(student wealth) / log(Bill Gates wealth) ?

A: 1/1000

B: 1/10

C: 1/5

D: 1/3

E: 1/2

A: 1/1000

B: 1/10

C: 1/5

D: 1/3

E: 1/2

Answer: D

A good way to approach this question is to take the log2, i.e. find the number of bits required to represent the number.

We use our rule that 1000 ≅ 10 bits.

Assume that a student has $8,000 and Bill Gates has $50,000,000,000. Representing student wealth requires 13 bits: 10 bits for 1,000 and 3 bits for 8 (23 = 8). Representing Bill Gates' wealth requires 36 bits: 3 * 10 bits for 1,000,000,000 and 6 bits for 50 (26 = 64).

Thus, in terms of log2, a student has a bit more than 1/3 of what Bill Gates has.

It is also easy to do this problem by counting digits in decimal: $8,000 is 4 digits, while $50,000,000,000 is 11 digits. 4 is a bit more than 1/3 of 11.

The lesson: log grows very slowly.

A good way to approach this question is to take the log2, i.e. find the number of bits required to represent the number.

We use our rule that 1000 ≅ 10 bits.

Assume that a student has $8,000 and Bill Gates has $50,000,000,000. Representing student wealth requires 13 bits: 10 bits for 1,000 and 3 bits for 8 (23 = 8). Representing Bill Gates' wealth requires 36 bits: 3 * 10 bits for 1,000,000,000 and 6 bits for 50 (26 = 64).

Thus, in terms of log2, a student has a bit more than 1/3 of what Bill Gates has.

It is also easy to do this problem by counting digits in decimal: $8,000 is 4 digits, while $50,000,000,000 is 11 digits. 4 is a bit more than 1/3 of 11.

The lesson: log grows very slowly.

How many bits are there in a word on your computer?

A: 8

B: 16

C: 32 / 64

D: thousands

E: millions

A: 8

B: 16

C: 32 / 64

D: thousands

E: millions

C

For over 20 years, most of the world's computers have used a 32-bit word, particularly in the Intel IA-32 architecture.

The word size is important, because it is:

the width of the communication path between the memory and CPU

the number of bits that the CPU does an operation on at one time

32 bits is also enshrined as the size of int and Integer in Java.

The Intel Core i5 and similar processors have a 64-bit word, but also have a 32-bit compatibility mode; even if you have one of these more modern processors, it is likely that much of what you do is running in 32-bit mode.

For over 20 years, most of the world's computers have used a 32-bit word, particularly in the Intel IA-32 architecture.

The word size is important, because it is:

the width of the communication path between the memory and CPU

the number of bits that the CPU does an operation on at one time

32 bits is also enshrined as the size of int and Integer in Java.

The Intel Core i5 and similar processors have a 64-bit word, but also have a 32-bit compatibility mode; even if you have one of these more modern processors, it is likely that much of what you do is running in 32-bit mode.

Can the national debt (in dollars) be represented in an int or an Integer?

A: neither

B: int

C: Integer

D: both

E: WTF

A: neither

B: int

C: Integer

D: both

E: WTF

A

The national debt is over $15,000,000,000,000.

We use our rule that 1000 ≅ 10 bits.

The national debt requires 44 bits: 4 * 10 bits for 1,000,000,000,000 and 4 bits for 15 (24 = 16).

Both int and Integer are 32 bits, which can represent ± 2,147,483,647, not even close to the national debt.

The national debt is over $15,000,000,000,000.

We use our rule that 1000 ≅ 10 bits.

The national debt requires 44 bits: 4 * 10 bits for 1,000,000,000,000 and 4 bits for 15 (24 = 16).

Both int and Integer are 32 bits, which can represent ± 2,147,483,647, not even close to the national debt.

When a program's time is plotted on log-log paper, the curve is not a straight line, but curves upward. The program is probably:

A: O(n)

B: O(n log n)

C: O(n2)

D: O(n3)

E: O(2n)

A: O(n)

B: O(n log n)

C: O(n2)

D: O(n3)

E: O(2n)

Answer: E

Polynomial-time programs (those whose Big O is O(nk) for some constant k) will plot as straight lines on log-log paper. A factor of log n will probably not be noticeable.

If a program's time curves upward on a log-log plot, it is probably intractable, exponential, NP-complete, O(2n), and very bad news: unless your problem is very small, you will not be able to solve it with any amount of computers.

However, some important NP-complete problems have polynomial-time approximate solutions that are pretty good.

Polynomial-time programs (those whose Big O is O(nk) for some constant k) will plot as straight lines on log-log paper. A factor of log n will probably not be noticeable.

If a program's time curves upward on a log-log plot, it is probably intractable, exponential, NP-complete, O(2n), and very bad news: unless your problem is very small, you will not be able to solve it with any amount of computers.

However, some important NP-complete problems have polynomial-time approximate solutions that are pretty good.

When the size of a program's input is increased by 2, the runtime increases by 8. The program is:

A: O(n)

B: O(n log n)

C: O(n2)

D: O(n3)

E: O(2n)

A: O(n)

B: O(n log n)

C: O(n2)

D: O(n3)

E: O(2n)

Answer: D

When the input size increases by 2 and the time increases by x, the Big O is O(nk) where x = 2k. In this case, 8 = 23, so the program is O(n3).

When the input size increases by 2 and the time increases by x, the Big O is O(nk) where x = 2k. In this case, 8 = 23, so the program is O(n3).

Integer costs 4 times as much storage as int (16 bytes for an Integer, 4 bytes for an int).

What benefit does Integer provide?

A: More accuracy

B: Useful methods

C: Can use e.g. with ArrayList

D: All of the above

E: B and C only

What benefit does Integer provide?

A: More accuracy

B: Useful methods

C: Can use e.g. with ArrayList

D: All of the above

E: B and C only

Answer: E

int and Integer have exactly the same accuracy, 32 bits.

Integer is the same as int, except that Integer comes in a really nice box. The box is so nice that it costs 3 times as much as the product inside.

If we want to use a parameterized Java container such as ArrayList, we must use Integer: only a reference type can be used as a type parameter.

Integer also has useful methods. Only a reference type can have methods.

int is a low-cost, bare-bones integer, which is useful for local variables within the program and cases where there is a large array and we want to save storage. ``

int and Integer have exactly the same accuracy, 32 bits.

Integer is the same as int, except that Integer comes in a really nice box. The box is so nice that it costs 3 times as much as the product inside.

If we want to use a parameterized Java container such as ArrayList, we must use Integer: only a reference type can be used as a type parameter.

Integer also has useful methods. Only a reference type can have methods.

int is a low-cost, bare-bones integer, which is useful for local variables within the program and cases where there is a large array and we want to save storage. ``

An Integer is immutable (its value cannot be changed).

Suppose we do:

Integer i = 3;

Integer j = i;

i++;

System.out.println("i = " + i + ", j = " + j);

What values are printed?

A: i = 4, j = 4

B: i = 4, j = 3

C: i = 3, j = 4

D: i = 3, j = 3

E: error

Suppose we do:

Integer i = 3;

Integer j = i;

i++;

System.out.println("i = " + i + ", j = " + j);

What values are printed?

A: i = 4, j = 4

B: i = 4, j = 3

C: i = 3, j = 4

D: i = 3, j = 3

E: error

Answer: B

Since Integer is an immutable reference type, it is stored in a box containing a value that is unchanged after the box has been created.

The variables i and j do not contain the numeric values, but contain pointers to boxes that contain the values. Initially, i and j point to the same box, containing 3.

What can Java do in response to i++? It cannot change the 3 value inside the box, since it is immutable. Instead, Java must find or make a new box containing the value 4. After the statement i++, i points to this new box, while j still points to the old box containing 3.

Java caches boxes for small integers so that it does not have to make a new box every time.

Since Integer is an immutable reference type, it is stored in a box containing a value that is unchanged after the box has been created.

The variables i and j do not contain the numeric values, but contain pointers to boxes that contain the values. Initially, i and j point to the same box, containing 3.

What can Java do in response to i++? It cannot change the 3 value inside the box, since it is immutable. Instead, Java must find or make a new box containing the value 4. After the statement i++, i points to this new box, while j still points to the old box containing 3.

Java caches boxes for small integers so that it does not have to make a new box every time.

Suppose we have an array myarray of length n, and we say:

int n = myarray.length;

What is the Big O of this statement?

A: O(1)

B: O(n)

C: O(n log n)

D: O(n2)

E: depends on the item type of myarray

int n = myarray.length;

What is the Big O of this statement?

A: O(1)

B: O(n)

C: O(n log n)

D: O(n2)

E: depends on the item type of myarray

Answer: A

An Array is a reference type, which contains its .length as a stored value. We can tell that .length is a stored value rather than a method because it has no parentheses after it.

Rule: any stored .field of a reference type can be accessed in O(1) time.

An Array is a reference type, which contains its .length as a stored value. We can tell that .length is a stored value rather than a method because it has no parentheses after it.

Rule: any stored .field of a reference type can be accessed in O(1) time.

Suppose that we say:

int [] myarray = new int[1000];

About how many bytes are used by (a) the variable myarray, and (b) what it points to?

A: 1000 and 1000

B: 4000 and 4000

C: 8 and 1000

D: 8 and 4000

E: 1000 and 4000

int [] myarray = new int[1000];

About how many bytes are used by (a) the variable myarray, and (b) what it points to?

A: 1000 and 1000

B: 4000 and 4000

C: 8 and 1000

D: 8 and 4000

E: 1000 and 4000

Answer: D

myarray is a reference variable, so it contains only a pointer to the actual value. Pointers are 8 bytes on a more modern machine.

Each int is 4 bytes; since there are 1000 of them, the total is 4000 bytes. There is some additional storage in the array for storing the Array class designation, .length, and hash code; this is small compared to the bulk of the array.

myarray is a reference variable, so it contains only a pointer to the actual value. Pointers are 8 bytes on a more modern machine.

Each int is 4 bytes; since there are 1000 of them, the total is 4000 bytes. There is some additional storage in the array for storing the Array class designation, .length, and hash code; this is small compared to the bulk of the array.

Integer [] myarray = new Integer[1000];

for (int i = 0; i < 1000; i++)

myarray[i] = new Integer(i);

About how many bytes are used by (a) the variable myarray, (b) what it points to, and (c) the total storage allocated by this code?

A: 8000, 8000 and 16000

B: 8, 8000 and 24000

C: 8, 8000 and 16000

D: 1000, 8000 and 9000

E: 1000, 8000 and 25000

for (int i = 0; i < 1000; i++)

myarray[i] = new Integer(i);

About how many bytes are used by (a) the variable myarray, (b) what it points to, and (c) the total storage allocated by this code?

A: 8000, 8000 and 16000

B: 8, 8000 and 24000

C: 8, 8000 and 16000

D: 1000, 8000 and 9000

E: 1000, 8000 and 25000

Answer: B

The variable myarray is a reference variable, so it has the pointer size, 8 bytes.

The array is an array of pointers, so it is about 8000 bytes.

The pointers point to individual Integer objects, each of size 16 bytes, so these occupy 16000 bytes.

The variable myarray is a reference variable, so it has the pointer size, 8 bytes.

The array is an array of pointers, so it is about 8000 bytes.

The pointers point to individual Integer objects, each of size 16 bytes, so these occupy 16000 bytes.

Suppose that we say:

double three = 3.0;

double point3 = 0.3;

What can we say about the stored values?

A: Both values are represented exactly.

B: Both values are represented approximately.

C: three is exact, point3 is approximate.

D: three is approximate, point3 is exact.

E: Depends on which CPU chip is used.

double three = 3.0;

double point3 = 0.3;

What can we say about the stored values?

A: Both values are represented exactly.

B: Both values are represented approximately.

C: three is exact, point3 is approximate.

D: three is approximate, point3 is exact.

E: Depends on which CPU chip is used.

Answer: C

Integers are represented exactly in floating point, up to the limits of the mantissa accuracy (about 15 digits for double).

Decimal fractions usually cannot be represented exactly in binary. Just as 1/3 = .3333333... in decimal, 1/10 is an infinitely repeating pattern in binary. Therefore, any floating-point number with nonzero digits after the decimal is probably represented as an approximation in binary.

Floating point representation is governed by an IEEE Standard, which all CPU chips follow. Therefore, the representation of a floating-point value will be the same no matter which CPU chip is used.

Integers are represented exactly in floating point, up to the limits of the mantissa accuracy (about 15 digits for double).

Decimal fractions usually cannot be represented exactly in binary. Just as 1/3 = .3333333... in decimal, 1/10 is an infinitely repeating pattern in binary. Therefore, any floating-point number with nonzero digits after the decimal is probably represented as an approximation in binary.

Floating point representation is governed by an IEEE Standard, which all CPU chips follow. Therefore, the representation of a floating-point value will be the same no matter which CPU chip is used.

What is (cons '(a) '(b)) ?

A: (a b)

B: ((a) (b))

C: ((a) b)

D: ((a b))

E: error

A: (a b)

B: ((a) (b))

C: ((a) b)

D: ((a b))

E: error

Answer: C

cons adds one new item to the front of a linked list: (cons 'a '(b c)) = (a b c).

In this case, the new item is a sublist, (a).

Rule: In (cons '(a) '(b)), that is (cons first rest), move the left paren of the rest argument to the left of the first argument; that is the answer.

cons adds one new item to the front of a linked list: (cons 'a '(b c)) = (a b c).

In this case, the new item is a sublist, (a).

Rule: In (cons '(a) '(b)), that is (cons first rest), move the left paren of the rest argument to the left of the first argument; that is the answer.

What is (first '((a b) (c d))) ?

A: a

B: (a b)

C: ((a b))

D: null

E: error

A: a

B: (a b)

C: ((a b))

D: null

E: error

Answer: B

first returns the first thing in a list; a "thing" is a simple item, such as a symbol (string) or number, or a balanced pair of parentheses including everything inside, no matter how big.

first returns the first thing in a list; a "thing" is a simple item, such as a symbol (string) or number, or a balanced pair of parentheses including everything inside, no matter how big.

What is (rest '((a b) (c d))) ?

A: ((b) (c d))

B: (c d)

C: (b (c d))

D: ((c d))

E: null

A: ((b) (c d))

B: (c d)

C: (b (c d))

D: ((c d))

E: null

Answer: D

rest returns the rest of a list after the first thing.

In the parenthesized notation, move the opening parenthesis to the right past the first thing; that is the answer. Moving the opening paren past (a b) leaves ((c d)).

rest returns the rest of a list after the first thing.

In the parenthesized notation, move the opening parenthesis to the right past the first thing; that is the answer. Moving the opening paren past (a b) leaves ((c d)).

What is (rest (rest '((a b) (c d)))) ?

A: (() (c d))

B: (c d)

C: ((c d))

D: null

E: error

A: (() (c d))

B: (c d)

C: ((c d))

D: null

E: error

Answer: D

(rest (rest ... )) moves the opening paren to the right past 2 things; in this case, that leaves () or null.

(rest (rest ... )) moves the opening paren to the right past 2 things; in this case, that leaves () or null.

What is (length '((a b) (c d)) ) ?

A: 1

B: 2

C: 3

D: 4

E: 5

A: 1

B: 2

C: 3

D: 4

E: 5

Answer: B

length returns the length of a list at top level; this is a list of 2 things, (a b) and (c d), so the length is 2.

length returns the length of a list at top level; this is a list of 2 things, (a b) and (c d), so the length is 2.

What is (reverse '((a b) (c d)) ) ?

A: ((b a) (d c))

B: ((b a) (c d))

C: ((c d) (a b))

D: ((d c) (b a))

E: ((a b) (c d))

A: ((b a) (d c))

B: ((b a) (c d))

C: ((c d) (a b))

D: ((d c) (b a))

E: ((a b) (c d))

Answer: C

reverse reverses the top level of a list, leaving the insides of elements unchanged.

reverse reverses the top level of a list, leaving the insides of elements unchanged.

Suppose that we say:

Cons lst = null;

for (int i = 0; i < 3; i++ )

lst = cons( i, lst );

What is the value of lst?

A: (1 2 3)

B: (3 2 1)

C: (0 1 2)

D: (2 1 0)

E: (((2) 1) 0)

Cons lst = null;

for (int i = 0; i < 3; i++ )

lst = cons( i, lst );

What is the value of lst?

A: (1 2 3)

B: (3 2 1)

C: (0 1 2)

D: (2 1 0)

E: (((2) 1) 0)

Answer: D

cons puts one new item onto the front of an existing linked list.

Because of this, it builds a list in backwards order compared to the order of insertion.

As the loop proceeds, the value of lst is:

() initially

(0)

(1 0)

(2 1 0)

cons puts one new item onto the front of an existing linked list.

Because of this, it builds a list in backwards order compared to the order of insertion.

As the loop proceeds, the value of lst is:

() initially

(0)

(1 0)

(2 1 0)

Suppose that we say:

Cons lst = null;

for (int i = 0; i < 3; i++ )

lst = cons( i, lst );

What is the runtime type of first(lst)?

A: int

B: Integer

C: null

D: Cons

E: Object

Cons lst = null;

for (int i = 0; i < 3; i++ )

lst = cons( i, lst );

What is the runtime type of first(lst)?

A: int

B: Integer

C: null

D: Cons

E: Object

Answer: B

The declared type of first(lst) is Object. When this code says cons(i, lst), the compiler coerces the int value i into the reference type Integer. Integer (a subtype of Object) is what first(lst) actually is at runtime.

The declared type of first(lst) is Object. When this code says cons(i, lst), the compiler coerces the int value i into the reference type Integer. Integer (a subtype of Object) is what first(lst) actually is at runtime.

What is (append '(a b) '(c d)) ?

A: ((a b) (c d))

B: (a b c d)

C: (a b (c d))

D: ((a b c d))

E: ((a b) c d)

A: ((a b) (c d))

B: (a b c d)

C: (a b (c d))

D: ((a b c d))

E: ((a b) c d)

Answer: B

append concatenates two lists at top level, making a single list that contains the elements of the two input lists.

append makes a copy of the first input list, and reuses the second input list.

append concatenates two lists at top level, making a single list that contains the elements of the two input lists.

append makes a copy of the first input list, and reuses the second input list.

Cons lst = append(x, y);

and that x has length n and y has length m.

What is the Big O of this statement?

A: O(n)

B: O(m)

C: O(n + m)

D: O(n) + O(m)

E: O(n2 + m2)

and that x has length n and y has length m.

What is the Big O of this statement?

A: O(n)

B: O(m)

C: O(n + m)

D: O(n) + O(m)

E: O(n2 + m2)

Answer: A

append makes a copy of the first input list, and reuses the second input list. Therefore, its Big O depends only on the size of the first input. The Big O is O(n) because the first input list is copied, one element at a time.

append makes a copy of the first input list, and reuses the second input list. Therefore, its Big O depends only on the size of the first input. The Big O is O(n) because the first input list is copied, one element at a time.

Suppose that we say:

Cons lst = list("a", "b", "c");

boolean test = ( lst == reverse(reverse(lst)) );

What is the value of test?

A: true

B: false

C: null

D: error

E: could be true or false

Cons lst = list("a", "b", "c");

boolean test = ( lst == reverse(reverse(lst)) );

What is the value of test?

A: true

B: false

C: null

D: error

E: could be true or false

Answer: B

reverse makes a backward copy of its input. What == does, for any reference types, is to compare equality of pointer values, i.e., do the two pointers reference the same numeric address in memory? Since reverse(reverse(lst)) is a backward copy of a backward copy, it resides at a different address than the original.

reverse makes a backward copy of its input. What == does, for any reference types, is to compare equality of pointer values, i.e., do the two pointers reference the same numeric address in memory? Since reverse(reverse(lst)) is a backward copy of a backward copy, it resides at a different address than the original.

Suppose that we say:

Cons lst = list( list("a", "b"), list("c", "d"));

boolean test = ( first(lst) ==

first(reverse(reverse(lst))) );

What is the value of test?

A: true

B: false

C: null

D: error

E: could be true or false

Cons lst = list( list("a", "b"), list("c", "d"));

boolean test = ( first(lst) ==

first(reverse(reverse(lst))) );

What is the value of test?

A: true

B: false

C: null

D: error

E: could be true or false

Answer: A

reverse operates at the top level of a list only, i.e. it makes a backward copy of the input list, but does not modify the objects that the list contains. reverse(reverse(lst)) is a backwards copy of a backwards copy, so it is a copy of the original in the original order. The first item of the copy is exactly the same item as in the original, so the pointers are equal in numeric value and are ==.

reverse operates at the top level of a list only, i.e. it makes a backward copy of the input list, but does not modify the objects that the list contains. reverse(reverse(lst)) is a backwards copy of a backwards copy, so it is a copy of the original in the original order. The first item of the copy is exactly the same item as in the original, so the pointers are equal in numeric value and are ==.

Suppose that we say:

Cons lst = null;

for (int i = 0; i < 3; i++ )

lst = append( list(i), lst );

What is the value of lst?

A: (1 2 3)

B: (3 2 1)

C: (0 1 2 3)

D: (0 1 2)

E: (2 1 0)

Cons lst = null;

for (int i = 0; i < 3; i++ )

lst = append( list(i), lst );

What is the value of lst?

A: (1 2 3)

B: (3 2 1)

C: (0 1 2 3)

D: (0 1 2)

E: (2 1 0)

Answer: E

This code is adding the item i to the front of the list (in a somewhat wasteful fashion: lst = cons( i, lst ) would do the same thing).

This code is adding the item i to the front of the list (in a somewhat wasteful fashion: lst = cons( i, lst ) would do the same thing).

Suppose that we say:

Cons lst = null;

for (int i = 0; i < n; i++ )

lst = append( list(i), lst );

What is the Big O of this code?

A: O(1)

B: O(n)

C: O(n log n)

D: O(n2)

E: error

Cons lst = null;

for (int i = 0; i < n; i++ )

lst = append( list(i), lst );

What is the Big O of this code?

A: O(1)

B: O(n)

C: O(n log n)

D: O(n2)

E: error

Answer: B

The Big O of append is the size of its first argument, always 1 in this case. Since it is in a loop up to n, the total Big O is O(n * 1) = O(n).

The Big O of append is the size of its first argument, always 1 in this case. Since it is in a loop up to n, the total Big O is O(n * 1) = O(n).