forked from SamirPaulb/DSAlgo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Samir Paul
committed
May 25, 2022
1 parent
8471ee2
commit 6f50c22
Showing
29 changed files
with
1,135 additions
and
0 deletions.
There are no files selected for viewing
43 changes: 43 additions & 0 deletions
43
04_LinkedList/Check if a LinkedList is palindrome or not..py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# https://leetcode.com/problems/palindrome-linked-list/ | ||
|
||
''' | ||
Go to the middle node and reverse the right-side linkedlist. | ||
Then take 2 pointers one from start and another from middle and check | ||
equality of value. | ||
''' | ||
|
||
class Solution: | ||
def isPalindrome(self, head: Optional[ListNode]) -> bool: | ||
if not head or not head.next: return True | ||
|
||
# Find Middle | ||
slow = head | ||
fast = head.next | ||
while fast and fast.next: | ||
slow = slow.next | ||
fast = fast.next.next | ||
# slow is just the previous node of middle as we need to reverse the Linkedlist also | ||
|
||
# Reverse LinkedList right-side of middle | ||
pre = slow | ||
cur = pre.next | ||
nex = cur.next | ||
|
||
while nex: | ||
cur.next = nex.next | ||
nex.next = pre.next | ||
pre.next = nex | ||
nex = cur.next | ||
|
||
# start checking equality of values | ||
left = head | ||
right = slow.next | ||
while left and right: | ||
if left.val != right.val: return False | ||
left = left.next | ||
right = right.next | ||
|
||
return True | ||
|
||
# Time: O(N) | ||
# Space: O(1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# https://leetcode.com/problems/intersection-of-two-linked-lists/ | ||
|
||
class Solution: | ||
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]: | ||
a = headA | ||
b = headB | ||
loopCount = 0 # if no intersection | ||
|
||
while True: | ||
if a == b: return a | ||
|
||
a = a.next | ||
b = b.next | ||
|
||
if not a: a = headB; loopCount += 1 | ||
if not b: b = headA | ||
|
||
if loopCount > 1: return None | ||
|
||
# Time: O(n + m) | ||
# Space: O(1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# https://practice.geeksforgeeks.org/problems/flattening-a-linked-list/1 | ||
|
||
''' | ||
Select 2 bottom directed linklist at a time and use the concept of "21. Merge Two Sorted Lists" | ||
on them. Start traversing from the begining. Assign 'a' linkedList wirh smaller head and | ||
'b' to the larger head. Change main head to a. At the end we will have the sorted Linkedlist with only bottom pointer. | ||
Input: | ||
a b c => take 'a' at smaller head | ||
5 -> 10 -> 19 -> 28 | ||
| | | | | ||
7 20 22 35 | ||
| | | | ||
8 50 40 | ||
| | | ||
30 45 | ||
Output: 5-> 7-> 8- > 10 -> 19-> 20-> 22-> 28-> 30-> 35-> 40-> 45-> 50 bottom pointer | ||
''' | ||
|
||
|
||
''' | ||
class Node: | ||
def __init__(self, d): | ||
self.data=d | ||
self.next=None | ||
self.bottom=None | ||
''' | ||
|
||
def flatten(head): | ||
while head: | ||
if not head.next: return head | ||
|
||
if head.data <= head.next.data: | ||
a = head | ||
b = head.next | ||
c = b.next | ||
else: | ||
a = head.next | ||
b = head | ||
c = a.next | ||
head = head.next | ||
|
||
while a: | ||
if b and a.bottom and a.bottom.data > b.data: | ||
tmp = a.bottom | ||
a.bottom = b | ||
b = tmp | ||
elif not a.bottom: | ||
a.bottom = b | ||
b = None | ||
elif not a.bottom and not b: | ||
a.bottom = c | ||
break | ||
a = a.bottom | ||
head.next = c | ||
|
||
return head | ||
|
||
|
||
# Time Complexity: O(N*N*M) | ||
# Auxiliary Space: O(1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# https://www.codingninjas.com/codestudio/problems/implement-trie_1387095 | ||
|
||
# https://youtu.be/ict1UawpXMM?t=359 | ||
|
||
class TrieNode: | ||
def __init__(self): | ||
self.children = {} | ||
self.endOfWordCount = 0 | ||
self.prefixOfWordCount = 0 | ||
|
||
class Trie: | ||
def __init__(self): | ||
self.root = TrieNode() | ||
|
||
def insert(self, word): | ||
cur = self.root | ||
for c in word: | ||
if c not in cur.children: | ||
cur.children[c] = TrieNode() | ||
cur = cur.children[c] | ||
cur.prefixOfWordCount += 1 | ||
cur.endOfWordCount += 1 | ||
|
||
def countWordsEqualTo(self, word): | ||
cur = self.root | ||
for c in word: | ||
if c not in cur.children: | ||
return 0 | ||
cur = cur.children[c] | ||
return cur.endOfWordCount | ||
|
||
def countWordsStartingWith(self, word): | ||
cur = self.root | ||
for c in word: | ||
if c not in cur.children: | ||
return 0 | ||
cur = cur.children[c] | ||
return cur.prefixOfWordCount | ||
|
||
def erase(self, word): # Dele te function | ||
cur = self.root | ||
toBeDeleted = None | ||
for c in word: # as it a delete function so word is present in trie so we don't need to check if key 'c' present in children hashmap or not. | ||
cur = cur.children[c] | ||
cur.prefixOfWordCount -= 1 | ||
if toBeDeleted: | ||
toBeDeleted = None | ||
if cur.prefixOfWordCount == 0: | ||
toBeDeleted = cur | ||
|
||
if toBeDeleted: | ||
toBeDeleted = None | ||
cur.endOfWordCount -= 1 | ||
|
||
|
||
# It will also work if we don't delete the node only decrease the counts | ||
def erase(self, word): # Dele te function | ||
cur = self.root | ||
for c in word: # as it a delete function so word is present in trie so we don't need to check if key 'c' present in children hashmap or not. | ||
cur = cur.children[c] | ||
cur.prefixOfWordCount -= 1 | ||
|
||
cur.endOfWordCount -= 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# https://leetcode.com/problems/maximum-xor-of-two-numbers-in-an-array/ | ||
|
||
''' | ||
Insert all the elements of nums in a trie with bit values in respective position. | ||
where every node can have 2 children either with 0 key or 1 key. | ||
As XOR is a inequality detector so we try to maximize the inequality between num and node. | ||
So that the XOR of num and value of node will give the max value. | ||
So we do the following steps While traversing the num from 31'th bit position to 0'th bit position: | ||
If the current bit of num is 1 then we try to move the cur pointer towards the child with 0 key. | ||
And if the current bit of num is 0 then we try to move the cur pointer towards the child with 1 key. | ||
''' | ||
|
||
class TrieNode: | ||
def __init__(self): | ||
self.children = {} | ||
self.val = -1 # used to store the value of entire number at the end of trie node | ||
|
||
class Trie: | ||
def __init__(self): | ||
self.root = TrieNode() # object of trienode class | ||
|
||
def addNum(self, num): | ||
cur = self.root # every time start from root | ||
for i in range(31, -1, -1): | ||
bit = 1 if num & (1 << i) else 0 # bit value i'th position of num | ||
if bit not in cur.children: | ||
cur.children[bit] = TrieNode() | ||
cur = cur.children[bit] | ||
cur.val = num # storing the value of entire num at the end of trie node | ||
|
||
|
||
class Solution: | ||
def findMaximumXOR(self, nums: List[int]) -> int: | ||
trie = Trie() # creating object of Trie class | ||
for num in nums: # adding all num to the trie structure | ||
trie.addNum(num) | ||
|
||
res = 0 | ||
for num in nums: | ||
cur = trie.root # every time start cur pointer from root | ||
for i in range(31, -1, -1): | ||
bit = 1 if num & (1 << i) else 0 # bit value of i'th position of num | ||
if bit == 1: # try to move towards opposite key ie. 0 | ||
if 0 in cur.children: # opposit key 0 exist then defenetly go towards the child 0 | ||
cur = cur.children[0] | ||
else: # opposit key 0 not exist so we have only option to go towards what we have ie. 1 | ||
cur = cur.children[1] | ||
else: # bit == 0 # try to move towards opposite key ie. 1 | ||
if 1 in cur.children: # opposit key 1 exist then defenetly go towards the child 1 | ||
cur = cur.children[1] | ||
else: # opposit key 1 not exist so we have only option to go towards what we have ie. 0 | ||
cur = cur.children[0] | ||
# as we tried to maximize the inequality between cur.val and num so XOR of them will give max value | ||
res = max(res, cur.val ^ num) | ||
|
||
return res | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# https://www.codingninjas.com/codestudio/problems/count-distinct-substrings_985292 | ||
# https://youtu.be/RV0QeTyHZxo | ||
class TrieNode: | ||
def __init__(self): | ||
self.children = {} | ||
|
||
class Trie: | ||
def __init__(self): | ||
self.root = TrieNode() | ||
def solve(self, s): | ||
res = 0 | ||
for i in range(len(s)): | ||
cur = self.root | ||
for j in range(i, len(s)): | ||
if s[j] not in cur.children: | ||
cur.children[s[j]] = TrieNode() | ||
res += 1 | ||
cur = cur.children[s[j]] | ||
return res + 1 # +1 for empty substring "" | ||
|
||
def countDistinctSubstrings(s): | ||
trie = Trie() | ||
return trie.solve(s) | ||
|
||
|
||
# Time: O(N^2) | ||
# Space: It is hard to predict spcace taken tries. It depends on the distinct elements of s. But as we are using only necessary keys in trie hashmap not all 26 keys so at max space can be N^2 | ||
# Space: in worst case O(N^2) | ||
|
37 changes: 37 additions & 0 deletions
37
11_Binary-Search/Aggressive Cows - Advanced Binary Search.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# https://www.codingninjas.com/codestudio/problems/aggressive-cows_1082559?leftPanelTab=1 | ||
# https://youtu.be/YTTdLgyqOLY?t=2626 | ||
''' | ||
Same binary search approach like 'Minimum Page Allocation Problem'. | ||
In the isValid function we need to check if with the current distance 'mid' | ||
we can place all the cows in the stalls or not. If we can place all the cows then | ||
try to increase the mid(ie. increase the low). If we can not place all cows then | ||
that distsnce(ie. mid) we need to decrease the distance etween cows ie. dicrease the | ||
mid. | ||
''' | ||
def aggressiveCows(stalls, k): | ||
def isValid(mid): | ||
count = 1 # count of cows | ||
lastPosition = stalls[0] # position where we recently placed the cow | ||
for i in range(1, len(stalls)): | ||
if stalls[i] - lastPosition >= mid: # checking if we can place cow in this i'th position | ||
count += 1 | ||
if count == k: return True | ||
lastPosition = stalls[i] | ||
return False | ||
|
||
stalls.sort() # as in isValid() function we need the distance in increasing order | ||
ans = 0 | ||
low = 0 | ||
high = max(stalls) | ||
while low <= high: | ||
mid = low + (high - low) // 2 | ||
if isValid(mid): # check if we can increase the distance or not | ||
ans = max(ans, mid) | ||
low = mid + 1 | ||
else: | ||
high = mid - 1 | ||
|
||
return ans | ||
|
||
# Time: n * log(max(stalls)) | ||
# Space: O(1) |
Oops, something went wrong.