Data Structures
Python List — Complete Beginner to Interview Guide
Learn Python lists from scratch: every method explained one by one with example code and output, plus interview patterns explained question-first, solution-second.
- Python
- List
- DSA
- Data Structures
- Algorithm
1. What is a List?
A list is one of the most commonly used data structures in Python.
In simple words:
- A list is a container that holds multiple items in a single variable.
- Think of it like a shopping list — you can add items, remove items, or check what’s on it.
- A list is ordered — the items stay in the order you put them in.
- A list is mutable — you can change it after creating it (add, remove, update items).
- A list can hold mixed data types — numbers, text, even other lists, all in the same list.
- Internally, Python stores a list as a dynamic array of pointers — it automatically grows in size as you add more items.
2. Creating a List (Every Way, One by One)
2.1 Creating an Empty List
2.2 Creating a List With Values
2.3 Creating a List Using list()
2.4 Creating a List by Repeating a Value
3. Accessing List Elements (Indexing)
Points to remember:
- Every item in a list has a position number called an index.
- Indexing starts from 0, not 1. The first item is at index
0. - You can also count from the end using negative numbers:
-1is the last item,-2is second-last, and so on. - If you use an index that doesn’t exist, Python raises an
IndexError.
4. List Slicing
Slicing means taking out a piece of the list instead of a single item.
Syntax: my_list[start : stop : step]
Points to remember:
startis where the slice begins (included).stopis where the slice ends (not included).stepis how many items to skip each time (default is 1).- All three parts are optional.
Beginner tip: Slicing never crashes your program even if the numbers are “out of range”:
5. Basic List Operations
5.1 Finding the Length — len()
5.2 Checking Membership — in and not in
5.3 Joining Two Lists — +
5.4 Repeating a List — *
6. Lists Are Mutable (You Can Change Them)
7. Every List Method — Explained One by One
Below is every built-in list method. Each one has its own explanation, syntax, and example with output.
7.1 append(x) — Add One Item to the End
Points:
- Adds a single item to the end of the list.
- Changes the list in place — it does not return a new list.
- Very fast — O(1) on average.
7.2 insert(index, x) — Add an Item at a Specific Position
Points:
- Inserts
xbefore the given index. - Every item after that index shifts one position to the right.
- Slower than
append()— O(n), because of the shifting.
7.3 extend(iterable) — Add Many Items at Once
Points:
- Adds every item from another list (or any iterable) to the end.
- Different from
append()—append()adds the whole thing as one item,extend()adds each item separately.
7.4 remove(x) — Remove the First Matching Value
Points:
- Removes the first item that equals
x. - If
xis not found, it raises aValueError. - It removes by value, not by index.
7.5 pop(index) — Remove and Return an Item
Points:
- Removes the item at the given index and returns it.
- If no index is given, it removes the last item — this is the fast, O(1) case.
- Popping from the front (
pop(0)) is slow — O(n) — because everything shifts left.
7.6 clear() — Remove Everything
7.7 index(x) — Find the Position of a Value
Points:
- Returns the index of the first occurrence of
x. - Raises a
ValueErrorifxisn’t in the list.
7.8 count(x) — Count How Many Times a Value Appears
7.9 sort() — Sort the List In Place
Points:
- Sorts the list in ascending order by default.
- Changes the original list — does not return a new one (returns
None). - Use
reverse=Trueto sort in descending order. - Use
key=to sort using a custom rule.
7.10 reverse() — Reverse the List In Place
7.11 copy() — Make a Shallow Copy
8. All Methods in One Table (Quick Reference)
| method | what it does | time complexity |
|---|---|---|
| append(x) | Add x to the end | O(1) average |
| insert(i, x) | Insert x before index i | O(n) |
| extend(iterable) | Add each item of iterable to the end | O(k) for k new items |
| remove(x) | Remove first item equal to x | O(n) |
| pop(i=-1) | Remove & return item at index i | O(1) at end, O(n) elsewhere |
| clear() | Remove all items | O(n) |
| index(x) | Find index of first x | O(n) |
| count(x) | Count occurrences of x | O(n) |
| sort() | Sort in place, ascending by default | O(n log n) |
| reverse() | Reverse in place | O(n) |
| copy() | Shallow copy | O(n) |
9. sort() vs sorted() and reverse() vs reversed()
Beginners mix these up all the time. Here is the difference, clearly:
| sort() | sorted() | |
|---|---|---|
| Changes original list? | Yes (in place) | No — returns a new list |
| Return value | None | A new list |
| Works on any iterable? | No — only lists | Yes — lists, tuples, strings, etc. |
10. Copying a List — Shallow Copy vs Deep Copy
Points to remember:
- Writing
b = adoes NOT copy the list — it just gives the same list a second name. - A shallow copy (
a.copy(),a[:], orlist(a)) makes a new outer list, but if it contains other lists inside, those inner lists are still shared. - A deep copy (
copy.deepcopy(a)) makes a completely independent copy, including everything nested inside.
11. Nested Lists (2D Lists) — A Common Beginner Trap
Points:
- A “2D list” is just a list of lists — often used to represent a grid or table.
[[0] * 3] * 4looks like it makes 4 independent rows, but it does not — it repeats the same inner list 4 times!- The correct way is to use a list comprehension, which creates a brand new inner list every time.
12. List Comprehensions (Basic → Medium → Advanced)
A list comprehension is a short, one-line way to build a list.
Basic syntax: [expression for item in iterable]
12.1 Basic
12.2 Medium — With a Condition
Syntax: [expression for item in iterable if condition]
12.3 Advanced — Nested Comprehension
12.4 Advanced — if / else Inside a Comprehension
13. Useful Built-in Functions That Work With Lists
13.1 enumerate() — Get Index and Value Together
13.2 zip() — Walk Through Two Lists Together
13.3 sum(), min(), max()
13.4 collections.Counter — Counting Items Fast
14. Using a List as a Stack or a Queue
Points:
- A stack follows Last-In-First-Out (LIFO) — the last item added is the first one removed.
- A queue follows First-In-First-Out (FIFO) — the first item added is the first one removed.
- A plain list makes a great stack (both
append()andpop()at the end are fast, O(1)). - A plain list makes a bad queue — removing from the front (
pop(0)) is slow, O(n). - For a queue, use
collections.dequeinstead.
15. Time Complexity Cheat Sheet
| operation | time complexity | why |
|---|---|---|
| a[i] (index access) | O(1) | Direct memory lookup |
| append(x) | O(1) average | Usually just adds to the end |
| pop() (from end) | O(1) | No shifting needed |
| pop(0) (from front) | O(n) | Every other item shifts left |
| insert(0, x) (at front) | O(n) | Every other item shifts right |
| x in a (search) | O(n) | Checks items one by one |
| len(a) | O(1) | Length is stored, not recounted |
| sort() | O(n log n) | Timsort algorithm |
| a[i:j] (slicing) | O(j - i) | Copies the sliced part |
16. Interview Patterns (Question First, Then Solution)
This section teaches you patterns that show up again and again in coding interviews. For each pattern, you will see:
- What the pattern is and when to use it.
- A real interview-style question.
- An example with input and expected output.
- A hint.
- The approach, explained in plain words.
- The final code, with output shown as comments.
- The time and space complexity.
16.1 Pattern: Two Pointers
What it is:
- Use two index variables (pointers) that move through the list — often from opposite ends, or one fast and one slow.
- Useful when you need to compare or swap items without using extra memory.
❓ Interview Question:
- Problem: Given a list of numbers, check whether it reads the same forwards and backwards (a palindrome).
- Example:
- Input:
[1, 2, 3, 2, 1] - Expected Output:
True - Input:
[1, 2, 3, 4] - Expected Output:
False
- Input:
- Hint: Compare the first and last item, then move inward. If they ever don’t match, it’s not a palindrome.
✅ Approach:
- Set
left = 0andright = len(list) - 1. - While
left < right: comparelist[left]andlist[right]. - If they don’t match, return
Falseimmediately. - Otherwise, move
leftforward by 1 andrightbackward by 1. - If the loop finishes without mismatches, return
True.
Complexity: Time = O(n), Space = O(1) — no extra list is created.
16.2 Pattern: Sliding Window
What it is:
- Keep a “window” (a range of items) and slide it across the list, one step at a time.
- Useful for problems about subarrays of a fixed or changing size.
- Much faster than recomputing everything from scratch at every step.
❓ Interview Question:
- Problem: Given a list of numbers and a window size
k, find the maximum sum of anykconsecutive numbers. - Example:
- Input:
nums = [2, 1, 5, 1, 3, 2],k = 3 - Expected Output:
9(from the subarray[5, 1, 3])
- Input:
- Hint: Don’t recompute the sum from scratch every time — just subtract the item leaving the window and add the item entering it.
✅ Approach:
- Calculate the sum of the first
kitems — this is the starting window. - Slide the window one step at a time: subtract the item that is leaving, add the item that is entering.
- Keep track of the biggest sum seen so far.
Complexity: Time = O(n) — a single pass. Space = O(1).
16.3 Pattern: Prefix Sum
What it is:
- Precompute the running total up to each index, one time.
- After that, any “sum between index A and B” question can be answered instantly, without looping again.
❓ Interview Question:
- Problem: You are given a list of numbers, and you will be asked the sum of a range
[left, right]many times. Answer each query as fast as possible. - Example:
- Input:
nums = [1, 2, 3, 4, 5], query: sum of index1to3 - Expected Output:
9(because2 + 3 + 4 = 9)
- Input:
- Hint: Build one extra list first, where each position stores the total sum “so far.”
✅ Approach:
- Build a
prefixlist whereprefix[i]= sum of all numbers before indexi. - To get the sum from
lefttoright, computeprefix[right + 1] - prefix[left]. - This turns every query into an O(1) lookup, after one O(n) setup step.
Complexity: Building the prefix list = O(n). Each query after that = O(1).
16.4 Pattern: Kadane’s Algorithm (Maximum Subarray Sum)
What it is:
- A classic technique to find the largest possible sum of any contiguous subarray.
- Works even when the list has negative numbers.
❓ Interview Question:
- Problem: Given a list of numbers (which can include negative numbers), find the maximum possible sum of a contiguous subarray.
- Example:
- Input:
[-2, 1, -3, 4, -1, 2, 1, -5, 4] - Expected Output:
6(from the subarray[4, -1, 2, 1])
- Input:
- Hint: At each position, decide: should I extend the previous subarray, or start a brand new one from here?
✅ Approach:
- Keep two values:
current_sum(best sum ending exactly at this position) andbest_sum(best sum seen anywhere so far). - At each number, decide: is it better to add this number to the running
current_sum, or start fresh from this number alone? - Update
best_sumwhenevercurrent_sumbeats it.
Complexity: Time = O(n), Space = O(1).
16.5 Pattern: Remove Duplicates From a Sorted List (Two Pointers, In Place)
❓ Interview Question:
- Problem: Given a sorted list, remove the duplicates in place so each value appears only once, and return the new length.
- Example:
- Input:
[1, 1, 2, 2, 3] - Expected Output: length
3, and the list becomes[1, 2, 3, ...](only the first 3 positions matter)
- Input:
- Hint: Use a “slow” pointer for where to write the next unique value, and a “fast” pointer to scan ahead.
✅ Approach:
slowstarts at index 0 — it marks the last confirmed unique value.fastscans through the rest of the list.- Whenever
nums[fast]is different fromnums[slow], it’s a new unique value — moveslowforward and copy it there.
Complexity: Time = O(n), Space = O(1) — done in place, no extra list.
17. Practice Problems (Try These Yourself)
- Find the second-largest number in a list, without using
sort(). - Rotate a list to the right by
ksteps. - Find all pairs in a list that add up to a given target number.
- Merge two already-sorted lists into one sorted list.
- Find the missing number in a list containing
1tonwith one number missing.
18. Key Takeaways
- A list is an ordered, mutable, resizable container — Python’s most flexible built-in data structure.
- Indexing starts at
0; negative indexes count from the end. sort()/reverse()change the list in place and returnNone;sorted()/reversed()return a new result and leave the original untouched.a.copy()only copies one level deep — for nested lists, usecopy.deepcopy().[[0]*3] * 4shares the same inner list across every row — always build 2D lists with a comprehension instead.- Lists are great stacks (fast at the end) but bad queues (slow at the front) — use
collections.dequefor queues. - Two pointers, sliding window, prefix sums, and Kadane’s algorithm are the core patterns behind the majority of list-based interview questions.