Python Tricks¶
Find Pair of Numbers in a Sorted Array with Target Sum¶
Overview¶
This solution uses the two-sum two-pointer algorithm.
- Pointer
leftpoints to the first element and pointerrightpoints to the last element. - If the sum at
leftandrightis greater than the target, decrease the right pointer to reduce the sum. - If the sum at
leftandrightis less than the target, increase the left pointer to increase the sum.
Code¶
def find_pair_with_target_sum(input_list, target):
"""
Finds all pairs in a sorted array that add up to a given target sum.
Args:
input_list (list): A sorted list of numbers.
target (int): The target sum.
Returns:
list: A list of tuples, where each tuple contains a pair of numbers that add up to the target sum.
"""
left, right = 0, len(input_list) - 1
combinations = []
while left < right:
s = input_list[left] + input_list[right]
if s < target:
# Increase the sum by moving the left pointer right
left += 1
elif s > target:
# Decrease the sum by moving the right pointer left
right -= 1
else:
# Found a pair
combinations.append((input_list[left], input_list[right]))
left += 1
right -= 1
return combinations
# Example usage:
numbers = [1, 2, 3, 4, 5]
target_sum = 7
result = find_pair_with_target_sum(numbers, target_sum)
print(result) # Output: [(2, 5), (3, 4)]
Find Three Numbers That Sum to Target in a Sorted Array (Three-Sum)¶
- Fix one pointer at the first element and find two-sum combinations in the remainder of the list.
- For each fixed element, look for pairs that sum to
target - fixed_element.
def three_sum(input_list, target):
for i in range(len(input_list)):
for j in two_sum(input_list[i+1:], target - input_list[i]):
print(input_list[i], j[0], j[1])
Find Pair of Numbers That Sum to Target in an Unsorted Array¶
-
If
arr = [1,4,2,3,5]andtarget=6and empty dictvisited={} -
Take first element
1and computetarget-1 = 5 -
if
5not invisitedadd it like{5:1} -
For next element
4,visited = {5:1, 2:4} -
For next element
2, 2 is already in visited. so the valid pair is4,2
find subarray of any length that has target sum(given array may be sorted or unsorted)¶
-
keep
current sum=0 andleftpointer 0 -
start iterating through the array and keep adding the elements to
current sum -
if sum becomes larger keep subtracting the left element form the sum until the sum is either equal or less than target sum. (using while loop).
Accumulate elements moving right while the sum is smaller; eliminate elements from the left if the sum is larger. Print the indices when the sum equals the target.
a = [1,5,9,3,7,1,2,4,7]
target_sum = 11
l = len(a)
left = 0
current_sum = 0
for i in range(l):
current_sum += a[i]
while current_sum > target_sum:
current_sum -= a[left]
left += 1
if current_sum == target_sum:
print(left, i)
Remove Duplicates In-place from a Sorted Array¶
-
iterate through the list from index 1 and also track the
leftpointer at 0. -
if the current element not equal to previous element, increment the
leftpointer and copy the ith to left pointer. (don't swap, just copy) -
return the
array[:left+1]at the end.
a = [1,1,1,2,2,2,3,3,3,4,4,4,4,5,5,5,6,6,6,7,7,7,8]
l = len(a)
left = 0
for i in range(1, l):
if a[i] != a[i-1]:
left += 1
a[left] = a[i]
print(a[:left+1])
Remove Duplicates In-place from an Unsorted Array¶
- Use a
seenset to track elements already copied. - If an element is not in
seen, copy it toa[left], incrementleft, and add it toseen.
a = [1,5,7,4,2,4,6,8,9,1,2,5,6,7,8,4,3]
l = len(a)
left = 0
seen = set()
for i in range(l):
if a[i] not in seen:
a[left] = a[i]
left += 1
seen.add(a[i])
print(a[:left])
Remove Last Element from a dict¶
d = {'a': 1, 'b': 2, 'c': 3}
# Using built-in (Python 3.7+ preserves insertion order)
d.popitem() # removes the last inserted key/value
# Using iterator
it = iter(reversed(d))
d.pop(next(it))
# Using OrderedDict
from collections import OrderedDict
d = OrderedDict(d)
d.popitem(last=True)
Remove First Element from a dict¶
d = {'a': 1, 'b': 2, 'c': 3}
# Using iterator
it = iter(d)
d.pop(next(it))
# Using OrderedDict
from collections import OrderedDict
d = OrderedDict(d)
d.popitem(last=False)
Move a Key to the End of a dict¶
# Pop the given key and add it at the end
d[key] = d.pop(key)
# OR
d.update({key: d.pop(key)})
# Using OrderedDict
from collections import OrderedDict
d = OrderedDict(d)
d.move_to_end(key, last=True)
Move a Key to the Beginning of a dict¶
from collections import OrderedDict
d = OrderedDict(d)
d.move_to_end(key, last=False)
dict.setdefault(key, default) and collections.defaultdict¶
Both setdefault and defaultdict help handle missing keys.
d = {}
# Returns the value of key 'a' if present; otherwise sets it to 0 and returns 0
d.setdefault('a', 0)
# =========================
from collections import defaultdict
d = defaultdict(int)
# Accessing a non-existent key creates it with a default value of 0
print(d['a']) # 0
Unpacking in Python¶
Unpacking extracts items from an iterable (list, tuple, set, string, dictionary) and assigns them to variables. The * notation collects leftover items into a list.
# Tuple unpacking
coordinates = (3, 4)
x, y = coordinates
a = (1, 2, 3, 4, 5, 6)
one, *rest, six = a
# Convert tuple to list via unpacking
a = (1, 2, 3, 4, 5, 6)
[*f] = a
print(f) # [1, 2, 3, 4, 5, 6]
Unpacking function arguments allows variable numbers of arguments:
def print_values(*args):
for value in args:
print(value)
print_values(1, 2, 3, 4, 5)
pop() Method on Lists¶
pop() removes and returns elements from a list. When the list is empty, it raises an IndexError.
a = [1, 2, 3, 4, 5, 6, 7]
while a:
print(a.pop(-1), end='', flush=True)
print(a) # []
One-line while Loop¶
A while loop can be written on one line; separate multiple statements with ;. Avoid complex logic on one line.
a = [1, 2, 3, 4, 5, 6, 7]
while a: print(a.pop(-1), end='', flush=True); print(" hello")
Docstrings in Python¶
Common docstring styles:
- Google style (supported by many tools)
- reStructuredText (official Python docs standard)
- NumPy/SciPy style
If-Else Ternary Operation¶
<expression1> if <condition> else <expression2>
Example:
print("Pass") if marks >= 45 else print("Fail")
importlib Standard Library¶
Use importlib.import_module to programmatically import modules.
For-If-Else in Comprehensions and Generators¶
List comprehensions and generator expressions can both use for, if, and else. Generators are more memory efficient.
for_if = [i for i in range(1, 10) if i < 6]
for_if_else = [5 if i < 5 else 10 for i in range(1, 20)]
if_else = True if 3 < 5 else False
type(self).name¶
print(type(self).__name__) prints the class name of an instance.
Single and Double Underscores¶
| Convention | Example | Meaning |
|---|---|---|
| Leading single underscore | _variable |
Intended for internal use (conventionally private) |
| Trailing single underscore | class_, float_ |
Avoids conflicts with Python keywords |
| Leading double underscore | __attribute |
Name mangling to make attributes harder to access from outside |
| Leading and trailing double underscore | __init__ |
Special methods and attributes |
Diátaxis¶
A systematic approach to technical documentation adopted widely in the Python community.
Keyword Listing¶
import keyword as _keyword
print(_keyword.kwlist)
Ellipsis¶
Use ... as a placeholder for incomplete code.
my_tuple = (1, 2, ...)
def my_function():
...
Integer String Conversion Limits¶
Python has configurable limits for converting very large strings to integers.
import sys
print(sys.int_info.default_max_str_digits)
print(sys.int_info.str_digits_check_threshold)
String Formatters¶
| Expr | Meaning | Example |
|---|---|---|
| {:d} | integer value | "{0:.0f}".format(10.5) → '10' |
| {:.2f} | floating point with two decimals | '{:.2f}'.format(0.5) → '0.50' |
| {:.2s} | string truncated to that many characters | '{:.2s}'.format('Python') → 'Py' |
| {:<6s} | left-aligned in a field of width 6 | '{:<6s}'.format('Py') → 'Py ' |
| {:>6s} | right-aligned in a field of width 6 | '{:>6s}'.format('Py') → ' Py' |
| {:^6s} | centered in a field of width 6 | '{:^6s}'.format('Py') → ' Py ' |
Queues, Stacks, and Deques¶
- Queue: FIFO (First-In, First-Out)
- Stack: LIFO (Last-In, First-Out)
- Deque: Double-ended queue, can act as FIFO or LIFO
Python Object-Oriented Concepts¶
Methods fall into several categories:
- Instance methods
- Class methods
- Static methods
Instance Methods¶
Instance methods receive self and operate on instance data.
Class Methods¶
Class methods are marked with @classmethod and receive cls.
Static Methods¶
Static methods are marked with @staticmethod and do not receive self or cls.
Miscellaneous¶
Three ways to set attribute values on a class instance:
@dataclass
class Student:
name: str
grade: str
age: int
s1 = Student('jeeva', 'C', 20)
setattr(s1, 'grade', 'A')
s1.grade = 'F'
Floor Division¶
print(15 // 4)
Match-Case (Python 3.10+)¶
match/case provides pattern matching similar to switch-case constructs.
len()¶
len(range(1, 20, 2)) returns 10.
weakref Example¶
import weakref
class MyClass:
def __init__(self, name):
self.name = name
def print_name(self):
print(self.name)
my_obj = MyClass("Nitrogen")
weak_reference = weakref.ref(my_obj)
if weak_reference() is not None:
print("Object alive")
del my_obj
if weak_reference() is not None:
print("Object alive")
else:
print("Object not alive")
Dictionary Examples¶
a = dict(one=1, two=2, three=3)
b = {'one': 1, 'two': 2, 'three': 3}
assert a == b
ChainMap¶
from collections import ChainMap
baseline = {'music': 'bach', 'art': 'rembrandt'}
adjustments = {'art': 'van gogh', 'opera': 'carmen'}
bboss = {'opera': [1, 2, 3, 4, 5], 'maven': 'kalmi'}
print(baseline | adjustments | bboss)
chain_obj = ChainMap(baseline, adjustments, bboss)
chain_obj = dict(chain_obj)
print(chain_obj)
collections.Counter and deque¶
from collections import Counter, deque
cnt = Counter(['red', 'blue', 'red', 'green', 'blue', 'blue'])
print(cnt)
d = deque()