Python Arrays & Lists (1D & 2D)

Python Arrays & Lists Interview Questions

What is a list in Python?
A list is a built-in data structure in Python that represents an ordered, mutable collection of items. Lists can contain elements of different data types and are created using square brackets [].
How to create a 1D list in Python?
# Different ways to create 1D lists # 1. Using square brackets list1 = [1, 2, 3, 4, 5] list2 = ['apple', 'banana', 'cherry'] mixed = [1, 'hello', 3.14, True] # 2. Using list() constructor list3 = list() # Empty list list4 = list(range(5)) # [0, 1, 2, 3, 4] list5 = list('hello') # ['h', 'e', 'l', 'l', 'o'] # 3. Using list comprehension squares = [x**2 for x in range(5)] # [0, 1, 4, 9, 16] # 4. From other iterables tuple_to_list = list((1, 2, 3)) # [1, 2, 3] string_to_list = list("abc") # ['a', 'b', 'c']
What is the difference between arrays and lists in Python?
AspectPython ListArray (array module/numpy)
TypeBuilt-in data typeFrom array module or numpy
Data typesCan store different typesStores same type elements
MemoryMore memory overheadMemory efficient
OperationsBasic operationsMathematical operations
PerformanceSlower for numerical opsFaster for numerical ops
Use caseGeneral purposeNumerical computations
How to create a 2D list (matrix) in Python?
# Different ways to create 2D lists (matrices) # 1. Direct initialization matrix1 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] # 2. Using nested list comprehension rows, cols = 3, 4 matrix2 = [[0 for _ in range(cols)] for _ in range(rows)] # [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] # 3. Using multiplication (CAUTION: Creates references!) matrix3 = [[0] * 3 for _ in range(3)] # Correct # matrix4 = [[0] * 3] * 3 # WRONG! Creates references # 4. From existing lists row1 = [1, 2, 3] row2 = [4, 5, 6] matrix4 = [row1, row2] # 5. Using numpy (for numerical work) import numpy as np matrix_np = np.zeros((3, 3)) # 3x3 matrix of zeros
What are the basic list operations in Python?
my_list = [1, 2, 3, 4, 5] # 1. Access elements print(my_list[0]) # 1 (first element) print(my_list[-1]) # 5 (last element) # 2. Slicing print(my_list[1:3]) # [2, 3] (index 1 to 2) print(my_list[:3]) # [1, 2, 3] (first 3) print(my_list[2:]) # [3, 4, 5] (from index 2) # 3. Length print(len(my_list)) # 5 # 4. Check existence print(3 in my_list) # True print(10 in my_list) # False # 5. Concatenation new_list = my_list + [6, 7, 8] # [1, 2, 3, 4, 5, 6, 7, 8] # 6. Repetition repeated = my_list * 2 # [1, 2, 3, 4, 5, 1, 2, 3, 4, 5] # 7. Iteration for item in my_list: print(item)
What are list methods in Python?
my_list = [1, 2, 3] # 1. append() - add to end my_list.append(4) # [1, 2, 3, 4] # 2. extend() - add multiple items my_list.extend([5, 6]) # [1, 2, 3, 4, 5, 6] # 3. insert() - insert at position my_list.insert(0, 0) # [0, 1, 2, 3, 4, 5, 6] # 4. remove() - remove first occurrence my_list.remove(3) # [0, 1, 2, 4, 5, 6] # 5. pop() - remove and return item at index item = my_list.pop(1) # item=1, list=[0, 2, 4, 5, 6] # 6. clear() - remove all items my_list.clear() # [] # 7. index() - find index of item my_list = [10, 20, 30, 20] idx = my_list.index(20) # 1 (first occurrence) # 8. count() - count occurrences cnt = my_list.count(20) # 2 # 9. sort() - sort in place my_list.sort() # [10, 20, 20, 30] my_list.sort(reverse=True) # [30, 20, 20, 10] # 10. reverse() - reverse in place my_list.reverse() # [10, 20, 20, 30] (original order) # 11. copy() - create shallow copy copy_list = my_list.copy()
How to access elements in a 2D list?
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] # 1. Access single element print(matrix[0][0]) # 1 (row 0, column 0) print(matrix[1][2]) # 6 (row 1, column 2) print(matrix[-1][-1]) # 9 (last row, last column) # 2. Access entire row row1 = matrix[0] # [1, 2, 3] row2 = matrix[1] # [4, 5, 6] # 3. Access column (requires iteration or list comprehension) col1 = [row[0] for row in matrix] # [1, 4, 7] col2 = [row[1] for row in matrix] # [2, 5, 8] # 4. Using loops for i in range(len(matrix)): # Row indices for j in range(len(matrix[i])): # Column indices print(f"matrix[{i}][{j}] = {matrix[i][j]}") # 5. Using enumerate for i, row in enumerate(matrix): for j, value in enumerate(row): print(f"Position ({i},{j}): {value}") # 6. Slicing 2D lists first_two_rows = matrix[:2] # [[1,2,3], [4,5,6]] first_two_cols = [row[:2] for row in matrix] # [[1,2], [4,5], [7,8]]
What is list comprehension and how is it used?
# List comprehension: concise way to create lists # Syntax: [expression for item in iterable if condition] # Basic examples squares = [x**2 for x in range(5)] # [0, 1, 4, 9, 16] # With condition evens = [x for x in range(10) if x % 2 == 0] # [0, 2, 4, 6, 8] # Transforming elements words = ['hello', 'world', 'python'] upper_words = [word.upper() for word in words] # ['HELLO', 'WORLD', 'PYTHON'] # Nested list comprehension (for 2D lists) matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] flattened = [num for row in matrix for num in row] # [1,2,3,4,5,6,7,8,9] # Transpose matrix transpose = [[row[i] for row in matrix] for i in range(3)] # [[1, 4, 7], [2, 5, 8], [3, 6, 9]] # With if-else numbers = [1, 2, 3, 4, 5] classified = ['even' if x % 2 == 0 else 'odd' for x in numbers] # ['odd', 'even', 'odd', 'even', 'odd'] # Creating 2D list rows, cols = 3, 4 matrix2 = [[i*j for j in range(cols)] for i in range(rows)] # [[0, 0, 0, 0], [0, 1, 2, 3], [0, 2, 4, 6]]
What is the difference between shallow copy and deep copy?
import copy # Original list with nested list original = [[1, 2, 3], [4, 5, 6]] # 1. Assignment (creates reference) reference = original reference[0][0] = 100 print(original[0][0]) # 100 (original changed!) # 2. Shallow copy (copy() or slicing) shallow = original.copy() # or original[:] shallow[0] = [7, 8, 9] # This doesn't affect original print(original[0]) # [100, 2, 3] (unchanged) shallow[1][0] = 400 # This affects original! print(original[1][0]) # 400 (original changed!) # 3. Deep copy (creates completely new objects) deep = copy.deepcopy(original) deep[1][0] = 9999 print(original[1][0]) # 400 (unchanged) print(deep[1][0]) # 9999 # Summary: # - Assignment: Both variables point to same list # - Shallow copy: New list, but nested objects are shared # - Deep copy: Completely independent copy
How to sort lists in Python?
# 1. sort() method (in-place) numbers = [3, 1, 4, 1, 5, 9, 2] numbers.sort() print(numbers) # [1, 1, 2, 3, 4, 5, 9] # 2. sorted() function (returns new list) numbers = [3, 1, 4, 1, 5, 9, 2] sorted_numbers = sorted(numbers) print(sorted_numbers) # [1, 1, 2, 3, 4, 5, 9] print(numbers) # [3, 1, 4, 1, 5, 9, 2] (original unchanged) # 3. Reverse sort numbers.sort(reverse=True) # [9, 5, 4, 3, 2, 1, 1] # 4. Sorting with custom key words = ['banana', 'apple', 'cherry', 'date'] words.sort(key=len) # Sort by length print(words) # ['date', 'apple', 'banana', 'cherry'] words.sort(key=str.lower) # Case-insensitive sort # 5. Sorting list of tuples students = [('Alice', 25), ('Bob', 20), ('Charlie', 23)] students.sort(key=lambda x: x[1]) # Sort by age print(students) # [('Bob', 20), ('Charlie', 23), ('Alice', 25)] # 6. Sorting 2D lists matrix = [[3, 2, 1], [6, 5, 4], [9, 8, 7]] matrix.sort(key=lambda x: x[0]) # Sort by first element of each row print(matrix) # [[3, 2, 1], [6, 5, 4], [9, 8, 7]] # 7. Natural sort (for strings with numbers) import re def natural_sort_key(s): return [int(text) if text.isdigit() else text.lower() for text in re.split(r'(\d+)', s)]
What are common list operations for 2D lists?
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] # 1. Transpose matrix transpose = [[row[i] for row in matrix] for i in range(3)] # [[1, 4, 7], [2, 5, 8], [3, 6, 9]] # 2. Flatten matrix flattened = [element for row in matrix for element in row] # [1, 2, 3, 4, 5, 6, 7, 8, 9] # 3. Get diagonal elements diagonal = [matrix[i][i] for i in range(3)] # [1, 5, 9] anti_diagonal = [matrix[i][2-i] for i in range(3)] # [3, 5, 7] # 4. Sum rows and columns row_sums = [sum(row) for row in matrix] # [6, 15, 24] col_sums = [sum(matrix[i][j] for i in range(3)) for j in range(3)] # [12, 15, 18] # 5. Find maximum/minimum in matrix max_val = max(max(row) for row in matrix) # 9 min_val = min(min(row) for row in matrix) # 1 # 6. Rotate matrix 90 degrees clockwise def rotate_90(matrix): return [[row[i] for row in reversed(matrix)] for i in range(len(matrix[0]))] # 7. Check if matrix is square is_square = len(matrix) == len(matrix[0]) # True # 8. Create identity matrix n = 3 identity = [[1 if i == j else 0 for j in range(n)] for i in range(n)] # [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
How to use the array module in Python?
import array # Creating arrays (more memory efficient than lists for numeric data) # Type codes: 'b' (signed char), 'B' (unsigned char), 'i' (signed int), # 'I' (unsigned int), 'f' (float), 'd' (double) # Create array of integers arr = array.array('i', [1, 2, 3, 4, 5]) print(arr) # array('i', [1, 2, 3, 4, 5]) # Basic operations print(arr[0]) # 1 print(len(arr)) # 5 arr.append(6) # Add element arr.extend([7, 8]) # Add multiple # Slicing print(arr[2:5]) # array('i', [3, 4, 5]) # Convert to list my_list = arr.tolist() # [1, 2, 3, 4, 5, 6, 7, 8] # Mathematical operations (limited compared to numpy) arr2 = array.array('i', [10, 20, 30, 40, 50]) # Memory efficiency comparison import sys list_data = [1, 2, 3, 4, 5] arr_data = array.array('i', [1, 2, 3, 4, 5]) print(f"List memory: {sys.getsizeof(list_data)} bytes") print(f"Array memory: {sys.getsizeof(arr_data)} bytes") # Limitations of array module: # - Only homogeneous data types # - Limited mathematical operations # - No built-in matrix operations # For numerical work, numpy is better
How to use numpy arrays for numerical computations?
import numpy as np # Creating numpy arrays arr1d = np.array([1, 2, 3, 4, 5]) # 1D array arr2d = np.array([[1, 2, 3], [4, 5, 6]]) # 2D array # Special arrays zeros = np.zeros((3, 3)) # 3x3 matrix of zeros ones = np.ones((2, 4)) # 2x4 matrix of ones identity = np.eye(3) # 3x3 identity matrix range_arr = np.arange(0, 10, 2) # [0, 2, 4, 6, 8] # Array operations (element-wise) a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) print(a + b) # [5, 7, 9] print(a * b) # [4, 10, 18] (element-wise multiplication) print(a @ b) # 32 (dot product) # Matrix operations A = np.array([[1, 2], [3, 4]]) B = np.array([[5, 6], [7, 8]]) print(A @ B) # Matrix multiplication print(A.T) # Transpose print(np.linalg.inv(A)) # Inverse # Statistical operations data = np.array([1, 2, 3, 4, 5]) print(np.mean(data)) # 3.0 print(np.std(data)) # Standard deviation print(np.sum(data)) # 15 print(np.min(data), np.max(data)) # 1, 5 # Slicing and indexing matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(matrix[0, 0]) # 1 print(matrix[:, 1]) # [2, 5, 8] (second column) print(matrix[1:, :2]) # [[4, 5], [7, 8]]
What are common mistakes when working with lists?
# 1. Modifying list while iterating numbers = [1, 2, 3, 4, 5] # for num in numbers: # if num % 2 == 0: # numbers.remove(num) # Unexpected behavior! # Solution: Create a copy or use list comprehension numbers = [num for num in numbers if num % 2 != 0] # 2. Using multiplication for nested lists matrix_wrong = [[0] * 3] * 3 # Creates references! matrix_wrong[0][0] = 1 print(matrix_wrong) # [[1, 0, 0], [1, 0, 0], [1, 0, 0]] # Solution: Use list comprehension matrix_correct = [[0] * 3 for _ in range(3)] # 3. Confusing append() and extend() lst = [1, 2, 3] lst.append([4, 5]) # [1, 2, 3, [4, 5]] (nested list) lst.extend([6, 7]) # [1, 2, 3, [4, 5], 6, 7] # 4. Forgetting that sort() modifies in-place numbers = [3, 1, 4, 1, 5] sorted_numbers = numbers.sort() # WRONG! sort() returns None # Correct: sorted_numbers = sorted(numbers) # 5. Index out of range lst = [1, 2, 3] # print(lst[5]) # IndexError print(lst[-1]) # 3 (safe way to get last element) # 6. Shallow copy issues original = [[1, 2], [3, 4]] copy = original.copy() copy[0][0] = 99 print(original[0][0]) # 99 (unexpected!) # 7. Comparing lists with == and is list1 = [1, 2, 3] list2 = [1, 2, 3] print(list1 == list2) # True (values equal) print(list1 is list2) # False (different objects)
How to find duplicates in a list?
numbers = [1, 2, 3, 2, 4, 5, 3, 6, 7, 7] # 1. Using set to find all duplicates seen = set() duplicates = set() for num in numbers: if num in seen: duplicates.add(num) else: seen.add(num) print(f"Duplicates: {list(duplicates)}") # [2, 3, 7] # 2. Using list comprehension and count() duplicates = list(set([x for x in numbers if numbers.count(x) > 1])) print(f"Duplicates: {duplicates}") # [2, 3, 7] # 3. Using collections.Counter from collections import Counter counter = Counter(numbers) duplicates = [item for item, count in counter.items() if count > 1] print(f"Duplicates: {duplicates}") # [2, 3, 7] # 4. Find first duplicate def first_duplicate(lst): seen = set() for item in lst: if item in seen: return item seen.add(item) return None print(f"First duplicate: {first_duplicate(numbers)}") # 2 # 5. Remove duplicates (preserve order) def remove_duplicates(lst): seen = set() result = [] for item in lst: if item not in seen: seen.add(item) result.append(item) return result print(f"Without duplicates: {remove_duplicates(numbers)}") # [1, 2, 3, 4, 5, 6, 7]
How to merge and split lists?
# Merging lists list1 = [1, 2, 3] list2 = [4, 5, 6] list3 = [7, 8, 9] # 1. Using + operator merged = list1 + list2 + list3 # [1, 2, 3, 4, 5, 6, 7, 8, 9] # 2. Using extend() merged = [] merged.extend(list1) merged.extend(list2) # [1, 2, 3, 4, 5, 6] # 3. Using unpacking (Python 3.5+) merged = [*list1, *list2, *list3] # [1, 2, 3, 4, 5, 6, 7, 8, 9] # 4. Using itertools.chain from itertools import chain merged = list(chain(list1, list2, list3)) # Splitting lists numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9] # 1. Using slicing first_half = numbers[:len(numbers)//2] # [1, 2, 3, 4] second_half = numbers[len(numbers)//2:] # [5, 6, 7, 8, 9] # 2. Split into chunks def split_into_chunks(lst, chunk_size): return [lst[i:i+chunk_size] for i in range(0, len(lst), chunk_size)] chunks = split_into_chunks(numbers, 3) # [[1, 2, 3], [4, 5, 6], [7, 8, 9]] # 3. Split based on condition evens = [x for x in numbers if x % 2 == 0] # [2, 4, 6, 8] odds = [x for x in numbers if x % 2 != 0] # [1, 3, 5, 7, 9] # 4. Using numpy array_split import numpy as np arr = np.array(numbers) chunks = np.array_split(arr, 3) # 3 approximately equal parts
How to perform matrix operations on 2D lists?
# Matrix operations using pure Python (without numpy) def matrix_add(A, B): """Add two matrices element-wise""" return [[A[i][j] + B[i][j] for j in range(len(A[0]))] for i in range(len(A))] def matrix_multiply(A, B): """Multiply two matrices""" result = [[0 for _ in range(len(B[0]))] for _ in range(len(A))] for i in range(len(A)): for j in range(len(B[0])): for k in range(len(B)): result[i][j] += A[i][k] * B[k][j] return result def matrix_transpose(matrix): """Transpose a matrix""" return [[matrix[j][i] for j in range(len(matrix))] for i in range(len(matrix[0]))] def matrix_scalar_multiply(matrix, scalar): """Multiply matrix by scalar""" return [[element * scalar for element in row] for row in matrix] # Example usage A = [[1, 2], [3, 4]] B = [[5, 6], [7, 8]] print("A + B:", matrix_add(A, B)) # [[6, 8], [10, 12]] print("A * B:", matrix_multiply(A, B)) # [[19, 22], [43, 50]] print("Transpose of A:", matrix_transpose(A)) # [[1, 3], [2, 4]] print("2 * A:", matrix_scalar_multiply(A, 2)) # [[2, 4], [6, 8]] # For complex operations, use numpy: import numpy as np A_np = np.array(A) B_np = np.array(B) print("A + B (numpy):", A_np + B_np) print("A * B (numpy):", A_np @ B_np) # Matrix multiplication print("Inverse of A:", np.linalg.inv(A_np)) print("Determinant of A:", np.linalg.det(A_np))
What are list slicing techniques and tricks?
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # Basic slicing: list[start:stop:step] print(numbers[2:5]) # [2, 3, 4] (index 2 to 4) print(numbers[:5]) # [0, 1, 2, 3, 4] (first 5) print(numbers[5:]) # [5, 6, 7, 8, 9] (from index 5) print(numbers[::2]) # [0, 2, 4, 6, 8] (every 2nd) print(numbers[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] (reverse) # Negative indices print(numbers[-3:]) # [7, 8, 9] (last 3) print(numbers[:-3]) # [0, 1, 2, 3, 4, 5, 6] (all except last 3) print(numbers[-5:-2]) # [5, 6, 7] (index -5 to -3) # Step with negative start/stop print(numbers[8:2:-2]) # [8, 6, 4] (from 8 to 3, step -2) # Useful tricks # 1. Get last n elements n = 3 print(numbers[-n:]) # [7, 8, 9] # 2. Get every nth element print(numbers[::3]) # [0, 3, 6, 9] # 3. Remove first and last elements print(numbers[1:-1]) # [1, 2, 3, 4, 5, 6, 7, 8] # 4. Get middle elements print(numbers[3:7]) # [3, 4, 5, 6] # 5. Replace slice numbers[2:5] = [20, 30, 40] print(numbers) # [0, 1, 20, 30, 40, 5, 6, 7, 8, 9] # 6. Delete slice del numbers[2:5] print(numbers) # [0, 1, 5, 6, 7, 8, 9] # 7. Copy list using slicing copy = numbers[:] # Shallow copy # 8. Reverse list in place numbers.reverse() # In-place reversal reversed_copy = numbers[::-1] # New reversed list
How to implement common algorithms with lists?
# 1. Linear search def linear_search(lst, target): for i, value in enumerate(lst): if value == target: return i return -1 # 2. Binary search (list must be sorted) def binary_search(lst, target): left, right = 0, len(lst) - 1 while left <= right: mid = (left + right) // 2 if lst[mid] == target: return mid elif lst[mid] < target: left = mid + 1 else: right = mid - 1 return -1 # 3. Bubble sort def bubble_sort(lst): n = len(lst) for i in range(n): for j in range(0, n - i - 1): if lst[j] > lst[j + 1]: lst[j], lst[j + 1] = lst[j + 1], lst[j] return lst # 4. Selection sort def selection_sort(lst): for i in range(len(lst)): min_idx = i for j in range(i + 1, len(lst)): if lst[j] < lst[min_idx]: min_idx = j lst[i], lst[min_idx] = lst[min_idx], lst[i] return lst # 5. Find second largest def second_largest(lst): if len(lst) < 2: return None first = second = float('-inf') for num in lst: if num > first: second = first first = num elif num > second and num != first: second = num return second if second != float('-inf') else None # 6. Find missing number in sequence def find_missing(numbers): n = len(numbers) + 1 expected_sum = n * (n + 1) // 2 actual_sum = sum(numbers) return expected_sum - actual_sum # 7. Rotate list def rotate_list(lst, k): k = k % len(lst) return lst[-k:] + lst[:-k]
What are list performance considerations?
# Time Complexity of List Operations: # Operation | Time Complexity | Example # ----------------|-----------------|--------- # Index access | O(1) | lst[5] # Append | O(1) average | lst.append(x) # Pop last | O(1) | lst.pop() # Pop intermediate| O(n) | lst.pop(0) # Insert | O(n) | lst.insert(0, x) # Delete | O(n) | del lst[0] # Search | O(n) | x in lst # Sort | O(n log n) | lst.sort() # Space Complexity: O(n) where n is number of elements # Performance tips: # 1. Use append() instead of insert(0, x) when possible # Append is O(1), insert at beginning is O(n) result = [] for i in range(1000000): result.append(i) # Fast # 2. Use collections.deque for queue operations from collections import deque queue = deque() queue.append(1) # O(1) queue.popleft() # O(1) (vs list.pop(0) which is O(n)) # 3. Use set for membership testing my_list = list(range(1000000)) my_set = set(my_list) # Slow: O(n) # if 999999 in my_list: # Linear search # Fast: O(1) average if 999999 in my_set: # Hash lookup pass # 4. Preallocate list when size is known size = 1000000 # Slow: # result = [] # for i in range(size): # result.append(0) # Fast: result = [0] * size # 5. Use list comprehension instead of loops # Slow: # result = [] # for i in range(1000000): # result.append(i**2) # Fast: result = [i**2 for i in range(1000000)] # 6. Avoid modifying list while iterating # This causes reindexing and is O(n^2) in worst case # 7. Use built-in functions (written in C) # sum(lst) is faster than manual loop summation
Note: These questions cover Python lists and arrays comprehensively. Remember: Lists are mutable, ordered collections that can hold heterogeneous data. For 2D lists, be careful with list multiplication (use list comprehension instead). For numerical computations, consider using numpy arrays. Always be aware of time and space complexity when working with large lists, and use appropriate data structures (like sets or deques) when needed.
Python Arrays & Lists (1D & 2D) Next