Array slicing and ranges in Ruby - Time & Space Complexity
When we use array slicing and ranges in Ruby, we want to know how the time it takes grows as the array gets bigger.
We ask: How does the work change when we slice bigger parts of the array?
Analyze the time complexity of the following code snippet.
arr = (1..1000).to_a
slice = arr[100..199]
This code creates an array of 1000 numbers and then slices out 100 elements from it using a range.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Copying elements from the original array to the new slice.
- How many times: Once for each element in the slice range.
When the slice size grows, the work grows in the same way because each element is copied once.
| Input Size (slice length) | Approx. Operations |
|---|---|
| 10 | 10 copies |
| 100 | 100 copies |
| 1000 | 1000 copies |
Pattern observation: The number of operations grows directly with the slice size.
Time Complexity: O(k)
This means the time grows linearly with the number of elements you slice out.
[X] Wrong: "Slicing an array is always a constant time operation."
[OK] Correct: Because Ruby creates a new array and copies each element in the slice, so the time depends on how many elements you take.
Understanding how slicing works helps you explain efficiency when working with parts of arrays, a common task in coding challenges and real projects.
"What if we used a single index instead of a range for slicing? How would the time complexity change?"
Practice
arr[1..3] do when arr = [10, 20, 30, 40, 50]?Solution
Step 1: Understand the range operator '..'
The range1..3includes both 1 and 3, so it covers indexes 1, 2, and 3.Step 2: Apply slicing to the array
Slicingarr[1..3]returns elements at indexes 1, 2, and 3, which are 20, 30, and 40.Final Answer:
Returns a new array with elements at indexes 1, 2, and 3 -> Option AQuick Check:
Range '..' includes end index = elements 20, 30, 40 [OK]
- Thinking '..' excludes the end index
- Confusing indexes with values
- Assuming slicing changes the original array
arr?Solution
Step 1: Identify the range operator for excluding end
In Ruby,...excludes the end index, so2...5means indexes 2, 3, and 4.Step 2: Check syntax correctness
Onlyarr[2...5]uses valid Ruby syntax for slicing excluding the end index.Final Answer:
arr[2...5] -> Option AQuick Check:
Use '...' to exclude end index in range [OK]
- Using '..' when exclusion is needed
- Using Python-style slicing syntax like ':'
- Using invalid range syntax like '2-5'
arr = [5, 10, 15, 20, 25] slice = arr[1...4] puts slice.inspect
Solution
Step 1: Understand the slicing range
The range1...4includes indexes 1, 2, and 3 but excludes 4.Step 2: Extract elements at these indexes
Elements at indexes 1, 2, 3 are 10, 15, and 20 respectively.Final Answer:
[10, 15, 20] -> Option CQuick Check:
Range '...' excludes end index = [10, 15, 20] [OK]
- Including element at index 4 mistakenly
- Confusing indexes with values
- Printing original array instead of slice
arr = [1, 2, 3, 4, 5] slice = arr[2..6] puts slice.inspect
Solution
Step 1: Check the range indexes against array size
The array has indexes 0 to 4. The range 2..6 goes beyond the last index.Step 2: Understand Ruby slicing behavior for out-of-bounds
Ruby returns elements from index 2 to the end (indexes 2, 3, 4) and ignores indexes beyond 4 without error.Final Answer:
Range end index 6 is out of bounds but Ruby returns elements up to the end of the array -> Option BQuick Check:
Ruby slices safely even if range exceeds array size [OK]
- Expecting runtime or syntax error
- Assuming slice will be empty
- Confusing Ruby with other languages that error here
arr = [2, 4, 6, 8, 10, 12], which expression returns a new array with every second element starting from index 1 up to index 5?Solution
Step 1: Slice array from index 1 to 5
arr[1..5]gives [4, 6, 8, 10, 12].Step 2: Select every second element starting from index 1 of the slice
Indexes inside the slice are 0 to 4. Selecting odd indexes (1, 3) gives elements 6 and 10.Step 3: Check options for correct syntax and output
arr[1..5].values_at(*arr[1..5].each_index.select(&:odd?)) usesvalues_atwith odd indexes on the slice correctly, returning [6, 10].Final Answer:
arr[1..5].values_at(*arr[1..5].each_index.select(&:odd?)) -> Option DQuick Check:
Use values_at with odd indexes on slice for every second element [OK]
- Confusing odd/even indexes inside the slice
- Using select without values_at returns elements, not indexes
- Using wrong range operator causing off-by-one errors
Ready to prove it?
Pass the test and this pattern moves unknown
