Skip to content

Commit c7c743a

Browse files
committed
array, binary search, bitmasking, dp, graph, hashing added
1 parent 6eafa10 commit c7c743a

8 files changed

+358
-13
lines changed

Array/reverse_pair.py

+12-12
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ class Solution:
2020
def merge(self, s, e, mid, temp, nums):
2121

2222
count = 0
23+
j = mid+1
24+
for i in range(s, mid+1): # count for each element
25+
while j <= e and nums[i] > 2*nums[j]: # find all elements in second half which is smaller
26+
j += 1
27+
count += (j-(mid+1))
28+
2329
i = s
2430
j = mid+1
2531
k = s
@@ -48,28 +54,22 @@ def merge(self, s, e, mid, temp, nums):
4854

4955
for i in range(s, e+1):
5056
nums[i] = temp[i]
51-
57+
58+
return count
5259

5360
def mergesort(self, s, e, nums, temp):
5461

5562
count = 0
5663
if s < e:
5764
mid = (s+e)//2
5865

59-
count = self.mergesort(s, mid, nums, temp) + self.mergesort(mid+1, e, nums, temp)
60-
61-
j = mid+1
62-
for i in range(s, mid+1): # count for each element
63-
while j <= e and nums[i] > 2*nums[j]: # find all elements in second half which is smaller
64-
j += 1
65-
count += j-(mid+1)
66-
67-
self.merge(s, e, mid, temp, nums)
66+
count += self.mergesort(s, mid, nums, temp)
67+
count += self.mergesort(mid+1, e, nums, temp)
68+
count += self.merge(s, e, mid, temp, nums)
6869
#nums[s: e + 1] = sorted(nums[s: e + 1])
69-
7070
return count
7171

72-
def reversePairs(self, nums: List[int]) -> int:
72+
def reversePairs(self, nums: List[int]):
7373

