---------------------------------------------------------
PART 1 – INHERITANCE
Question 2: True/False – Can a subclass access each item?
---------------------------------------------------------
a. public String aString;
TRUE.
Public members are accessible from anywhere, including subclasses
in other packages.
b. protected boolean aBoolean;
TRUE.
Protected members are accessible to subclasses regardless of
package, which is exactly what 'protected' is designed for.
c. int anInt; (package-private / default access)
IT DEPENDS – effectively TRUE only if the subclass is in the
same package as the superclass; FALSE if they are in different
packages. Default (package-private) access allows access within
the same package but not outside it.
d. private double aDouble;
FALSE.
Private members are accessible only within the class that declares
them. Subclasses cannot directly access private superclass fields;
they must use public/protected getter methods instead.
e. public String aMethod()
TRUE.
Public methods are accessible from any class, including subclasses.
A subclass can call, override, or inherit a public superclass method.
f. private class aNestedClass
FALSE.
A private nested class is accessible only within its enclosing
(outer) class. Subclasses cannot reference or instantiate it.
g. public aClassConstructor()
FALSE – not directly, and not in the usual sense.
Constructors are NOT inherited in Java. A subclass must define
its own constructor and may call the superclass constructor
explicitly with super(), but it cannot call it as if it were
an inherited method.
---------------------------------------------------------
PART 2 – SORTING & SEARCHING
Question 2: Big-O Complexity Table
---------------------------------------------------------
Algorithm Worst case Average Case Best Case
selection O(n^2) O(n^2) O(n^2)
bubble O(n^2) O(n^2) O(
merge O(n log n) O(n log n) O(n log n)
WHICH PERFORMS BEST ON AVERAGE?
Merge Sort performs best on average (and in all cases). Its
O(n log n) time complexity is asymptotically superior to the O(n^2)
of Selection and Bubble Sort, which means the performance gap widens
dramatically as n grows. For small n the difference is negligible,
but for large datasets Merge Sort is the clear winner among these
three.
---------------------------------------------------------
PART 2 – SORTING & SEARCHING
Question 3: Linear Search vs. Binary Search
---------------------------------------------------------
LINEAR (SEQUENTIAL) SEARCH
- Examines each element one by one from the beginning of the array.
- Works on both sorted AND unsorted arrays.
- Time complexity: O(n) in the worst and average case.
- Simple to implement; no pre-condition on the data.
- Example: searching for 42 in {7, 3, 42, 15, 8} → checks index 0,
1, 2 → found at index 2.
BINARY SEARCH
- Requires the array to be SORTED first.
- Repeatedly divides the search interval in half: compare the target
to the middle element; if smaller search the left half, if larger
search the right half, repeat until found or interval is empty.
- Time complexity: O(log n) in the worst and average case.
- Much faster than linear search for large sorted datasets (e.g.,
finding an element in 1,000,000 items takes at most ~20 comparisons
versus up to 1,000,000 for linear search).
- Example: searching for 42 in {3, 7, 8, 15, 42} → mid = 8 (too
small), right half → mid = 15 (too small), right half → 42 found.
KEY DIFFERENCE: Binary search is significantly more efficient but
requires sorted data; linear search is simpler and works on any array.
---------------------------------------------------------
PART 2 – SORTING & SEARCHING
Question 4: Sorting Order for Strings and Numbers
---------------------------------------------------------
NUMBERS
Numeric sorting compares the mathematical values of the elements.
e.g., 2 < 10 < 100
STRINGS
String sorting is determined by LEXICOGRAPHIC (dictionary) order,
which is based on the Unicode/ASCII value of each character, compared
left-to-right.
Rules:
1. Characters are compared position by position.
2. The character with the lower Unicode value is considered "smaller".
3. Uppercase letters (A–Z, codes 65–90) come BEFORE lowercase
letters (a–z, codes 97–122) in Unicode order.
4. Digits (0–9, codes 48–57) come before uppercase letters.
Examples:
"Apple" < "Banana" (A=65, B=66)
"apple" > "Banana" (a=97 > B=66 — lowercase > uppercase)
"10" < "9" (as Strings: '1'=49 < '9'=57, so "10" < "9")
MIXED DATA (Strings containing numbers)
When numbers are stored as Strings, they sort lexicographically,
NOT numerically. This means "10" sorts before "2" because '1' < '2'
as characters. To sort numerically, the Strings must be converted to
numeric types before comparison, or a custom comparing system must be used.
---------------------------------------------------------
PART 3 – RECURSION
Question 3: Trace factorial(7) using backwards thinking
---------------------------------------------------------
FORWARD CALL STACK (each call waits for the one below it):
Call 1: factorial(7) → waits for factorial(6)
Call 2: factorial(6) → waits for factorial(5)
Call 3: factorial(5) → waits for factorial(4)
Call 4: factorial(4) → waits for factorial(3)
Call 5: factorial(3) → waits for factorial(2)
Call 6: factorial(2) → waits for factorial(1)
Call 7: factorial(1) → BASE CASE: returns 1
BACKWARDS UNWINDING (return values bubble back up):
Step | Call | Returns
7 | factorial(1) | 1 (base case)
6 | factorial(2) | 2 * 1 = 2
5 | factorial(3) | 3 * 2 = 6
4 | factorial(4) | 4 * 6 = 24
3 | factorial(5) | 5 * 24 = 120
2 | factorial(6) | 6 * 120 = 720
1 | factorial(7) | 7 * 720 = 5040
RESULT: factorial(7) = 5040
BACKWARDS-THINKING EXPLANATION:
To find factorial(7) we need factorial(6).
To find factorial(6) we need factorial(5).
continuing until we reach the base case factorial(1) = 1.
Once the base case is known, each prior result can be computed:
factorial(2)=2, factorial(3)=6, , factorial(7)=5040.