Python lists store references to objects. Consequently, a list of integers does not have precisely the same memory representation as a low-level contiguous array of machine integers. For large numerical data, libraries such as NumPy provide specialized homogeneous arrays, although such libraries are outside the core language. 3.3 Resizing and amortized analysisSuppose a dynamic array has capacity For A programmer can often improve performance by reserving an appropriate initial capacity when the approximate data size is known: ArrayList<Integer> readings = new ArrayList<>(10_000); Capacity and logical size are different. Capacity describes allocated storage; size describes the number of elements currently present. 4. Strings and Text ProcessingA string is a sequence of characters or, more precisely in modern software, a sequence of encoded code units representing text. Text processing requires care because a visible character may occupy multiple code units in encodings such as UTF-8 or UTF-16. Java stringsJava String language = "Java"; String message = language + " is widely used."; int length = message.length(); char ch = message.charAt(0); String part = message.substring(0, 4); For repeated construction, use StringBuilder builder = new StringBuilder();
for (int i = 1; i <= 5; i++) {
builder.append(i).append(' ');
}
String result = builder.toString();Comparing strings should normally use Python stringsPython strings are immutable sequences. text = "data structures" print(text[0]) print(text[0:4]) words = text.split() result = "-".join(words) Repeated concatenation in a loop can create unnecessary intermediate strings. Building a list of pieces and using pieces = []
for number in range(1, 6):
pieces.append(str(number))
result = " ".join(pieces)String algorithmsA naive substring search checks a pattern at each possible starting position. If the text has length A palindrome test compares symmetric positions. It takes O(n) time and O(1) extra space when performed with two indices rather than constructing a reversed copy. def is_palindrome(text):
left, right = 0, len(text) - 1
while left < right:
if text[left] != text[right]:
return False
left += 1
right -= 1
return TrueThe definition of “palindrome” must be specified in real applications: case sensitivity, spaces, punctuation, accents, and Unicode normalization can all affect the result. 5. Multidimensional Arrays and MatricesA matrix is a rectangular arrangement of values with rows and columns. An Java rectangular arraysint[][] matrix = new int[3][4];
matrix[1][2] = 7;
for (int row = 0; row < matrix.length; row++) {
for (int column = 0; column < matrix[row].length; column++) {
System.out.print(matrix[row][column] + " ");
}
System.out.println();
}Java’s two-dimensional arrays are arrays of arrays. Rows may therefore have different lengths: int[][] jagged = {
{1, 2},
{3, 4, 5},
{6}
};This flexibility is useful but means that Python nested listsmatrix = [[0 for _ in range(4)] for _ in range(3)] matrix[1][2] = 7 The nested-list construction above is safe. The expression Matrix traversal takes O(rc) time because every one of the Matrix multiplicationFor matrices C[i][j] = ∑ from t = 0 to k − 1 A[i][t] × B[t][j] The standard algorithm performs 6. Sparse MatricesA sparse matrix contains mostly zero or default values. Storing every position wastes memory when only a small number of entries are nonzero. A coordinate representation stores triples such as For example, the matrix 0 0 5 0 0 0 7 0 0 can be represented as: (0, 2, 5) (2, 0, 7) A dictionary representation is convenient in Python: sparse = {(0, 2): 5, (2, 0): 7}
value = sparse.get((1, 1), 0)A Java implementation might use a map from a coordinate object to a numeric value. Sparse representations save space when the number of stored entries 7. Prefix SumsA prefix sum array supports efficient range-sum queries. Given values p[i + 1] = p[i] + a[i] The sum from index sum(l, r) = p[r + 1] − p[l] The indices must satisfy 0 ≤ Worked exampleFor p[4] − p[1] = 10 − 3 = 7 The method is particularly useful when many static range queries are required. If values change frequently, a simple prefix array must be rebuilt; other structures, such as a Fenwick tree, may then be more suitable. A two-dimensional prefix sum extends the same principle to rectangular regions. If P[i + 1][j + 1] = A[i][j] + P[i][j + 1] + P[i + 1][j] − P[i][j] The subtraction prevents the upper-left region from being counted twice. 8. Sliding WindowsA sliding window maintains a contiguous interval while moving through a sequence. It avoids recomputing information that overlaps between consecutive intervals. For a fixed window length newsum = oldsum − outgoing + incoming This produces O(n) time rather than O(nk) for recalculating every window independently. def maximum_window_sum(values, k):
if k <= 0 or k > len(values):
raise ValueError("Invalid window size")
current = sum(values[:k])
best = current
for right in range(k, len(values)):
current += values[right] - values[right - k]
best = max(best, current)
return bestFor variable-size windows, two boundaries move according to a condition. For example, when all values are nonnegative, the smallest subarray with sum at least 9. Two-Pointer TechniquesTwo pointers are indices that move through a sequence according to a structured rule. They are useful for sorted arrays, partitioning, palindrome checks, and pair-sum problems. Pair sum in a sorted arrayGiven a sorted array and target def has_pair_with_sum(values, target):
left, right = 0, len(values) - 1
while left < right:
total = values[left] + values[right]
if total == target:
return True
if total < target:
left += 1
else:
right -= 1
return FalseThis algorithm is O(n) after sorting. If the input is not sorted, sorting costs typically O(n log n), so the total complexity is usually O(n log n). A hash-set method can provide expected O(n) time without sorting, but uses additional storage and has different ordering implications. The correctness depends on sorted order. Without that property, moving a pointer based on the current sum does not safely eliminate candidates. 10. Applied Case: Sensor-Reading AnalysisBackgroundConsider an illustrative monitoring system that records hourly temperatures from a manufacturing line. The engineering team needs to answer three questions: the average temperature over selected intervals, whether any three-hour period exceeds a safety threshold, and whether two readings differ by a specified amount. Problem analysisThe readings are received in chronological order and are not frequently modified. Thousands of interval queries may be issued after collection. A simple loop for every interval would repeat work and could become slow. Approach and solution
For readings
The maximum is 65. A sliding window computes this in linear time after reading the data, rather than recomputing each sum from three values. Outcome and learning pointsThe selected structures match the workload: arrays provide efficient sequential access, prefix sums support repeated static range queries, and sliding windows exploit overlap. The case also demonstrates that the “best” structure depends on update frequency, ordering requirements, memory constraints, and the required queries—not merely on the data type. 11. Challenges, Limitations, and Best Practices
Modern runtimes optimize allocation and memory access, but these optimizations do not remove the need for sound representation choices. In data-intensive and AI-related systems, arrays often hold feature vectors, images, token identifiers, and model parameters. Correct indexing, predictable memory use, and validation are essential because an unnoticed off-by-one error can corrupt an entire computation. Chapter SummaryArrays provide constant-time indexed access through contiguous addressing, but insertion and deletion near the beginning are linear because elements must shift. Java arrays have fixed length. Java Strings are immutable in both Java and Python, which supports safe sharing but makes repeated modification costly unless builders or joining techniques are used. Multidimensional arrays represent matrices, while sparse representations save space when most entries are zero. Prefix sums convert repeated static range queries into constant-time queries after linear preprocessing. Sliding windows exploit overlap between contiguous intervals, and two-pointer methods exploit ordering or boundary structure. Effective data-structure selection depends on access patterns, update frequency, locality, memory, and algorithmic assumptions. Key TermsArray: A fixed-size indexed sequence of elements. Index: The integer position used to access an element. Contiguous storage: Adjacent memory locations used for sequential elements. Locality: The performance benefit of accessing nearby memory locations. Dynamic array: An array-like structure that grows when capacity is exhausted. Capacity: Allocated storage available in a dynamic array. Amortized analysis: Analysis of average cost over a sequence of operations.
Python list: A built-in dynamic array of object references. String: An immutable sequence used to represent text. Matrix: A rectangular arrangement of values indexed by rows and columns. Jagged array: An array whose rows may have different lengths. Sparse matrix: A matrix containing mostly zero or default entries. Prefix sum: A cumulative-sum structure supporting efficient range queries. Sliding window: A moving contiguous interval maintained during a scan. Two-pointer technique: An algorithm using two moving indices. Time complexity: The growth of computational work as input size increases. Space complexity: The growth of additional memory required by an algorithm. Review QuestionsShort Answer Questions
Long Answer Questions
Analytical / Application Questions
Multiple Choice Questions with AnswersQuestion 1Which operation is typically O(1) in a conventional array? A. Inserting at index 0 B. Deleting at index 0 C. Reading by index D. Searching an unsorted array Correct Answer: C. Reading by index Question 2What is the usual amortized complexity of appending to a geometrically growing dynamic array? A. O(1) B. O(log n) C. O(n) D. O(n log n) Correct Answer: A. O(1) Question 3Which Java structure has a fixed length after creation? A. ArrayList B. Array C. StringBuilder D. HashSet Correct Answer: B. Array Question 4For prefix sums p[0] = 0 and p[i + 1] = p[i] + a[i], what is the sum from l through r? A. p[r] − p[l] B. p[r + 1] − p[l] C. p[r] + p[l] D. p[l + 1] − p[r] Correct Answer: B. p[r + 1] − p[l] Question 5Which representation is most appropriate when a matrix is overwhelmingly zero? A. Dense two-dimensional array B. Coordinate or dictionary representation C. A string containing every value D. A sorted scalar variable Correct Answer: B. Coordinate or dictionary representation Question 6What is the standard time complexity of multiplying an r × k matrix by a k × c matrix? A. O(r + k + c) B. O(rc) C. O(rkc) D. O(log(rkc)) Correct Answer: C. O(rkc) Question 7Why is StringBuilder useful in Java? A. It makes arrays fixed-length B. It supports efficient repeated string construction C. It automatically sorts characters D. It converts strings into matrices Correct Answer: B. It supports efficient repeated string construction Question 8A fixed-size sliding-window sum updates by which operation? A. Multiply the old sum by the window size B. Subtract the outgoing value and add the incoming value C. Sort every window D. Rebuild the entire array necessarily Correct Answer: B. Subtract the outgoing value and add the incoming value Question 9The two-pointer pair-sum method described in the chapter requires which important property? A. The values must be strings B. The array must be sorted C. The array must contain only zeros D. The array must be two-dimensional Correct Answer: B. The array must be sorted Question 10What is the typical time complexity of traversing every entry of an r × c matrix? A. O(r + c) B. O(r − c) C. O(rc) D. O(1) Correct Answer: C. O(rc)
Data Structures and Algorithms in Java and Python
|
Chapter 4 of 15 |