7474
n = len(nums)
7575
temp = [0]*n
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'''
2+
https://leetcode.com/problems/subarrays-with-k-different-integers/
3+
Given an array A of positive integers, call a (contiguous, not necessarily distinct) subarray of A good if the number of different integers in that subarray is exactly K.
4+
(For example, [1,2,3,1,2] has 3 different integers: 1, 2, and 3.)
5+
Return the number of good subarrays of A.
6+
7+
Example 1:
8+
Input: A = [1,2,1,2,3], K = 2
9+
Output: 7
10+
Explanation: Subarrays formed with exactly 2 different integers: [1,2], [2,1], [1,2], [2,3], [1,2,1], [2,1,2], [1,2,1,2].
11+
12+
Example 2:
13+
Input: A = [1,2,1,3,4], K = 3
14+
Output: 3
15+
Explanation: Subarrays formed with exactly 3 different integers: [1,2,1,3], [2,1,3], [1,3,4].
16+
'''
17+
18+
class Solution:
19+
def subarraysWithKDistinct(self, A: List[int], K: int):
20+
21+
# cnt = count number of distict number
22+
# prefix_count = numbers with same distinct number in which we shrink our window
23+
m = collections.defaultdict(int)
24+
cnt, prefix_count, res, left = 0, 0, 0, 0
25+
26+
for right in range(len(A)):
27+
m[A[right]] += 1
28+
if m[A[right]] == 1:
29+
cnt += 1
30+
31+
if cnt > K: # start new window with new distinct elements thats why make prefix 0
32+
m[A[left]] -= 1
33+
left += 1
34+
cnt -= 1
35+
prefix_count = 0
36+
37+
while m[A[left]] > 1:
38+
m[A[left]] -= 1
39+
left += 1
40+
prefix_count += 1
41+
42+
if cnt == K:
43+
res += prefix_count + 1
44+
45+
return res
46+
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
'''
2+
https://leetcode.com/problems/median-of-two-sorted-arrays/
3+
Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays.
4+
Follow up: The overall run time complexity should be O(log (m+n)).
5+
6+
Example 1:
7+
Input: nums1 = [1,3], nums2 = [2]
8+
Output: 2.00000
9+
Explanation: merged array = [1,2,3] and median is 2.
10+
11+
Example 2:
12+
Input: nums1 = [1,2], nums2 = [3,4]
13+
Output: 2.50000
14+
Explanation: merged array = [1,2,3,4] and median is (2 + 3) / 2 = 2.5.
15+
16+
Example 3:
17+
Input: nums1 = [], nums2 = [1]
18+
Output: 1.00000
19+
20+
'''
21+
22+
class Solution:
23+
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]):
24+
25+
if len(nums1) > len(nums2):
26+
return self.findMedianSortedArrays(nums2, nums1)
27+
28+
lengthA = len(nums1)
29+
lengthB = len(nums2)
30+
31+
low = 0
32+
high = lengthA
33+
34+
while low <= high:
35+
36+
partitionA = low + (high - low)//2
37+
partitionB = ((lengthA + lengthB + 1)//2) - partitionA
38+
39+
maxLeftA = nums1[partitionA-1] if partitionA != 0 else float('-inf')
40+
minRightA = nums1[partitionA] if partitionA < lengthA else float('inf')
41+
42+
maxLeftB = nums2[partitionB-1] if partitionB != 0 else float('-inf')
43+
minRightB = nums2[partitionB] if partitionB < lengthB else float('inf')
44+
45+
if maxLeftA <= minRightB and maxLeftB <= minRightA:
46+
if (lengthA + lengthB) & 1:
47+
return max(maxLeftA, maxLeftB)
48+
else:
49+
return (max(maxLeftA, maxLeftB) + min(minRightA, minRightB))/2
50+
elif maxLeftA > minRightB:
51+
high = partitionA - 1
52+
else:
53+
low = partitionA + 1

Bitmasking/divide_2_integers.py

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
'''
2+
https://leetcode.com/problems/divide-two-integers/
3+
Given two integers dividend and divisor, divide two integers without using multiplication, division, and mod operator.
4+
Return the quotient after dividing dividend by divisor.
5+
The integer division should truncate toward zero, which means losing its fractional part. For example, truncate(8.345) = 8 and truncate(-2.7335) = -2.
6+
7+
Note:
8+
Assume we are dealing with an environment that could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. For this problem, assume that your function returns 231 − 1 when the division result overflows.
9+
10+
Example 1:
11+
Input: dividend = 10, divisor = 3
12+
Output: 3
13+
Explanation: 10/3 = truncate(3.33333..) = 3.
14+
15+
Example 2:
16+
Input: dividend = 7, divisor = -3
17+
Output: -2
18+
Explanation: 7/-3 = truncate(-2.33333..) = -2.
19+
20+
Example 3:
21+
Input: dividend = 0, divisor = 1
22+
Output: 0
23+
'''
24+
25+
# take a = 10, b = 3
26+
# step 1: 10 - (3) = 7
27+
# step 2: 7 - (3*2) = 1
28+
# step 3: 1 - (3*4) = ...
29+
# each time subtract double the number which we subtracted last time and add number of time in ans
30+
class Solution:
31+
def divide(self, A: int, B: int):
32+
33+
if B == 1:
34+
return A
35+
36+
a = abs(A)
37+
b = abs(B)
38+
res = 0
39+
while a - b >= 0:
40+
x = 0
41+
while (a - (b << x)) >= 0: # 3*1, 3*2, 3*4.... where b = 3 and 2*(..) = x
42+
a -= (b<<x)
43+
res += (1 << x)
44+
x += 1
45+
46+
# check sign
47+
ans = res if ((A >=0 ) == (B >=0)) else -res
48+
49+
# check integer overflow
50+
return ((2**31)-1) if ans < (-(2**31)) or ans > ((2**31) - 1) else ans
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'''
2+
https://leetcode.com/problems/palindrome-partitioning/
3+
Given a string s, partition s such that every substring of the partition is a palindrome.
4+
Return all possible palindrome partitioning of s.
5+
Example:
6+
Input: "aab"
7+
Output:
8+
[
9+
["aa","b"],
10+
["a","a","b"]
11+
]
12+
'''
13+
14+
# use recursion to find all substrings
15+
# store store result of pallindrome in dp
16+
# initialize dp false, if extreme (s[idx] == s[i]) are equal and between them string is also pallindrome(check from dp)
17+
# then current string is also pallindrome
18+
class Solution:
19+
def partition(self, s: str):
20+
21+
def pallindromePartitioning(idx, output):
22+
23+
if idx == n:
24+
ans.append(output)
25+
return
26+
27+
for i in range(idx, n):
28+
# if extreme equal and either length is 2 or string between extreme is pallindrome
29+
if (s[idx] == s[i]) and (i-idx <= 2 or dp[idx+1][i-1]== True):
30+
dp[idx][i] = True
31+
pallindromePartitioning(i+1, output + [s[idx:i+1]])
32+
33+
n, ans = len(s), []
34+
dp = [[False]*n for _ in range(n)]
35+
pallindromePartitioning(0, [])
36+
return ans

Graph/clone_graph.py

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
'''
2+
https://leetcode.com/problems/clone-graph/
3+
Given a reference of a node in a connected undirected graph. Return a deep copy (clone) of the graph.
4+
Each node in the graph contains a val (int) and a list (List[Node]) of its neighbors.
5+
6+
Test case format:
7+
For simplicity sake, each node's value is the same as the node's index (1-indexed). For example, the first node with val = 1, the second node with val = 2, and so on. The graph is represented in the test case using an adjacency list.
8+
Adjacency list is a collection of unordered lists used to represent a finite graph. Each list describes the set of neighbors of a node in the graph.
9+
10+
Example 1:
11+
Input: adjList = [[2,4],[1,3],[2,4],[1,3]]
12+
Output: [[2,4],[1,3],[2,4],[1,3]]
13+
Explanation: There are 4 nodes in the graph.
14+
1st node (val = 1)'s neighbors are 2nd node (val = 2) and 4th node (val = 4).
15+
2nd node (val = 2)'s neighbors are 1st node (val = 1) and 3rd node (val = 3).
16+
3rd node (val = 3)'s neighbors are 2nd node (val = 2) and 4th node (val = 4).
17+
4th node (val = 4)'s neighbors are 1st node (val = 1) and 3rd node (val = 3).
18+
19+
Example 2:
20+
Input: adjList = [[]]
21+
Output: [[]]
22+
Explanation: Note that the input contains one empty list. The graph consists of only one node with val = 1 and it does not have any neighbors.
23+
24+
Example 4:
25+
Input: adjList = [[2],[1]]
26+
Output: [[2],[1]]
27+
'''
28+
29+
'''
30+
Definition for a Node.
31+
class Node:
32+
def __init__(self, val = 0, neighbors = None):
33+
self.val = val
34+
self.neighbors = neighbors if neighbors is not None else []
35+
'''
36+
37+
# method - 1
38+
from collections import defaultdict, deque
39+
class Solution:
40+
def cloneGraph(self, node: 'Node'):
41+
42+
if node == None:
43+
return None
44+
45+
visited = defaultdict(bool)
46+
copyvisited = defaultdict()
47+
queue = deque()
48+
49+
src = Node(node.val)
50+
queue.append([node, src])
51+
copyvisited[node.val] = src
52+
53+
while len(queue) > 0:
54+
55+
original, copy = queue.popleft()
56+
visited[original] = True
57+
58+
for nbr in original.neighbors:
59+
# if node is not visited
60+
if not visited[nbr]:
61+
# if node is already created by some other node then refer that node else create
62+
if nbr.val not in copyvisited:
63+
child = Node(nbr.val)
64+
copyvisited[nbr.val] = child
65+
else:
66+
child = copyvisited[nbr.val]
67+
68+
copy.neighbors.append(child)
69+
child.neighbors.append(copy)
70+
71+
queue.append([nbr, child])
72+
73+
return src
74+
75+
# method - 2
76+
from collections import deque
77+
class Solution:
78+
def cloneGraph(self, node: 'Node'):
79+
80+
if node == None:
81+
return None
82+
83+
# keep mapping of node: clone
84+
clone = {}
85+
queue = deque()
86+
cloneroot = Node(node.val)
87+
88+
clone = {node: cloneroot}
89+
queue.append(node)
90+
91+
while len(queue) > 0:
92+
93+
n = queue.popleft()
94+
95+
# process all neighbors of node
96+
for nbr in n.neighbors:
97+
# if node is not created then create, add in map and queue
98+
if nbr not in clone:
99+
child = Node(nbr.val)
100+
clone[nbr] = child
101+
queue.append(nbr)
102+
# if already created then only refer and no need to append in queue as it is seen already and processed
103+
# but needed to be connect by some other node
104+
else:
105+
child = clone[nbr]
106+
# always append the neighbors
107+
clone[n].neighbors.append(child)
108+
109+
return cloneroot
110+
111+

0 commit comments

Comments
 (0)