├── LinkedList
├── Lecture 03
│ ├── Delete Node in a Linked List.py
│ ├── Delete Node.cpp
│ ├── Delete Node.java
│ └── README.md
├── Lecture 05
│ ├── Middle of Linked List Approach 2.py
│ ├── Middle of Linked List.py
│ ├── Middle of a Linked List Approach 1.cpp
│ ├── Middle of a Linked List Approach 1.java
│ ├── Middle of a Linked List Approach 2.cpp
│ ├── Middle of a Linked List Approach 2.java
│ └── README.md
├── Lecture 06
│ ├── Convert Binary Number in a Linked List to Integer.py
│ ├── Convert Binary Number in a LinkedList to Integer.cpp
│ ├── Convert Binary Number in a LinkedList to Integer.java
│ └── README.md
├── Lecture 08
│ ├── Design HashSet.cpp
│ ├── Design HashSet.java
│ ├── Design a Hashset.py
│ └── README.md
├── Lecture 09
│ ├── Design Hash Map.py
│ ├── Design HashMap.cpp
│ ├── Design HashMap.java
│ └── README.md
├── Lecture 10
│ ├── README.md
│ ├── Reverse Linked List Approach 1.py
│ ├── Reverse Linked List Approach 2.py
│ ├── Reverse a Linked List Approach 1.cpp
│ ├── Reverse a Linked List Approach 1.java
│ ├── Reverse a Linked List Approach 2.cpp
│ └── Reverse a Linked List Approach 2.java
├── Lecture 11
│ ├── README.md
│ ├── Reverse Nodes in K-Group Approach 2.cpp
│ ├── Reverse Nodes in K-Group Approach 2.java
│ ├── Reverse Nodes in K-Group.java
│ ├── Reverse Nodes in k-Group Approach 1.cpp
│ ├── Reverse Nodes in k-Group Approach 1.py
│ └── Reverse Nodes in k-Group Approach 2.py
├── Lecture 13
│ ├── Merge Two Sorted Lists Approach 1.cpp
│ ├── Merge Two Sorted Lists Approach 1.java
│ ├── Merge Two Sorted Lists Approach 1.py
│ ├── Merge Two Sorted Lists Approach 2.cpp
│ ├── Merge Two Sorted Lists Approach 2.java
│ ├── Merge Two Sorted Lists Approach 2.py
│ └── README.md
├── Lecture 14
│ ├── Merge K Sorted Lists.cpp
│ ├── Merge K Sorted Lists.java
│ ├── Merge K Sorted Lists.py
│ └── README.md
├── Lecture 15
│ ├── README.md
│ ├── Remove Duplicates from Sorted List Approach 1.cpp
│ ├── Remove Duplicates from Sorted List Approach 1.java
│ ├── Remove Duplicates from Sorted List Approach 1.py
│ ├── Remove Duplicates from Sorted List Approach 2.cpp
│ ├── Remove Duplicates from Sorted List Approach 2.java
│ └── Remove Duplicates from Sorted List Approach 2.py
├── Lecture 16
│ ├── Linked List Cycle.cpp
│ ├── Linked List Cycle.java
│ ├── Linked List Cycle.py
│ └── README.md
├── Lecture 17
│ ├── Linked List Cycle II.cpp
│ ├── Linked List Cycle II.java
│ ├── Linked List Cycle II.py
│ └── README.md
├── Lecture 18
│ ├── Intersection of Linked list.cpp
│ ├── Intersection of Linked list.java
│ ├── Intersection of Linked list.py
│ └── README.md
├── Lecture 19
│ ├── Palindrome Linked List.cpp
│ ├── Palindrome Linked List.java
│ ├── Palindrome Linked List.py
│ └── README.md
├── Lecture 20
│ ├── README.md
│ ├── Remove Linked List Elements Approach 1.cpp
│ ├── Remove Linked List Elements Approach 1.java
│ ├── Remove Linked List Elements Approach 1.py
│ ├── Remove Linked List Elements Approach 2.cpp
│ ├── Remove Linked List Elements Approach 2.java
│ ├── Remove Linked List Elements Approach 2.py
│ ├── Remove Linked List Elements Approach 3.cpp
│ └── Remove Linked List Elements Approach 3.java
├── Lecture 21
│ ├── Design Browser History.cpp
│ ├── Design Browser History.java
│ ├── Design Browser History.py
│ └── README.md
├── Lecture 22
│ ├── LRU Cache.cpp
│ ├── LRU Cache.java
│ ├── LRU Cache.py
│ └── README.md
├── Lecture 23
│ ├── Copy List with Random Pointer.cpp
│ ├── Copy List with Random Pointer.java
│ ├── Copy List with Random Pointer.py
│ └── README.md
├── Lecture 24
│ ├── Copy List with Random Pointer Approach 2.cpp
│ ├── Copy List with Random Pointer Approach 2.py
│ └── README.md
└── READEME.md
├── README.md
└── Recursion
├── Lecture 01
└── CodeStudio
│ ├── Factorial of a Number.cpp
│ ├── Factorial of a Number.java
│ ├── Factorial of a Number.js
│ ├── Factorial of a Number.py
│ └── README.md
├── Lecture 03
├── CodeStudio
│ ├── Nth Fibnacci .py
│ ├── Nth Fibnacci Number_Optimised.py
│ ├── Nth Fibonacci Number.cpp
│ ├── Nth Fibonacci Number.java
│ └── README.md
└── LeetCode
│ ├── Fibonacci Number.cpp
│ ├── Fibonacci Number.java
│ ├── Fibonacci Number.py
│ └── README.md
├── Lecture 04
├── CodeStudio
│ ├── Find power of a number.cpp
│ ├── Find power of a number.java
│ ├── Find power of a number.py
│ └── README.md
└── LeetCode
│ ├── Pow(x, n).cpp
│ ├── Pow(x, n).py
│ └── READEME.md
├── Lecture 05
├── CodeStudio
│ ├── Check Palindrome.cpp
│ ├── Check Palindrome.java
│ ├── Check Palindrome.py
│ └── README.md
└── LeetCode
│ ├── README.md
│ ├── Valid Palindrome.cpp
│ └── Valid Palindrome.py
├── Lecture 06
└── CodeStudio
│ ├── README.md
│ ├── Reverse The Array.cpp
│ ├── Reverse The Array.java
│ └── Reverse The Array.py
├── Lecture 07
├── CodeStudio
│ ├── Power Set.cpp
│ ├── Power Set.java
│ ├── Power Set.py
│ └── README.md
└── LeetCode
│ ├── README.md
│ ├── Subsets.cpp
│ ├── Subsets.java
│ └── Subsets.py
├── Lecture 08
├── CodeStudio
│ ├── Permutations of a String.cpp
│ ├── Permutations of a String.java
│ ├── Permutations of a String.py
│ └── README.md
└── LeetCode
│ ├── Permutations II.py
│ ├── Permutations.cpp
│ ├── Permutations.java
│ ├── Permutations.py
│ └── README.md
├── Lecture 09
├── CodeStudio
│ ├── All Unique Permutations lecture code.py
│ ├── All Unique Permutations.cpp
│ ├── All Unique Permutations.java
│ ├── All Unique Permutations_Optimised.py
│ └── README.md
└── LeetCode
│ ├── Permutations II.cpp
│ ├── Permutations II.java
│ ├── Permutations II.py
│ └── README.md
├── Lecture 10
├── CodeStudio
│ ├── README.md
│ ├── Subsets II.cpp
│ └── Subsets II.py
└── LeetCode
│ ├── README.md
│ ├── Subsets II.cpp
│ ├── Subsets II.java
│ └── Subsets II.py
├── Lecture 11
├── CodeStudio
│ ├── Combinations.cpp
│ ├── Combinations.java
│ ├── Combinations.py
│ └── README.md
└── LeetCode
│ ├── Combinations.cpp
│ ├── Combinations.java
│ ├── Combinations.py
│ └── README.md
├── Lecture 12
├── CodeStudio
│ ├── Combination Sum.cpp
│ ├── Combination Sum.java
│ ├── Combination Sum.py
│ └── README.md
└── LeetCode
│ ├── Combination Sum-1.cpp
│ ├── Combination Sum.java
│ ├── Combination Sum.py
│ └── README.md
├── Lecture 13
├── CodeStudio
│ ├── Combination Sum II.cpp
│ ├── Combination Sum II.java
│ ├── Combination Sum-II.py
│ └── README.md
└── LeetCode
│ ├── Combination Sum II.java
│ ├── Combination Sum-2.cpp
│ ├── Combination Sum-II.py
│ └── README.md
├── Lecture 14
├── CodeStudio
│ ├── Combination Sum III.cpp
│ ├── Combination Sum III.java
│ ├── Combination Sum-III.py
│ └── README.md
└── LeetCode
│ ├── Combination Sum III.java
│ ├── Combination Sum-3.cpp
│ ├── Combination Sum-III.py
│ └── README.md
├── Lecture 15
├── CodeStudio
│ ├── Letter Combinations of a Phone Number.cpp
│ ├── Letter Combinations of a Phone Number.java
│ ├── Letter Combinations of a Phone Number.py
│ └── README.md
└── LeetCode
│ ├── Letter Combination of a Phone Number.cpp
│ ├── Letter Combinations of a Phone Number.java
│ ├── Letter Combinations of a Phone Number.py
│ └── README.md
├── Lecture 16
├── CodeStudio
│ ├── Partition to K equal Sum Subsets.java
│ ├── Partition to K equal sum subsets.cpp
│ ├── Partition to K equal sum subsets.py
│ └── README.md
└── LeetCode
│ ├── Partition to K Equal Sum Subsets.cpp
│ ├── Partition to K Equal Sum Subsets.py
│ ├── Partition to K equal Sum Subsets.java
│ └── README.md
├── Lecture 17
├── CodeStudio
│ ├── Maximum Length of a Concatenated String with Unique Characters.cpp
│ ├── Maximum Length of a Concatenated String with Unique Characters.java
│ └── README.md
└── LeetCode
│ ├── Max Length of a Concatenated String with Unique Characters.cpp
│ ├── Maximum Length of a Concatenated String with Unique Characters.java
│ └── README.md
├── Lecture 18
├── CodeStudio
│ ├── Flood Fill Algorithm.cpp
│ ├── Flood Fill Algorithm.java
│ └── README.md
└── LeetCode
│ ├── Flood Fill Algorithm.java
│ ├── Flood Fill.cpp
│ └── README.md
├── Lecture 19
├── CodeStudio
│ ├── README.md
│ └── Word Search.cpp
└── LeetCode
│ ├── README.md
│ └── Word Search.cpp
├── Lecture 20
└── CodeStudio
│ ├── README.md
│ └── Rat in a Maze.cpp
└── Lecture 21
├── CodeStudio
├── N Queens Approach 1.cpp
├── N Queens Approach 2.cpp
└── README.md
└── LeetCode
├── N Queens Approach 1.cpp
├── N Queens Approach 2.cpp
└── README.md
/LinkedList/Lecture 03/Delete Node in a Linked List.py:
--------------------------------------------------------------------------------
1 | # Definition for singly-linked list.
2 | # class ListNode:
3 | # def __init__(self, x):
4 | # self.val = x
5 | # self.next = None
6 |
7 | '''In this problem, we are given the reference to the Node which is to be deleted
8 | Since, we cannot go back to the previous Node in any way and it is guaranteed that the given Node will never be a Tail Node,
9 | Thus, we store Node -> next in temp2 and we swap the data / val of given Node with next Node, and make Node -> next point to Node -> next -> next.
10 | Lastly, we delete temp2
11 | '''
12 |
13 | class Solution:
14 | def deleteNode(self, node):
15 | """
16 | :type node: ListNode
17 | :rtype: void Do not return anything, modify node in-place instead.
18 | """
19 | while node.next: #checking whether next node is None or not
20 | # if it is not None then make its value copy to current Node
21 | # In this Approach We are not using any temporary Node to copy the data
22 | node.val = node.next.val
23 | if node.next.next == None:
24 | node.next = None
25 | break
26 | node = node.next # shift the node pointing to current to current->next in each iteration
27 |
28 |
29 | '''
30 | Time Complexity: O(1)
31 | Space Complexity: O(1)
32 |
33 | '''
34 |
35 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 03/Delete Node.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * struct ListNode {
4 | * int val;
5 | * ListNode *next;
6 | * ListNode(int x) : val(x), next(NULL) {}
7 | * };
8 | */
9 |
10 | /* In this problem, we are given the reference to the Node which is to be deleted
11 | Since, we cannot go back to the previous Node in any way and it is guaranteed that the given Node will never be a Tail Node,
12 | Thus, we store Node -> next in temp2 and we swap the data / val of given Node with next Node, and make Node -> next point to Node -> next -> next.
13 | Lastly, we delete temp2
14 | */
15 |
16 | class Solution {
17 | public:
18 | void deleteNode(ListNode* node) {
19 |
20 | // Since it's given that Last Node will Never be Tail Node, so this condition will never be true
21 |
22 | if(node -> next == NULL)
23 | delete node ;
24 |
25 | // We swap the values of Node and Node's Next Node
26 |
27 | swap(node -> val , node -> next -> val) ;
28 |
29 | // We now need to delete Node's Next Node so we store that Node's address in temp2
30 |
31 | ListNode *temp2 = node -> next ;
32 |
33 | // Lastly, we need to point Node -> next with temp2 -> next(node -> next -> next)
34 |
35 | node -> next = node -> next -> next ;
36 |
37 | delete temp2 ;
38 |
39 | }
40 | };
41 |
42 | /*
43 | Time Complexity: O(1)
44 | Space Complexity: O(1)
45 | */
46 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 03/Delete Node.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * public class ListNode {
4 | * int val;
5 | * ListNode next;
6 | * ListNode(int x) { val = x; }
7 | * }
8 | */
9 |
10 |
11 | // In this problem, we are given the reference to the Node which is to be deleted
12 | // Since, we cannot go back to the previous Node in any way and it is guaranteed that the given Node will never be a Tail Node
13 |
14 | class Solution {
15 |
16 | public void deleteNode(ListNode node) {
17 |
18 | // we copy the value of next node to the current node which is to be deleted.
19 |
20 | node.val=node.next.val;
21 |
22 | // After copying the value , we make the current node next to next of next of current node
23 | // Suppose Linked list is 1 2 3 4 , 2 is to be delete
24 | // First we will copy the 3 to 2 i.e new list will be 1 3 3 4
25 | // now the first 3's next will be 4 , here we can observe that 2 is deleted.
26 |
27 | node.next=node.next.next;
28 |
29 | }
30 |
31 | }
32 | /*
33 | Time Complexity: O(1)
34 | Space Complexity: O(1)
35 | */
--------------------------------------------------------------------------------
/LinkedList/Lecture 03/README.md:
--------------------------------------------------------------------------------
1 | ## 237. Delete Node in a Linked List
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 05/Middle of Linked List Approach 2.py:
--------------------------------------------------------------------------------
1 | # Definition for singly-linked list.
2 | # class ListNode:
3 | # def __init__(self, val=0, next=None):
4 | # self.val = val
5 | # self.next = next
6 |
7 | '''
8 | In 2nd Approach, we don't need to count the Number of Nodes present inside the LinkedList
9 | We will use Two Pointers - Slow and Fast
10 | Slow will move with a Single Node every time
11 | Fast will move with a speed double that of Slow, that is, by Moving Two Nodes everytime
12 | When our Fast will be NULL or our Fast will be at the Last Node, then our Slow pointer will
13 | '''
14 | class Solution:
15 | def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
16 | slow = head
17 | fast = head
18 | # We will come out of the While Loop whenever we our Fast pointer becomes NULL or our Fast pointer is pointing to the Last Node
19 | while fast != None and fast.next != None:
20 | slow = slow.next
21 | fast = fast.next.next
22 |
23 | # At the end, our Slow pointer will be pointing to the Middle of the LinkedList
24 | return slow
25 |
26 | '''
27 | Time Complexity: O(N) { Only a Single iteration is used }
28 | Space Complexity: O(1)
29 | '''
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 05/Middle of Linked List.py:
--------------------------------------------------------------------------------
1 | # Definition for singly-linked list.
2 | # class ListNode:
3 | # def __init__(self, val=0, next=None):
4 | # self.val = val
5 | # self.next = next
6 | ''' In 1st Approach, we will count the Number of Nodes present inside the Linked-List.
7 | Lastly, we will use another While Loop which will run till (N / 2) times.
8 | And the Node where it will stop will be our Middle of LinkedList
9 |
10 | '''
11 | class Solution:
12 | def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
13 | # N will store the number of Nodes present in the Linked List
14 | n = 0
15 | # We always use a temp pointer so that our head pointer doesn't get lost
16 | temp = head
17 | while temp != None:
18 | n+=1
19 | temp = temp.next
20 | # Again we Assign head to temp for thr second iteration
21 | temp = head
22 | half = n//2
23 | # Second While Loop runs till half is greater than 0
24 | while half:
25 | temp = temp.next
26 | half-=1
27 | # At the end our temp Node will be pointing to the middle of the Linked List
28 | return temp
29 | '''
30 | Time Complexity: O(N) { Two iterations are used }
31 | Space Complexity: O(1)
32 | '''
33 |
34 |
35 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 05/Middle of a Linked List Approach 1.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * struct ListNode {
4 | * int val;
5 | * ListNode *next;
6 | * ListNode() : val(0), next(nullptr) {}
7 | * ListNode(int x) : val(x), next(nullptr) {}
8 | * ListNode(int x, ListNode *next) : val(x), next(next) {}
9 | * };
10 | */
11 |
12 | /* In 1st Approach, we will count the Number of Nodes present inside the Linked-List.
13 | Lastly, we will use another While Loop which will run till (N / 2) times.
14 | And the Node where it will stop will be our Middle of LinkedList
15 | */
16 |
17 | class Solution {
18 | public:
19 | ListNode* middleNode(ListNode* head) {
20 |
21 | // N will store the number of Nodes present in the LinkedList
22 |
23 | int n = 0 ;
24 |
25 | // We always use a temp pointer so that our head pointer doesn't get lost
26 |
27 | ListNode *temp = head ;
28 |
29 | // In the first iteration, we count the Number of Nodes present inside the LinkedList
30 |
31 | while(temp != NULL)
32 | {
33 | n++ ;
34 |
35 | temp = temp -> next ;
36 |
37 | }
38 |
39 | // We re-assign temp to head for second iteration
40 |
41 | temp = head ;
42 |
43 | // We calculate half which is N / 2
44 |
45 | int half = n / 2 ;
46 |
47 | // Second While Loop runs till half is greater than 0
48 |
49 | while(half--)
50 | {
51 | temp = temp -> next ;
52 |
53 | }
54 |
55 | // At the end our temp Node will be pointing to the middle of the Linked List
56 |
57 | return temp ;
58 | }
59 | };
60 |
61 | /*
62 | Time Complexity: O(N) { Two iterations are used }
63 | Space Complexity: O(1)
64 | */
65 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 05/Middle of a Linked List Approach 1.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * public class ListNode {
4 | * int val;
5 | * ListNode next;
6 | * ListNode() {}
7 | * ListNode(int val) { this.val = val; }
8 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
9 | * }
10 | */
11 | class Solution {
12 | public ListNode middleNode(ListNode head) {
13 |
14 | // N will store the number of Nodes present in the LinkedList
15 |
16 | int n=0;
17 |
18 | // We always use a temp pointer so that our head pointer doesn't get lost
19 |
20 | ListNode temp=head;
21 |
22 | // In the first iteration, we count the Number of Nodes present inside the LinkedList
23 |
24 | while(temp!=null){
25 |
26 | n++;
27 |
28 | temp=temp.next;
29 |
30 | }
31 | // We re-assign temp to head for second iteration
32 |
33 | temp=head;
34 |
35 | // We calculate half which is N / 2
36 |
37 | int half=n/2;
38 |
39 | // Second While Loop runs till half is greater than 0
40 |
41 | while(half-->0){
42 |
43 | temp=temp.next;
44 |
45 | }
46 | // At the end our temp Node will be pointing to the middle of the Linked List
47 |
48 | return temp;
49 |
50 | }
51 | }
52 |
53 |
54 | /*
55 | Time Complexity: O(N) { Two iterations are used }
56 | Space Complexity: O(1)
57 | */
58 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 05/Middle of a Linked List Approach 2.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * struct ListNode {
4 | * int val;
5 | * ListNode *next;
6 | * ListNode() : val(0), next(nullptr) {}
7 | * ListNode(int x) : val(x), next(nullptr) {}
8 | * ListNode(int x, ListNode *next) : val(x), next(next) {}
9 | * };
10 | */
11 |
12 | /* In 2nd Approach, we don't need to count the Number of Nodes present inside the LinkedList
13 | We will use Two Pointers - Slow and Fast
14 | Slow will move with a Single Node every time
15 | Fast will move with a speed double that of Slow, that is, by Moving Two Nodes everytime
16 | When our Fast will be NULL or our Fast will be at the Last Node, then our Slow pointer will be pointing to the Middle of the LinkedList
17 | */
18 |
19 | class Solution {
20 | public:
21 | ListNode* middleNode(ListNode* head) {
22 |
23 | // Slow and Fast pointers both should be initialised with head
24 |
25 | ListNode *slow = head ;
26 | ListNode *fast = head ;
27 |
28 | // We will come out of the While Loop whenever we our Fast pointer becomes NULL or our Fast pointer is pointing to the Last Node
29 |
30 | while(fast != NULL && fast -> next != NULL)
31 | {
32 | slow = slow -> next ;
33 |
34 | fast = fast -> next -> next ;
35 |
36 | }
37 |
38 | // At the end, our Slow pointer will be pointing to the Middle of the LinkedList
39 |
40 | return slow ;
41 |
42 | }
43 | };
44 |
45 | /*
46 | Time Complexity: O(N) { Only a Single iteration is used }
47 | Space Complexity: O(1)
48 | */
49 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 05/Middle of a Linked List Approach 2.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * public class ListNode {
4 | * int val;
5 | * ListNode next;
6 | * ListNode() {}
7 | * ListNode(int val) { this.val = val; }
8 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
9 | * }
10 | */
11 | class Solution {
12 |
13 | public ListNode middleNode(ListNode head) {
14 |
15 | // Slow and Fast pointers both should be initialised with head
16 |
17 | ListNode slow = head;
18 | ListNode fast = head;
19 |
20 | // We will come out of the while loop whenever we our Fast pointer becomes null or our fast pointer is pointing to the last node
21 |
22 | while (fast != null && fast.next != null) {
23 | slow = slow.next;
24 | fast = fast.next.next;
25 | }
26 | // At the end, our slow pointer will be pointing to the middle of the LinkedList
27 |
28 | return slow;
29 | }
30 | }
31 | /*
32 | Time Complexity: O(N) { Only a Single iteration is used }
33 | Space Complexity: O(1)
34 | */
35 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 05/README.md:
--------------------------------------------------------------------------------
1 | ## 876. Middle of the Linked List
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 06/Convert Binary Number in a Linked List to Integer.py:
--------------------------------------------------------------------------------
1 | # Definition for singly-linked list.
2 | # class ListNode:
3 | # def __init__(self, val=0, next=None):
4 | # self.val = val
5 | # self.next = next
6 |
7 | '''
8 | We are standing at the Head of the Linked-List consisting of only 0 and 1. We need to return the corresponding decimal number after converting the Binary Linked-List to Decimal
9 | We can do this in a single traversal only.
10 | Everytime we stand at a Node, we assume that it is the Last Node and we add it's value to our ans varible
11 | Again, when we encounter another Node, we increment all the powers of the previous Nodes by 1, that is, multiplying our ans by 2
12 |
13 | '''
14 | class Solution:
15 | def getDecimalValue(self, head: ListNode) -> int:
16 | # ans will store our final decimal number after traversing the given LinkedList
17 |
18 | ans = 0
19 | temp = head
20 | while temp != None:
21 | # Everytime we encourage a Node, we multiply ans by 2 to increment the power of all
22 | ans*=2
23 |
24 | # we add the data presentin temp Node to our ans variable
25 | ans+=(temp.val)
26 | temp = temp.next
27 | return ans
28 | '''
29 | Time Complexity: O(N)
30 | Space Complexity: O(1)
31 |
32 | '''
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 06/Convert Binary Number in a LinkedList to Integer.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * struct ListNode {
4 | * int val;
5 | * ListNode *next;
6 | * ListNode() : val(0), next(nullptr) {}
7 | * ListNode(int x) : val(x), next(nullptr) {}
8 | * ListNode(int x, ListNode *next) : val(x), next(next) {}
9 | * };
10 | */
11 |
12 | /* We are standing at the Head of the Linked-List consisting of only 0 and 1. We need to return the corresponding decimal number after converting the Binary Linked-List to Decimal
13 | We can do this in a single traversal only.
14 | Everytime we stand at a Node, we assume that it is the Last Node and we add it's value to our ans varible
15 | Again, when we encounter another Node, we increment all the powers of the previous Nodes by 1, that is, multiplying our ans by 2
16 | */
17 |
18 | class Solution {
19 |
20 | public:
21 | int getDecimalValue(ListNode* head) {
22 |
23 | // ans will store our Final Decimal Number after traversing the given LinkedList
24 |
25 | int ans = 0 ;
26 |
27 | // We move with temp so that it doesn't get lost
28 |
29 | ListNode *temp = head ;
30 |
31 | while(temp != NULL)
32 | {
33 | // Everytime we encounter a Node, we multiply ans by 2 to increment the power of all the previously encountered Nodes by 1
34 |
35 | ans *= 2 ;
36 |
37 | // We add the data present in temp Node to our ans variable
38 |
39 | ans += (temp -> val) ;
40 |
41 | // We move temp to the Next Node
42 |
43 | temp = temp -> next ;
44 | }
45 |
46 | // At the end, we return ans which contains our Decimal Number
47 |
48 | return ans ;
49 | }
50 | };
51 |
52 | /*
53 | Time Complexity: O(N)
54 | Space Complexity: O(1)
55 | */
56 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 06/Convert Binary Number in a LinkedList to Integer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * public class ListNode {
4 | * int val;
5 | * ListNode next;
6 | * ListNode() {}
7 | * ListNode(int val) { this.val = val; }
8 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
9 | * }
10 | */
11 |
12 | /* We are standing at the Head of the Linked-List consisting of only 0 and 1. We need to return the corresponding decimal number after converting the Binary Linked-List to Decimal
13 | We can do this in a single traversal only.
14 | Everytime we stand at a Node, we assume that it is the Last Node and we add it's value to our ans varible
15 | Again, when we encounter another Node, we increment all the powers of the previous Nodes by 1, that is, multiplying our ans by 2
16 | */
17 |
18 | class Solution {
19 |
20 | public int getDecimalValue(ListNode head) {
21 | // ans will store our Final Decimal Number after traversing the given LinkedList
22 |
23 | int ans = 0;
24 |
25 | // We move with temp so that it doesn't get lost
26 |
27 | ListNode temp = head;
28 |
29 | while (temp != null) {
30 | // Everytime we encounter a Node, we multiply ans by 2 to increment the power of all the previously encountered Nodes by 1
31 |
32 | ans *= 2;
33 |
34 | // We add the data present in temp Node to our ans variable
35 |
36 | ans += temp.val;
37 |
38 | // We move temp to the Next Node
39 |
40 | temp = temp.next;
41 | }
42 |
43 | // At the end, we return ans which contains our Decimal Number
44 |
45 | return ans;
46 | }
47 | }
48 | // Time Complexity: O(N)
49 | // Space Complexity: O(1)
50 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 06/README.md:
--------------------------------------------------------------------------------
1 | ## 1290. Convert Binary Number in a Linked List to Integer
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 08/Design HashSet.java:
--------------------------------------------------------------------------------
1 | class MyHashSet {
2 | // We use a ArrayList of Linked List to store all our elements of HashSet Class
3 | ArrayList> list;
4 | int size = 100;
5 |
6 | public MyHashSet() {
7 | // Inside the constructor we initialise arraylist with empty linked list
8 | list = new ArrayList<>(size);
9 | for (int i = 0; i < size; i++) {
10 | list.add(new LinkedList());
11 | }
12 | }
13 |
14 | // Our hash function simply returns the index by taking modulo with list.size()
15 | public int hash(int key) {
16 | return key % list.size();
17 | }
18 | // search operation is being performed here
19 | public int search(int key) {
20 | int i = hash(key);
21 |
22 | LinkedList temp = list.get(i);
23 | int ans = -1;
24 |
25 | for (int j = 0; j < temp.size(); j++) {
26 | if (key == temp.get(j)) {
27 | return j;
28 | }
29 | }
30 | return ans;
31 | }
32 | //Search() function returns us the position where the key is present
33 |
34 | public void add(int key) {
35 | // If the key is already present then there is no need to add again
36 | //Otherwise , we will find the index i where we need to add our key using hash() function
37 | if (search(key) == -1) {
38 | int i = hash(key);
39 | // we add the key at the end in O(1) Time Complexity
40 | list.get(i).add(key);
41 | }
42 | }
43 | // remove method will delete the given key from our ArrayList>
44 | public void remove(int key) {
45 | if (search(key) != -1) {
46 | int i = hash(key);
47 | list.get(i).remove(Integer.valueOf(key));
48 | }
49 | }
50 | // contains() function return true if the key is present , else it will return false
51 | public boolean contains(int key) {
52 | return search(key) != -1;
53 | }
54 | }
55 |
56 | /*
57 | Time Complexity: O(N) --> In the worst case, we need to search the entire list[i] to check if key is present
58 | Space Complexity: O(N) --> We use a ArrayList> list; to store all the Unique Keys
59 | */
60 |
61 |
62 |
63 | /**
64 | * Your MyHashSet object will be instantiated and called as such:
65 | * MyHashSet obj = new MyHashSet();
66 | * obj.add(key);
67 | * obj.remove(key);
68 | * boolean param_3 = obj.contains(key);
69 | */
--------------------------------------------------------------------------------
/LinkedList/Lecture 08/Design a Hashset.py:
--------------------------------------------------------------------------------
1 | '''
2 | We need to design a HashSet Class which contains only Unique Values like any HashSet Class.
3 | Our HashSet class contains the following operations:
4 | a) void add(int key) --> Adds an element into the HashSet
5 | b) void remove(int key) --> Removes the key element from the HashSet
6 | c) bool contains(int key) --> Returns true if key is present in our HashSet else returns false
7 |
8 | Instead of using unneccessary space, we can use limited space by using the concept of Hashing & Chaining
9 | We require chaining to prevent collisions in our HashSet
10 |
11 | '''
12 |
13 |
14 | class MyHashSet:
15 | # We Use a list to store all our elements of Hashset Class
16 |
17 | def __init__(self):
18 | self.L = []
19 |
20 |
21 | def add(self, key: int) -> None:
22 | # add() function adds the given Key into our Hash List at the index specified by our hash() function
23 | # If the key is already present, we don't need to add it again
24 | if key in self.L:
25 | pass
26 | # Otherwise, we will find the index i where we need to add our key using hash() function
27 | else:
28 | # We add the key at the end in O(1) Time Complexity so we appended it to list
29 | self.L.append(key)
30 |
31 | # remove() function deletes the given Key from our List L
32 | def remove(self, key: int) -> None:
33 | # Firstly, we need to check whether our key is present inside our List. If the key is not present, we cannot delete it, thus we directly return
34 | try:
35 | self.L.remove(key)
36 | except:
37 | pass
38 |
39 |
40 | # contains() function returns true if the key is present else returns false
41 | def contains(self, key: int) -> bool:
42 | return key in self.L
43 |
44 |
45 |
46 | # Your MyHashSet object will be instantiated and called as such:
47 | # obj = MyHashSet()
48 | # obj.add(key)
49 | # obj.remove(key)
50 | # param_3 = obj.contains(key)
51 | """"
52 | Time Complexity: O(N) --> In the worst case, we need to search the entire m[i] to check if key is present
53 | Space Complexity: O(N) --> We use a vector> to store all the Unique Keys
54 |
55 | """
56 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 08/README.md:
--------------------------------------------------------------------------------
1 | ## 705. Design HashSet
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 09/README.md:
--------------------------------------------------------------------------------
1 | ## 706. Design HashMap
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 10/README.md:
--------------------------------------------------------------------------------
1 | ## 206. Reverse Linked List
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 10/Reverse Linked List Approach 1.py:
--------------------------------------------------------------------------------
1 | # Definition for singly-linked list.
2 | # class ListNode:
3 | # def __init__(self, val=0, next=None):
4 | # self.val = val
5 | # self.next = next
6 |
7 | '''
8 | To reverse a LinkedList iteratively, we require 3 pointers - Previous(p) , Current(c) and Next(n)
9 | Previous pointer will be initially pointing to NULL
10 | Current pointer will be intially pointing to head
11 | Next pointer will be initally pointing to head -> next
12 | Our While Loop runs till our Current Pointer becomes NULL
13 | Everytime we will make Current Pointer's next point to Previous Pointer
14 | And then move Previous to Current , Current to Next and Next to it's Next Node(if it exists)
15 |
16 | '''
17 | class Solution:
18 | def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
19 | # If head is Equal to None, we don't have a LinkedList to reverse, so we directly return None
20 | if head == None:
21 | return None
22 | # Previous variable(p) initially points to None
23 | p = None
24 | # Current variable(c) initially points to head
25 | c = head
26 |
27 | # Next refrence variable(n) initally points to head -> next
28 |
29 | n = head.next
30 |
31 | #Our Loop runs till Current becomes Not Equal to None
32 | while c is not None:
33 | c.next = p
34 | # We move Previous to Current
35 | p = c
36 | # Current moves to Next
37 | c = n
38 | # Next refrence variable to it's next node
39 | if n != None:
40 | n = n.next
41 |
42 |
43 |
44 | return p
45 |
46 | """
47 | Time Complexity: O(N)
48 | Space Complexity: O(1)
49 | """
50 |
51 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 10/Reverse Linked List Approach 2.py:
--------------------------------------------------------------------------------
1 | # Definition for singly-linked list.
2 | # class ListNode:
3 | # def __init__(self, val=0, next=None):
4 | # self.val = val
5 | # self.next = next
6 |
7 | """
8 | To reverse a LinkedList recursively, we need to design a Recursive function reverse(head) which takes the head of the Head of the intial LinkedList and returns the Head of the Reversed LinkedList
9 | We will just reverse Two Nodes & ask recursion to do rest of the Task
10 | We will just change Reverse Two Nodes: head and the Node next to head
11 | To reverse, we will make head -> next -> next to point to head
12 | After that, we will return the Reversed-Head given to us by LinkedList
13 | We will stop when we are at the Last Node because a Single Node cannot be Reversed
14 |
15 |
16 | """
17 | class Solution:
18 | def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
19 | def reverse(head):
20 | # Base Condition
21 | if head.next == None:
22 | return head
23 |
24 | # Ask Recursion to return head
25 | reverseHead = reverse(head.next)
26 | # Reverse the Adjascent Nodes that is, Head & Head's next Node
27 | head.next.next = head
28 | head.next = None
29 |
30 | # Returns the Reversed Head at the end
31 | return reverseHead
32 | # If head is Equal to NULL, we don't have a LinkedList to reverse, so we directly return NULL
33 | if head == None:
34 | return None
35 | # Otherwise we return the Reversed-Head given to us by the Recursive function reverse()
36 | return reverse(head)
37 |
38 |
39 | """
40 | Time Complexity: O(N)
41 | Space Complexity: O(N) { Auxillary Stack Space of Recursion }
42 |
43 | """
44 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 10/Reverse a Linked List Approach 1.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * struct ListNode {
4 | * int val;
5 | * ListNode *next;
6 | * ListNode() : val(0), next(nullptr) {}
7 | * ListNode(int x) : val(x), next(nullptr) {}
8 | * ListNode(int x, ListNode *next) : val(x), next(next) {}
9 | * };
10 | */
11 |
12 | /* To reverse a LinkedList iteratively, we require 3 pointers - Previous(p) , Current(c) and Next(n)
13 | Previous pointer will be initially pointing to NULL
14 | Current pointer will be intially pointing to head
15 | Next pointer will be initally pointing to head -> next
16 | Our While Loop runs till our Current Pointer becomes NULL
17 | Everytime we will make Current Pointer's next point to Previous Pointer
18 | And then move Previous to Current , Current to Next and Next to it's Next Node(if it exists)
19 | */
20 |
21 | class Solution {
22 | public:
23 | ListNode* reverseList(ListNode* head) {
24 |
25 | // If head is Equal to NULL, we don't have a LinkedList to reverse, so we directly return NULL
26 |
27 | if(head == NULL)
28 | return NULL ;
29 |
30 | // Previous pointer(p) initially points to NULL
31 |
32 | ListNode *p = NULL ;
33 |
34 | // Current pointer(c) initially points to head
35 |
36 | ListNode *c = head ;
37 |
38 | // Next pointer(n) initally points to head -> next
39 |
40 | ListNode *n = head -> next ;
41 |
42 | // Our Loop runs till Current Pointer becomes Not Equal to NULL
43 |
44 | while(c != NULL)
45 | {
46 | // We reverse the Nodes by making Current's next point to Previous
47 |
48 | c -> next = p ;
49 |
50 | // We move Previous to Current Pointer
51 |
52 | p = c ;
53 |
54 | // Current moves to Next Pointer
55 |
56 | c = n ;
57 |
58 | // Next Pointer to it's Next Node(if it exists)
59 |
60 | if(n != NULL)
61 | n = n -> next ;
62 |
63 | }
64 |
65 | // At the end, our Previous Pointer will be the Head of the Reversed LinkedList
66 |
67 | return p ;
68 | }
69 | };
70 |
71 | /*
72 | Time Complexity: O(N)
73 | Space Complexity: O(1)
74 | */
75 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 10/Reverse a Linked List Approach 1.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * public class ListNode {
4 | * int val;
5 | * ListNode next;
6 | * ListNode() {}
7 | * ListNode(int val) { this.val = val; }
8 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
9 | * }
10 | */
11 |
12 | /* To reverse a LinkedList iteratively, we require 3 pointers - Previous(p) , Current(c) and Next(n)
13 | Previous pointer will be initially pointing to null
14 | Current pointer will be intially pointing to head
15 | Next pointer will be initally pointing to head.next
16 | Our while loop runs till our Current Pointer becomes NULL
17 | Everytime we will make Current Pointer's next point to Previous Pointer
18 | And then move Previous to Current , Current to Next and Next to it's Next Node(if it exists)
19 | */
20 |
21 | class Solution {
22 |
23 | public ListNode reverseList(ListNode head) {
24 |
25 | // If head is Equal to null, we don't have a LinkedList to reverse, so we directly return null
26 |
27 | if (head == null) {
28 | return null;
29 | }
30 | // Previous pointer(p) initially points to null
31 |
32 | ListNode p = null;
33 |
34 | // Current pointer(c) initially points to head
35 |
36 | ListNode c = head;
37 |
38 | // Next pointer(n) initally points to head.next
39 |
40 | ListNode n = head.next;
41 |
42 | // Our loop runs till Current Pointer becomes not equal to null
43 |
44 | while (c != null) {
45 |
46 | // We reverse the Nodes by making Current's next pointer to Previous
47 |
48 | c.next = p;
49 | // We move Previous to Current Pointer
50 |
51 | p = c;
52 | // Current moves to Next Pointer
53 |
54 | c = n;
55 | // Next Pointer to it's Next Node(if it exists)
56 |
57 | if (n != null) {
58 | n = n.next;
59 | }
60 | }
61 | // At the end, our Previous Pointer will be the Head of the Reversed LinkedList
62 |
63 | return p;
64 | }
65 | }
66 | /*
67 | Time Complexity: O(N)
68 | Space Complexity: O(1)
69 | */
70 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 10/Reverse a Linked List Approach 2.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * struct ListNode {
4 | * int val;
5 | * ListNode *next;
6 | * ListNode() : val(0), next(nullptr) {}
7 | * ListNode(int x) : val(x), next(nullptr) {}
8 | * ListNode(int x, ListNode *next) : val(x), next(next) {}
9 | * };
10 | */
11 |
12 | /* To reverse a LinkedList recursively, we need to design a Recursive function reverse(head) which takes the head of the Head of the intial LinkedList and returns the Head of the Reversed LinkedList
13 | We will just reverse Two Nodes & ask recursion to do rest of the Task
14 | We will just change Reverse Two Nodes: head and the Node next to head
15 | To reverse, we will make head -> next -> next to point to head
16 | After that, we will return the Reversed-Head given to us by LinkedList
17 | We will stop when we are at the Last Node because a Single Node cannot be Reversed
18 | */
19 |
20 | class Solution {
21 |
22 | private:
23 |
24 | ListNode *reverse(ListNode *head)
25 | {
26 | // Base Condition
27 |
28 | if(head -> next == NULL)
29 | return head ;
30 |
31 | // Ask recursion to return the Reversed Head
32 |
33 | ListNode *reverseHead = reverse(head -> next) ;
34 |
35 | // Reverse the Adjacent Nodes that is, Head & Head's Next Node
36 |
37 | head -> next -> next = head ;
38 |
39 | head -> next = NULL ;
40 |
41 | // Return the Reversed Head at the end
42 |
43 | return reverseHead ;
44 | }
45 | public:
46 | ListNode* reverseList(ListNode* head) {
47 |
48 | // If head is Equal to NULL, we don't have a LinkedList to reverse, so we directly return NULL
49 |
50 | if(head == NULL)
51 | return NULL ;
52 |
53 | // Otherwise we return the Reversed-Head given to us by the Recursive function reverse()
54 |
55 | return reverse(head) ;
56 | }
57 | };
58 |
59 | /*
60 | Time Complexity: O(N)
61 | Space Complexity: O(N) { Auxillary Stack Space of Recursion }
62 | */
63 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 10/Reverse a Linked List Approach 2.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * public class ListNode {
4 | * int val;
5 | * ListNode next;
6 | * ListNode() {}
7 | * ListNode(int val) { this.val = val; }
8 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
9 | * }
10 | */
11 |
12 | /* To reverse a LinkedList recursively, we need to design a Recursive function reverse(head) which takes the head of the Head of the intial LinkedList and returns the Head of the Reversed LinkedList
13 | We will just reverse Two Nodes & ask recursion to do rest of the Task
14 | We will just change Reverse Two Nodes: head and the Node next to head
15 | To reverse, we will make head.next.next to point to head
16 | After that, we will return the Reversed-Head given to us by LinkedList
17 | We will stop when we are at the Last Node because a Single Node cannot be Reversed
18 | */
19 |
20 | class Solution {
21 |
22 | private ListNode reverse(ListNode head) {
23 | // Base Condition
24 |
25 | if (head.next == null) {
26 | return head;
27 | }
28 | // Ask recursion to return the Reversed Head
29 | // Have Faith
30 |
31 | ListNode reverseHead = reverse(head.next);
32 |
33 | // Reverse the Adjacent Nodes that is, Head & Head's Next Node
34 |
35 | head.next.next = head;
36 | head.next = null;
37 |
38 | // Return the Reversed Head at the end
39 |
40 | return reverseHead;
41 | }
42 |
43 | public ListNode reverseList(ListNode head) {
44 |
45 | // If head is Equal to null, we don't have a LinkedList to reverse, so we directly return NULL
46 |
47 | if (head == null) {
48 |
49 | return null;
50 |
51 | }
52 |
53 | // Otherwise we return the Reversed-Head given to us by the Recursive function reverse()
54 |
55 | return reverse(head);
56 | }
57 | }
58 | /*
59 | Time Complexity: O(N)
60 | Space Complexity: O(N) { Auxillary Stack Space of Recursion }
61 | */
62 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 11/README.md:
--------------------------------------------------------------------------------
1 | ## 25. Reverse Nodes in k-Group
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 13/README.md:
--------------------------------------------------------------------------------
1 | ## 21. Merge Two Sorted Lists
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 14/Merge K Sorted Lists.py:
--------------------------------------------------------------------------------
1 | from queue import PriorityQueue
2 | """
3 | In Python A library named Queue Provides already standard implemented Priority Queue under in PriorityQueue Module
4 |
5 | The optimised approach of the problem - Merge K Sorted Lists, involves the usage of Min-Heap
6 |
7 | At the begining, we will be storing only K Elements, into our Min-Heap.
8 | We will also have a dummy Node to keep track of the Head of our Merged LinkedList.
9 | Tail pointer will intially point to dummy but keeps on Nodes in order to form the Merged K Sorted LinkedList
10 | After adding first K Elements, we will use a While Loop which runs till our Priority-Queue has not become empty.
11 | Everytime, we will pick the Top Element from the Priority-Queue(which will also be smallest among all K Nodes present). We will make Tail's Next point to that Top Node. Make Tail shift to that Node. And, also add it's Next Node(if it exists)
12 | By repeating the process, we will have our Merged K Sorted LinkedList ready. The Head of that LinkedList will be pointed by Dummy's Next
13 |
14 |
15 |
16 | """
17 | class Solution:
18 | def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
19 | pq = PriorityQueue()
20 |
21 | for node in lists:
22 | if node:
23 | pq.put((node.val, id(node), node))
24 |
25 | """ Two Dummy nodes have been created """
26 | dummy = ListNode(val=-1)
27 | tail = dummy
28 |
29 | # Loop till Our Prorrity Queue is not Empty
30 | while not pq.empty():
31 | #Fetch the top most value of the Priority Queue
32 | val, _id, node = pq.get()
33 | tail.next = ListNode(val=val)
34 | # Now move tail tail->next
35 | tail = tail.next
36 |
37 | """ We enter Temp's Next Node into our Priority-Queue if it exists """
38 | if node.next:
39 | pq.put((node.next.val, id(node.next), node.next))
40 |
41 | # At the End we return the dummy's next which contains the head address
42 |
43 | return dummy.next
44 | """
45 | Time Complexity: O(N*LogK)
46 | Space Complexity: O(K)
47 |
48 |
49 | """
50 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 14/README.md:
--------------------------------------------------------------------------------
1 | ## 23. Merge k Sorted Lists
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 15/README.md:
--------------------------------------------------------------------------------
1 | ## 83. Remove Duplicates from Sorted List
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 15/Remove Duplicates from Sorted List Approach 1.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * struct ListNode {
4 | * int val;
5 | * ListNode *next;
6 | * ListNode() : val(0), next(nullptr) {}
7 | * ListNode(int x) : val(x), next(nullptr) {}
8 | * ListNode(int x, ListNode *next) : val(x), next(next) {}
9 | * };
10 | */
11 | /* In Approach - 1, we will be discussing the Recursive Solution to remove Duplicates from Sorted LinkedList.
12 | We will check for the values of pointed by Head and Head's Next pointer.
13 | If their values match, then we don't need to include Head in our LinkedList
14 | Otherwise, if the values don't match, then we make Head's Next point to the New-Head pointer given to us by Recursion.
15 | If at any moment our Head has become NULL or our Head's Next is pointing to NULL, that is, we are standing on the Last Node, in that scenario, we will simoly return Head without moving further
16 | */
17 |
18 | class Solution {
19 | public:
20 | ListNode* deleteDuplicates(ListNode* head) {
21 |
22 | // If our Head is NULL , OR , Head's Next is pointing to NULL, we then directly return Head
23 |
24 | if(head == NULL || head -> next == NULL)
25 | return head ;
26 |
27 | // We ask Recursion to remove all Duplicates starting from Head's Next
28 |
29 | ListNode *newHead = deleteDuplicates(head -> next) ;
30 |
31 | // If the values pointed by Head and newHead(given to us by Recursion) are same, we don't need to add Head into our new Sorted LinkedList without any Duplicates, so we directly return newHead
32 |
33 | if(head -> val == newHead -> val)
34 | return newHead ;
35 |
36 | // Otherwise, their values don't match, so we need to include Head into our Linkedlist. So we make Head's Next point oto newHead and we return head
37 |
38 | else
39 | {
40 | head -> next = newHead ;
41 |
42 | return head ;
43 | }
44 |
45 | }
46 | };
47 |
48 | /*
49 | Time Complexity: O(N) { N is the Number of Nodes present in Linkedlist }
50 | Space Complexity: O(N) { Auxillary Recursive Stack Space }
51 | */
52 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 15/Remove Duplicates from Sorted List Approach 1.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * public class ListNode {
4 | * int val;
5 | * ListNode next;
6 | * ListNode() {}
7 | * ListNode(int val) { this.val = val; }
8 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
9 | * }
10 | */
11 | class Solution {
12 | public ListNode deleteDuplicates(ListNode head) {
13 |
14 | // If our Head is null , OR , Head's Next is pointing to NULL, we then directly return Head
15 |
16 | if(head==null || head.next==null){
17 | return head;
18 | }
19 |
20 | // We ask Recursion to remove all Duplicates starting from Head's Next
21 |
22 | ListNode newHead=deleteDuplicates(head.next);
23 |
24 | // If the values pointed by Head and newHead(given to us by Recursion) are same, we don't need to add Head into our new Sorted LinkedList without any Duplicates, so we directly return newHead
25 |
26 | if(head.val==newHead.val){
27 |
28 | return newHead;
29 | }
30 |
31 | // Otherwise, their values don't match, so we need to include Head into our Linkedlist. So we make Head's Next point oto newHead and we return head
32 |
33 |
34 | else{
35 |
36 | head.next=newHead;
37 |
38 | return head;
39 | }
40 |
41 | }
42 | }
43 |
44 | /*
45 | Time Complexity: O(N) { N is the Number of Nodes present in Linkedlist }
46 | Space Complexity: O(N) { Auxillary Recursive Stack Space }
47 | */
48 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 15/Remove Duplicates from Sorted List Approach 1.py:
--------------------------------------------------------------------------------
1 | # Definition for singly-linked list.
2 | # class ListNode:
3 | # def __init__(self, val=0, next=None):
4 | # self.val = val
5 | # self.next = next
6 |
7 | """
8 | In Approach - 1, we will be discussing the Recursive Solution to remove Duplicates from Sorted LinkedList.
9 | We will check for the values of pointed by Head and Head's Next pointer.
10 | If their values match, then we don't need to include Head in our LinkedList
11 | Otherwise, if the values don't match, then we make Head's Next point to the New-Head pointer given to us by Recursion.
12 | If at any moment our Head has become NULL or our Head's Next is pointing to NULL, that is, we are standing on the Last Node, in that scenario, we will simoly return Head without moving further
13 |
14 | """
15 | class Solution:
16 | def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
17 |
18 | # if our head is None or Head's Next is poinitng to None,we then dierectly return Head
19 | if head == None or head.next == None:
20 | return head
21 |
22 | """ We ask Recursion to remove all duplicates starting from Head's next"""
23 | newHead = self.deleteDuplicates(head.next)
24 | # If the values pointed by Head and newHead(given to us by Recursion) are same, we don't need to add Head into our new Sorted LinkedList without any Duplicates, so we directly return newHead
25 | if head.val == newHead.val:
26 | return newHead
27 | else: # Otherwise, their values don't match, so we need to include Head into our Linkedlist
28 | head.next = newHead
29 | return head
30 |
31 | """
32 | Time Complexity: O(N) { N is the Number of Nodes present in Linkedlist }
33 | Space Complexity: O(N) { Auxillary Recursive Stack Space }
34 |
35 |
36 | """
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 15/Remove Duplicates from Sorted List Approach 2.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * public class ListNode {
4 | * int val;
5 | * ListNode next;
6 | * ListNode() {}
7 | * ListNode(int val) { this.val = val; }
8 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
9 | * }
10 | */
11 | class Solution {
12 | public ListNode deleteDuplicates(ListNode head) {
13 |
14 | // If Head is null , OR , Head's Next is null , that is, we have only One Node, in that case, we directly return Head
15 |
16 | if(head==null || head.next==null){
17 | return head;
18 | }
19 |
20 | // Otherwise, we store Head into our Temp Node
21 |
22 | ListNode temp=head;
23 |
24 | // Our While Loop runs till Temp's Next doesn't become NULL
25 |
26 | while(temp.next!=null){
27 |
28 | // If the value of Two Adjacent Nodes are same, we simply Delete Temp's Next Node
29 |
30 | if(temp.val==temp.next.val){
31 |
32 | // We store Temp's Next Node into a Del reference
33 | ListNode del=temp.next;
34 |
35 | // We make Temp's Next point to Del's Next
36 |
37 | temp.next=del.next;
38 |
39 | // But our Temp Pointer moves only when values pointed by Temp & Temp's Next are different
40 |
41 | }else{
42 | temp=temp.next;
43 | }
44 | }
45 |
46 | // At the end, we return Head pointing to the Head of the LinkedList
47 |
48 |
49 | return head;
50 |
51 | }
52 | }
53 |
54 | /*
55 | Time Complexity: O(N) { N is the Number of Nodes present in Linkedlist }
56 | Space Complexity: O(1)
57 | */
58 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 15/Remove Duplicates from Sorted List Approach 2.py:
--------------------------------------------------------------------------------
1 | # Definition for singly-linked list.
2 | # class ListNode:
3 | # def __init__(self, val=0, next=None):
4 | # self.val = val
5 | # self.next = next
6 |
7 | """
8 | In Approach - 2, we will be discussing the Iterative Solution to remove Duplicates from Sorted LinkedList.
9 | In the iterative solution, we will using Temp pointer to iterate over the entire LinkedList. And we will stop whenever our Temp's Next become NULL, that is, we are standing at the Last Node of the LinkedList
10 |
11 | We will check if the values of adjacent nodes , that is , value pointed by Temp & value pointed by Temp's Next are same or not.
12 | If they are same, we will store Temp's Next Node in a Del pointer. And we make Temp's Next point to Del's Next. (If you have any issue understanding this part, please refer to the Lecture's Video or Article)
13 | And we will delete the Del Node.
14 | If the values are not same, in that part, we just need to move Temp to Temp's Next
15 |
16 | """
17 | class Solution:
18 | def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
19 |
20 | # if head is None or Head's next is Noneso in that case return head
21 | if head == None or head.next == None:
22 | return head
23 | # Otherwise store Head into our temp Node
24 | temp = head
25 | # Our while Loop runs till Temp's next node does not became None
26 |
27 | while temp.next != None:
28 | # If the value of Two Adjacent Nodes are same, we simply Delete Temp's Next Node
29 | if temp.val == temp.next.val:
30 | # WE store temp's next Node into a del variable
31 | Del = temp.next
32 | # we make temp's next point Del's next
33 | temp.next = Del.next
34 | # we simply delete Del Node
35 | del Del
36 |
37 | # But our Temp Pointer moves only when values pointed by Temp & Temp's Next are different
38 | else:
39 | temp = temp.next
40 | # at the end we return head of the linked list
41 |
42 | return head
43 |
44 | """
45 | Time Complexity: O(N) { N is the Number of Nodes present in Linkedlist }
46 | Space Complexity: O(1)
47 |
48 | """
49 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 16/Linked List Cycle.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * struct ListNode {
4 | * int val;
5 | * ListNode *next;
6 | * ListNode(int x) : val(x), next(NULL) {}
7 | * };
8 | */
9 |
10 | /* To detect LinkedList Cycle, we will use the concept of Slow and Fast pointer.
11 | We will make our Fast Pointer move with a Speed twice to that of our Slow Pointer.
12 | If there's a Cycle in the LinkedList, then eventually our Fast Pointer will catch our Slow pointer.
13 | Otherwise, if there's no Cycle in the LinkedList, we come out of the While Loop and return false
14 | */
15 |
16 | class Solution {
17 | public:
18 | bool hasCycle(ListNode *head) {
19 |
20 | // Initally, both Fast and Slow pointer will point to Head
21 |
22 | ListNode *fast = head ;
23 | ListNode *slow = head ;
24 |
25 | // While Loop runs till our Fast Pointer doesn't become NULL or our Fast pointer doesn't point to the Last Node of the LinkedList
26 |
27 | while(fast != NULL && fast -> next != NULL)
28 | {
29 | // Slow pointer will move by a Single Node everytime
30 |
31 | slow = slow -> next ;
32 |
33 | // Fast Pointer will move with a speed twice to that of Slow Pointer
34 |
35 | fast = fast -> next -> next ;
36 |
37 | // If there's a Cycle in the LinkedList, then Fast and Slow pointer will eventually meet
38 |
39 | if(fast == slow)
40 | return true ;
41 | }
42 |
43 | // If we come out of the While Loop, it implies there's no Cycle present in the LinkedList, so we return false
44 |
45 | return false ;
46 | }
47 | };
48 |
49 | /*
50 | Time Complexity: O(N)
51 | Space Complexity: O(1)
52 | */
53 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 16/Linked List Cycle.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * class ListNode {
4 | * int val;
5 | * ListNode next;
6 | * ListNode(int x) {
7 | * val = x;
8 | * next = null;
9 | * }
10 | * }
11 | */
12 |
13 |
14 | /* To detect LinkedList Cycle, we will use the concept of Slow and Fast pointer.
15 | We will make our Fast Pointer move with a Speed twice to that of our Slow Pointer.
16 | If there's a Cycle in the LinkedList, then eventually our Fast Pointer will catch our Slow pointer.
17 | Otherwise, if there's no Cycle in the LinkedList, we come out of the While Loop and return false
18 | */
19 |
20 | public class Solution {
21 | public boolean hasCycle(ListNode head) {
22 |
23 | // Initally, both Fast and Slow pointer will point to Head
24 |
25 | ListNode fast=head;
26 | ListNode slow=head;
27 |
28 | // While Loop runs till our Fast Pointer doesn't become null or our Fast pointer doesn't point to the Last Node of the LinkedList
29 |
30 | // fast!=null for even length linked list
31 | // fast.next for odd length linked list
32 |
33 | while(fast!=null && fast.next!=null){
34 |
35 | // Slow pointer will move by a Single Node everytime
36 |
37 | slow=slow.next;
38 |
39 | // Fast Pointer will move with a speed twice to that of Slow Pointer
40 |
41 | fast=fast.next.next;
42 |
43 | // If there's a Cycle in the LinkedList, then Fast and Slow pointer will eventually meet
44 |
45 | if(fast==slow){
46 | return true;
47 | }
48 | }
49 |
50 | // If we come out of the While Loop, it implies there's no Cycle present in the LinkedList, so we return false
51 |
52 | return false;
53 |
54 | }
55 | }
56 |
57 | /*
58 | Time Complexity: O(N)
59 | Space Complexity: O(1)
60 | */
61 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 16/Linked List Cycle.py:
--------------------------------------------------------------------------------
1 | # Definition for singly-linked list.
2 | # class ListNode:
3 | # def __init__(self, x):
4 | # self.val = x
5 | # self.next = None
6 |
7 |
8 | """
9 | To detect LinkedList Cycle, we will use the concept of Slow and Fast pointer.
10 | We will make our Fast Pointer move with a Speed twice to that of our Slow Pointer.
11 | If there's a Cycle in the LinkedList, then eventually our Fast Pointer will catch our Slow pointer.
12 | Otherwise, if there's no Cycle in the LinkedList, we come out of the While Loop and return false
13 |
14 | """
15 |
16 | class Solution:
17 | def hasCycle(self, head: Optional[ListNode]) -> bool:
18 | # Initailly , both fast and slow pointer will point to head
19 | fast = head
20 | slow = head
21 |
22 | # While Loop runs till our fst pointer does nnot None or Our Fst pointer Does not point to last node if linked list
23 |
24 | while fast != None and fast.next != None:
25 | # slow pointer will move by a single node everytime
26 | slow = slow.next
27 |
28 | # fast will move speed twicw that of slow pointer
29 | fast = fast.next.next
30 |
31 | # If there's a Cycle in the LinkedList, then Fast and Slow pointer will eventually meet
32 |
33 | if fast == slow:
34 | return True
35 | return False
36 |
37 | """
38 | Time Complexity: O(N)
39 | Space Complexity: O(1)
40 |
41 | """
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 16/README.md:
--------------------------------------------------------------------------------
1 | ## 141. Linked List Cycle
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 17/Linked List Cycle II.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * struct ListNode {
4 | * int val;
5 | * ListNode *next;
6 | * ListNode(int x) : val(x), next(NULL) {}
7 | * };
8 | */
9 | /* This question is exactly similar to the Linked List Cycle I. Only difference is that in this problem we need to find the Node from where the cycle begins.
10 | But our apporach remains same. We will use 2 pointers - slow & fast where fast moves with a speed double the speed of slow.
11 | If slow and fast meet, then the LinkedList definetly contains a Cycle.
12 | To find the starting point of tat Cycle, we will use 2 pointers again- ptr1 & ptr2
13 | Ptr1 will start from the Head of the LinkedList, while ptr2 will start from the Slow pointer
14 | Both ptr1 & ptr2 will move at the same time. The point where ptr1 & ptr2 meets is the Required Node
15 | */
16 |
17 | class Solution {
18 | public:
19 | ListNode *detectCycle(ListNode *head) {
20 |
21 | // Intially, Slow & Fast pointer both will start from Head of the LinkedList
22 |
23 | ListNode *slow = head ;
24 | ListNode *fast = head ;
25 |
26 | while(fast != NULL && fast -> next != NULL)
27 | {
28 | slow = slow -> next ;
29 |
30 | // Fast Pointer moves with a speed double that speed of Slow pointer
31 |
32 | fast = fast -> next -> next ;
33 |
34 | // If Slow & Fast pointer meets, then there's a Cycle in the LinkedList
35 |
36 | if(slow == fast)
37 | break ;
38 | }
39 |
40 | // If our Fast becomes NULL or our Fast's Next Node is NULL, it means there's No Loop in the LinkedList
41 |
42 | if(fast == NULL || fast -> next == NULL)
43 | return NULL ;
44 |
45 | // To find the starting point of the Loop, ptr1 starts from head while ptr2 starts from slow
46 |
47 | ListNode *ptr1 = head ;
48 | ListNode *ptr2 = slow ;
49 |
50 | while(ptr1 != ptr2)
51 | {
52 | // Ptr1 & Ptr2 moves with the same speed
53 |
54 | ptr1 = ptr1 -> next ;
55 | ptr2 = ptr2 -> next ;
56 | }
57 |
58 | // At the end, both Ptr1 or Ptr2 will point to the starting Node of the LinkedList Cycle / Loop
59 |
60 | return ptr1 ;
61 |
62 | }
63 | };
64 |
65 | /*
66 | Time Complexity: O(N)
67 | Space Complexity: O(1)
68 | */
69 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 17/Linked List Cycle II.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * class ListNode {
4 | * int val;
5 | * ListNode next;
6 | * ListNode(int x) {
7 | * val = x;
8 | * next = null;
9 | * }
10 | * }
11 | */
12 |
13 | /* This question is exactly similar to the Linked List Cycle I. Only difference is that in this problem we need to find the Node from where the cycle begins.
14 | But our apporach remains same. We will use 2 pointers - slow & fast where fast moves with a speed double the speed of slow.
15 | If slow and fast meet, then the LinkedList definetly contains a Cycle.
16 | To find the starting point of tat Cycle, we will use 2 pointers again- ptr1 & ptr2
17 | Ptr1 will start from the Head of the LinkedList, while ptr2 will start from the Slow pointer
18 | Both ptr1 & ptr2 will move at the same time. The point where ptr1 & ptr2 meets is the Required Node
19 | */
20 |
21 | public class Solution {
22 | public ListNode detectCycle(ListNode head) {
23 |
24 | // Intially, Slow & Fast pointer both will start from Head of the LinkedList
25 |
26 | ListNode slow=head;
27 | ListNode fast=head;
28 |
29 | while(fast!=null && fast.next!=null){
30 |
31 | slow=slow.next;
32 |
33 | // Fast Pointer moves with a speed double that speed of Slow pointer
34 |
35 | fast=fast.next.next;
36 |
37 | // If Slow & Fast pointer meets, then there's a Cycle in the LinkedList
38 |
39 | if(slow==fast){
40 | break;
41 | }
42 | }
43 |
44 | // If our Fast becomes NULL or our Fast's Next Node is NULL, it means there's No Loop in the LinkedList
45 |
46 | if(fast==null || fast.next==null){
47 | return null;
48 | }
49 |
50 | // To find the starting point of the Loop, ptr1 starts from head while ptr2 starts from slow
51 |
52 | ListNode ptr1=head;
53 | ListNode ptr2=slow;
54 |
55 | while(ptr1!=ptr2){
56 |
57 | // Ptr1 & Ptr2 moves with the same speed
58 |
59 | ptr1=ptr1.next;
60 |
61 | ptr2=ptr2.next;
62 |
63 | }
64 |
65 | // At the end, both Ptr1 or Ptr2 will point to the starting Node of the LinkedList Cycle / Loop
66 |
67 |
68 | return ptr1;
69 | }
70 |
71 | }
72 |
73 | /*
74 | Time Complexity: O(N)
75 | Space Complexity: O(1)
76 | */
77 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 17/Linked List Cycle II.py:
--------------------------------------------------------------------------------
1 | # Definition for singly-linked list.
2 | # class ListNode:
3 | # def __init__(self, x):
4 | # self.val = x
5 | # self.next = None
6 |
7 | """
8 | This question is exactly similar to the Linked List Cycle I. Only difference is that in this problem we need to find the Node from where the cycle begins.
9 | But our apporach remains same. We will use 2 pointers - slow & fast where fast moves with a speed double the speed of slow.
10 | If slow and fast meet, then the LinkedList definetly contains a Cycle.
11 | To find the starting point of tat Cycle, we will use 2 pointers again- ptr1 & ptr2
12 | Ptr1 will start from the Head of the LinkedList, while ptr2 will start from the Slow pointer
13 | Both ptr1 & ptr2 will move at the same time. The point where ptr1 & ptr2 meets is the Required Node
14 |
15 | """
16 |
17 |
18 | class Solution:
19 | def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
20 |
21 | # Intially, Slow & Fast pointer both will start from Head of the LinkedList
22 | slow = head
23 | fast = head
24 |
25 | # Loop till Fast or Fast's next not None
26 | while fast != None and fast.next != None:
27 | slow = slow.next
28 |
29 | # Fast pointer moves with speed double that of slow pointer
30 | fast = fast.next.next
31 |
32 | # if slow and Fast pointer meets, then there's a Cycle in the LinkedList
33 |
34 | if slow == fast:
35 | break
36 |
37 | # If our Fast becomes NULL or our Fast's Next Node is NULL, it means there's No Loop in the LinkedList
38 | if fast == None or fast.next == None:
39 | return None
40 | # To find the starting point of the Loop, ptr1 starts from head while ptr2 starts from slow
41 | ptr1 = head
42 | ptr2 = slow
43 |
44 | while ptr1 != ptr2:
45 |
46 | # ptr1 and ptr2 moves with same speed
47 | ptr1 = ptr1.next
48 | ptr2 = ptr2.next
49 |
50 | # At the end, both Ptr1 or Ptr2 will point to the starting Node of the LinkedList Cycle / Loop
51 | return ptr1
52 |
53 | """
54 | Time Complexity: O(N)
55 | Space Complexity: O(1)
56 |
57 | """
58 |
59 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 17/README.md:
--------------------------------------------------------------------------------
1 | ## 142. Linked List Cycle II
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 18/Intersection of Linked list.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * struct ListNode {
4 | * int val;
5 | * ListNode *next;
6 | * ListNode(int x) : val(x), next(NULL) {}
7 | * };
8 | */
9 | /* To get the Intersection of Two LinkedLists, we will use Two pointers A & B which will initallly point to HeadA & HeadB respetively
10 | To get the intersection point, we will simply run a While Loop. The While Loop runs A is not equal to B.
11 | And at any moment, if A becomes NULL, we make A point to HeadB
12 | Similarly, at any moment, if B becomes NULL, we make B point to HeadA
13 | In this way, we can get the Intersection point of Two LinkedLists
14 | */
15 |
16 | class Solution {
17 | public:
18 | ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
19 |
20 | // Initally, both A & B points to HeadA & HeadB respectively
21 |
22 | ListNode *a = headA ;
23 | ListNode *b = headB ;
24 |
25 | while(a != b)
26 | {
27 | // If A has become NULL, we assign it to HeadB
28 |
29 | if(a == NULL)
30 | a = headB ;
31 |
32 | // Else we move A to it's Next Node
33 |
34 | else
35 | a = a -> next ;
36 |
37 | // Similarly, if B has become NULL , we assign it to HeadA
38 |
39 | if(b == NULL)
40 | b = headA ;
41 |
42 | // Else we move B to it's Next Node
43 |
44 | else
45 | b = b -> next ;
46 | }
47 |
48 | // At the end, A will point to NULL, if the LinkedList's don't have an Intersection Point
49 | // Otherwise, it will point to the Intersecting Node of the LinkedList
50 |
51 | return a ;
52 |
53 | }
54 | };
55 |
56 | /*
57 | Time Complexity: O(M + N)
58 | Space Complexity: O(1)
59 | */
60 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 18/Intersection of Linked list.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * public class ListNode {
4 | * int val;
5 | * ListNode next;
6 | * ListNode(int x) {
7 | * val = x;
8 | * next = null;
9 | * }
10 | * }
11 | */
12 | public class Solution {
13 | public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
14 |
15 | // Initally, both A & B points to HeadA & HeadB respectively
16 |
17 | ListNode a=headA;
18 | ListNode b=headB;
19 | while(a!=b){
20 |
21 | // If A has become NULL, we assign it to HeadB
22 |
23 | if(a==null){
24 | a=headB;
25 | }
26 |
27 | // Else we move A to it's Next Node
28 |
29 | else{
30 | a=a.next;
31 | }
32 |
33 | // Similarly, if B has become NULL , we assign it to HeadA
34 |
35 |
36 | if(b==null){
37 | b=headA;
38 | }
39 |
40 | // Else we move B to it's Next Node
41 |
42 | else{
43 | b=b.next;
44 | }
45 |
46 | }
47 |
48 | // At the end, A will point to NULL, if the LinkedList's don't have an Intersection Point
49 | // Otherwise, it will point to the Intersecting Node of the LinkedList
50 | return a;
51 |
52 | }
53 | }
54 |
55 |
56 | /*
57 | Time Complexity: O(M + N)
58 | Space Complexity: O(1)
59 | */
60 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 18/Intersection of Linked list.py:
--------------------------------------------------------------------------------
1 | # Definition for singly-linked list.
2 | # class ListNode:
3 | # def __init__(self, x):
4 | # self.val = x
5 | # self.next = None
6 |
7 |
8 | """
9 | To get the Intersection of Two LinkedLists, we will use Two pointers A & B which will initallly point to HeadA & HeadB respetively
10 | To get the intersection point, we will simply run a While Loop. The While Loop runs A is not equal to B.
11 | And at any moment, if A becomes NULL, we make A point to HeadB
12 | Similarly, at any moment, if B becomes NULL, we make B point to HeadA
13 | In this way, we can get the Intersection point of Two LinkedLists
14 |
15 | """
16 | class Solution:
17 | def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
18 |
19 | # intially, both A & B points to HeadA & HeadB respectively
20 |
21 | a = headA
22 | b = headB
23 |
24 | while a != b:
25 |
26 | # if A has became None, we assign it to HeadB
27 |
28 | if a == None:
29 | a = headB
30 |
31 | # Else we move to it's Next Node
32 | else:
33 | a = a.next
34 | # Similarly , if B has became None , we assign it to HeadA
35 |
36 | if b == None:
37 | b = headA
38 | # Else we move B to it's Next Node
39 |
40 | else:
41 | b = b.next
42 |
43 | '''
44 |
45 | At the end, A will point to NULL, if the LinkedList's don't have an Intersection Point
46 | Otherwise, it will point to the Intersecting Node of the LinkedList
47 |
48 | '''
49 | return a
50 | """
51 | Time Complexity: O(M + N)
52 | Space Complexity: O(1)
53 |
54 | """
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 18/README.md:
--------------------------------------------------------------------------------
1 | ## 160. Intersection of Two Linked Lists
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 19/README.md:
--------------------------------------------------------------------------------
1 | ## 234. Palindrome Linked List
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 20/README.md:
--------------------------------------------------------------------------------
1 | ## 203. Remove Linked List Elements
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 20/Remove Linked List Elements Approach 1.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Definition for singly-linked list.
3 | * public class ListNode {
4 | * int val;
5 | * ListNode next;
6 | * ListNode() {}
7 | * ListNode(int val) { this.val = val; }
8 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
9 | * }
10 | */
11 |
12 | /* In Approach - 1, we will use iteration to remove the occurrences of val(key) from the given LinkedList
13 | We will create a Dummy Node to keep track of our new LinkedList after removing all occurrences from the given Linkedlist.
14 | We require another point Tail to traverse the LinkedList. Tail initally points to Dummy
15 | We move Tail till Tail is not Equal to null OR Tail's Next is Not Equal to null.
16 | If Tail's Value is equal to Tail's Next Node's Value, we perform Deletion
17 | Otherwise, we keep moving Tail to Next Node
18 | */
19 |
20 | class Solution {
21 | public ListNode removeElements(ListNode head, int val) {
22 | // If head is null, we directly return null
23 |
24 | if(head == null)
25 | return null ;
26 |
27 | // We create Dummy to keep track of the Linkedlist after removing all occurrences of Val
28 |
29 | ListNode dummy = new ListNode(-1) ;
30 |
31 | dummy.next = head ;
32 |
33 | // Tail initally points to Dummy
34 |
35 | ListNode tail = dummy ;
36 |
37 | while(tail != null && tail.next != null)
38 | {
39 | // If Tail's Next is equal to Val(key)
40 |
41 | if(tail.next.val == val)
42 | {
43 | // We make Temp point to Tail's Next Node
44 |
45 | ListNode temp = tail.next ;
46 |
47 | tail.next = temp.next ;
48 |
49 | }
50 |
51 | // Else the values are not equal, so we make Tail move to Tail's Next Node
52 |
53 | else
54 | {
55 | tail = tail.next ;
56 | }
57 | }
58 |
59 | // At the end, we return Dummy's Next which points to LinkedList after removing all occurrences of Val(key)
60 |
61 | return dummy.next ;
62 |
63 | }
64 | }
--------------------------------------------------------------------------------
/LinkedList/Lecture 20/Remove Linked List Elements Approach 1.py:
--------------------------------------------------------------------------------
1 | # Definition for singly-linked list.
2 | # class ListNode:
3 | # def __init__(self, val=0, next=None):
4 | # self.val = val
5 | # self.next = next
6 | """
7 | In Approach - 1, we will use iteration to remove the occurrences of val(key) from the given LinkedList
8 | We will create a Dummy Node to keep track of our new LinkedList after removing all occurrences from the given Linkedlist.
9 | We require another point Tail to traverse the LinkedList. Tail initally points to Dummy
10 | We move Tail till Tail is not Equal to NULL OR Tail's Next is Not Equal to NULL.
11 | If Tail's Value is equal to Tail's Next Node's Value, we perform Deletion
12 | Otherwise, we keep moving Tail to Next Node
13 |
14 | """
15 |
16 |
17 | class Solution:
18 | def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
19 |
20 | # if head is None , then we dierectly Return it
21 | if head == None:
22 | return head
23 | # We create Dummy to keep track of the Linkedlist after removing all occurrences of Val
24 |
25 | dummy = ListNode(-1)
26 | dummy.next = head
27 |
28 | # Tail initially points to head
29 | tail = dummy
30 |
31 | while tail != None and tail.next != None:
32 |
33 | # if Tail's Next is Equal to Val(key)
34 |
35 | if tail.next.val == val:
36 |
37 | # We make temp to tail's next node
38 | temp = tail.next
39 | tail.next = temp.next
40 | # And then delete temp
41 | del temp
42 | # Else the values are not equal , so we make tail move to tail's next node
43 |
44 | else:
45 | tail = tail.next
46 | # At the end, we return Dummy's Next which points to LinkedList after removing all occurrences of Val(key)
47 | return dummy.next
48 |
49 | """
50 | Time Complexity: O(N)
51 | Space Complexity: O(1)
52 |
53 | """
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 20/Remove Linked List Elements Approach 2.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * struct ListNode {
4 | * int val;
5 | * ListNode *next;
6 | * ListNode() : val(0), next(nullptr) {}
7 | * ListNode(int x) : val(x), next(nullptr) {}
8 | * ListNode(int x, ListNode *next) : val(x), next(next) {}
9 | * };
10 | */
11 | /* In Approach - 2, we will use Recursion to remove the occurrences of val(key) from the given LinkedList
12 | Unlike in iteration, we will ask Recursion to do most of the Task. We will only do a small Task
13 | We will ask recursion to remove all occurrences of Val from LinkedList starting from Head's Next Node and return the newHead
14 | After that we will check if Head's Val is equal to newHead or Not.
15 | If true, we shouldn't add Head into our LinkedList so we return newHead
16 | Else, Value is not equal to Val(Key), so we add Head's Next to newHead and return head
17 | */
18 |
19 | class Solution {
20 | public:
21 | ListNode* removeElements(ListNode* head, int val)
22 | {
23 | // If head is NULL, wr directly return NULL
24 |
25 | if(head == NULL)
26 | return NULL ;
27 |
28 | // Otherwise, we ask Recursion to do rest of the task and remove all the occurrences of Val(Key) starting from Head's Next Node
29 |
30 | head -> next = removeElements(head -> next , val) ;
31 |
32 | // If Head' Value is equal to Val(Key)
33 |
34 | if(head -> val == val)
35 | {
36 | // We store Head's Next in Ans pointer
37 |
38 | ListNode *ans = head -> next ;
39 |
40 | // We delete Head
41 |
42 | delete head ;
43 |
44 | // We return Ans
45 |
46 | return ans ;
47 | }
48 |
49 | // Else, Head will be a part our LinkedList, so we return Head
50 |
51 | else
52 | {
53 | return head ;
54 | }
55 | }
56 | };
57 |
58 | /*
59 | Time Complexity: O(N)
60 | Space Complexity: O(N) { Auxillary Stack Space }
61 | */
62 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 20/Remove Linked List Elements Approach 2.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Definition for singly-linked list.
3 | * public class ListNode {
4 | * int val;
5 | * ListNode next;
6 | * ListNode() {}
7 | * ListNode(int val) { this.val = val; }
8 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
9 | * }
10 | */
11 |
12 | /* In Approach - 2, we will use Recursion to remove the occurrences of val(key) from the given LinkedList
13 | Unlike in iteration, we will ask Recursion to do most of the Task. We will only do a small Task
14 | We will ask recursion to remove all occurrences of Val from LinkedList starting from Head's Next Node and return the newHead
15 | After that we will check if Head's Val is equal to newHead or Not.
16 | If true, we shouldn't add Head into our LinkedList so we return newHead
17 | Else, Value is not equal to Val(Key), so we add Head's Next to newHead and return head
18 | */
19 |
20 | class Solution {
21 | public ListNode removeElements(ListNode head, int val) {
22 | // If head is null, wr directly return null
23 |
24 | if(head == null)
25 | return null ;
26 |
27 | // Otherwise, we ask Recursion to do rest of the task and remove all the occurrences of Val(Key) starting from Head's Next Node
28 |
29 | head.next = removeElements(head.next , val) ;
30 |
31 | // If Head' Value is equal to Val(Key)
32 |
33 | if(head.val == val)
34 | {
35 | // We store Head's Next in Ans pointer
36 |
37 | ListNode ans = head.next ;
38 | // We return Ans
39 |
40 | return ans ;
41 | }
42 |
43 | // Else, Head will be a part our LinkedList, so we return Head
44 |
45 | else
46 | {
47 | return head ;
48 | }
49 |
50 | }
51 | }
52 | /*
53 | Time Complexity: O(N)
54 | Space Complexity: O(N) { Auxillary Stack Space }
55 | */
56 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 20/Remove Linked List Elements Approach 2.py:
--------------------------------------------------------------------------------
1 | # Definition for singly-linked list.
2 | # class ListNode:
3 | # def __init__(self, val=0, next=None):
4 | # self.val = val
5 | # self.next = next
6 |
7 | """
8 | In Approach - 2, we will use Recursion to remove the occurrences of val(key) from the given LinkedList
9 | Unlike in iteration, we will ask Recursion to do most of the Task. We will only do a small Task
10 | We will ask recursion to remove all occurrences of Val from LinkedList starting from Head's Next Node and return the newHead
11 | After that we will check if Head's Val is equal to newHead or Not.
12 | If true, we shouldn't add Head into our LinkedList so we return newHead
13 | Else, Value is not equal to Val(Key), so we add Head's Next to newHead and return head
14 |
15 | """
16 |
17 | class Solution:
18 | def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
19 | # if head is None then dierectly return it
20 |
21 | if head == None:
22 | return head
23 |
24 | # Otherwise , we ask Recursion to do the task and remove all the occurences of Val(Key) starting from Head's Next Node
25 | head.next = self.removeElements(head.next,val)
26 |
27 | # if Head's Value is equal to Val(key)
28 |
29 | if head.val == val:
30 | # we store head's next in ans pointer
31 | ans = head.next
32 |
33 | # we delete head
34 |
35 | del head
36 |
37 | # we return Ans
38 | return ans
39 | else:
40 | return head
41 |
42 | """
43 | Time Complexity: O(N)
44 | Space Complexity: O(N) { Auxillary Stack Space }
45 |
46 | """
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 20/Remove Linked List Elements Approach 3.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * struct ListNode {
4 | * int val;
5 | * ListNode *next;
6 | * ListNode() : val(0), next(nullptr) {}
7 | * ListNode(int x) : val(x), next(nullptr) {}
8 | * ListNode(int x, ListNode *next) : val(x), next(next) {}
9 | * };
10 | */
11 | /* In Approach - 3, we will again use Recursion to remove the occurrences of val(key) from the given LinkedList.
12 | All our logic remains the same, but our code becomes more compact and clean (3 - liner code)
13 | */
14 |
15 | class Solution {
16 | public:
17 | ListNode* removeElements(ListNode* head, int val)
18 | {
19 | // If head is NULL, wr directly return NULL
20 |
21 | if(head == NULL)
22 | return NULL ;
23 |
24 | // We ask recursion to do rest of the task
25 |
26 | head -> next = removeElements(head -> next , val) ;
27 |
28 | // We make our code more compact using Ternary Operator
29 | // The Logic still remains the same. Only difference is that we are not actually deleteing the Head Node if it's Value is equal to Val(Key)
30 |
31 | return head -> val == val? head -> next : head ;
32 | }
33 | };
34 |
35 | /*
36 | Time Complexity: O(N)
37 | Space Complexity: O(N) { Auxillary Stack Space }
38 | */
39 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 20/Remove Linked List Elements Approach 3.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Definition for singly-linked list.
3 | * public class ListNode {
4 | * int val;
5 | * ListNode next;
6 | * ListNode() {}
7 | * ListNode(int val) { this.val = val; }
8 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
9 | * }
10 | */
11 |
12 | /* In Approach - 3, we will again use Recursion to remove the occurrences of val(key) from the given LinkedList.
13 | All our logic remains the same, but our code becomes more compact and clean (3 - liner code)
14 | */
15 |
16 | class Solution {
17 | public ListNode removeElements(ListNode head, int val) {
18 | // If head is null, wr directly return null
19 |
20 | if(head == null)
21 | return null ;
22 |
23 | // We ask recursion to do rest of the task
24 |
25 | head.next = removeElements(head.next , val) ;
26 |
27 | // We make our code more compact using Ternary Operator
28 | // The Logic still remains the same. Only difference is that we are not actually deleteing the Head Node if it's Value is equal to Val(Key)
29 |
30 | return head.val == val? head.next : head ;
31 |
32 | }
33 | }
34 |
35 | /*
36 | Time Complexity: O(N)
37 | Space Complexity: O(N) { Auxillary Stack Space }
38 | */
39 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 21/Design Browser History.java:
--------------------------------------------------------------------------------
1 | class BrowserHistory {
2 | int current;
3 | ArrayList history;
4 | public BrowserHistory(String homepage) {
5 | this.history = new ArrayList<>();
6 | history.add(homepage);
7 | this.current = 0;
8 | }
9 |
10 | public void visit(String url) {
11 |
12 | //delete forward history
13 |
14 | while (history.size()-1 > current) {
15 | //which means delete everything beyond our current website
16 | history.remove(history.size()-1);
17 | }
18 | history.add(url);
19 | ++current;
20 | }
21 |
22 | public String back(int steps) {
23 |
24 | //if we can't get enough back, we return first thing in our history
25 |
26 | if (steps>current) current = 0;
27 |
28 | //if there will be no arrayindexoutofrange error, go back
29 |
30 | else current -= steps;
31 |
32 | //return current webpage
33 |
34 | return history.get(current);
35 | }
36 |
37 | public String forward(int steps) {
38 |
39 | //if we are going to move more than our arraylist then we will return the last element
40 |
41 | if (steps+current>=history.size()) current = history.size() - 1;
42 |
43 | //if there will be no arrayindexoutofrange error, go forward!
44 |
45 | else current += steps;
46 |
47 | return history.get(current);
48 |
49 | //return the current webpage
50 | }
51 | }
52 |
53 | /**
54 | * Your BrowserHistory object will be instantiated and called as such:
55 | * BrowserHistory obj = new BrowserHistory(homepage);
56 | * obj.visit(url);
57 | * String param_2 = obj.back(steps);
58 | * String param_3 = obj.forward(steps);
59 | */
--------------------------------------------------------------------------------
/LinkedList/Lecture 21/README.md:
--------------------------------------------------------------------------------
1 | ## 1472. Design Browser History
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 22/README.md:
--------------------------------------------------------------------------------
1 | ## 146. LRU Cache
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 23/Copy List with Random Pointer.java:
--------------------------------------------------------------------------------
1 | /*
2 | // Definition for a Node.
3 | class Node {
4 | int val;
5 | Node next;
6 | Node random;
7 |
8 | public Node(int val) {
9 | this.val = val;
10 | this.next = null;
11 | this.random = null;
12 | }
13 | }
14 | */
15 | class Solution {
16 | public Node copyRandomList(Node head) {
17 |
18 | Node temp=head;
19 |
20 | // We store the Nodes And their Deep Copies inside m M
21 | HashMap m=new HashMap<>();
22 |
23 | // In 1st iteration, we create copies and store the Nodes and their Copies as Key-Value pair inside our Map M
24 |
25 |
26 | while(temp!=null)
27 | {
28 | // We create a Copy of the Given Node using Temp's Value
29 | m.put(temp,new Node(temp.val));
30 | temp=temp.next;
31 | }
32 |
33 | // We again reinitialise Temp to Head to iterate again
34 |
35 | temp=head;
36 |
37 | // In 2nd iteration, we will make connections of the copies stored in Map M
38 |
39 | while(temp!=null)
40 | {
41 | // Writing in the form of array for better understandability
42 | // M[Temp] will give us the Copy Node of Temp
43 | // M[Temp -> Next] will give us th Copy Node of Temp's Next
44 | // Copied Node's Next should point to the Copied Node of Temp's Next
45 | // check out the syntax below
46 |
47 | m.get(temp).next=m.get(temp.next);
48 |
49 | // Similarly, M[Temp -> Random] will give us the Copy Node of Temp's Random
50 |
51 | m.get(temp).random=m.get(temp.random);
52 |
53 | temp=temp.next;
54 | }
55 |
56 | // At the end, we return M[head] which is actually Head of our Copied LinkedList
57 |
58 | return m.get(head);
59 | }
60 | }
61 |
62 | /*
63 | Time Complexity: O(N)
64 | Space Complexity: O(N)
65 | */
66 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 23/README.md:
--------------------------------------------------------------------------------
1 | ## 138. Copy List with Random Pointer
2 |
--------------------------------------------------------------------------------
/LinkedList/Lecture 24/README.md:
--------------------------------------------------------------------------------
1 | ## 138. Copy List with Random Pointer
2 |
--------------------------------------------------------------------------------
/LinkedList/READEME.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LeadCoding Codes
2 |
3 | ## Recursion
4 | 21 Lectures
5 | ## Linked List
6 | 24 Lectures
7 |
8 | # Content
9 |
10 | - The main directories of this repository contains the series
11 | - Each series contains lectures which are taught in the respective series
12 | - Each lecture contains the question, LeetCode solution, and CodeStudio solution
13 | - All the solutions are provided in 4 languages:
14 | - C++
15 | - Java
16 | - Python
17 | - Java Script
18 |
19 |
20 | Subscribe to LeadCoding channel for all the video lectures
21 |
--------------------------------------------------------------------------------
/Recursion/Lecture 01/CodeStudio/Factorial of a Number.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | using namespace std;
3 |
4 | // this function fac() will return us the factorial of the number n
5 | int fac(int n)
6 | {
7 | // base condition
8 | if (n == 0)
9 | return 1;
10 |
11 | // recursion call
12 | return n * fac(n - 1);
13 | }
14 | int main()
15 | {
16 | // Write your code here
17 | int n;
18 | cin >> n;
19 | if (n < 0)
20 | cout << "Error";
21 | else
22 | {
23 | cout << fac(n);
24 | }
25 | return 0;
26 | }
27 |
28 | /*
29 | time complexity : O(n)
30 | space complexity : O(n)
31 | */
32 |
--------------------------------------------------------------------------------
/Recursion/Lecture 01/CodeStudio/Factorial of a Number.java:
--------------------------------------------------------------------------------
1 | import java.io.*;
2 | import java.util.*;
3 |
4 | class Solution {
5 |
6 | // this function fac() will return us the factorial of the number n
7 | static int fac(int n){
8 | if(n==0) return 1;
9 |
10 | // recursion call
11 | return n*fac(n-1);
12 | }
13 |
14 | public static void main(String args[]) {
15 | // Write code here
16 | Scanner sc=new Scanner(System.in);
17 | int n=sc.nextInt();
18 | if(n<0){
19 | System.out.println("Error");
20 | }
21 | else{
22 | System.out.println(fac(n));
23 | }
24 | }
25 | }
26 |
27 | /*
28 | time complexity : O(n)
29 | space complexity : O(n)
30 | */
31 |
--------------------------------------------------------------------------------
/Recursion/Lecture 01/CodeStudio/Factorial of a Number.js:
--------------------------------------------------------------------------------
1 | // this function fac() will return us the factorial of the number n
2 | function fact(n) {
3 | /* Write your code here */
4 | if (n == 0) return 1;
5 | if (n < 0) return "Error";
6 |
7 | // recursion call
8 | else return n * fact(n - 1);
9 | }
10 |
11 | /*
12 | time complexity : O(n)
13 | space complexity : O(n)
14 | */
15 |
--------------------------------------------------------------------------------
/Recursion/Lecture 01/CodeStudio/Factorial of a Number.py:
--------------------------------------------------------------------------------
1 | # Your code goes here
2 | # this function fac() will return us the factorial of the number n
3 | def fac(n):
4 | if n == 0:
5 | return 1
6 |
7 | # recursion call
8 | return n*fac(n-1)
9 |
10 |
11 | n = int(input())
12 | if n < 0:
13 | print("Error")
14 | else:
15 | print(fac(n))
16 |
17 |
18 | """
19 | time complexity: O(n)
20 | space complexity: O(n)
21 | """
22 |
23 |
--------------------------------------------------------------------------------
/Recursion/Lecture 01/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Factorial of a Number
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 03/CodeStudio/Nth Fibnacci .py:
--------------------------------------------------------------------------------
1 | def fib(n):
2 |
3 | # Base case
4 | if n == 0:
5 | return 0
6 | if n == 1 or n == 2:
7 | return 1
8 |
9 |
10 |
11 | ans1 = fib(n -1) # recursion call that will give us the (n-1)th fibo number
12 | ans2 = fib(n - 2) # recursion call that will give us the (n-2)th fibo number
13 | return ans1 + ans2 # will return the addition of (n-1)th & (n-2)th fibo number which is the nth fibo number
14 |
15 | n = int(input())
16 | print(fib(n)) # calling the function
17 |
18 | """ALgorithm
19 | Time complexity : O(2**n)
20 | Space complexity : O(n)
21 | """
22 |
--------------------------------------------------------------------------------
/Recursion/Lecture 03/CodeStudio/Nth Fibnacci Number_Optimised.py:
--------------------------------------------------------------------------------
1 | def fib(n):
2 |
3 | # Base case
4 | if n < 2:
5 | return n
6 |
7 | # memoization | searching for "n" in memo, if available retriving it will save time.
8 | # it'll save redundant calculations
9 | if n in memo:
10 | return memo[n]
11 |
12 | # storing calculated fibonaci numbers in memo, if it's not previously calculated
13 | memo[n-1] = fib(n-1)
14 | memo[n-2] = fib(n-2)
15 |
16 | # Formula for nth fibonachi number is, fib(n) = fib(n-1) + fib(n-2)
17 | return memo[n-1] + memo[n-2]
18 |
19 | n = int(input())
20 | # memo is a dictionary in python | it's refered as a Hashmap is other lang
21 | memo = {}
22 | # calling the function
23 | print(fib(n))
24 |
25 | """
26 | ALgorithm
27 | Time complexity : O(2**n)
28 | Space complexity : O(n)
29 |
30 | MEMOIZING
31 | 1. We have to create A dictionary: with key & value pair as follow | Key == n -> value == fib(n)
32 | 2. store the pair in dictionary for each recursive calls for fib(n) | memo[n] = fin(n)
33 | 3. At the begining of fib function after Base case, To avoid redundant calculation of fib(n)
34 | search for key() -> n if already stored in "memo", If found return that value.
35 |
36 | EXAMPLE | To View redundant calculation in a recursive tree
37 | Link >> https://realpython.com/fibonacci-sequence-python/
38 | """
39 |
40 |
--------------------------------------------------------------------------------
/Recursion/Lecture 03/CodeStudio/Nth Fibonacci Number.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | using namespace std;
3 |
4 | // this function fibo() will return us the nth fibonacci number
5 | int fibo(int n)
6 | {
7 | // base condition
8 | if (n == 1 || n == 2)
9 | return 1;
10 |
11 | // recursion call that will give us the (n-1)th fibo number
12 | int ans1 = fibo(n - 1);
13 |
14 | // recursion call that will give us the (n-2)th fibo number
15 | int ans2 = fibo(n - 2);
16 |
17 | // will return the addition of (n-1)th & (n-2)th fibo number which is actually our nth fibo number that we need
18 | return ans1 + ans2;
19 | }
20 | int main()
21 | {
22 | // Write your code here.
23 | int n;
24 | cin >> n;
25 | n = fibo(n);
26 | cout << n;
27 | }
28 |
29 | /*
30 | time complexity : O(2^n)
31 | space complexity : O(n)
32 | */
33 |
--------------------------------------------------------------------------------
/Recursion/Lecture 03/CodeStudio/Nth Fibonacci Number.java:
--------------------------------------------------------------------------------
1 | import java.util.*;
2 | import java.io.*;
3 | public class Solution {
4 | // this function fibo() will return us the nth fibonacci number
5 | public static int fibo(int n){
6 |
7 | // base condition
8 | if(n==1 || n==2) return 1;
9 |
10 | // recursion call that will return (n-1)th & (n-2)th fibo number which will then be added to give us the nth fibo number
11 | return fibo(n-1)+fibo(n-2);
12 | }
13 |
14 | public static void main(String[] args) {
15 | Scanner sc=new Scanner(System.in);
16 | int n=sc.nextInt();
17 | System.out.println(fibo(n));
18 | }
19 |
20 | }
21 |
22 | /*
23 | time complexity : O(2^n)
24 | space complexity : O(n)
25 | */
26 |
--------------------------------------------------------------------------------
/Recursion/Lecture 03/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Nth Fibonacci Number
2 |
3 | #### NOTE
4 | PYTHON SOLUTIONS ONLY:
5 |
6 | We have two solutions for python:
7 | 1. "Nth Fibonacci Number.py" this solution is taught in the lecture, it is only a recursion-based solution. It may give "TLE" for the upper bound.
8 | 2. "Nth Fibonacci Number_Optimised.py" is an accepted solution, used memoization technique to optimize the solution. Please follow the comments for a better understanding.
9 |
--------------------------------------------------------------------------------
/Recursion/Lecture 03/LeetCode/Fibonacci Number.cpp:
--------------------------------------------------------------------------------
1 | class Solution {
2 | public:
3 | int fib(int n) {
4 |
5 | // base condition
6 | if (n == 0)
7 | return 0;
8 |
9 | if (n == 1 || n == 2)
10 | return 1;
11 |
12 | // recursion call that will give us the (n-1)th fibo number
13 | int ans1 = fib(n - 1);
14 |
15 | // recursion call that will give us the (n-2)th fibo number
16 | int ans2 = fib(n - 2);
17 |
18 | // will return the addition of (n-1)th & (n-2)th fibo number which is actually our nth fibo number that we need
19 | return ans1 + ans2;
20 | }
21 | };
22 |
23 | /*
24 | time complexity : O(2^n)
25 | space complexity : O(n)
26 | */
27 |
--------------------------------------------------------------------------------
/Recursion/Lecture 03/LeetCode/Fibonacci Number.java:
--------------------------------------------------------------------------------
1 | class Solution {
2 | public int fib(int n) {
3 | // base condition
4 | if(n==0)
5 | return 0;
6 | if(n==1 || n==2)
7 | return 1;
8 |
9 | // recursion call that will return (n-1)th & (n-2)th fibo number which will then be added to give us the nth fibo number
10 | return fib(n-1)+fib(n-2);
11 | }
12 | }
13 |
14 | /*
15 | time complexity : O(2^n)
16 | space complexity : O(n)
17 | */
18 |
--------------------------------------------------------------------------------
/Recursion/Lecture 03/LeetCode/Fibonacci Number.py:
--------------------------------------------------------------------------------
1 | class Solution:
2 | def fib(self, n: int) -> int:
3 |
4 | # Base case
5 | if n == 0:
6 | return 0
7 |
8 | if n == 1 or n == 2:
9 | return 1
10 |
11 | # recursion call that will give us the (n-1)th fibo number
12 | ans1 = self.fib(n - 1)
13 |
14 | # recursion call that will give us the (n-2)th fibo number
15 | ans2 = self.fib(n - 2)
16 |
17 | # will return the addition of (n-1)th & (n-2)th fibo number which is the nth fibo number
18 | return ans1 + ans2
19 |
20 | """
21 | ALgorithm
22 | Time complexity : O(2**n)
23 | Space complexity : O(n)
24 |
25 | """
26 |
27 |
--------------------------------------------------------------------------------
/Recursion/Lecture 03/LeetCode/README.md:
--------------------------------------------------------------------------------
1 | ## Fibonacci Number
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 04/CodeStudio/Find power of a number.cpp:
--------------------------------------------------------------------------------
1 | long long Pow(int X, int N)
2 | {
3 | // base condition
4 | if(N==0) return 1;
5 |
6 | // return type is long long & as we are returning temp therefore it also has to be a long long datatype
7 | long long temp=Pow(X,N/2); // recursion call
8 |
9 | // if N is odd then we will have to multiply X
10 | if(N%2==1) return temp*temp*X;
11 | return temp*temp;
12 | }
13 |
14 | /*
15 | time complexity : O(log n)
16 | space complexity : O(log n)
17 | */
18 |
--------------------------------------------------------------------------------
/Recursion/Lecture 04/CodeStudio/Find power of a number.java:
--------------------------------------------------------------------------------
1 | class Solution {
2 |
3 | public static long Pow(int X, int N) {
4 | // base condition
5 | if(N==0) return 1;
6 |
7 | long temp=Pow(X,N/2); // recursion call
8 |
9 | // if N is odd then we will have to multiply X
10 | if(N%2==1) return temp*temp*X;
11 | return temp*temp;
12 | }
13 | }
14 |
15 |
16 | /*
17 | time complexity : O(log n)
18 | space complexity : O(log n)
19 | */
20 |
--------------------------------------------------------------------------------
/Recursion/Lecture 04/CodeStudio/Find power of a number.py:
--------------------------------------------------------------------------------
1 | def pow(X, N):
2 |
3 | # base case
4 | if N == 0:
5 | return 1
6 |
7 | # recurssion call
8 | temp = pow(X, N//2)
9 |
10 | # if N is odd then we will have to multiply x
11 | if N%2 == 1:
12 | return temp*temp*X
13 |
14 | return temp*temp
15 |
16 | """
17 | Algorithm
18 |
19 | time complexity : O(log n)
20 | space complexity : O(log n)
21 | """
22 |
--------------------------------------------------------------------------------
/Recursion/Lecture 04/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Find power of a number
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 04/LeetCode/Pow(x, n).cpp:
--------------------------------------------------------------------------------
1 | class Solution
2 | {
3 | public:
4 | double myPow(double x, int n)
5 | {
6 | // base condition
7 | if (n == 0)
8 | return 1;
9 |
10 | // when n is negative then this if-statement will be execute
11 | if (n < 0)
12 | {
13 | x = 1 / x;
14 | n = abs(n);
15 | }
16 | double temp = myPow(x, n / 2);
17 |
18 | // if N is odd then we will have to multiply X
19 | if (n % 2 == 1)
20 | return temp * temp * x;
21 |
22 | return temp * temp;
23 | }
24 | };
25 |
26 | /*
27 | time complexity : O(log n)
28 | space complexity : O(log n)
29 | */
--------------------------------------------------------------------------------
/Recursion/Lecture 04/LeetCode/Pow(x, n).py:
--------------------------------------------------------------------------------
1 | class Solution:
2 | def myPow(self, x: float, n: int) -> float:
3 |
4 | # base case
5 | if n == 0:
6 | return 1
7 |
8 | # when n is negative then this if-statement will be execute
9 | if n < 0:
10 | x = 1 / x
11 | n = abs(n)
12 |
13 | temp = self.myPow(x, n // 2) # "//" is floor divisinon operator
14 |
15 | # if n is odd then we will have to multiply x
16 | if n % 2 == 1:
17 | return temp * temp * x
18 |
19 | else:
20 | return temp * temp
21 |
22 | """
23 | Algorithm
24 |
25 | time complexity : O(log n)
26 | space complexity : O(log n)
27 | """
28 |
--------------------------------------------------------------------------------
/Recursion/Lecture 04/LeetCode/READEME.md:
--------------------------------------------------------------------------------
1 | ## 50. Pow(x, n)
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 05/CodeStudio/Check Palindrome.cpp:
--------------------------------------------------------------------------------
1 | bool isPalindromeNumber(int l, int r, string &s)
2 | {
3 | // base condition
4 | // l : left pointer, r : right pointer
5 | if (l >= r)
6 | return true;
7 |
8 | // base condition
9 | // when character at s[left] is not equal to character at s[right] that means it is not a palindrome thus return false
10 | if (s[l] != s[r])
11 | return false;
12 |
13 | // recursion call
14 | return isPalindromeNumber(l + 1, r - 1, s);
15 | }
16 |
17 | bool isPalindrome(string &s)
18 | {
19 | // Write your code here.
20 | // here we are going to use two pointer approach
21 | // left pointer starting from first index 0
22 | // right pointer starting from last index s.size() - 1
23 | return isPalindromeNumber(0, s.size() - 1, s);
24 | }
25 |
26 | /*
27 | time complexity : O(n)
28 | space complexity : O(n)
29 | */
--------------------------------------------------------------------------------
/Recursion/Lecture 05/CodeStudio/Check Palindrome.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 | static Boolean helper(int l, int r, String s){
3 | // base condition
4 | // l : left pointer, r : right pointer
5 | if(l>=r) return true;
6 |
7 | // base condition
8 | // when character at s[left] is not equal to character at s[right] that means it is not a palindrome thus return false
9 | if(s.charAt(l)!=s.charAt(r)) return false;
10 |
11 | // recursion call
12 | return helper(l+1,r-1,s);
13 | }
14 |
15 | public static Boolean isPalindrome(String s) {
16 | // Write your code here..
17 | // here we are going to use two pointer approach
18 | // left pointer starting from first index 0
19 | // right pointer starting from last index s.size() - 1
20 | return helper(0,s.length()-1,s);
21 | }
22 | }
23 |
24 | /*
25 | time complexity : O(n)
26 | space complexity : O(n)
27 | */
--------------------------------------------------------------------------------
/Recursion/Lecture 05/CodeStudio/Check Palindrome.py:
--------------------------------------------------------------------------------
1 | def isPalindrome(s: str) -> bool:
2 |
3 | # helper function to check for palindrome
4 | def isPalindromeHelper(l, r, s):
5 |
6 | # Base case, checking if the left pointer crosses the right pointer, or overlaps then it's a palindrome
7 | if l >= r:
8 | return True
9 |
10 | # at any moment if the s[left] != s[right] stop and return Fasle
11 | if s[l] != s[r]:
12 | return False
13 |
14 | return isPalindromeHelper(l+1, r-1, s)
15 |
16 | # Recursive call
17 | return isPalindromeHelper(0, len(s)-1, s)
18 |
19 | """
20 | Algorithm
21 | Tc : O(n/2)
22 | Sc : O(1) || O(n/2) stack memory
23 |
24 | """
25 |
--------------------------------------------------------------------------------
/Recursion/Lecture 05/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Check Palindrome
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 05/LeetCode/README.md:
--------------------------------------------------------------------------------
1 | ## 125. Valid Palindrome
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 05/LeetCode/Valid Palindrome.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | NOTE:
3 | The Question is exactly similar to checking a Palindrome
4 | Only difference is that we need to create a new string which contains only AlphaNumeric characters and all alphabets shoould be in Lower Case only
5 | */
6 |
7 | class Solution {
8 | private :
9 | bool isPalindromeHelper(int l , int r , string &s)
10 | {
11 | // While checking if our left pointer crosses our right pointer, it indicates the string is Palindrome
12 |
13 | if(l >= r)
14 | return true ;
15 |
16 | // At any moment if s[l] != s[r], we are sure it's not an Palindrome
17 |
18 | if(s[l] != s[r])
19 | return false ;
20 |
21 | // Asking recursion to do rest of the task
22 |
23 | return isPalindromeHelper(l + 1 , r - 1 , s) ;
24 | }
25 |
26 | public:
27 | bool isPalindrome(string s) {
28 |
29 | // We need to create a seperate string devoid of spaces and Non-Alphanumeirc Values
30 |
31 | string str = "" ;
32 |
33 | for(char ch : s)
34 | {
35 | // isalnum(ch) returns true if the character is a digit or alpbhabet else returns false
36 |
37 | if(isalnum(ch) == false)
38 | continue ;
39 |
40 | // If ch is equal to white space, we don't include it in our new string
41 |
42 | if(ch == ' ')
43 | continue ;
44 |
45 | // If ch is in Upper-Case, we can convert it in Lower Case easily by adding 32 to it's ASCII Value
46 |
47 | if(isupper(ch) )
48 | ch = ch + 32 ;
49 |
50 | // At the end, we push ch into our new string
51 |
52 | str.push_back(ch) ;
53 |
54 | }
55 |
56 | // If our new string is still empty, we directly return true
57 |
58 | if(str.size() == 0)
59 | return true ;
60 |
61 | bool ans = isPalindromeHelper(0 , str.size() - 1 , str) ;
62 |
63 | return ans ;
64 |
65 | }
66 | };
67 |
68 | /* Time Complexity: O(N)
69 | Space Complexity: O(N)
70 | */
71 |
--------------------------------------------------------------------------------
/Recursion/Lecture 05/LeetCode/Valid Palindrome.py:
--------------------------------------------------------------------------------
1 | class Solution:
2 | def isPalindrome(self, s: str) -> bool:
3 |
4 | def isPalindromeHelper(l, r, s):
5 |
6 | # Base case, checking if the left pointer crosses the right pointer, or overlaps then it's a palindrome
7 | if l >= r:
8 | return True
9 |
10 | # at any moment if the s[left] != s[right] stop and return Fasle
11 | if s[l] != s[r]:
12 | return False
13 |
14 | return isPalindromeHelper(l+1, r-1, s)
15 |
16 | charString = ""
17 |
18 | for char in s:
19 |
20 | # remoes value of indices other then character or digit
21 | if char.isalnum() == False:
22 | continue
23 |
24 | # skipping spaces
25 | if char == " ":
26 | continue
27 |
28 | # converting upperCase to lowerCase
29 | if char.isupper():
30 | char = char.lower()
31 |
32 | # creating string only with characters by string concatination
33 | charString += char
34 |
35 | # recursive function call
36 | ans = isPalindromeHelper(0, len(charString)-1, charString)
37 |
38 | return ans
39 |
40 | """
41 | Algorithm
42 | Tc : O(n)
43 | Sc : O(n)
44 | """
--------------------------------------------------------------------------------
/Recursion/Lecture 06/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Reverse The Array
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 06/CodeStudio/Reverse The Array.cpp:
--------------------------------------------------------------------------------
1 | void reverse(int l, int r, vector &arr)
2 | {
3 | // base condition
4 | if (l >= r)
5 | return;
6 |
7 | // do the small task
8 | swap(arr[l], arr[r]);
9 |
10 | // ask recursion to do the remaining task
11 | reverse(l + 1, r - 1, arr);
12 | }
13 | void reverseArray(vector &arr, int m)
14 | {
15 | // Write your code here.
16 | return reverse(m + 1, arr.size() - 1, arr);
17 | }
18 |
19 | /*
20 | time complexity : O(n)
21 | space complexity : O(n)
22 | */
--------------------------------------------------------------------------------
/Recursion/Lecture 06/CodeStudio/Reverse The Array.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Collections;
3 | public class Solution
4 | {
5 | static int helper(int l, int r,ArrayList arr){
6 | // base condition
7 | if(l>=r) return 1;
8 |
9 | // do the small task
10 | Collections.swap(arr, l, r);
11 |
12 | // ask recursion to do the remaining task
13 | return helper(l+1,r-1,arr);
14 | }
15 | public static void reverseArray(ArrayList arr, int m)
16 | {
17 | // Write your code here.
18 | helper(m+1,arr.size()-1,arr);
19 | }
20 | }
21 |
22 |
23 | /*
24 | time complexity : O(n)
25 | space complexity : O(n)
26 | */
--------------------------------------------------------------------------------
/Recursion/Lecture 06/CodeStudio/Reverse The Array.py:
--------------------------------------------------------------------------------
1 | def reverseArray(arr, m):
2 |
3 | # Function to reverse the required position of array
4 | def helper(l, r):
5 |
6 | # base case
7 | if l >= r:
8 | return arr
9 |
10 | #swapping the indices of the arr
11 | arr[l], arr[r] = arr[r], arr[l]
12 |
13 | # recursive call
14 | return helper(l+1, r-1)
15 |
16 | return helper(m+1, len(arr)-1)
17 | """
18 | Algorithm
19 | TC : O(m/2)
20 | Sc : O(1) || O(m/2) i.e stack memory for recursive call
21 |
22 | NOTE
23 | considering 0 based indexing so the subarray {5, 6} will be reversed and our output array will be {1, 2, 3, 4, 6, 5} """
24 |
--------------------------------------------------------------------------------
/Recursion/Lecture 07/CodeStudio/Power Set.cpp:
--------------------------------------------------------------------------------
1 | void helper(vector &v, int i, vector &subSet, vector> &ans)
2 | {
3 | // base condition
4 | if (i == v.size())
5 | {
6 | ans.push_back(subSet);
7 | return;
8 | }
9 |
10 | // pick the ith element
11 | subSet.push_back(v[i]);
12 | helper(v, i + 1, subSet, ans);
13 |
14 | // backtrack & undo the changes that were made
15 | subSet.pop_back();
16 |
17 | // skip the ith element
18 | helper(v, i + 1, subSet, ans);
19 | }
20 |
21 | vector> pwset(vector v)
22 | {
23 | vector> ans;
24 | vector subSet;
25 | helper(v, 0, subSet, ans);
26 | return ans;
27 | }
28 |
29 | /*
30 | time complexity : O(2^n)
31 | space complexity : O(n)
32 | */
--------------------------------------------------------------------------------
/Recursion/Lecture 07/CodeStudio/Power Set.java:
--------------------------------------------------------------------------------
1 | import java.util.*;
2 | public class Solution
3 | {
4 | static void helper(ArrayList v, int i, ArrayList subSet, ArrayList> ans)
5 | {
6 | // base condition
7 |
8 | if (i == v.size())
9 | {
10 | ans.add(new ArrayList(subSet));
11 | return;
12 | }
13 |
14 | // pick the ith element
15 |
16 | subSet.add(v.get(i));
17 | helper(v, i + 1, subSet, ans);
18 |
19 | // backtrack & undo the changes that were made
20 |
21 | subSet.remove(subSet.size()-1);
22 |
23 | // skip the ith element
24 |
25 | helper(v, i + 1, subSet, ans);
26 | }
27 | public static ArrayList> pwset(ArrayList arr)
28 | {
29 | ArrayList> ans = new ArrayList<>();
30 | ArrayList subSet = new ArrayList<>();
31 | helper(arr, 0, subSet, ans);
32 | return ans;
33 | }
34 | }
35 |
36 | /*
37 | time complexity : O(2^n)
38 | space complexity : O(n)
39 | */
40 |
--------------------------------------------------------------------------------
/Recursion/Lecture 07/CodeStudio/Power Set.py:
--------------------------------------------------------------------------------
1 | def pwset(v):
2 | def helper(v, i, subSet, ans):
3 |
4 | # Our base case will hit when our i pointer reaches the end of given array v[]
5 | if i == len(v):
6 | ans.append(subSet.copy())
7 | return
8 |
9 | # we pick ith Element
10 | subSet.append(v[i])
11 |
12 | # We ask recursion to do rest of the task
13 | helper(v, i+1, subSet, ans)
14 |
15 | # Backtrack and Undo the change we have done
16 | subSet.pop()
17 |
18 | # We don't pick the ith element
19 | helper(v, i+1, subSet, ans)
20 |
21 | # varibles in pwset() scope
22 | ans = []
23 | subSet = []
24 | # Helper will store the ans in ans list
25 | helper(v, 0, subSet, ans)
26 | return ans
27 |
--------------------------------------------------------------------------------
/Recursion/Lecture 07/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Power Set
--------------------------------------------------------------------------------
/Recursion/Lecture 07/LeetCode/README.md:
--------------------------------------------------------------------------------
1 | ## 78. Subsets
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 07/LeetCode/Subsets.cpp:
--------------------------------------------------------------------------------
1 | /* At any stage of our Recursion, we will have 2 choices only -
2 | a) Pick the i-th Element
3 | b) Don't Pick the i-th Elemenent
4 |
5 | As all our elements are Unique, our Subsets generated will be Unique as well
6 | */
7 |
8 | class Solution {
9 | private :
10 |
11 | void helper(int i , vector &subSet , vector &nums , vector> &ans)
12 | {
13 | // Our base case will hit when our i pointer reaches the end of given array nums[]
14 |
15 | if(i == nums.size() )
16 | {
17 | ans.push_back(subSet) ;
18 | return ;
19 | }
20 |
21 | // We pick i-th Element
22 |
23 | subSet.push_back(nums[i]) ;
24 |
25 | // We ask recursion to do rest of the task
26 | helper(i + 1 , subSet , nums , ans) ;
27 |
28 | // Backtrack and Undo the change we have done
29 |
30 | subSet.pop_back() ;
31 |
32 | // We don't pick the i-th element
33 |
34 | helper(i + 1 , subSet , nums , ans) ;
35 |
36 | return ;
37 | }
38 |
39 | public:
40 | vector> subsets(vector& nums) {
41 |
42 | vector> ans ;
43 | vector subSet ;
44 |
45 | helper(0 , subSet , nums , ans) ;
46 |
47 | return ans ;
48 | }
49 | };
50 |
51 | /*
52 | Time Complexity : O(2^N)
53 | Space Complexity : O(N)
54 | */
55 |
--------------------------------------------------------------------------------
/Recursion/Lecture 07/LeetCode/Subsets.java:
--------------------------------------------------------------------------------
1 | /* At any stage of our Recursion, we will have 2 choices only -
2 | a) Pick the i-th Element
3 | b) Don't Pick the i-th Elemenent
4 | As all our elements are Unique, our Subsets generated will be Unique as well
5 | */
6 |
7 | class Solution
8 | {
9 | public List> subsets(int[] nums)
10 | {
11 | List> ans = new ArrayList<>();
12 | helper(nums , 0, new ArrayList() , ans);
13 | return ans;
14 | }
15 | void helper(int nums[],int ci,List subset,List> ans)
16 | {
17 | // Our base case will hit when our i pointer reaches the end of given array nums[]
18 |
19 | if(ci==nums.length)
20 | {
21 | ans.add(new ArrayList<>(subset));
22 | return ;
23 | }
24 |
25 | // We pick i-th Element
26 |
27 | subset.add(nums[ci]);
28 |
29 | // We ask recursion to do rest of the task
30 |
31 | helper(nums, ci + 1, subset, ans);
32 |
33 | // Backtrack and Undo the change we have done
34 |
35 | subset.remove(subset.size() - 1);
36 |
37 | // We don't pick the i-th element
38 |
39 | helper(nums, ci + 1, subset, ans);
40 | return ;
41 | }
42 | }
43 |
44 | /*
45 | Time Complexity : O(2^N)
46 | Space Complexity : O(N)
47 | */
48 |
--------------------------------------------------------------------------------
/Recursion/Lecture 07/LeetCode/Subsets.py:
--------------------------------------------------------------------------------
1 | """
2 | At any stage of our Recursion, we will have 2 choices only -
3 | a) Pick the i-th Element
4 | b) Don't Pick the i-th Elemenent
5 | As all our elements are Unique, our Subsets generated will be Unique as well
6 | """
7 | class Solution:
8 | def subsets(self, nums: List[int]) -> List[List[int]]:
9 |
10 | def helper(i, subSet, nums, ans):
11 |
12 | # Our base case will hit when our i pointer reaches the end of given array nums[]
13 | if i == len(nums):
14 | ans.append(subSet.copy())
15 | return
16 |
17 | # we pick ith Element
18 | subSet.append(nums[i])
19 |
20 | # We ask recursion to do rest of the task
21 | helper(i+1, subSet, nums, ans)
22 |
23 | # Backtrack and Undo the change we have done
24 | subSet.pop()
25 |
26 | # We don't pick the ith element
27 | helper(i+1, subSet, nums, ans)
28 |
29 | return
30 |
31 | # Global Variables for helper functions
32 | ans = []
33 | subSet = []
34 | # Helper will store the ans in ans list
35 | helper(0, subSet, nums, ans)
36 |
37 | return ans
38 |
39 | """
40 | Time Complexity : O(2^N)
41 | Space Complexity : O(N)
42 | """
43 |
--------------------------------------------------------------------------------
/Recursion/Lecture 08/CodeStudio/Permutations of a String.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | void helper(int pos, string &str, vector &ans)
3 | {
4 | // when we have traversed the entire str, then we should put str into ans[]
5 | if (pos >= str.size())
6 | {
7 | ans.push_back(str);
8 | }
9 |
10 | // Iterating from currentposition till size of str and trying to generate all possible Permutations
11 | for (int i = pos; i < str.size(); i++)
12 | {
13 | // swapping the ith element with the current element
14 | swap(str[pos], str[i]);
15 |
16 | // ask recursion to do the remaining task
17 | helper(pos + 1, str, ans);
18 |
19 | // backtrack & undo the changes
20 | swap(str[pos], str[i]);
21 | }
22 | }
23 | vector generatePermutations(string &str)
24 | {
25 |
26 | // to keep the final result in store
27 | vector ans;
28 |
29 | helper(0, str, ans);
30 |
31 | // Specific to this problem because we want the strings sorted in lexicographical order
32 | sort(ans.begin(), ans.end());
33 | return ans;
34 | }
35 |
36 | /*
37 | time complexity : O(n * n!)
38 | space complexity : O(n)
39 | */
--------------------------------------------------------------------------------
/Recursion/Lecture 08/CodeStudio/Permutations of a String.java:
--------------------------------------------------------------------------------
1 | import java.util.*;
2 |
3 | public class Solution {
4 | private static void permute(ArrayList ans, String str, int curr, int n)
5 | {
6 | // when we have traversed the entire str, then we should put str into ans[]
7 | if (curr == n)
8 | ans.add(str);
9 | else
10 | {
11 | // Iterating from currentposition till size of str and trying to generate all possible Permutations
12 | for (int i = curr; i < n; i++)
13 | {
14 | // call swap function for swapping the ith element with the current element
15 | str = swap(str,curr,i);
16 |
17 | // ask recursion to do the remaining task
18 | permute(ans, str, curr+1, n);
19 |
20 | // backtrack & undo the changes
21 | str = swap(str,curr,i);
22 | }
23 | }
24 | }
25 |
26 | // function that will swap the ith element with the current element
27 | public static String swap(String s, int i, int j)
28 | {
29 | char temp;
30 | char[] strArray = s.toCharArray();
31 | temp = strArray[i] ;
32 | strArray[i] = strArray[j];
33 | strArray[j] = temp;
34 | return String.valueOf(strArray);
35 | }
36 |
37 | public static ArrayList generatePermutations(String str) {
38 | // Write your code here
39 | ArrayList ans = new ArrayList<>();
40 | int n = str.length();
41 | permute(ans, str, 0, n);
42 |
43 | // Specific to this problem because we want the strings sorted in lexicographical order
44 | Collections.sort(ans);
45 | return ans;
46 | }
47 | }
48 |
49 | /*
50 | time complexity : O(n * n!)
51 | space complexity : O(n)
52 | */
--------------------------------------------------------------------------------
/Recursion/Lecture 08/CodeStudio/Permutations of a String.py:
--------------------------------------------------------------------------------
1 | def generatePermutations(str):
2 |
3 | # Swap API | As sting in python is imutable we have to take use of extra space using an list to swap the indices,
4 | def swap(i, j, s):
5 | # Converting string to a list of string[i] where 0<= i <= len(s)-1
6 | arr = list(s)
7 | # Swaping in the list
8 | arr[i], arr[j] = arr[j], arr[i]
9 | # concatinating the swaped indece to a empty string
10 | s = ""
11 | for i in arr:
12 | s += i
13 | return s
14 |
15 | def helper(pos, str, ans, n):
16 |
17 | # If we have reached the end of str, we have found a Valid Permutations of str
18 | if pos >= len(str):
19 | # appending a copy of str, else it wold be passed by referemced,
20 | # any change to str will change the appended ans. Don't worry about the extra space, Garbage
21 | # collector will handel the extra space
22 | ans.append(str[:])
23 | return
24 |
25 | # Otherwise we iterate over all the other elements and try to generate Permutations by swapping str[pos] with str[i]
26 |
27 | for i in range(pos, len(str)):
28 |
29 | # We create one Unique Permutation by swapping str[i] with str[pos]
30 |
31 | str = swap(pos, i, str)
32 |
33 | # And we ask Recursion to handle rest of the task
34 |
35 | helper(pos+1, str, ans, n)
36 |
37 | # But after we come back, we must backtrack and undo the changes we have done
38 |
39 | str = swap(pos, i, str)
40 |
41 | ans = []
42 | n = len(str)
43 | helper(0, str, ans, n)
44 | return sorted(ans)
45 |
46 | """
47 | Time Complexity : O(N * N!)
48 | Space Complexity : O(N)
49 | """
50 |
--------------------------------------------------------------------------------
/Recursion/Lecture 08/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Permutations of a String
--------------------------------------------------------------------------------
/Recursion/Lecture 08/LeetCode/Permutations.cpp:
--------------------------------------------------------------------------------
1 | /* The idea is to generate all Possible Permutations by swapping the nums[currentIndex] with nums[i]
2 | As all the characters are Unique, the Permutations generated will also be Unique
3 | We make neccessary changes in nums[] vector only. We don't use any other data structure
4 | For Permutations, order doesn't matter
5 | */
6 |
7 | class Solution {
8 | private :
9 |
10 | void helper(int pos , int n , vector &nums , vector> &ans)
11 | {
12 | // If we have reached the end of nums[], we have found a Valid Permutations of nums[]
13 |
14 | if(pos >= n)
15 | {
16 | ans.push_back(nums) ;
17 | return ;
18 | }
19 |
20 | // Otherwise we iterate over all the other elements and try to generate Permutations by swapping nums[pos] with nums[i]
21 |
22 | for(int i = pos ; i < n ; i++)
23 | {
24 | // We create one Unique Permutation by swapping nums[pos] with nums[i]
25 |
26 | swap(nums[pos] , nums[i]) ;
27 |
28 | // And we ask Recursion to handle rest of the task
29 |
30 | helper(pos + 1 , n , nums , ans) ;
31 |
32 | // But after we come back, we must backtrack and undo the changes we have done
33 |
34 | swap(nums[pos] , nums[i]) ;
35 | }
36 |
37 | return ;
38 | }
39 |
40 | public:
41 | vector> permute(vector& nums) {
42 |
43 | vector> ans ;
44 |
45 | helper(0 , nums.size() , nums , ans) ;
46 |
47 | return ans ;
48 | }
49 | };
50 | /*
51 | Time Complexity : O(N * N!)
52 | Space Complexity : O(N)
53 | */
54 |
--------------------------------------------------------------------------------
/Recursion/Lecture 08/LeetCode/Permutations.java:
--------------------------------------------------------------------------------
1 | /* The idea is to generate all Possible Permutations by swapping the nums[currentIndex] with nums[i]
2 | As all the characters are Unique, the Permutations generated will also be Unique
3 | We make neccessary changes in nums[] vector only. We don't use any other data structure
4 | For Permutations, order doesn't matter
5 |
6 | NOTE : In java there are no swap function so we need to create our own swap function
7 |
8 | NOTE : The array must be converted into List before storing it in answer
9 | */
10 |
11 |
12 | class Solution
13 | {
14 | public void helper(int pos , int n , int[] nums , List> ans)
15 | {
16 | // If we have reached the end of nums, we have found a Valid Permutations of nums
17 |
18 | if(pos >= n)
19 | {
20 | List permutation = ConverttoArray(nums);
21 | ans.add(new ArrayList(permutation)) ;
22 | return ;
23 | }
24 |
25 | // Otherwise we iterate over all the other elements and try to generate Permutations by swapping element at pos with element at i
26 |
27 | for(int i = pos ; i < n ; i++)
28 | {
29 | // We create one Unique Permutation by swapping
30 |
31 | swap(pos , i, nums) ;
32 |
33 | // And we ask Recursion to handle rest of the task
34 |
35 | helper(pos + 1 , n , nums , ans) ;
36 |
37 | // But after we come back, we must backtrack and undo the changes we have done
38 |
39 | swap(pos , i, nums) ;
40 | }
41 |
42 | return ;
43 | }
44 |
45 | public void swap (int i, int j, int[] nums)
46 | {
47 | // Swaping the elements
48 |
49 | int temp = nums[i];
50 | nums[i] = nums[j];
51 | nums[j] = temp;
52 | }
53 |
54 | public List ConverttoArray(int[] nums)
55 | {
56 | // Converting the array into List
57 |
58 | List ans = new ArrayList<>();
59 | for(int ele : nums)
60 | ans.add(ele);
61 | return ans;
62 | }
63 |
64 | public List> permute(int[] nums)
65 | {
66 | List> ans = new ArrayList<>();
67 |
68 | helper(0 , nums.length , nums , ans) ;
69 |
70 | return ans ;
71 | }
72 | }
73 |
74 | /*
75 | Time Complexity : O(N * N!)
76 | Space Complexity : O(N)
77 | */
78 |
--------------------------------------------------------------------------------
/Recursion/Lecture 08/LeetCode/Permutations.py:
--------------------------------------------------------------------------------
1 | """
2 | * The idea is to generate all Possible Permutations by swapping the nums[currentIndex] with nums[i]
3 | * As all the characters are Unique, the Permutations generated will also be Unique
4 | * We make neccessary changes in nums[] vector only. We don't use any other data structure
5 | * For Permutations, order doesn't matter
6 | """
7 | class Solution:
8 | def permute(self, nums: List[int]) -> List[List[int]]:
9 |
10 | # makes swaps in nums array
11 | def swap(i, j):
12 | nums[i], nums[j] = nums[j], nums[i]
13 | return
14 |
15 | def helper(pos, n, nums, ans):
16 |
17 | # If we have reached the end of nums[], we have found a Valid Permutations of nums[]
18 | if pos >= n:
19 | # appending a copy of nums, else it wold be passed by referemced,
20 | # any change to nums will change the appended ans. Don't worry about the extra space, Garbage
21 | # collector will handel the extra space
22 | ans.append(nums.copy())
23 | return
24 |
25 | # Otherwise we iterate over all the other elements and try to generate Permutations by swapping nums[pos] with nums[i]
26 |
27 | for i in range(pos, n):
28 |
29 | # We create one Unique Permutation by swapping nums[i] with nums[pos]
30 |
31 | swap(i, pos)
32 |
33 | # And we ask Recursion to handle rest of the task
34 |
35 | helper(pos+1, n, nums, ans)
36 |
37 | # But after we come back, we must backtrack and undo the changes we have done
38 |
39 | swap(i, pos)
40 |
41 | ans = []
42 |
43 | helper(0, len(nums), nums, ans)
44 |
45 | return ans
46 |
47 | """
48 | Time Complexity : O(N * N!)
49 | Space Complexity : O(N)
50 | """
51 |
52 |
--------------------------------------------------------------------------------
/Recursion/Lecture 08/LeetCode/README.md:
--------------------------------------------------------------------------------
1 | ## 46. Permutations
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 09/CodeStudio/All Unique Permutations lecture code.py:
--------------------------------------------------------------------------------
1 | def uniquePermutations(arr, n):
2 | def helper(pos, n):
3 |
4 | # Base Case executes when we have traversed the entire nums[]
5 | if pos >= n:
6 | ans.append(arr.copy())
7 | return
8 |
9 | # The rest logic remains exactly the same
10 |
11 | for i in range(pos, n):
12 |
13 | # We simply use our swapping logic to create Permutations
14 |
15 | arr[i], arr[pos] = arr[pos], arr[i]
16 |
17 | # And we ask Recursion to handle rest of the task
18 | # To ensure we're not storing any duplicate | we check if the hash(nums) is already not present in the numsMap
19 | if arr not in ans:
20 | helper(pos+1, n)
21 |
22 | # Backtrack and undo the change we have done
23 |
24 | arr[i], arr[pos] = arr[pos], arr[i]
25 | return
26 |
27 | ans = []
28 |
29 | # Dictionary to store each permutation of nums as key | before storing it in key we need to convert nums [] to a String, as list are not hashable
30 |
31 | helper(0, len(arr))
32 |
33 | return ans
34 |
35 |
36 | """
37 | Time Complexity : O(N * N!)
38 | Space Complexity : O(N)
39 | """
40 |
--------------------------------------------------------------------------------
/Recursion/Lecture 09/CodeStudio/All Unique Permutations.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | void helper(int pos, int n, vector &arr, vector> &ans)
3 | {
4 | // If we have traversed entire arr[], we have got an Unique Permutation this push it into the ans
5 | if (pos >= n)
6 | {
7 | ans.push_back(arr);
8 | }
9 | unordered_set m;
10 | for (int i = pos; i < n; i++)
11 | {
12 | // First check whether we have already taken arr[i] in our Permutation or not
13 | if (m.find(arr[i]) != m.end())
14 | continue;
15 |
16 | // If not we insert it in our current unordered_set
17 | m.insert(arr[i]);
18 |
19 | // We use our simple swapping logic to generate all Permutations
20 | swap(arr[pos], arr[i]);
21 |
22 | // Ask recursion to do the remaining task
23 | helper(pos + 1, n, arr, ans);
24 |
25 | // Backtrack and undo the changes
26 | swap(arr[pos], arr[i]);
27 | }
28 | }
29 | vector> uniquePermutations(vector &arr, int n)
30 | {
31 | // Write your code here.
32 | vector> ans;
33 |
34 | // Call the Recursive function to generate all the Unique Permutations
35 | helper(0, n, arr, ans);
36 |
37 | sort(ans.begin(), ans.end());
38 | return ans;
39 | }
40 |
41 | /*
42 | time complexity : O(N * N!)
43 | space complexity : O(N)
44 | */
45 |
--------------------------------------------------------------------------------
/Recursion/Lecture 09/CodeStudio/All Unique Permutations.java:
--------------------------------------------------------------------------------
1 | import java.util.*;
2 | public class Solution
3 | {
4 | public static void helper(int pos , int n , ArrayList nums , ArrayList> ans)
5 | {
6 | // If we have reached the end of nums, we have found a Valid Permutations of nums
7 |
8 | if(pos >= n)
9 | {
10 | ans.add(new ArrayList(nums)) ;
11 | return ;
12 | }
13 |
14 | // Otherwise we iterate over all the other elements and try to generate Permutations by swapping element at pos with element at i
15 |
16 | // Hashset ensures we are not taking duplicates and thus not making Duplicate Permutation
17 |
18 | HashSet set = new HashSet<>();
19 |
20 | for(int i = pos ; i < n ; i++)
21 | {
22 | // If we have encountered the element before, we will simply skip the rest of iterations
23 |
24 | if(set.contains( nums.get(i) ))
25 | continue;
26 |
27 | // We insert nums[i] so that we don't create Duplicate Permutations
28 |
29 | set.add(nums.get(i));
30 |
31 | // We create one Unique Permutation by swapping
32 |
33 | Collections.swap( nums, pos , i) ;
34 |
35 | // And we ask Recursion to handle rest of the task
36 |
37 | helper(pos + 1 , n , nums , ans) ;
38 |
39 | // But after we come back, we must backtrack and undo the changes we have done
40 |
41 | Collections.swap( nums, pos , i) ;
42 | }
43 |
44 | return ;
45 | }
46 |
47 | public static ArrayList> uniquePermutations(ArrayList arr, int n)
48 | {
49 | ArrayList> ans = new ArrayList<>();
50 |
51 | helper(0 , arr.size() , arr , ans) ;
52 |
53 | return ans ;
54 | }
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/Recursion/Lecture 09/CodeStudio/All Unique Permutations_Optimised.py:
--------------------------------------------------------------------------------
1 | def uniquePermutations(arr, n):
2 | def hashKey(arr):
3 | s = ""
4 | for i in arr:
5 | s += str(i)
6 | return s
7 |
8 | def helper(pos, n, key):
9 |
10 | # Base Case executes when we have traversed the entire nums[]
11 | if pos >= n:
12 | ans.append(arr.copy())
13 | numsMap[key] = 1
14 | return
15 |
16 | # The rest logic remains exactly the same
17 |
18 | for i in range(pos, n):
19 |
20 | # We simply use our swapping logic to create Permutations
21 |
22 | arr[i], arr[pos] = arr[pos], arr[i]
23 |
24 | # hasing the nums arry to a string, to store in numsMap dictionary
25 |
26 | key = hashKey(arr)
27 |
28 | # And we ask Recursion to handle rest of the task
29 | # To ensure we're not storing any duplicate | we check if the hash(nums) is already not present in the numsMap
30 | if key not in numsMap:
31 | helper(pos+1, n, key)
32 |
33 | # Backtrack and undo the change we have done
34 |
35 | arr[i], arr[pos] = arr[pos], arr[i]
36 | return
37 |
38 | ans = []
39 |
40 | # Dictionary to store each permutation of nums as key | before storing it in key we need to convert nums [] to a String, as list are not hashable
41 | # Dictionary is used to optimise the Time complexit as search TC is O(1)
42 | numsMap = {}
43 |
44 | helper(0, len(arr), hashKey(arr))
45 |
46 | return ans
47 |
48 | """
49 | Time Complexity : O(N * N!)
50 | Space Complexity : O(N)
51 | """
52 |
--------------------------------------------------------------------------------
/Recursion/Lecture 09/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## All Unique Permutations
2 |
3 | ### NOTE
4 | #### FOR PYTON CODE ONLY
5 | 1. "All Unique Permutations.py" code following lecture | As we can't store list in python set(), We have to search in ans arry to check for duplicate permutation of nums array. which would cost TC : O(N).
6 | 2. "All Unique Permutations lecture code.py" | In this code we have used python dictionary to store permutations of nums[]. On searching for duplicate it would cost TC : (1).
7 |
--------------------------------------------------------------------------------
/Recursion/Lecture 09/LeetCode/Permutations II.cpp:
--------------------------------------------------------------------------------
1 | /* This question is exactly similar to Permutations - I
2 | Only difference being we have duplicate elements in nums[]. But we need to print Unique Permutations only
3 | For that purpose, we have used a local unordered_set data structure which tells us if that particular element has been previosuly encountered or not
4 | If we have taken / chosen the element before, we will not include it anymore.
5 | But if we haven't included the element, we will include it now
6 | */
7 |
8 | class Solution {
9 | private :
10 |
11 | void helper(int pos , int n , vector &nums , vector> &ans)
12 | {
13 | // Base Case executes when we have traversed the entire nums[]
14 |
15 | if(pos >= n)
16 | {
17 | ans.push_back(nums) ;
18 | return ;
19 | }
20 |
21 | // Unordered_set ensures we are not taking duplicates and thus not making Duplicate Permutation
22 |
23 | unordered_set set ;
24 |
25 | // The rest logic remains exactly the same
26 |
27 | for(int i = pos ; i < n ; i++)
28 | {
29 | // If we have encountered the element before, we will simply skip the rest of iterations
30 |
31 | if(set.find(nums[i]) != set.end() )
32 | continue ;
33 |
34 | // We insert nums[i] so that we don't create Duplicate Permutations
35 |
36 | set.insert(nums[i]) ;
37 |
38 | // We simply use our swapping logic to create Permutations
39 |
40 | swap(nums[pos] , nums[i]) ;
41 |
42 | // Ask recursion to do rest of the task
43 |
44 | helper(pos + 1 , n , nums , ans) ;
45 |
46 | // Backtrack and undo the change we have done
47 |
48 | swap(nums[pos] , nums[i]) ;
49 | }
50 |
51 | return ;
52 | }
53 |
54 | public:
55 | vector> permuteUnique(vector& nums) {
56 |
57 | vector> ans ;
58 |
59 | helper(0 , nums.size() , nums , ans) ;
60 |
61 | return ans ;
62 |
63 | }
64 | };
65 |
66 | /*
67 | Time Complexity = O(N * N!)
68 | Space Complexity = O(N)
69 | */
70 |
--------------------------------------------------------------------------------
/Recursion/Lecture 09/LeetCode/Permutations II.py:
--------------------------------------------------------------------------------
1 | """
2 | This question is exactly similar to Permutations - I
3 | Only difference being we have duplicate elements in nums[]. But we need to print Unique Permutations only
4 | For that purpose, we have used a local unordered_set data structure which tells us if that particular element has been previosuly encountered or not
5 | If we have taken / chosen the element before, we will not include it anymore.
6 | But if we haven't included the element, we will include it now
7 | """
8 | class Solution:
9 | def permuteUnique(self, nums: List[int]) -> List[List[int]]:
10 |
11 | def helper(pos, n):
12 |
13 | # Base Case executes when we have traversed the entire nums[]
14 | if pos >= n:
15 |
16 | ans.append(nums.copy())
17 | return
18 |
19 | # The rest logic remains exactly the same
20 |
21 | for i in range(pos, n):
22 |
23 | # We simply use our swapping logic to create Permutations
24 |
25 | nums[i], nums[pos] = nums[pos], nums[i]
26 |
27 | # And we ask Recursion to handle rest of the task
28 | # To ensure we're not storing any duplicate | we check if the nums is already not present in the ans []
29 | if nums not in ans:
30 | helper(pos+1, n)
31 |
32 | # Backtrack and undo the change we have done
33 |
34 | nums[i], nums[pos] = nums[pos], nums[i]
35 | return
36 |
37 | ans = []
38 |
39 |
40 | helper(0, len(nums))
41 |
42 | return ans
43 |
44 | """
45 | Time Complexity : O(N * N!)
46 | Space Complexity : O(N)
47 | """
48 |
--------------------------------------------------------------------------------
/Recursion/Lecture 09/LeetCode/README.md:
--------------------------------------------------------------------------------
1 | ## 47. Permutation II
2 |
3 |
4 | ### NOTE
5 | #### FOR PYTON CODE ONLY
6 | 1. PERMUTATIONII.PY code following lecture | As we can't store list in python set(), We have to search in ans arry to check for duplicate permutation of nums []. which would cost TC : O(N).
7 | 2. PERMUTATIONII.PY OPTIMISED CODE | In this code we have used python dictionary to store permutations of nums[]. On searching for duplicate it would cost TC : (1)
8 |
--------------------------------------------------------------------------------
/Recursion/Lecture 10/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Subsets II
--------------------------------------------------------------------------------
/Recursion/Lecture 10/CodeStudio/Subsets II.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | void helper(int i, vector &arr, vector &subset, vector> &ans)
3 | {
4 | // when we have traversed the entire arr[], then we should put arr into ans[]
5 | if (i >= arr.size())
6 | {
7 | ans.push_back(subset);
8 | return;
9 | }
10 |
11 | // pick the ith element
12 | subset.push_back(arr[i]);
13 |
14 | // picked ith element and recursion will find the remaining subsets with ith element
15 | helper(i + 1, arr, subset, ans);
16 |
17 | // firstly, we need to backtrack and undo the changes that we have made
18 | subset.pop_back();
19 |
20 | // ensure we don't pick any other occurrences ofi-th element in order to generate Unique Subsets
21 | while (i + 1 < arr.size() && arr[i] == arr[i + 1]) i++;
22 |
23 | // currentIndex will now point to the Last Occurrence of ith Element
24 | // we ignored ith element and now recursion will do find the remaining subsets without the ith element
25 | // skip the ith element
26 | helper(i + 1, arr, subset, ans);
27 | }
28 |
29 | vector> uniqueSubsets(int n, vector &arr)
30 | {
31 | // Write your code here.
32 | vector> ans;
33 | vector subset;
34 |
35 | // to ensure our logic work,we need a sorted array
36 | sort(arr.begin(), arr.end());
37 | helper(0, arr, subset, ans);
38 |
39 | // this is specific to the given problem, they wanted each subset in sorted order
40 | sort(ans.begin(), ans.end());
41 | return ans;
42 | }
43 |
44 | /*
45 | time complexity : O(2^n)
46 | space complexity : O(n)
47 | */
48 |
--------------------------------------------------------------------------------
/Recursion/Lecture 10/CodeStudio/Subsets II.py:
--------------------------------------------------------------------------------
1 | from typing import *
2 |
3 | def uniqueSubsets(n :int,arr :List[int]) -> List[List[int]]:
4 |
5 | def helper(i, subset, arr, ans):
6 |
7 | #Base Case, When we have reached the end of nums[] , we have generated a Valid Unique Subset for sure
8 |
9 | if i >= len(arr):
10 | ans.append(subset.copy())
11 | return
12 |
13 | # pick the ith element
14 | subset.append(arr[i])
15 |
16 | # picked ith element and recursion will find the remaining subsets with ith element | Left Subtree
17 |
18 | helper(i+1, subset, arr, ans)
19 |
20 | # firstly, we need to backtrack and undo the changes that we have made
21 |
22 | subset.pop()
23 |
24 | # ensure we don't pick any other occurrences ofi-th element in order to generate Unique Subsets
25 |
26 | while i+1 < len(arr) and arr[i] == arr[i+1]:#Preventon step
27 | i += 1
28 |
29 | # currentIndex will now point to the Last Occurrence of ith Element
30 | # we ignored ith element and now recursion will do find the remaining subsets without the ith element
31 | # skip the ith element
32 |
33 | helper(i+1, subset, arr, ans)
34 |
35 | # For our logic to work, we need to sort the given nums[] vector
36 | arr.sort()
37 |
38 | ans = []
39 |
40 | subset= []
41 |
42 | helper(0, subset, arr, ans)
43 |
44 | # this is specific to the given problem, they wanted each subset in sorted order
45 | ans.sort()
46 | return ans
47 |
48 | """
49 | Time Complexity : O(2^N)
50 | Space Complexity : O(N)
51 | """
52 |
--------------------------------------------------------------------------------
/Recursion/Lecture 10/LeetCode/README.md:
--------------------------------------------------------------------------------
1 | ## Subsets II
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 10/LeetCode/Subsets II.cpp:
--------------------------------------------------------------------------------
1 | /* This Question is exactly similar to Subsets - I.
2 | Instead of All Unique Elements we have given an array nums[] containing Dupicate Elements
3 | Our Logic remains the same. We will generate Subsets by using - Pick & Don't Pick condition only
4 | Only difference is that, while we are not picking any element, we must skip all it's Duplicate occrurrences in nums[] .
5 | This can be acheived by using a While Loop. Also we need to sort nums[] as the array might be given as unsorted
6 | */
7 |
8 | class Solution {
9 | private :
10 |
11 | void helper(int i , vector &subset , vector &nums , vector> &ans)
12 | {
13 | // When we have reached the end of nums[] , we have generated a Valid Unique Subset for sure
14 |
15 | if(i >= nums.size() )
16 | {
17 | ans.push_back(subset) ;
18 | return ;
19 | }
20 |
21 | // Otherwise we will use our Pick & Don't Pick Logic
22 |
23 | // Consider the Element
24 |
25 | subset.push_back(nums[i]) ;
26 |
27 | // Ask Recursion to do rest of the task
28 |
29 | helper(i + 1 , subset , nums , ans) ;
30 |
31 | // Backtrack and undo the change you have done
32 |
33 | subset.pop_back() ;
34 |
35 | // While using Don't Pick option, we must ensure we skip all the Duplicate Occurrences of nums[i]
36 |
37 | while(i < nums.size() - 1 && (nums[i] == nums[i + 1] ) )
38 | {
39 | i++ ;
40 | }
41 |
42 | // Our i pointer will stop on the last Duplciate Occurencce of nums[i]
43 |
44 | // Don't Consider the Element and Ask Recursion to generate Unique Subsets
45 |
46 | helper(i + 1 , subset , nums , ans) ;
47 |
48 | return ;
49 | }
50 |
51 | public:
52 | vector> subsetsWithDup(vector& nums) {
53 |
54 | // For our logic to work, we need to sort the given nums[] vector
55 |
56 | sort(nums.begin() , nums.end() ) ;
57 |
58 | vectorsubset ;
59 |
60 | vector > ans ;
61 |
62 | // Call the helper() function to generate all Unique Subsets
63 |
64 | helper(0 , subset , nums , ans) ;
65 |
66 | return ans ;
67 | }
68 | };
69 |
70 | /*
71 | Time Complexity : O(2^N)
72 | Space Complexity : O(N)
73 | */
74 |
--------------------------------------------------------------------------------
/Recursion/Lecture 10/LeetCode/Subsets II.java:
--------------------------------------------------------------------------------
1 | /* This Question is exactly similar to Subsets - I.
2 | Instead of All Unique Elements we have given an array nums[] containing Dupicate Elements
3 | Our Logic remains the same. We will generate Subsets by using - Pick & Don't Pick condition only
4 | Only difference is that, while we are not picking any element, we must skip all it's Duplicate occrurrences in nums[] .
5 | This can be acheived by using a While Loop. Also we need to sort nums[] as the array might be given as unsorted
6 | */
7 | class Solution
8 | {
9 | public List> subsetsWithDup(int[] nums)
10 | {
11 |
12 | // In this logic we to sort the array
13 |
14 | Arrays.sort(nums);
15 |
16 | List> ans = new ArrayList<>();
17 |
18 | helper(nums , 0, new ArrayList() , ans);
19 |
20 | return ans;
21 | }
22 |
23 | void helper(int nums[],int i,List subset,List> ans)
24 | {
25 | // Our base case will hit when our i pointer reaches the end of given array nums[]
26 |
27 | if(i==nums.length)
28 | {
29 | ans.add(new ArrayList<>(subset));
30 | return ;
31 | }
32 |
33 | // We pick i-th Element
34 |
35 | subset.add(nums[i]);
36 |
37 | // We ask recursion to do rest of the task
38 |
39 | helper(nums, i + 1, subset, ans);
40 |
41 | // Backtrack and Undo the change we have done
42 |
43 | subset.remove(subset.size() - 1);
44 |
45 | // While using Don't Pick option, we must ensure we skip all the Duplicate Occurrences of nums[i]
46 |
47 | while(i < nums.length - 1 && (nums[i] == nums[i + 1] ) )
48 | {
49 | i++ ;
50 | }
51 |
52 | // Our i pointer will stop on the last Duplciate Occurencce of nums[i]
53 |
54 | // Don't Consider the Element and Ask Recursion to generate Unique Subsets
55 |
56 | helper(nums, i + 1, subset, ans);
57 | return ;
58 | }
59 | }
60 |
61 | /*
62 | Time Complexity : O(2^N)
63 | Space Complexity : O(N)
64 | */
65 |
--------------------------------------------------------------------------------
/Recursion/Lecture 10/LeetCode/Subsets II.py:
--------------------------------------------------------------------------------
1 | class Solution:
2 | def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
3 |
4 | def helper(i, subset, nums, ans):
5 |
6 | #Base Case When we have reached the end of nums[] , we have generated a Valid Unique Subset for sure
7 |
8 | if i >= len(nums): #LVI
9 | ans.append(subset.copy())
10 | return
11 |
12 | subset.append(nums[i])
13 |
14 | # Ask Recursion to do rest of the task | Left Subtree
15 |
16 | helper(i+1, subset, nums, ans)
17 |
18 | # Backtrack and undo the change you have done
19 |
20 | subset.pop()
21 |
22 | # While using Don't Pick option, we must ensure we skip all the Duplicate Occurrences of nums[i]
23 |
24 | while i+1 < len(nums) and nums[i] == nums[i+1]:#Preventon step
25 | i += 1
26 |
27 | # Our i pointer will stop on the last Duplciate Occurencce of nums[i]
28 | # Don't Consider the Element and Ask Recursion to generate Unique Subsets | Right subtree
29 |
30 | helper(i+1, subset, nums, ans)
31 |
32 | # For our logic to work, we need to sort the given nums[] vector
33 | nums.sort()
34 |
35 | ans = []
36 |
37 | subset= []
38 |
39 | helper(0, subset, nums, ans)
40 |
41 | return ans
42 |
43 | """
44 | Time Complexity : O(2^N)
45 | Space Complexity : O(N)
46 | """
47 |
--------------------------------------------------------------------------------
/Recursion/Lecture 11/CodeStudio/Combinations.cpp:
--------------------------------------------------------------------------------
1 | void help(int i, int n, int k, vector &subSet, vector> &ans)
2 | {
3 | // base condition
4 | if (k == 0)
5 | {
6 | ans.push_back(subSet);
7 | return;
8 | }
9 |
10 | // if the required element (k) is greater than the remaining element (n - i + 1) in that case return because we are in the wrong direction & there is no point going any further down in this direction
11 | if (k > n - i + 1)
12 | return;
13 |
14 | if (i > n)
15 | return;
16 |
17 | // pick the ith element
18 | subSet.push_back(i);
19 |
20 | // ask recursion to do the remaining task
21 | help(i + 1, n, k - 1, subSet, ans);
22 |
23 | // backtrack & undo the changes that has been made
24 | subSet.pop_back();
25 |
26 | // skip the ith element
27 | help(i + 1, n, k, subSet, ans);
28 | }
29 |
30 | vector> combinations(int n, int k)
31 | {
32 | vector subSet;
33 | vector> ans;
34 | help(1, n, k, subSet, ans);
35 | return ans;
36 | }
37 |
38 | /*
39 | time complexity : O(2^n)
40 | space complexity : O(n)
41 | */
42 |
--------------------------------------------------------------------------------
/Recursion/Lecture 11/CodeStudio/Combinations.java:
--------------------------------------------------------------------------------
1 | import java.util.*;
2 | public class Solution
3 | {
4 | static void help(int i, int n, int k, ArrayList subSet, ArrayList> ans)
5 | {
6 | // If k is equal to 0, we have generated a Valid Subset of K length
7 |
8 | if (k == 0)
9 | {
10 | ans.add(new ArrayList(subSet));
11 | return;
12 | }
13 |
14 | // If we don't have enough elements to make our subset, we shouldn't proceed further
15 |
16 | if (k > n - i + 1)
17 | return;
18 |
19 | // If i becomes greater than N, we should stop going forward
20 |
21 | if (i > n)
22 | return;
23 |
24 | // Our logic remains exactly same as Generating Subsets
25 |
26 | // Pick i-th Element
27 |
28 | subSet.add(i);
29 |
30 | // Ask Recursion to do the Rest of the Task
31 |
32 | help(i + 1, n, k - 1, subSet, ans);
33 |
34 | // Backtrack and undo the change
35 |
36 | subSet.remove(subSet.size()-1);
37 |
38 | // Don't pick the i-th Element
39 |
40 | help(i + 1, n, k, subSet, ans);
41 | }
42 | public static ArrayList> combinations(int n, int k)
43 | {
44 | ArrayList> ans = new ArrayList<>() ;
45 | ArrayList subSet = new ArrayList<>() ;
46 |
47 | help(1 , n , k , subSet , ans) ;
48 |
49 | return ans ;
50 | }
51 |
52 | }
53 |
54 | /*
55 | Time Complexity : O(2^N)
56 | Space Complexity : O(N)
57 | */
58 |
--------------------------------------------------------------------------------
/Recursion/Lecture 11/CodeStudio/Combinations.py:
--------------------------------------------------------------------------------
1 | from typing import *
2 |
3 |
4 | def combinations(n :int,k :int) -> List[List[int]]:
5 |
6 | def helper(i, n, k):
7 |
8 | # base case | If k is equal to 0, we have generated a Valid Subset of K length
9 | if k == 0:
10 | ans.append(subSet.copy())
11 | return
12 |
13 | # If we don't have enough elements to make our subset, we shouldn't proceed further
14 | if k > n-i+1:
15 | return
16 |
17 | # If i becomes greater than N, we should stop going forward
18 | if i > n:
19 | return
20 |
21 | # Our logic remains exactly same as Generating Subsets
22 |
23 | # Pick i-th Element
24 | subSet.append(i)
25 |
26 | # Ask Recursion to do the Rest of the Task
27 | helper(i + 1, n, k - 1)
28 | # Backtrack and undo the change
29 | subSet.pop()
30 | # Don't pick the i-th Element
31 | helper(i + 1, n, k)
32 |
33 | """
34 | Note : we've to pass ans, subSet array by their references so we've not included it on the helper function's parameter
35 | """
36 | ans = []
37 | subSet = []
38 |
39 | helper(1, n, k)
40 | return ans
41 |
42 | """
43 | Time Complexity : O(2^N)
44 | Space Complexity : O(N)
45 |
46 | """
47 |
--------------------------------------------------------------------------------
/Recursion/Lecture 11/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Combinations
--------------------------------------------------------------------------------
/Recursion/Lecture 11/LeetCode/Combinations.cpp:
--------------------------------------------------------------------------------
1 | /* Generating Combinations is exactly similar to generating Subsets.
2 | At every stage we will - a) Pick i-th Element
3 | b) Don't Pick i-th Element
4 | Instead of giving us an array or vector, we are asked to generate all Combinations from 1 to N (both inclsive) and length of each Subset should be exactly K
5 | We use the same Pick & Don't Pick Logic to solve the Question
6 | We should always remember - Relative order matters in Combination just like Subsets
7 | */
8 |
9 | class Solution {
10 | private :
11 |
12 | void help(int i, int n, int k, vector &subSet, vector> &ans)
13 | {
14 | // If k is equal to 0, we have generated a Valid Subset of K length
15 |
16 | if (k == 0)
17 | {
18 | ans.push_back(subSet);
19 | return;
20 | }
21 |
22 | // If we don't have enough elements to make our subset, we shouldn't proceed further
23 |
24 | if (k > n - i + 1)
25 | return;
26 |
27 | // If i becomes greater than N, we should stop going forward
28 |
29 | if (i > n)
30 | return;
31 |
32 | // Our logic remains exactly same as Generating Subsets
33 |
34 | // Pick i-th Element
35 |
36 | subSet.push_back(i);
37 |
38 | // Ask Recursion to do the Rest of the Task
39 |
40 | help(i + 1, n, k - 1, subSet, ans);
41 |
42 | // Backtrack and undo the change
43 | subSet.pop_back();
44 |
45 | // Don't pick the i-th Element
46 |
47 | help(i + 1, n, k, subSet, ans);
48 | }
49 |
50 | public:
51 | vector> combine(int n, int k) {
52 |
53 | vector> ans ;
54 | vector subSet ;
55 |
56 | help(1 , n , k , subSet , ans) ;
57 |
58 | return ans ;
59 | }
60 | };
61 |
62 | /*
63 | Time Complexity : O(2^N)
64 | Space Complexity : O(N)
65 | */
66 |
--------------------------------------------------------------------------------
/Recursion/Lecture 11/LeetCode/Combinations.java:
--------------------------------------------------------------------------------
1 | /* Generating Combinations is exactly similar to generating Subsets.
2 | At every stage we will - a) Pick i-th Element
3 | b) Don't Pick i-th Element
4 | Instead of giving us an array or vector, we are asked to generate all Combinations from 1 to N (both inclsive) and length of each Subset should be exactly K
5 | We use the same Pick & Don't Pick Logic to solve the Question
6 | We should always remember - Relative order matters in Combination just like Subsets
7 | */
8 |
9 | class Solution
10 | {
11 | public void help(int i, int n, int k, List subSet, List> ans)
12 | {
13 | // If k is equal to 0, we have generated a Valid Subset of K length
14 |
15 | if (k == 0)
16 | {
17 | ans.add(new ArrayList(subSet));
18 | return;
19 | }
20 |
21 | // If we don't have enough elements to make our subset, we shouldn't proceed further
22 |
23 | if (k > n - i + 1)
24 | return;
25 |
26 | // If i becomes greater than N, we should stop going forward
27 |
28 | if (i > n)
29 | return;
30 |
31 | // Our logic remains exactly same as Generating Subsets
32 |
33 | // Pick i-th Element
34 |
35 | subSet.add(i);
36 |
37 | // Ask Recursion to do the Rest of the Task
38 |
39 | help(i + 1, n, k - 1, subSet, ans);
40 |
41 | // Backtrack and undo the change
42 |
43 | subSet.remove(subSet.size()-1);
44 |
45 | // Don't pick the i-th Element
46 |
47 | help(i + 1, n, k, subSet, ans);
48 | }
49 | public List> combine(int n, int k)
50 | {
51 | List> ans = new ArrayList<>() ;
52 | List subSet = new ArrayList<>() ;
53 |
54 | help(1 , n , k , subSet , ans) ;
55 |
56 | return ans ;
57 | }
58 | }
59 |
60 | /*
61 | Time Complexity : O(2^N)
62 | Space Complexity : O(N)
63 | */
64 |
--------------------------------------------------------------------------------
/Recursion/Lecture 11/LeetCode/Combinations.py:
--------------------------------------------------------------------------------
1 | """
2 | Generating Combinations is exactly similar to generating Subsets.
3 | At every stage we will - a) Pick i-th Element
4 | b) Don't Pick i-th Element
5 | Instead of giving us an array or vector, we are asked to generate all Combinations from 1 to N (both inclsive) and length of each Subset should be exactly K
6 | We use the same Pick & Don't Pick Logic to solve the Question
7 | We should always remember - Relative order matters in Combination just like Subsets
8 |
9 |
10 | """
11 |
12 | class Solution:
13 | def combine(self, n: int, k: int) -> List[List[int]]:
14 |
15 | def helper(i, n, k):
16 |
17 | # base case | If k is equal to 0, we have generated a Valid Subset of K length
18 | if k == 0:
19 | ans.append(subSet.copy())
20 | return
21 |
22 | # If we don't have enough elements to make our subset, we shouldn't proceed further
23 | if k > n-i+1:
24 | return
25 |
26 | # If i becomes greater than N, we should stop going forward
27 | if i > n:
28 | return
29 |
30 | # Our logic remains exactly same as Generating Subsets
31 |
32 | # Pick i-th Element
33 |
34 | subSet.append(i)
35 |
36 | # Ask Recursion to do the Rest of the Task
37 |
38 | helper(i + 1, n, k - 1)
39 |
40 | # Backtrack and undo the change
41 | subSet.pop()
42 |
43 | # Don't pick the i-th Element
44 |
45 | helper(i + 1, n, k)
46 |
47 | """
48 | Note : we've to pass ans, subSet array by their references so we've not included it on the helper function's parameter
49 | """
50 | ans = []
51 | subSet = []
52 |
53 | helper(1, n, k)
54 | return ans
55 |
56 | """
57 | Time Complexity : O(2^N)
58 | Space Complexity : O(N)
59 |
60 | """
61 |
--------------------------------------------------------------------------------
/Recursion/Lecture 11/LeetCode/README.md:
--------------------------------------------------------------------------------
1 | ## 77. Combinations
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 12/CodeStudio/Combination Sum.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | using namespace std;
3 |
4 | void help(int i, vector &arr, int B, int sumTillNow, vector &subSet, vector> &ans)
5 | {
6 | // base condition
7 | // if sumTillNow == required sum (B) this means that we have reached a Valid Combination thus include it into the vector> ans
8 | if (sumTillNow == B)
9 | {
10 | ans.push_back(subSet);
11 | return;
12 | }
13 |
14 | // base condition
15 | // if sumTillNow > required sum (B) this means that we are exceeding the limit of required sum therefore simply return
16 | if (sumTillNow > B)
17 | return;
18 |
19 | // base condition
20 | // if current Index (i) is exceeding the array size then return
21 | if (i >= arr.size())
22 | return;
23 |
24 | // skip the ith element
25 | help(i + 1, arr, B, sumTillNow, subSet, ans);
26 |
27 | // pick the ith element
28 | sumTillNow += arr[i];
29 | subSet.push_back(arr[i]);
30 |
31 | // ask recursion to do the remaining task
32 | help(i, arr, B, sumTillNow, subSet, ans);
33 |
34 | // backtrack & undo the changes that were made while picking the ith element
35 | sumTillNow -= arr[i];
36 | subSet.pop_back();
37 | }
38 |
39 | vector> combSum(vector &ARR, int B)
40 | {
41 | vector subSet;
42 | int sumTillNow = 0;
43 | vector> ans;
44 |
45 | // as elements in each combination need to be sorted, therefore we are sorting ARR[] vector to ensure that our combinations are also generated in sorted manner
46 | sort(ARR.begin(), ARR.end());
47 | help(0, ARR, B, sumTillNow, subSet, ans);
48 | return ans;
49 | }
50 |
51 | /*
52 | Time Complexity: O(Exponential)
53 | Space Complexity: O(TargetSum) {Recursive Stack Space}
54 | */
55 |
--------------------------------------------------------------------------------
/Recursion/Lecture 12/CodeStudio/Combination Sum.java:
--------------------------------------------------------------------------------
1 | import java.util.*;
2 | public class Solution
3 | {
4 | static void help(int i, ArrayList arr, int B, int sumTillNow, ArrayList subSet, ArrayList> ans)
5 | {
6 |
7 | // If our sumTillNow is equal to B(Target), we have reached a Valid Combination
8 |
9 | if(sumTillNow == B)
10 | {
11 | ans.add(new ArrayList(subSet));
12 | return;
13 | }
14 |
15 | // If our sumTillNow exceeds B(Target), there's no point in proceeding further
16 |
17 | if(sumTillNow > B) return;
18 |
19 | // If we have reached the end of arr, we cannot go further as we don't have anymore elements
20 |
21 | if(i >= arr.size()) return;
22 |
23 | // We skip the i-th element
24 |
25 | help(i + 1, arr, B, sumTillNow, subSet, ans);
26 |
27 | // We include the i-th into our sumTillNow
28 |
29 | sumTillNow += arr.get(i);
30 |
31 | // We push the i-th Element into our subSet
32 |
33 | subSet.add(arr.get(i));
34 |
35 | // We keep on the i-th Element & ask recursion to do rest of the task
36 |
37 | help(i, arr, B, sumTillNow, subSet, ans);
38 |
39 | // When we come back, we need to backtrack & undo the change
40 |
41 | sumTillNow -= arr.get(i);
42 |
43 | subSet.remove(subSet.size()-1);
44 | }
45 | public static ArrayList> combSum(ArrayList arr, int b)
46 | {
47 | ArrayList subSet = new ArrayList<>();
48 |
49 | int sumTillNow = 0;
50 |
51 | ArrayList> ans = new ArrayList<>();
52 |
53 | // This sorting ensures all the elements in each Subset are also in sorted order
54 |
55 | Collections.sort(arr);
56 |
57 | help(0, arr, b, sumTillNow, subSet, ans);
58 |
59 | return ans;
60 | }
61 | }
62 |
63 | /*
64 | Time Complexity: O(Expoential) or O(2^n)
65 | Space Complexity: O(n+m) n for stack memory and m = size of ans array
66 | */
67 |
--------------------------------------------------------------------------------
/Recursion/Lecture 12/CodeStudio/Combination Sum.py:
--------------------------------------------------------------------------------
1 | def combSum(ARR, B):
2 |
3 | def helper(i, sumTillNow):
4 |
5 | # base condition
6 | # if sumTillNow == required sum (B) this means that we have reached a Valid Combination thus include it into the ans []
7 |
8 | if sumTillNow == B:
9 | ans.append(subSet.copy())
10 | return
11 | # base condition
12 | # if sumTillNow > required sum (B) this means that we are exceeding the limit of required sum therefore simply return
13 |
14 | if sumTillNow > B:
15 | return
16 |
17 | # Base Case
18 | # if current Index (i) is exceeding the array size then return
19 |
20 | if i >= len(ARR):
21 | return
22 |
23 | # We skip the i-th element
24 |
25 | helper(i+1, sumTillNow)
26 |
27 | # We pick the ith element
28 |
29 | sumTillNow += ARR[i]
30 | subSet.append(ARR[i])
31 |
32 | # We keep the i-th Element & ask recursion to do rest of the task
33 |
34 | helper(i, sumTillNow)
35 |
36 | # backtrack & undo the changes that were made while picking the ith element
37 |
38 | sumTillNow -= ARR[i]
39 | subSet.pop()
40 |
41 | # Global Scope reference variables
42 | subSet = []
43 | ans = []
44 | sumTillNow = 0
45 |
46 | # This sorting ensures all the elements in each Subset are also in sorted order
47 |
48 | ARR.sort()
49 |
50 | helper(0, sumTillNow)
51 |
52 | return ans
53 |
54 | """
55 | Time Complexity: O(Exponential) or O(n^2)
56 |
57 | Explanation: : As it's very difficult to predict how many children one
58 | particular node can have, evident from the Recursive Tree, as one
59 | element can occur multiple times and also we won't be generating
60 | all the subsets in one go. So, the Time Complexity can be said to be
61 | Exponential only!!
62 |
63 |
64 | Space Complexity: O(n+m) | n for stack memory and m = size of ans array
65 |
66 | Explanation: Space Complexity will be equal to height of the recursive
67 | tree, Which in the worst Case is equal to Target-Sum if we had 1 in
68 | arr[] and we kept on picking only 1 till we reach Target-Sum. That's
69 | why Time complexity is (Target-Sum)
70 | """
71 |
--------------------------------------------------------------------------------
/Recursion/Lecture 12/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Combination Sum
--------------------------------------------------------------------------------
/Recursion/Lecture 12/LeetCode/Combination Sum-1.cpp:
--------------------------------------------------------------------------------
1 | /* The idea of this question is to return all such combinations whose individual sum is equal to Target
2 | We use the same logic as generating Combinations - only difference is that we calculate the sum of each subset every time.
3 | We can use an element as many times as we want
4 | Our given vector arr[] contains only Unique Subsets that's for sure
5 | */
6 |
7 | class Solution {
8 | private :
9 |
10 | void help(int i, vector &arr, int B, int sumTillNow, vector &subSet, vector> &ans) {
11 |
12 | // If our sumTillNow is equal to B(Target), we have reached a Valid Combination
13 |
14 | if(sumTillNow == B)
15 | {
16 | ans.push_back(subSet);
17 | return;
18 | }
19 |
20 | // If our sumTillNow exceeds B(Target), there's no point in proceeding further
21 |
22 | if(sumTillNow > B) return;
23 |
24 | // If we have reached the end of arr[], we cannot go further as we don't have anymore elements
25 |
26 | if(i >= arr.size()) return;
27 |
28 | // We skip the i-th element
29 |
30 | help(i + 1, arr, B, sumTillNow, subSet, ans);
31 |
32 | // We include the i-th into our sumTillNow
33 |
34 | sumTillNow += arr[i];
35 |
36 | // We push the i-th Element into our subSet
37 |
38 | subSet.push_back(arr[i]);
39 |
40 | // We keep on the i-th Element & ask recursion to do rest of the task
41 |
42 | help(i, arr, B, sumTillNow, subSet, ans);
43 |
44 | // When we come back, we need to backtrack & undo the change
45 |
46 | sumTillNow -= arr[i];
47 |
48 | subSet.pop_back();
49 | }
50 |
51 |
52 | public:
53 | vector> combinationSum(vector& candidates, int target) {
54 |
55 | vector subSet;
56 |
57 | int sumTillNow = 0;
58 |
59 | vector> ans;
60 |
61 | // This sorting ensures all the elements in each Subset are also in sorted order
62 |
63 | sort(candidates.begin(), candidates.end());
64 |
65 | help(0, candidates, target, sumTillNow, subSet, ans);
66 |
67 | return ans;
68 | }
69 | };
70 |
71 | /*
72 | Time Complexity: O(Exponential)
73 | Space Complexity: O(TargetSum) {Recursive Stack Space}
74 | */
75 |
--------------------------------------------------------------------------------
/Recursion/Lecture 12/LeetCode/Combination Sum.java:
--------------------------------------------------------------------------------
1 |
2 | /* The idea of this question is to return all such combinations whose individual sum is equal to Target
3 | We use the same logic as generating Combinations - only difference is that we calculate the sum of each subset every time.
4 | We can use an element as many times as we want
5 | Our given array arr[] contains only Unique Subsets that's for sure
6 | */
7 |
8 | class Solution
9 | {
10 | public void help(int i, int[] arr, int B, int sumTillNow, List subSet, List> ans)
11 | {
12 |
13 | // If our sumTillNow is equal to B(Target), we have reached a Valid Combination
14 |
15 | if(sumTillNow == B)
16 | {
17 | ans.add(new ArrayList(subSet));
18 | return;
19 | }
20 |
21 | // If our sumTillNow exceeds B(Target), there's no point in proceeding further
22 |
23 | if(sumTillNow > B) return;
24 |
25 | // If we have reached the end of arr[], we cannot go further as we don't have anymore elements
26 |
27 | if(i >= arr.length) return;
28 |
29 | // We skip the i-th element
30 |
31 | help(i + 1, arr, B, sumTillNow, subSet, ans);
32 |
33 | // We include the i-th into our sumTillNow
34 |
35 | sumTillNow += arr[i];
36 |
37 | // We push the i-th Element into our subSet
38 |
39 | subSet.add(arr[i]);
40 |
41 | // We keep on the i-th Element & ask recursion to do rest of the task
42 |
43 | help(i, arr, B, sumTillNow, subSet, ans);
44 |
45 | // When we come back, we need to backtrack & undo the change
46 |
47 | sumTillNow -= arr[i];
48 |
49 | subSet.remove(subSet.size()-1);
50 | }
51 | public List> combinationSum(int[] candidates, int target)
52 | {
53 | List subSet = new ArrayList<>();
54 |
55 | int sumTillNow = 0;
56 |
57 | List> ans = new ArrayList<>();
58 |
59 | // This sorting ensures all the elements in each Subset are also in sorted order
60 |
61 | Arrays.sort(candidates);
62 |
63 | help(0, candidates, target, sumTillNow, subSet, ans);
64 |
65 | return ans;
66 | }
67 | }
68 |
69 | /*
70 | Time Complexity: O(Expoential) or O(2^n)
71 | Space Complexity: O(n+m) n for stack memory and m = size of ans array
72 | */
73 |
--------------------------------------------------------------------------------
/Recursion/Lecture 12/LeetCode/README.md:
--------------------------------------------------------------------------------
1 | ## 39. Combination Sum
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 13/CodeStudio/Combination Sum II.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | using namespace std;
4 |
5 | void help(int i, vector &arr, int n, vector &subSet, vector> &powerSet, int sum, int target)
6 | {
7 | // base condition
8 | // when sum == target this means that we have reached a Valid Combination thus include it into the vector> powerSet
9 | if (sum == target)
10 | {
11 | powerSet.push_back(subSet);
12 | return;
13 | }
14 |
15 | // base condition
16 | // when sum > target this means that we are exceeding the limit of the required sum (target) therefore simply return
17 | if (sum > target)
18 | return;
19 |
20 | // base condition
21 | // if current Index (i) is exceeding the array size then return
22 | if (i == n)
23 | return;
24 |
25 | // pick the ith element
26 | subSet.push_back(arr[i]);
27 | sum += arr[i];
28 |
29 | // ask recursion to do the remaining task
30 | help(i + 1, arr, n, subSet, powerSet, sum, target);
31 |
32 | // backtrack & undo the changes that were made while picking the ith element
33 | subSet.pop_back();
34 | sum -= arr[i];
35 |
36 | // loop to ensure that we don't pick any other occurrences of ith element
37 | while (i + 1 < arr.size() && arr[i] == arr[i + 1])
38 | i++;
39 |
40 | // skip the ith element
41 | help(i + 1, arr, n, subSet, powerSet, sum, target);
42 | }
43 |
44 | vector> combinationSum2(vector &arr, int n, int target)
45 | {
46 | vector subSet;
47 | vector> powerSet;
48 | int sum = 0;
49 |
50 | // as we have to bring all the similar elements together therefore we need to sort arr[]
51 | // now as all the similar elements comes together therefore we will be able to ignore all the duplicate occurences of elements
52 | sort(arr.begin(), arr.end());
53 | help(0, arr, n, subSet, powerSet, sum, target);
54 | return powerSet;
55 | }
56 |
57 | /*
58 | time complexity : O(2^n)
59 | space complexity : O(n)
60 | */
--------------------------------------------------------------------------------
/Recursion/Lecture 13/CodeStudio/Combination Sum II.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.*;
3 | public class Solution
4 | {
5 | static void help(int i, ArrayList arr, int n, ArrayList subSet, ArrayList> powerSet, int sum, int target)
6 | {
7 |
8 | // If sum is equal to target, we have reached a Valid Combination
9 |
10 | if(sum == target)
11 | {
12 | powerSet.add(new ArrayList(subSet)) ;
13 | return;
14 | }
15 |
16 | // If at any moment, sum becomes greater than target, we don't need to proceed further
17 |
18 | if(sum > target) return ;
19 |
20 | // If we reach the end of arr, we cannot go any further so we return back
21 |
22 | if(i == n) return;
23 |
24 | // Include the i-th Element into our Subset & Sum
25 |
26 | subSet.add(arr.get(i)) ;
27 | sum += arr.get(i) ;
28 |
29 | // Ask recursion to do rest of the task
30 | help(i + 1, arr, n, subSet, powerSet, sum, target) ;
31 |
32 | // Backtrack and undo the change we have done
33 |
34 | subSet.remove(subSet.size()-1);
35 | sum -= arr.get(i);
36 |
37 | // Use the While Loop to skip all the duplicate occurrences of i-th Element
38 |
39 | while(i + 1 < arr.size() && arr.get(i) == arr.get(i+1)) i++ ;
40 |
41 | // Don't pick the i-th Element and ask recursion to do rest of the task
42 |
43 | help(i + 1, arr, n, subSet, powerSet, sum, target) ;
44 | }
45 | public static ArrayList> combinationSum2(ArrayList arr, int n, int target)
46 | {
47 | ArrayList subSet = new ArrayList<>() ;
48 | ArrayList> powerSet = new ArrayList<>() ;
49 | int sum = 0;
50 | Collections.sort(arr) ;
51 |
52 | help(0, arr, n, subSet, powerSet, sum, target) ;
53 |
54 | return powerSet ;
55 | }
56 | }
57 |
58 | /*
59 | Time Complexity: O(2^N)
60 | Space Complexity: O(N)
61 | */
62 |
--------------------------------------------------------------------------------
/Recursion/Lecture 13/CodeStudio/Combination Sum-II.py:
--------------------------------------------------------------------------------
1 | """
2 | This question is exactly similar to Combination Sum -I.
3 | The only difference is that we have duplicates inside the given arr[].
4 | We need to skip the duplicate elements. Else they would generate Duplicate Combinations which we don't want.
5 | To skip the Duplicate Elements, we will sort candidates [] and use a While Loop to skip all the Duplicate Elements.
6 |
7 | In python we need to pass candidates [], powerSet [] to pass by reference so we are'nt including those in the helper() parameter.
8 |
9 | Note :
10 | Please reffer this article befoe solving the problem to understand the naming convention.
11 | """
12 | # link - https://leetcode.com/discuss/interview-question/2357412/Subarray-vs-Subsequence-vs-Subset-vs-Powerset
13 |
14 | def combinationSum2(arr, n, target):
15 |
16 | def helper(i, n, subsetSum):
17 |
18 | # BASE CONDITIONS
19 | # If sum is equal to target, we have reached a Valid Combination
20 |
21 | if subsetSum == target:
22 | powerSet.append(subset.copy())
23 | return
24 |
25 | # If at any moment, sum becomes greater than target, we don't need to proceed further
26 |
27 | if subsetSum > target:
28 | return
29 | # If we reach the end of arr[], we cannot go any further so we return back
30 |
31 | if i == n:
32 | return
33 |
34 | # include the i-th element into our subseq & subseqSum
35 |
36 | subset.append(arr[i])
37 | subsetSum += arr[i]
38 |
39 | # Ask recursion to do rest of the task
40 |
41 | helper(i+1, n, subsetSum)
42 |
43 | # Backtrack and undo the change we have done
44 |
45 | subset.pop()
46 | subsetSum -= arr[i]
47 |
48 | # use the While Loop to skip all the duplicate occurrences of i-th Element
49 |
50 | while i+1 < len(arr) and arr[i] == arr[i+1]:
51 | i += 1
52 | # Don't pick the i-th Element and ask recursion to do rest of the task
53 |
54 | helper(i+1, n, subsetSum)
55 |
56 | subset = []
57 | powerSet = []
58 | subsetSum = 0
59 |
60 | arr.sort()
61 |
62 | helper(0, n, subsetSum)
63 |
64 | return powerSet
65 |
66 | """
67 | Time Complexity: O(2^N)
68 | Space Complexity: O(N)
69 | """
70 |
--------------------------------------------------------------------------------
/Recursion/Lecture 13/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Combination Sum II
--------------------------------------------------------------------------------
/Recursion/Lecture 13/LeetCode/Combination Sum II.java:
--------------------------------------------------------------------------------
1 | /* This question is exactly similar to Combination Sum -I.
2 | The only difference is that we have duplicates inside the given array arr[]
3 | We need to skip the duplicate elements. Else they would generate Duplicate Combinations which we don't want
4 | To skip the Duplicate Elements, we will sort arr[] and use a While Loop to skip all the Duplicate Elements
5 | */
6 |
7 | class Solution
8 | {
9 | public void help(int i, int[] arr, int n, List subSet, List> powerSet, int sum, int target)
10 | {
11 |
12 | // If sum is equal to target, we have reached a Valid Combination
13 |
14 | if(sum == target)
15 | {
16 | powerSet.add(new ArrayList(subSet)) ;
17 | return;
18 | }
19 |
20 | // If at any moment, sum becomes greater than target, we don't need to proceed further
21 |
22 | if(sum > target) return ;
23 |
24 | // If we reach the end of arr[], we cannot go any further so we return back
25 |
26 | if(i == n) return;
27 |
28 | // Include the i-th Element into our Subset & Sum
29 |
30 | subSet.add(arr[i]) ;
31 | sum += arr[i] ;
32 |
33 | // Ask recursion to do rest of the task
34 | help(i + 1, arr, n, subSet, powerSet, sum, target) ;
35 |
36 | // Backtrack and undo the change we have done
37 |
38 | subSet.remove(subSet.size()-1);
39 | sum -= arr[i];
40 |
41 | // Use the While Loop to skip all the duplicate occurrences of i-th Element
42 |
43 | while(i + 1 < arr.length && arr[i] == arr[i + 1]) i++ ;
44 |
45 | // Don't pick the i-th Element and ask recursion to do rest of the task
46 |
47 | help(i + 1, arr, n, subSet, powerSet, sum, target) ;
48 | }
49 | public List> combinationSum2(int[] candidates, int target)
50 | {
51 | List subSet = new ArrayList<>() ;
52 | List> powerSet = new ArrayList<>() ;
53 | int sum = 0;
54 | int n = candidates.length ;
55 | Arrays.sort(candidates) ;
56 |
57 | help(0, candidates, n, subSet, powerSet, sum, target) ;
58 |
59 | return powerSet ;
60 | }
61 | }
62 |
63 | /*
64 | Time Complexity: O(2^N)
65 | Space Complexity: O(N)
66 | */
67 |
--------------------------------------------------------------------------------
/Recursion/Lecture 13/LeetCode/Combination Sum-2.cpp:
--------------------------------------------------------------------------------
1 | /* This question is exactly similar to Combination Sum -I.
2 | The only difference is that we have duplicates inside the given vector arr[]
3 | We need to skip the duplicate elements. Else they would generate Duplicate Combinations which we don't want
4 | To skip the Duplicate Elements, we will sort arr[] and use a While Loop to skip all the Duplicate Elements
5 | */
6 |
7 | class Solution {
8 | private :
9 |
10 | void help(int i, vector &arr, int n, vector &subSet, vector> &powerSet, int sum, int target) {
11 |
12 | // If sum is equal to target, we have reached a Valid Combination
13 |
14 | if(sum == target)
15 | {
16 | powerSet.push_back(subSet) ;
17 | return;
18 | }
19 |
20 | // If at any moment, sum becomes greater than target, we don't need to proceed further
21 |
22 | if(sum > target) return ;
23 |
24 | // If we reach the end of arr[], we cannot go any further so we return back
25 |
26 | if(i == n) return;
27 |
28 | // Include the i-th Element into our Subset & Sum
29 |
30 | subSet.push_back(arr[i]) ;
31 | sum += arr[i] ;
32 |
33 | // Ask recursion to do rest of the task
34 | help(i + 1, arr, n, subSet, powerSet, sum, target) ;
35 |
36 | // Backtrack and undo the change we have done
37 |
38 | subSet.pop_back();
39 | sum -= arr[i];
40 |
41 | // Use the While Loop to skip all the duplicate occurrences of i-th Element
42 |
43 | while(i + 1 < arr.size() && arr[i] == arr[i + 1]) i++ ;
44 |
45 | // Don't pick the i-th Element and ask recursion to do rest of the task
46 |
47 | help(i + 1, arr, n, subSet, powerSet, sum, target) ;
48 | }
49 |
50 |
51 | public:
52 | vector> combinationSum2(vector& candidates, int target) {
53 |
54 | vector subSet ;
55 | vector> powerSet ;
56 | int sum = 0;
57 | int n = candidates.size() ;
58 | sort(candidates.begin(), candidates.end()) ;
59 |
60 | help(0, candidates, n, subSet, powerSet, sum, target) ;
61 |
62 | return powerSet ;
63 | }
64 | };
65 |
66 | /*
67 | Time Complexity: O(2^N)
68 | Space Complexity: O(N)
69 | */
70 |
--------------------------------------------------------------------------------
/Recursion/Lecture 13/LeetCode/README.md:
--------------------------------------------------------------------------------
1 | ## 40. Combination Sum II
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 14/CodeStudio/Combination Sum III.cpp:
--------------------------------------------------------------------------------
1 | void help(int i, int k, int sumTillNow, int n, vector &subSet, vector> &ans)
2 | {
3 | // base condition
4 | // if the sumTillNow becomes greater than n, then we don't need to proceed further
5 | if (sumTillNow > n)
6 | return;
7 |
8 | // base condition
9 | // if k becomes equal to zero(0) , then check if the sumTillNow is equal to n or not
10 | if (k == 0)
11 | {
12 | // if the sumTillNow is equal to n, then include the subset into ans[][]
13 | if (sumTillNow == n)
14 | {
15 | ans.push_back(subSet);
16 | }
17 |
18 | // else we simply return without including the subset
19 | return;
20 | }
21 |
22 | // base condition
23 | // if i becomes equal to 10, then we don't need to proceed any further
24 | if (i == 10)
25 | return;
26 |
27 | // pick the ith element
28 | sumTillNow += i;
29 | subSet.push_back(i);
30 |
31 | // ask recursion to do the rest of the task
32 | help(i + 1, k - 1, sumTillNow, n, subSet, ans);
33 |
34 | // backtrack and undo the changes that have been done
35 | sumTillNow -= i;
36 | subSet.pop_back();
37 |
38 | // skip ith element
39 | help(i + 1, k, sumTillNow, n, subSet, ans);
40 | }
41 | vector> combinationSum3(int k, int n)
42 | {
43 | // Write your code here.
44 | vector subSet;
45 | vector> ans;
46 | help(1, k, 0, n, subSet, ans);
47 | return ans;
48 | }
49 |
50 | /*
51 | time complexity: O(2^K)
52 | space complexity: O(K)
53 | */
--------------------------------------------------------------------------------
/Recursion/Lecture 14/CodeStudio/Combination Sum III.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | public class Solution
3 | {
4 | static void help(int i, int k, int sumTillNow, int n, ArrayList subSet, ArrayList> ans)
5 | {
6 | // If the Sum-Till-Now becomes greater than n, we don't need to proceed further
7 |
8 | if(sumTillNow > n)
9 | return ;
10 |
11 | // If k becomes equal to zero(0) , we need to check if the Sum-Till-Now is equal to n or not
12 |
13 | if(k == 0)
14 | {
15 | // If the Sum-Till-Now is equal to n, we include the Subset into our ans
16 |
17 | if(sumTillNow == n)
18 | {
19 | ans.add(new ArrayList(subSet));
20 | }
21 |
22 | // Else we simply return without including the Subset
23 |
24 | return;
25 | }
26 |
27 | // If i becomes equal to 10, we don't need to proceed any further
28 |
29 | if(i == 10)
30 | return ;
31 |
32 | // We include the i-th Number into our Sum-Till-Now & also into our Subset
33 |
34 | sumTillNow += i ;
35 | subSet.add(i) ;
36 |
37 | // Ask Recursion to do the rest of the task
38 |
39 | help(i + 1, k - 1, sumTillNow, n, subSet, ans) ;
40 |
41 | // Backtrack and undo the change we have done
42 |
43 | sumTillNow -= i ;
44 | subSet.remove(subSet.size()-1) ;
45 |
46 | // We don't include the i-th Number and ask recursion to do the rest of the Combinations
47 |
48 | help(i + 1, k, sumTillNow, n, subSet, ans);
49 |
50 | }
51 | static ArrayList> combinationSum3(int k, int n)
52 | {
53 | ArrayList subSet = new ArrayList<>();
54 |
55 | ArrayList> ans = new ArrayList<>();
56 |
57 | help(1, k, 0, n, subSet, ans) ;
58 |
59 | return ans ;
60 | }
61 | }
62 |
63 | /*
64 | Time Complexity: O(2^N)
65 | Space Complexity: O(K)
66 | */
67 |
--------------------------------------------------------------------------------
/Recursion/Lecture 14/CodeStudio/Combination Sum-III.py:
--------------------------------------------------------------------------------
1 | """
2 | This question is exactly similar to Combination Sum -I.
3 | The only difference is that we have duplicates inside the given vector arr[]
4 | We need to skip the duplicate elements. Else they would generate Duplicate Combinations which we don't want
5 | To skip the Duplicate Elements, we will sort arr[] and use a While Loop to skip all the Duplicate Elements
6 |
7 | NOTE:
8 | As we haev to pass subset [] and ans [] by it's reference I haven't incuded it in heper() parameter
9 | """
10 | def combinationSum3(K: int, N: int) -> [[]]:
11 |
12 | def helper(i, k, sumTillNow , n):
13 |
14 | # If the Sum-Till-Now becomes greater than n, we don't need to proceed further
15 |
16 | if sumTillNow > n:
17 | return
18 |
19 | # If k becomes equal to zero(0) , we need to check if the Sum-Till-Now is equal to n or not
20 |
21 | if k == 0:
22 |
23 | # If the Sum-Till-Now is equal to n, we include the Subset into our ans[][]
24 |
25 | if sumTillNow == n:
26 | ans.append(subset.copy())
27 |
28 | # else we simply return without including the Subset
29 |
30 | return
31 |
32 | # If i becomes equal to 10, we don't need to proceed any further
33 |
34 | if i == 10:
35 | return
36 |
37 | # We include the i-th Number into our Sum-Till-Now & also into our Subset[]
38 |
39 | sumTillNow += i
40 | subset.append(i)
41 |
42 | # Ask Recursion to do the rest of the task
43 |
44 | helper(i+1, k-1, sumTillNow, n)
45 |
46 | # Backtrack and undo the change we have done
47 |
48 | subset.pop()
49 | sumTillNow -= i
50 |
51 | # We don't include the i-th Number and ask recursion to do the rest of the Combinations
52 | helper(i+1, k, sumTillNow, n)
53 |
54 | subset = []
55 |
56 | ans = []
57 |
58 | helper(1, K, 0, N)
59 |
60 | return ans
61 |
62 | """
63 | Time Complexity: O(2^N)
64 | Space Complexity: O(K)
65 | """
66 |
--------------------------------------------------------------------------------
/Recursion/Lecture 14/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Combination Sum III
--------------------------------------------------------------------------------
/Recursion/Lecture 14/LeetCode/Combination Sum III.java:
--------------------------------------------------------------------------------
1 | /* This question is the continuation of Combination Sum 1 & 2
2 | The only difference is that, instead of giving us an array
3 | We are asked to print all possible combinations using numbers 1 to 9 (both inclusive)
4 | */
5 |
6 | class Solution
7 | {
8 | public void help(int i, int k, int sumTillNow, int n, List subSet, List> ans)
9 | {
10 | // If the Sum-Till-Now becomes greater than n, we don't need to proceed further
11 |
12 | if(sumTillNow > n)
13 | return ;
14 |
15 | // If k becomes equal to zero(0) , we need to check if the Sum-Till-Now is equal to n or not
16 |
17 | if(k == 0)
18 | {
19 | // If the Sum-Till-Now is equal to n, we include the Subset into our ans
20 |
21 | if(sumTillNow == n)
22 | {
23 | ans.add(new ArrayList(subSet));
24 | }
25 |
26 | // Else we simply return without including the Subset
27 |
28 | return;
29 | }
30 |
31 | // If i becomes equal to 10, we don't need to proceed any further
32 |
33 | if(i == 10)
34 | return ;
35 |
36 | // We include the i-th Number into our Sum-Till-Now & also into our Subset
37 |
38 | sumTillNow += i ;
39 | subSet.add(i) ;
40 |
41 | // Ask Recursion to do the rest of the task
42 |
43 | help(i + 1, k - 1, sumTillNow, n, subSet, ans) ;
44 |
45 | // Backtrack and undo the change we have done
46 |
47 | sumTillNow -= i ;
48 | subSet.remove(subSet.size()-1) ;
49 |
50 | // We don't include the i-th Number and ask recursion to do the rest of the Combinations
51 |
52 | help(i + 1, k, sumTillNow, n, subSet, ans);
53 |
54 | }
55 | public List> combinationSum3(int k, int n)
56 | {
57 | List subSet = new ArrayList<>();
58 |
59 | List> ans = new ArrayList<>();
60 |
61 | help(1, k, 0, n, subSet, ans) ;
62 |
63 | return ans ;
64 | }
65 | }
66 |
67 | /*
68 | Time Complexity: O(2^N)
69 | Space Complexity: O(K)
70 | */
71 |
--------------------------------------------------------------------------------
/Recursion/Lecture 14/LeetCode/Combination Sum-3.cpp:
--------------------------------------------------------------------------------
1 | /* This question is the continuation of Combination Sum 1 & 2
2 | The only difference is that, instead of giving us an array / vector,
3 | We are asked to print all possible combinations using numbers 1 to 9 (both inclusive)
4 | */
5 |
6 | class Solution {
7 | private :
8 |
9 | void help(int i, int k, int sumTillNow, int n, vector &subSet, vector> &ans)
10 | {
11 | // If the Sum-Till-Now becomes greater than n, we don't need to proceed further
12 |
13 | if(sumTillNow > n)
14 | return ;
15 |
16 | // If k becomes equal to zero(0) , we need to check if the Sum-Till-Now is equal to n or not
17 |
18 | if(k == 0)
19 | {
20 | // If the Sum-Till-Now is equal to n, we include the Subset into our ans[][]
21 |
22 | if(sumTillNow == n)
23 | {
24 | ans.push_back(subSet);
25 | }
26 |
27 | // Else we simply return without including the Subset
28 |
29 | return;
30 | }
31 |
32 | // If i becomes equal to 10, we don't need to proceed any further
33 |
34 | if(i == 10)
35 | return ;
36 |
37 | // We include the i-th Number into our Sum-Till-Now & also into our Subset[]
38 |
39 | sumTillNow += i ;
40 | subSet.push_back(i) ;
41 |
42 | // Ask Recursion to do the rest of the task
43 |
44 | help(i + 1, k - 1, sumTillNow, n, subSet, ans) ;
45 |
46 | // Backtrack and undo the change we have done
47 |
48 | sumTillNow -= i ;
49 | subSet.pop_back() ;
50 |
51 | // We don't include the i-th Number and ask recursion to do the rest of the Combinations
52 |
53 | help(i + 1, k, sumTillNow, n, subSet, ans);
54 |
55 | }
56 |
57 | public:
58 | vector> combinationSum3(int k, int n) {
59 |
60 | vector subSet ;
61 |
62 | vector> ans ;
63 |
64 | help(1, k, 0, n, subSet, ans) ;
65 |
66 | return ans ;
67 | }
68 | };
69 |
70 | /*
71 | Time Complexity: O(2^N)
72 | Space Complexity: O(K)
73 | */
74 |
--------------------------------------------------------------------------------
/Recursion/Lecture 14/LeetCode/README.md:
--------------------------------------------------------------------------------
1 | ## 216. Combination Sum III
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 15/CodeStudio/Letter Combinations of a Phone Number.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | using namespace std;
3 |
4 | void help(int i, string &s, string &temp, vector &ans, unordered_map &m)
5 | {
6 | // base condition
7 | // i : current Index
8 | // if we have reached till the end of the string s then include temp into ans[][]
9 | if (i == s.size())
10 | {
11 | ans.push_back(temp);
12 | return;
13 | }
14 |
15 | // this gives the entire string that is present in the map m corresponding to the ith element in the string s
16 | // eg: s = 2 3, i = 1
17 | // str = m[s[i]] = m[s[1]] = m[3] = def
18 | string str = m[s[i]];
19 |
20 | // loop for traversing every element in str
21 | for (int j = 0; j < str.size(); j++)
22 | {
23 | // do the small task
24 | temp.push_back(str[j]);
25 |
26 | // ask recursion to do the remaining task
27 | help(i + 1, s, temp, ans, m);
28 |
29 | // backtrack & undo the changes that were made
30 | temp.pop_back();
31 | }
32 | }
33 |
34 | vector combinations(string s)
35 | {
36 | // for solving this problem we need to know what all characters are represented by each of the numbers
37 | // therefore we are storing all the corresponding characters from digit 2 to 9 in the unordered_map m
38 | unordered_map m;
39 | m['2'] = "abc";
40 | m['3'] = "def";
41 | m['4'] = "ghi";
42 | m['5'] = "jkl";
43 | m['6'] = "mno";
44 | m['7'] = "pqrs";
45 | m['8'] = "tuv";
46 | m['9'] = "wxyz";
47 |
48 | vector ans;
49 | string temp;
50 | help(0, s, temp, ans, m);
51 | return ans;
52 | }
53 |
54 | /*
55 | time complexity: O(3^N)
56 | space complexity: O(N)
57 | */
--------------------------------------------------------------------------------
/Recursion/Lecture 15/CodeStudio/Letter Combinations of a Phone Number.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.*;
3 | public class Solution
4 | {
5 | static void help(int i, String s, String temp, ArrayList ans, HashMap m)
6 | {
7 | // If i has reached till the end of given string, we have reached a Valid Combination
8 | // We should include it into ans and return back
9 |
10 | if (i == s.length())
11 | {
12 | ans.add(temp);
13 | return;
14 | }
15 |
16 | // Since, we have mapped all the digits with their corresponding Letters
17 | // m.get( s.charAt(i) ) will give us the actual string corresponding to that digit using HashMap m
18 |
19 | char chr = s.charAt(i);
20 | String str = m.get(chr);
21 |
22 | // loop for traversing every element in str
23 |
24 | for (int j = 0; j < str.length(); j++)
25 | {
26 |
27 | char c = str.charAt(j);
28 |
29 | // Ask recursion to do rest of the task
30 |
31 | help(i + 1, s, temp + c, ans, m);
32 |
33 | }
34 | }
35 | public static ArrayList combinations(String s)
36 | {
37 | // To solve this question, we need to map all the letters of a particular digit with it's corresponding digit. This is done with the help of HashMap m.
38 |
39 | HashMap m = new HashMap<>();
40 | m.put('2',"abc");
41 | m.put('3',"def");
42 | m.put('4',"ghi");
43 | m.put('5',"jkl");
44 | m.put('6',"mno");
45 | m.put('7',"pqrs");
46 | m.put('8',"tuv");
47 | m.put('9',"wxyz");
48 |
49 | ArrayList ans = new ArrayList<>();
50 |
51 | if(s.length() == 0)
52 | return ans;
53 |
54 | String temp = "";
55 |
56 | help(0 , s , temp , ans , m) ;
57 |
58 | return ans;
59 | }
60 | }
61 |
62 | /*
63 | Time Complexity: O(3^N)
64 | Space Complexity: O(N)
65 | */
66 |
--------------------------------------------------------------------------------
/Recursion/Lecture 15/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Letter Combinations of a Phone Number
--------------------------------------------------------------------------------
/Recursion/Lecture 15/LeetCode/Letter Combination of a Phone Number.cpp:
--------------------------------------------------------------------------------
1 | /* This question requries us to print all Valid Combinations of the given string digits which comprises of digits from 2 to 9.
2 | The only thing we require extra in this question is to map all the letter combinations of the phone number to its corresponding digits.
3 | The rest part of the question remains exactly same
4 | */
5 |
6 | class Solution {
7 | private:
8 |
9 | void help(int i, string &s, string &temp, vector &ans, unordered_map &m)
10 | {
11 | // If i has reached till the end of given string, we have reached a Valid Combination
12 | // We should include it into ans[][] and return back
13 |
14 | if (i == s.size())
15 | {
16 | ans.push_back(temp);
17 | return;
18 | }
19 |
20 | // Since, we have mapped all the digits with their corresponding Letters
21 | // m[s[i]] will give us the actual string corresponding to that digit using unordered_map m
22 |
23 | string str = m[s[i]];
24 |
25 | // loop for traversing every element in str
26 |
27 | for (int j = 0; j < str.size(); j++)
28 | {
29 | // Push the i-th character of str into our temp string
30 |
31 | temp.push_back(str[j]);
32 |
33 | // Ask recursion to do rest of the task
34 |
35 | help(i + 1, s, temp, ans, m);
36 |
37 | // Backtrack and undo the change we have already done
38 |
39 | temp.pop_back();
40 | }
41 | }
42 |
43 | public:
44 | vector letterCombinations(string digits) {
45 |
46 | // As per the problem, for an empty string, we need to return an empty vector
47 |
48 | if(digits.size() == 0)
49 | return {} ;
50 |
51 | // To solve this question, we need to map all the letters of a particular digit with it's corresponding digit. This is done with the help of unordered_map m.
52 |
53 | unordered_map m;
54 | m['2'] = "abc";
55 | m['3'] = "def";
56 | m['4'] = "ghi";
57 | m['5'] = "jkl";
58 | m['6'] = "mno";
59 | m['7'] = "pqrs";
60 | m['8'] = "tuv";
61 | m['9'] = "wxyz";
62 |
63 | vector ans ;
64 |
65 | string temp ;
66 |
67 | help(0 , digits , temp , ans , m) ;
68 |
69 | return ans;
70 |
71 | }
72 | };
73 |
74 | /*
75 | Time Complexity: O(3^N)
76 | Space Complexity: O(N)
77 | */
78 |
--------------------------------------------------------------------------------
/Recursion/Lecture 15/LeetCode/Letter Combinations of a Phone Number.java:
--------------------------------------------------------------------------------
1 | /* This question requries us to print all Valid Combinations of the given string digits which comprises of digits from 2 to 9.
2 | The only thing we require extra in this question is to map all the letter combinations of the phone number to its corresponding digits.
3 | The rest part of the question remains exactly same
4 | */
5 |
6 | class Solution
7 | {
8 | void help(int i, String s, String temp, List ans, HashMap m)
9 | {
10 | // If i has reached till the end of given string, we have reached a Valid Combination
11 | // We should include it into ans and return back
12 |
13 | if (i == s.length())
14 | {
15 | ans.add(temp);
16 | return;
17 | }
18 |
19 | // Since, we have mapped all the digits with their corresponding Letters
20 | // m.get( s.charAt(i) ) will give us the actual string corresponding to that digit using HashMap m
21 |
22 | char chr = s.charAt(i);
23 | String str = m.get(chr);
24 |
25 | // loop for traversing every element in str
26 |
27 | for (int j = 0; j < str.length(); j++)
28 | {
29 |
30 | char c = str.charAt(j);
31 |
32 | // Ask recursion to do rest of the task
33 |
34 | help(i + 1, s, temp + c, ans, m);
35 |
36 | }
37 | }
38 |
39 | public List letterCombinations(String digits)
40 | {
41 |
42 | // To solve this question, we need to map all the letters of a particular digit with it's corresponding digit. This is done with the help of HashMap m.
43 |
44 | HashMap m = new HashMap<>();
45 | m.put('2',"abc");
46 | m.put('3',"def");
47 | m.put('4',"ghi");
48 | m.put('5',"jkl");
49 | m.put('6',"mno");
50 | m.put('7',"pqrs");
51 | m.put('8',"tuv");
52 | m.put('9',"wxyz");
53 |
54 | List ans = new ArrayList<>();
55 |
56 | if(digits.length() == 0)
57 | return ans;
58 |
59 | String temp = "";
60 |
61 | help(0 , digits , temp , ans , m) ;
62 |
63 | return ans;
64 | }
65 | }
66 |
67 | /*
68 | Time Complexity: O(3^N)
69 | Space Complexity: O(N)
70 | */
71 |
--------------------------------------------------------------------------------
/Recursion/Lecture 15/LeetCode/README.md:
--------------------------------------------------------------------------------
1 | ## 17. Letter Combinations of a Phone Number
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 16/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Partition to K equal sum subsets
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 16/LeetCode/README.md:
--------------------------------------------------------------------------------
1 | ## Partition to K Equal Sum Subsets
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 17/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Maximum Length of a Concatenated String with Unique Characters
--------------------------------------------------------------------------------
/Recursion/Lecture 17/LeetCode/README.md:
--------------------------------------------------------------------------------
1 | ## 1239. Maximum Length of a Concatenated String with Unique Characters
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 18/CodeStudio/Flood Fill Algorithm.cpp:
--------------------------------------------------------------------------------
1 | void flood(int i, int j, vector> &image, int oldColor, int newColor, int n, int m)
2 | {
3 | // [i][j] denotes the current cell
4 | // n*m is the size of the images which is also denoting the boundary of the image
5 |
6 | // base condition
7 | if (i < 0 || j < 0 || i == n || j == m || image[i][j] != oldColor)
8 | return;
9 |
10 | // change the current cell to newColor
11 | image[i][j] = newColor;
12 |
13 | // recursive call in the downward direction
14 | flood(i + 1, j, image, oldColor, newColor, n, m);
15 |
16 | // recursive call in the upward direction
17 | flood(i - 1, j, image, oldColor, newColor, n, m);
18 |
19 | // recursive call in the right direction
20 | flood(i, j + 1, image, oldColor, newColor, n, m);
21 |
22 | // recursive call in the left direction
23 | flood(i, j - 1, image, oldColor, newColor, n, m);
24 | }
25 |
26 | vector> floodFill(vector> &image, int x, int y, int newColor)
27 | {
28 | // it is denoting the oldcolor
29 | int oldColor = image[x][y];
30 |
31 | // incase the oldColor & newColor is same then there is a possibility of forming an infinite recursion therefore to avoid such type of situation we are putting this condition over here if oldColor != newColor then it will proceed else it will return us the same image
32 | if (oldColor == newColor)
33 | return image;
34 |
35 | int n = image.size(), m = image[0].size();
36 |
37 | // recursion call
38 | flood(x, y, image, oldColor, newColor, n, m);
39 |
40 | return image;
41 | }
42 |
43 | /*
44 | time complexity: O(M * N)
45 | space complexity: O(M * N)
46 | */
--------------------------------------------------------------------------------
/Recursion/Lecture 18/CodeStudio/Flood Fill Algorithm.java:
--------------------------------------------------------------------------------
1 | /* This Question asks us to color all the Neighbouring Cells of (x , y) with the given Color
2 | By Neighbouring we can move in 4 directions - a) Up , b) Down , c) Left , d) Right
3 | And we change colors of only those Neighbouring Cells which have the same color as the Original Cell(x , y)
4 | If old-Color of (x , y) is same as New-Color, we don't need to modify anything. Just return the previous Matrix
5 | */
6 |
7 | public class Solution
8 | {
9 | static void flood(int i, int j, int[][] image, int oldColor, int newColor, int n, int m)
10 | {
11 |
12 | // If we move out of the Matrix Or oldColor is not equal to newColor, we just return back
13 |
14 | if (i < 0 || j < 0 || i == n || j == m || image[i][j] != oldColor)
15 | return;
16 |
17 | // We change the color of the Current-Cell to newColor
18 |
19 | image[i][j] = newColor;
20 |
21 | // Recursive call in Downward direction
22 |
23 | flood(i + 1, j, image, oldColor, newColor, n, m);
24 |
25 | // Recursive call in the Upward direction
26 |
27 | flood(i - 1, j, image, oldColor, newColor, n, m);
28 |
29 | // Recursive call in the Right direction
30 |
31 | flood(i, j + 1, image, oldColor, newColor, n, m);
32 |
33 | // Recursive call in the left direction
34 |
35 | flood(i, j - 1, image, oldColor, newColor, n, m);
36 | }
37 |
38 | public static int[][] floodFill(int[][] image, int x, int y, int newColor)
39 | {
40 | // We calculate oldColor first using the coordinates (sr , sc)
41 |
42 | int oldColor = image[x][y];
43 |
44 | // Incase the oldColor & new Color is same, we can simply return the Original Image
45 |
46 | if (oldColor == newColor)
47 | return image;
48 |
49 | // We calculate the Dimmensions of image matrix[]
50 |
51 | int n = image.length, m = image[0].length;
52 |
53 | flood(x , y , image, oldColor, newColor , n, m);
54 |
55 | // We return the new image[][] matrix after changing all the Neighbouring Cells of (sr , sc) having OldColor to Color
56 |
57 | return image;
58 | }
59 | }
60 |
61 | /*
62 | Time Complexity: O(N * M)
63 | Space Complexity: O(N * M)
64 | */
65 |
--------------------------------------------------------------------------------
/Recursion/Lecture 18/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Flood Fill Algorithm
--------------------------------------------------------------------------------
/Recursion/Lecture 18/LeetCode/Flood Fill Algorithm.java:
--------------------------------------------------------------------------------
1 | /* This Question asks us to color all the Neighbouring Cells of (sr , sc) with the given Color
2 | By Neighbouring we can move in 4 directions - a) Up , b) Down , c) Left , d) Right
3 | And we change colors of only those Neighbouring Cells which have the same color as the Original Cell(sr, sc)
4 | If old-Color of (sr , sc) is same as New-Color, we don't need to modify anything. Just return the previous Matrix
5 | */
6 |
7 | class Solution
8 | {
9 | public void flood(int i, int j, int[][] image, int oldColor, int newColor, int n, int m)
10 | {
11 |
12 | // If we move out of the Matrix Or oldColor is not equal to newColor, we just return back
13 |
14 | if (i < 0 || j < 0 || i == n || j == m || image[i][j] != oldColor)
15 | return;
16 |
17 | // We change the color of the Current-Cell to newColor
18 |
19 | image[i][j] = newColor;
20 |
21 | // Recursive call in Downward direction
22 |
23 | flood(i + 1, j, image, oldColor, newColor, n, m);
24 |
25 | // Recursive call in the Upward direction
26 |
27 | flood(i - 1, j, image, oldColor, newColor, n, m);
28 |
29 | // Recursive call in the Right direction
30 |
31 | flood(i, j + 1, image, oldColor, newColor, n, m);
32 |
33 | // Recursive call in the left direction
34 |
35 | flood(i, j - 1, image, oldColor, newColor, n, m);
36 | }
37 |
38 | public int[][] floodFill(int[][] image, int sr, int sc, int color)
39 | {
40 | // We calculate oldColor first using the coordinates (sr , sc)
41 |
42 | int oldColor = image[sr][sc];
43 |
44 | // Incase the oldColor & given Color is same, we can simply return the Original Image
45 |
46 | if (oldColor == color)
47 | return image;
48 |
49 | // We calculate the Dimmensions of image matrix[]
50 |
51 | int n = image.length, m = image[0].length;
52 |
53 | flood(sr , sc , image, oldColor, color , n, m);
54 |
55 | // We return the new image[][] matrix after changing all the Neighbouring Cells of (sr , sc) having OldColor to Color
56 |
57 | return image;
58 | }
59 | }
60 |
61 | /*
62 | Time Complexity: O(N * M)
63 | Space Complexity: O(N * M)
64 | */
65 |
--------------------------------------------------------------------------------
/Recursion/Lecture 18/LeetCode/Flood Fill.cpp:
--------------------------------------------------------------------------------
1 | /* This Question asks us to color all the Neighbouring Cells of (sr , sc) with the given Color
2 | By Neighbouring we can move in 4 directions - a) Up , b) Down , c) Left , d) Right
3 | And we change colors of only those Neighbouring Cells which have the same color as the Original Cell(sr, sc)
4 | If old-Color of (sr , sc) is same as New-Color, we don't need to modify anything. Just return the previous Matrix
5 | */
6 |
7 | class Solution {
8 | private :
9 |
10 | void flood(int i, int j, vector> &image, int oldColor, int newColor, int n, int m)
11 | {
12 |
13 | // If we move out of the Matrix Or oldColor is not equal to newColor, we just return back
14 |
15 | if (i < 0 || j < 0 || i == n || j == m || image[i][j] != oldColor)
16 | return;
17 |
18 | // We change the color of the Current-Cell to newColor
19 |
20 | image[i][j] = newColor;
21 |
22 | // Recursive call in Downward direction
23 |
24 | flood(i + 1, j, image, oldColor, newColor, n, m);
25 |
26 | // Recursive call in the Upward direction
27 |
28 | flood(i - 1, j, image, oldColor, newColor, n, m);
29 |
30 | // Recursive call in the Right direction
31 |
32 | flood(i, j + 1, image, oldColor, newColor, n, m);
33 |
34 | // Recursive call in the left direction
35 |
36 | flood(i, j - 1, image, oldColor, newColor, n, m);
37 | }
38 |
39 | public:
40 | vector> floodFill(vector>& image, int sr, int sc, int color) {
41 |
42 | // We calculate oldColor first using the coordinates (sr , sc)
43 |
44 | int oldColor = image[sr][sc];
45 |
46 | // Incase the oldColor & given Color is same, we can simply return the Original Image
47 |
48 | if (oldColor == color)
49 | return image;
50 |
51 | // We calculate the Dimmensions of image matrix[]
52 |
53 | int n = image.size(), m = image[0].size();
54 |
55 | flood(sr , sc , image, oldColor, color , n, m);
56 |
57 | // We return the new image[][] matrix after changing all the Neighbouring Cells of (sr , sc) having OldColor to Color
58 |
59 | return image;
60 | }
61 | };
62 |
63 | /*
64 | Time Complexity: O(N * M)
65 | Space Complexity: O(N * M)
66 | */
67 |
--------------------------------------------------------------------------------
/Recursion/Lecture 18/LeetCode/README.md:
--------------------------------------------------------------------------------
1 | ## 733. Flood Fill
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 19/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Word Search - l
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 19/LeetCode/README.md:
--------------------------------------------------------------------------------
1 | ## 79. Word Search
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 20/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## Rat In A Maze
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 21/CodeStudio/README.md:
--------------------------------------------------------------------------------
1 | ## N Queens
2 |
--------------------------------------------------------------------------------
/Recursion/Lecture 21/LeetCode/README.md:
--------------------------------------------------------------------------------
1 | ## 51. N-Queens
2 |
--------------------------------------------------------------------------------