Here are some Python hacks for competitive programming that can help you write efficient and concise code.
Table of Contents
String Operation
Join
- The join() method takes all items in an iterable and joins them into one string.
- A string must be specified as the separator.
- Iterable –> string
Synatx
string.join(iterable)
PythonExample
myTuple = ("John", "Peter", "Vicky")
x = "->".join(myTuple)
print(x) #John->Peter->Vicky
myList = ["John", "Peter", "Vicky"]
x = "".join(myList)
print(x) #JohnPeterVicky
PythonPerform join in integer
lst = ['1','2','3','4']
print("".join(lst)) #1234
lst = [1,2,3,4]
print("".join(lst)) #TypeError: sequence item 0: expected str instance, int found
PythonSolution
lst = [1,2,3,4]
print("".join(map(str,lst))) #1234
PythonDictionary
When using a dictionary as an iterable, the returned values are the keys, not the values.
myDict = {"name": "John", "country": "Norway"}
mySeparator = "="
x = mySeparator.join(myDict)
print(x) #name=country
PythonSplit
The split() method splits a string into a list.
You can specify the separator, default separator is any whitespace.
Syntax
string.split(separator, maxsplit)
Python- separator Optional. Specifies the separator to use when splitting the string. By default any whitespace is a separator
- maxsplit Optional. Specifies how many splits to do. Default value is -1, which is “all occurrences”
Example
txt = "welcome to the jungle"
x = txt.split()
print(x) # ['welcome', 'to', 'the', 'jungle']
txt = "hello, my name is Peter, I am 26 years old"
x = txt.split()
y = txt.split(", ")
z = txt.split(", ",1)
print(x) # ['hello,', 'my', 'name', 'is', 'Peter,', 'I', 'am', '26', 'years', 'old']
print(y) # ['hello', 'my name is Peter', 'I am 26 years old']
print(z) # ['hello', 'my name is Peter, I am 26 years old']
Pythonstrip()
- The strip() method removes any leading, and trailing whitespaces.
- Leading means at the beginning of the string, trailing means at the end.
- You can specify which character(s) to remove, if not, any whitespaces will be removed.
Syntax
string.strip(characters)
PythonExample
txt = " banana "
x = txt.strip()
print(x) # banana
txt = ",,,,,rrttgg.....banana....rrr"
x = txt.strip(",.grt") # banana
print(x)
Python“,.grt” –> stripping , . g r t
rstrip and lstrip
- The lstrip() method removes any leading characters (space is the default leading character to remove)
- The rstrip() method removes any trailing characters (characters at the end a string), space is the default trailing character to remove.
txt = "...banana,,,,,ssqqqww....."
print(txt.rstrip(",.qsw")) # ...banana
print(txt.lstrip(",.qsw")) # banana,,,,,ssqqqww.....
Pythonindex() and find()
find()
- The find() method finds the first occurrence of the specified value.
- The find() method returns -1 if the value is not found.
index()
- The index() method finds the first occurrence of the specified value.
- The index() method raises an exception if the value is not found.
Syntax
string.index(value, start, end)
string.find(value, start, end)
PythonExample
txt = "Mi casa, su casa."
print(txt.find("casa")) # 3
print(txt.index("casa")) # 3
print(txt.find("hi")) # -1
#print(txt.index("hi")) # error ValueError: substring not found
Pythonrindex() and rfind()
rfind()
- The rfind() method finds the last occurrence of the specified value.
- The rfind() method returns -1 if the value is not found.
rindex()
- The rindex() method finds the last occurrence of the specified value.
- The rindex() method raises an exception if the value is not found.
Syntax
string.rfind(value, start, end)
string.rindex(value, start, end)
PythonExample
txt = "Mi casa, su casa."
print(txt.rfind("casa")) # 12
print(txt.rindex("casa")) # 12
print(txt.rfind("hi")) # -1
print(txt.rindex("hi")) # error ValueError: substring not found
PythonFind out all occurrence
result = []
lst = "my name is backendmesh"
index = lst.find("m")
while(index>-1):
result.append(index)
lst = lst[index+1:]
index = lst.find("m")
print(result) #[0, 4, 12]
Pythonpartition()
- The partition() method searches for a specified string, and splits the string into a tuple containing three elements.
- The first element contains the part before the specified string.
- The second element contains the specified string.
- The third element contains the part after the string.
txt = "I could eat bananas all day"
x = txt.partition("bananas")
print(x) # ('I could eat ', 'bananas', ' all day')
Pythonreplace()
The replace() method replaces a specified phrase with another specified phrase.
string.replace(oldvalue, newvalue, count)
Python- oldvalue Required. The string to search for
- newvalue Required. The string to replace the old value with
- count Optional. A number specifying how many occurrences of the old value you want to replace. Default is all occurrences
txt = "one one one one"
print(txt.replace("one", "three")) # three three three three
print(txt.replace("one", "three", 2)) # three three one one
PythonString to list
#String to list
word = "hello"
print(list(word)) #['h', 'e', 'l', 'l', 'o']
#list to string
lst = ['h', 'e', 'l', 'l', 'o']
print("".join(lst)) #hello
PythonString to ASCII
print(ord('a')) #97
print(ord('A')) #65
PythonQuestion: Assign A=1,……Z=26
print(ord('A')-64) #1
print(ord('Z')-64) #26
OR
print(ord('A')-ord('A')+1) #1
print(ord('Z')-ord('A')+1) #26
PythonASCII to String
print(chr(97)) #a
print(chr(65)) #A
PythonLoops
Range
- range(start, stop, step)
- Generates numbers from start to stop – 1, incrementing by step.
for i in range(2,n) # 2 to n-1
for i in range(0,n) # 0 to n-1
for i in range(0,n,2) # 0,2,4,6 ...
for i in range(n) # 0 to n-1
for i in range(n,0,-1) # n to 1
for i in range(n,-1,-1) # n to 0
PythonArray/List
Python does not have built-in support for arrays like other languages (C, Java), but lists can be used as dynamic arrays.
Initialisation with Default value
arr = [0] * 10 # Creates an array of size 10 with all elements as 0
arr = [1] * 10 # Creates an array of size 10 with all elements as 1
PythonDelete
Delete an element from a list.
Way 1: Using remove() (by value):
my_list = [1, 2, 3, 4, 5,3]
my_list.remove(3) # Removes the first occurrence of 3
print(my_list) # [1, 2, 4, 5, 3]
PythonWay 2: Slice
my_list = [1, 2, 3, 4, 5,3]
my_list = my_list[:2]+my_list[3:] # 0 to 1 and 3 to end
print(my_list)
PythonWay 3: Using pop() (by index):
my_list = [1, 2, 3, 4, 5, 3]
my_list.pop(2) # Removes the element at index 2 (which is 3)
print(my_list) # [1, 2, 4, 5, 3]
PythonWay 4: Using del (by index):
my_list = [1, 2, 3, 4, 5, 3]
del my_list[2] # Deletes the element at index 2
print(my_list) # [1, 2, 4, 5, 3]
Pythonpop vs del
Feature | pop() | del |
---|---|---|
Purpose | Removes an element and returns it | Just deletes the element (no return) |
Usage | list.pop(index) | del list[index] |
Default | If no index, removes last item (pop() ) | No default; you must give an index or slice |
Error on wrong index | Yes (IndexError ) | Yes (IndexError ) |
Return value | Yes, returns the removed item | No, just deletes |
with power comes responsibility
length = len(nums)
for i in range(0, length):
nums.pop(i). #IndexError: pop index out of range
Python- gives an error because you are modifying the list (pop) while looping through it forward — but when you pop(i), the list shrinks, and the indices shift!
👉 So i becomes out of range very quickly.
Example:
nums = [10, 20, 30, 40, 50]
for i in range(2, length):
nums.pop(i). #IndexError: pop index out of range
#or
#del nums[i]
explanation
del nums[2] # [10, 20, 40, 50]
del nums[3] # [10,20,40]
del nums[4] # error
Python- i = 2, you pop(2), list becomes [10, 20, 40, 50]
- Now i = 3, but after pop, the list is smaller, so nums[3] = 50 is still OK
- Then i = 4, but now list length is only 4, so nums[4] ❌ IndexError.
Solution 1 :slice
del nums[j:]
PythonSolution 2 : Loop backward (so popping doesn’t affect upcoming elements):
length = len(nums)
for i in range(length-1, j-1, -1):
nums.pop(i)
PythonNegative index in List
lst = [1,2,3,4,5,6,7,8,9]
print(lst[-1]) #9
print(lst[-2]) #8
print(lst[-3]) #7
PythonDictionary
Default Value
Instead of manually checking if a key exists in a dictionary, use defaultdict.
from collections import defaultdict
my_dict = {}
my_dict['a'] = 4
print(my_dict['a']) # 4
print(my_dict['b']) # error KeyError: 'b'
d = defaultdict(int) # Default value is 0
d['a'] = 1
print(d['a']) # 1
print(d['b']) # 0 (instead of KeyError)
my_dict = defaultdict(int)
print(my_dict['my_key']) # 0
my_dict = defaultdict(list)
print(my_dict['my_key']) # []
PythonDefault Values
- int : 0
- float : 0.0
- str : ”
- bool : False
Why?
Without defaultdict: Everytime before using value , we needs to check if exist
counts = {}
words = ['apple', 'banana', 'apple']
for word in words:
if word in counts:
counts[word] += 1
else:
counts[word] = 1
PythonWith defaultdict:
from collections import defaultdict
counts = defaultdict(int) # int() defaults to 0
for word in ['apple', 'banana', 'apple']:
counts[word] += 1
print(counts)
Python- It’s shorthand
- count[‘any_key’] will never throw an error. Will always get a default value
Example 2
List as default value
from collections import defaultdict
d = defaultdict(list) # Automatically assigns an empty list as the default value
d['a'].append(10) # Since 'a' doesn't exist, it's initialized to [] first, then 10 is appended
print(d['a']) # Output: [10]
print(d['b']) # []
PythonSwap Two Variables
a, b = 5, 10
a, b = b, a
print(a, b) # 10, 5
PythonAdditional variable not required
It’s very usefully and handy to use.
Example: Reverse a list
arr = [1, 2, 3, 4, 5,6,7,8,9,10]
start = 0
lst = len(arr)-1
while start<=lst:
arr[lst],arr[start] = arr[start],arr[lst]
start+=1
lst-=1
print(arr)
PythonUse itertools for Combinations & Permutations
from itertools import permutations, combinations
print(list(permutations([1, 2, 3], 2))) # [(1,2), (1,3), (2,1), ...]
print(list(combinations([1, 2, 3], 2))) # [(1,2), (1,3), (2,3)]
PythonUse enumerate to Avoid Extra Index Handling
arr = [10, 20, 30]
for i, val in enumerate(arr, start=1):
print(i, val)
PythonUse divmod() for Simultaneous Quotient & Remainder
q, r = divmod(10, 3)
print(q, r) # 3 1
PythonUse enumerate() for Cleaner Loops
Instead of:
arr = [10, 20, 30]
for i in range(len(arr)):
print(i, arr[i])
PythonUse:
for i, val in enumerate(arr, start=1):
print(i, val)
PythonReverse a String or List in One Line
s = "hello"
print(s[::-1]) # "olleh"
arr = [1, 2, 3, 4]
print(arr[::-1]) # [4, 3, 2, 1]
PythonFor in-place list reversal (better performance):
arr.reverse()
PythonThis will not work for string
reversed()
- It works on sequences like lists, tuples, strings, etc.
- It does not modify the original sequence; it just gives you the items in reverse order.
- Since it returns an iterator, if you want a reversed list, you can do:
reversed_list = list(reversed(my_list))
print(reversed_list)
# Output: [5, 4, 3, 2, 1]
word = "hello"
print(reversed(word)) #<reversed object at 0x100c27d60>
print(''.join(reversed(word))) # Output: "olleh"
PythonTake out every thing except ‘i’ element
lst = [1,2,3,4,5,6,7,8]
i =3
current = lst[i]
remaining = lst[:i]+lst[i+1:]
print(current) # 4
print(remaining) # [1, 2, 3, 5, 6, 7, 8]
PythonOne-Liner If-Else (Ternary Operator)
Instead of:
x = 10
if x > 5:
y = "big"
else:
y = "small"
PythonUse:
y = "big" if x > 5 else "small"
PythonFind Unique Elements in a List Faster
arr = [1, 2, 2, 3, 3, 4]
unique_arr = list(set(arr))
print(unique_arr)
Pythona = path vs a = path[:]
In Python, assigning a list can either create a reference or a copy:
- a = path creates a reference to the same list. Changes to a will affect path and vice versa.
- a = path[:] creates a shallow copy of the list. Changes to a will not affect path.
Use a = path[:] when:
- You want to preserve the original list.
- You’re in recursive or backtracking algorithms and need a snapshot of the current state.
Use a = path when:
- You want to modify the original list through another name.
- You don’t need to preserve the original list.
In backtracking, always use res.append(path[:]) to avoid bugs from shared list references.Refer
Common List Lengths in String/Array Operations
Operation | List Length | Reason |
---|---|---|
String Multiplication | [0] * (len(num1) + len(num2)) | Max digits in result = m + n |
String Addition | [0] * (max(len(num1), len(num2)) + 1) | One extra digit possible from carry |
Array Number Addition | [0] * (max(len(arr1), len(arr2)) + 1) | Same as string addition |
Polynomial Multiplication | [0] * (len(A) + len(B) - 1) | Degree of result = (m-1) + (n-1) |
Prefix Sum Array | [0] * (len(nums) + 1) | Extra space for simpler range sum queries |
Suffix Sum Array | [0] * (len(nums) + 1) | Similar to prefix sum, but in reverse |
1D DP Array | [0] * (n + 1) | Space for base cases and up to n |
2D DP Table | [[0] * (m + 1) for _ in range(n + 1)] | For problems needing rows × cols + base cases |
Multi-key sorting
Sorting by multiple columns
Example
employees = [
{"name": "Zara", "age": 25, "salary": 90000},
{"name": "Alex", "age": 30, "salary": 90000},
{"name": "Mike", "age": 25, "salary": 80000},
{"name": "Bob", "age": 30, "salary": 80000},
]
PythonSorting Priorities:
- Salary → descending (highest salary first)
- Age → ascending (youngest first)
- Name → lexicographically (alphabetical order)
Expected Output
[
{"name": "Zara", "age": 25, "salary": 90000}, # Salary 90k, youngest in 90k group
{"name": "Alex", "age": 30, "salary": 90000}, # Same salary, older
{"name": "Mike", "age": 25, "salary": 80000}, # Salary 80k, youngest in 80k group
{"name": "Bob", "age": 30, "salary": 80000}, # Same salary, older
]
PythonFollow same priority order as it is.
employees = [
{"name": "Zara", "age": 25, "salary": 90000},
{"name": "Alex", "age": 30, "salary": 90000},
{"name": "Mike", "age": 25, "salary": 80000},
{"name": "Bob", "age": 30, "salary": 80000},
]
Step 1 Salary → descending (highest salary first)
employees = [
{"name": "Zara", "age": 25, "salary": 90000},
{"name": "Alex", "age": 30, "salary": 90000},
{"name": "Mike", "age": 25, "salary": 80000},
{"name": "Bob", "age": 30, "salary": 80000},
]
Step 2 Age → ascending (youngest first)
employees = [
{"name": "Zara", "age": 25, "salary": 90000},
{"name": "Mike", "age": 25, "salary": 80000},
{"name": "Alex", "age": 30, "salary": 90000},
{"name": "Bob", "age": 30, "salary": 80000},
]
Step 3 : Name → lexicographically (alphabetical order)
Our Output
employees = [
{"name": "Alex", "age": 30, "salary": 90000},
{"name": "Bob", "age": 30, "salary": 80000},
{"name": "Mike", "age": 25, "salary": 80000},
{"name": "Zara", "age": 25, "salary": 90000},
]
Expected Output
[
{"name": "Zara", "age": 25, "salary": 90000}, # Salary 90k, youngest in 90k group
{"name": "Alex", "age": 30, "salary": 90000}, # Same salary, older
{"name": "Mike", "age": 25, "salary": 80000}, # Salary 80k, youngest in 80k group
{"name": "Bob", "age": 30, "salary": 80000}, # Same salary, older
]
PythonWhy this is wrong:
- Sorting by age after sorting by salary does not preserve the salary order because you’re sorting the full list again, not just within salary groups.
- Sorting by name last again sorts the whole list, destroying the previous order completely.
Reverse priority orde
When sorting by multiple columns, apply the last rule first and first rule last, to preserve priority.”
Note:
- If you want to sort by multiple criteria (say, A then B), the primary sort key should be applied last.
- The secondary (and less important) sort keys should be applied first.
This is because each successive sort must preserve the order of the previous more important sort — and this is only guaranteed when the sorting is stable (i.e., elements with equal keys retain their relative order).
Why this works:
Sorting from least to most important key (i.e., last rule first) ensures that when a more important rule is applied later, it groups the items while keeping the relative order imposed by less important rules.
This avoids overwriting the priority of the more important keys.
Example
employees = [
{"name": "Zara", "age": 25, "salary": 90000},
{"name": "Alex", "age": 30, "salary": 90000},
{"name": "Mike", "age": 25, "salary": 80000},
{"name": "Bob", "age": 30, "salary": 80000},
]
Step 1 :Name → lexicographically (alphabetical order)
employees = [
{"name": "Alex", "age": 30, "salary": 90000},
{"name": "Bob", "age": 30, "salary": 80000},
{"name": "Mike", "age": 25, "salary": 80000},
{"name": "Zara", "age": 25, "salary": 90000},
]
Step 2 Age → ascending (youngest first)
employees = [
{"name": "Mike", "age": 25, "salary": 80000},
{"name": "Zara", "age": 25, "salary": 90000},
{"name": "Alex", "age": 30, "salary": 90000},
{"name": "Bob", "age": 30, "salary": 80000},
]
Step 3 Salary → descending (highest salary first)
# Our Output
employees = [
{"name": "Zara", "age": 25, "salary": 90000},
{"name": "Alex", "age": 30, "salary": 90000},
{"name": "Mike", "age": 25, "salary": 80000},
{"name": "Bob", "age": 30, "salary": 80000},
]
# Expected Output
[
{"name": "Zara", "age": 25, "salary": 90000}, # Salary 90k, youngest in 90k group
{"name": "Alex", "age": 30, "salary": 90000}, # Same salary, older
{"name": "Mike", "age": 25, "salary": 80000}, # Salary 80k, youngest in 80k group
{"name": "Bob", "age": 30, "salary": 80000}, # Same salary, older
]
PythonCode
employees.sort(key=lambda x:x["name"])
employees.sort(key=lambda x:x["age"])
employees.sort(key=lambda x:x["salary"],reverse=True)
# Output
[
{'name': 'Zara', 'age': 25, 'salary': 90000},
{'name': 'Alex', 'age': 30, 'salary': 90000},
{'name': 'Mike', 'age': 25, 'salary': 80000},
{'name': 'Bob', 'age': 30, 'salary': 80000}
]
PythonWhen sorting by multiple columns, apply the last rule first and first rule last, to preserve priority.