├── README.md ├── Week 4 - Hashmap ├── README.md ├── hashmap ├── hashmapwithdjb2.cpp ├── hello.cpp ├── modulo └── test.cpp ├── Week 6 Dynamic Arrays or Lists └── BasicDynamicArray.cpp └── Week 7 - Queue ├── concept-of-circular-queue.cpp ├── implementation-of-queue-using-arrays.cpp └── implementation-of-queue-using-linked-list.cpp /README.md: -------------------------------------------------------------------------------- 1 | # DevWeekend's Data Structures Course 2 | Some **considerations** while starting with problem-solving till 100+ Leetcode problems are solved: 3 | 4 | - Start with the most-easiest problems. 5 | - DO NOT try to solve each problem yourself, instead try to learn and understand how different problems are being solved 6 | - Do not try to solve a problem for more than 1 hour initially to get fast and to achieve more in less time, for any problem taking more than 1 hour, put it in a backlog and solve it later 7 | - Average time to solve a problem should be 30-45 minutes 8 | - Do not try to solve a lot of problems from one topic, instead try to solve 5-10 problems per topic 9 | - Do not try to jump into problem-solving directly without the necessary pre-requisites, For example 10 | > If you are trying to solve a problem that requires HashSet/HashMap then make sure you have studied HashMap before solving the problem 11 | > If you are trying to solve a problem that uses recursion, first make sure you learn recursion properly 12 | > If you are trying to solve a problem that uses graphs/trees, first make sure you learn graphs/trees properly 13 | > If you are trying to solve a problem that uses dynamic programming, first make sure you learn dynamic programming properly. 14 | 15 | ---- 16 | ## Week 1- Array 17 | 1. https://leetcode.com/problems/running-sum-of-1d-array/description/ 18 | 2. https://leetcode.com/problems/find-the-highest-altitude/ 19 | 3. https://leetcode.com/problems/final-value-of-variable-after-performing-operations/description/ 20 | 4. https://leetcode.com/problems/squares-of-a-sorted-array/description/ 21 | 5. https://leetcode.com/problems/concatenation-of-array/ 22 | 6. https://leetcode.com/problems/number-of-good-pairs/description/ 23 | 7. https://leetcode.com/problems/shuffle-the-array/description/ 24 | 8. https://leetcode.com/problems/move-zeroes/description/ 25 | 26 | - Basic Understanding of Data structures in your language (C++ STL, C# Collections, Python Standard Library) 27 | - If you like C++ and more details > My code school Data Structures 28 | 29 | https://www.youtube.com/playlist?list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P (C++) 30 | 31 | ---- 32 | ## Week 2- String 33 | 1. https://leetcode.com/problems/jewels-and-stones/description/ 34 | 2. https://leetcode.com/problems/reverse-string/description/ 35 | 3. https://leetcode.com/problems/merge-strings-alternately/description/ 36 | 4. https://leetcode.com/problems/fizz-buzz/description/ 37 | 5. https://leetcode.com/problems/valid-anagram/description/ 38 | 6. https://leetcode.com/problems/reverse-vowels-of-a-string/ 39 | 7. https://leetcode.com/problems/valid-palindrome/description/ 40 | 8. https://leetcode.com/problems/repeated-substring-pattern/description/ 41 | 9. https://leetcode.com/problems/isomorphic-strings/description/ 42 | 10. https://leetcode.com/problems/is-subsequence/description/ 43 | 44 | 45 | - Stl for C++ Programmers (It will help to speed up the coding part using built-in functions and short hands) 46 | - Note: The given lecture has Data structures like set and hashmap which we haven't studied yet, don't worry we will be having a dedicated lecture on them for now just have a high-level idea. 47 | 48 | https://youtu.be/RRVYpIET_RU?si=xI1JBIVbtCkj_Iq7 49 | 50 | ---- 51 | ## Week 3 - Hashmap 52 | 1. https://leetcode.com/problems/next-greater-element-i/ 53 | 2. https://leetcode.com/problems/two-sum/ 54 | 3. https://leetcode.com/problems/find-the-difference-of-two-arrays/description/ 55 | 4. https://leetcode.com/problems/missing-number/description/ 56 | 5. https://leetcode.com/problems/jewels-and-stones/description/ 57 | 6. https://leetcode.com/problems/contains-duplicate/description/ 58 | 7. https://leetcode.com/problems/length-of-last-word/description/ 59 | 8. https://leetcode.com/problems/valid-anagram/description/ 60 | 61 | ---- 62 | ## Week 4 - LinkedList 63 | 1. https://leetcode.com/problems/reverse-linked-list/description/ 64 | 2. https://leetcode.com/problems/middle-of-the-linked-list/description/ 65 | 3. https://leetcode.com/problems/linked-list-cycle/description/ 66 | 4. https://leetcode.com/problems/maximum-twin-sum-of-a-linked-list/ 67 | 5. https://leetcode.com/problems/intersection-of-two-linked-lists/description/ 68 | 6. https://leetcode.com/problems/remove-duplicates-from-sorted-list/description/ 69 | 7. https://leetcode.com/problems/convert-binary-number-in-a-linked-list-to-integer/description/ 70 | 8. https://leetcode.com/problems/design-hashmap/description/ 71 | 72 | ---- 73 | ## Week 5 - Dynamic Arrays 74 | 1. [Container With Most Water](https://leetcode.com/problems/container-with-most-water) 75 | 2. [Design HashMap](https://leetcode.com/problems/design-hashmap) 76 | 3. [Best Time to Buy and Sell Stock](https://leetcode.com/problems/best-time-to-buy-and-sell-stock) 77 | 4. [Design HashSet](https://leetcode.com/problems/design-hashset) 78 | 5. [Design Browser History](https://leetcode.com/problems/design-browser-history/) 79 | 6. [Maximum Subarray](https://leetcode.com/problems/maximum-subarray/) 80 | 7. [Range Sum Query - Immutable](https://leetcode.com/problems/range-sum-query-immutable/) 81 | 82 | ---- 83 | ## Week 6 - Stack 84 | 1. [Backspace String Compare](https://leetcode.com/problems/backspace-string-compare/) 85 | 2. [Valid Parentheses](https://leetcode.com/problems/valid-parentheses/) 86 | 3. [Make The String Great](https://leetcode.com/problems/make-the-string-great/) 87 | 4. [Remove All Adjacent Duplicates In String](https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string/) 88 | 5. [Removing Stars From a String](https://leetcode.com/problems/removing-stars-from-a-string/) 89 | 6. [Implement Queue using Stacks](https://leetcode.com/problems/implement-queue-using-stacks/) 90 | 91 | ---- 92 | ## Week 7 - Queue 93 | 1. [Number of Students Unable to Eat Lunch](https://leetcode.com/problems/number-of-students-unable-to-eat-lunch/) 94 | 2. [Time Needed to Buy Tickets](https://leetcode.com/problems/time-needed-to-buy-tickets/) 95 | 3. [First Unique Character in a String](https://leetcode.com/problems/first-unique-character-in-a-string/) 96 | 4. [Dota2 Senate](https://leetcode.com/problems/dota2-senate/) 97 | 5. [Number of Recent Calls](https://leetcode.com/problems/number-of-recent-calls/) 98 | 6. [Implement Stack using Queues](https://leetcode.com/problems/implement-stack-using-queues/) 99 | 100 | ---- 101 | ## Week 8 - Recursion 102 | 1. [Fibonacci Number](https://leetcode.com/problems/fibonacci-number/description/) 103 | 2. [Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists/description/) 104 | 3. [Power of Two](https://leetcode.com/problems/power-of-two/) 105 | 4. [Power of Three](https://leetcode.com/problems/power-of-three/) 106 | 5. [Power of Four](https://leetcode.com/problems/power-of-four/description/) 107 | 6. [Pow(x, n)](https://leetcode.com/problems/powx-n/) 108 | 109 | - Everyone who crossed the leetcode count 50 must watch the basics of [Time and Space Complexity](https://youtu.be/FPu9Uld7W-E?si=_tlstN7PZsDirIpe). 110 | - As we are moving towards advance data structures and medium problems for that you must need to have an idea of optimization. 111 | 112 | ---- 113 | # Phase 2 114 | 115 | **Instructions** 116 | - Understand the problem by yourself 117 | - If having difficulty find any video on YouTube and watch the starting part to understand the problem then pause the video try your solution. 118 | - Then watch the solution even if your solution is submitted or not. 119 | - Recommended channels (Neetcode.io, striver) 120 | 121 | ## Week 9 122 | ### Array 123 | 1. [Merge Intervals](https://leetcode.com/problems/merge-intervals/) 124 | 2. [3Sum](https://leetcode.com/problems/3sum/) 125 | 3. [Product of Array Except Self](https://leetcode.com/problems/product-of-array-except-self/) 126 | 4. [Insert Delete GetRandom O(1)](https://leetcode.com/problems/insert-delete-getrandom-o1/) 127 | 5. [Subarray Sum Equals K](https://leetcode.com/problems/subarray-sum-equals-k/) 128 | 129 | ### String 130 | 1. [Longest Substring Without Repeating Characters](https://leetcode.com/problems/longest-substring-without-repeating-characters/) 131 | 2. [Minimum Remove to Make Valid Parentheses](https://leetcode.com/problems/minimum-remove-to-make-valid-parentheses/) 132 | 3. [Longest Palindromic Substring](https://leetcode.com/problems/longest-palindromic-substring/) 133 | 4. [Group Anagrams](https://leetcode.com/problems/group-anagrams/) 134 | 5. [Generate Parentheses](https://leetcode.com/problems/generate-parentheses/) 135 | 136 | ---- 137 | ## Week 10 138 | ### Greedy 139 | 1. [Task Scheduler](https://leetcode.com/problems/task-scheduler/) 140 | 2. [Gas Station](https://leetcode.com/problems/gas-station/) 141 | 3. [Minimum Time to Make Rope Colorful](https://leetcode.com/problems/minimum-deletion-cost-to-avoid-repeating-letters/) 142 | 4. [Maximum Number of Events That Can Be Attended](https://leetcode.com/problems/maximum-number-of-events-that-can-be-attended/) 143 | 5. [Minimum Deletions to Make Character Frequencies Unique](https://leetcode.com/problems/minimum-deletions-to-make-character-frequencies-unique/) 144 | 145 | ### Math 146 | 1. [Encode and Decode TinyURL](https://leetcode.com/problems/encode-and-decode-tinyurl/) 147 | 2. [String to Integer (atoi)](https://leetcode.com/problems/string-to-integer-atoi/) 148 | 3. [Multiply Strings](https://leetcode.com/problems/multiply-strings/) 149 | 4. [Angle Between Hands of a Clock](https://leetcode.com/problems/angle-between-hands-of-a-clock/) 150 | 5. [Integer Break](https://leetcode.com/problems/integer-break/) 151 | 152 | ---- 153 | ## Week 11 154 | ### Intervals 155 | 1. [Insert Interval](https://leetcode.com/problems/insert-interval/) 156 | 2. [Merge Interval](https://leetcode.com/problems/merge-intervals/description/) 157 | 3. [Non-overlapping Intervals](https://leetcode.com/problems/non-overlapping-intervals/description/) 158 | 4. [Meeting Rooms](https://neetcode.io/problems/meeting-schedule) 159 | 5. [Meeting Rooms II](https://neetcode.io/problems/meeting-schedule-ii) 160 | 6. [Minimum Interval to Include Each Query](https://leetcode.com/problems/minimum-interval-to-include-each-query/) 161 | -------------------------------------------------------------------------------- /Week 4 - Hashmap/README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Mathemetics Basics: 3 | 4 | ### modulo 5 | 6 | modulo operator (%) returns the remainder of a division operation. For example, the expression 26 % 5 would return 1, because 26 divided by 5 is 5 with a remainder of 1. 7 | 8 | So in your example, 5 modulo 26 would also return 5, because 5 cannot be divided by 26 evenly, and the remainder is 5. Therefore, the expression 5 % 26 would evaluate to 5. 9 | 10 | 11 | ## Computer Architecture and Memory 12 | 13 | ### Padding 14 | 15 | Padding, also known as alignment, is the insertion of extra bytes of memory between data elements in a data structure in order to satisfy the alignment requirements of the CPU architecture. CPU architectures have different alignment requirements, which specify how data must be stored in memory so that it can be accessed efficiently by the CPU. 16 | 17 | For example, on a 32-bit architecture, 32-bit integers must be aligned on a 4-byte boundary, while on a 64-bit architecture, 64-bit integers must be aligned on an 8-byte boundary. If data is not properly aligned, it can cause performance issues or even result in a crash. 18 | 19 | Consider the following struct in C++: 20 | 21 | 22 | struct Example { 23 | char c; 24 | int i; 25 | double d; 26 | }; 27 | 28 | Assuming a 64-bit architecture where int is 4 bytes and double is 8 bytes, the size of this struct would be 24 bytes (1 byte for char + 3 bytes of padding, 4 bytes for int, and 8 bytes for double). This is because the int member must be aligned on a 4-byte boundary, so there are 3 bytes of padding added after the char member to achieve this alignment. 29 | 30 | Padding can also occur within arrays and structures of arrays. For example, if we have an array of 32-bit integers, and we want to access the second element of the array, we need to start at an address that is a multiple of 4 bytes. If the first element is not properly aligned, the CPU may have to read two memory accesses to retrieve the data, which can cause a performance penalty. 31 | 32 | Padding is usually inserted automatically by the compiler or runtime system, so it is typically not something that developers need to worry about in most high-level programming languages. However, it is important to be aware of padding and alignment requirements when working with low-level programming languages or when optimizing performance-critical code. 33 | 34 | ### Finding memory address 35 | 36 | Python: 37 | 38 | x = 42 39 | print(id(x)) # prints something like 140597269098400 40 | 41 | C#; 42 | 43 | int x = 42; 44 | IntPtr address = Marshal.AllocHGlobal(Marshal.SizeOf(x)); 45 | 46 | Marshal.StructureToPtr(x, address, false); 47 | Console.WriteLine(address); 48 | 49 | 50 | c++ 51 | 52 | int x = 42; 53 | int* address = &x; 54 | cout << address << endl; 55 | 56 | Javascript: 57 | let x = { foo: 42 }; 58 | console.log(Object.prototype.toString.call(x)); 59 | 60 | ## Data structures internals 61 | 62 | ### Hash functions 63 | 64 | The djb2 function is a simple hash function that was created by Dan Bernstein. It takes a string as input and produces a hash value as output. The hash value is a 32-bit unsigned integer that is used to identify the string. 65 | 66 | Here's the implementation of the djb2 function in Python: 67 | 68 | def djb2(string): 69 | hash_value = 5381 70 | for char in string: 71 | hash_value = ((hash_value << 5) + hash_value) + ord(char) 72 | return hash_value & 0xFFFFFFFF 73 | 74 | 75 | Let's break down how this function works: 76 | 77 | The function takes a string as input. 78 | 79 | It initializes a hash value to 5381. 80 | 81 | It loops through each character in the string and updates the hash value based on the ASCII value of the character. Specifically, it performs the following operation: 82 | 83 | hash_value = ((hash_value << 5) + hash_value) + ord(char) 84 | 85 | This operation left-shifts the hash value by 5 bits (multiplies by 32), adds the original hash value to it, and adds the ASCII value of the current character to it. 86 | 87 | Finally, the function returns the hash value modulo 2^32, which ensures that the hash value is a 32-bit unsigned integer. 88 | 89 | Here's an example of how to use the djb2 function: 90 | 91 | >>> string = "hello, world!" 92 | >>> hash_value = djb2(string) 93 | >>> print(hash_value) 94 | 1540932062 95 | 96 | C++: 97 | 98 | #include 99 | #include 100 | 101 | unsigned long djb2(std::string str) { 102 | unsigned long hash = 5381; 103 | int c; 104 | 105 | for (char& c : str) { 106 | hash = ((hash << 5) + hash) + c; 107 | } 108 | 109 | return hash; 110 | } 111 | 112 | int main() { 113 | std::string string = "hello, world!"; 114 | unsigned long hash_value = djb2(string); 115 | std::cout << hash_value << std::endl; 116 | return 0; 117 | } 118 | 119 | 120 | JS: 121 | 122 | function djb2(str) { 123 | let hash = 5381; 124 | 125 | for (let i = 0; i < str.length; i++) { 126 | hash = ((hash << 5) + hash) + str.charCodeAt(i); 127 | } 128 | 129 | return hash; 130 | } 131 | 132 | let string = "hello, world!"; 133 | let hash_value = djb2(string); 134 | console.log(hash_value); 135 | 136 | C#: 137 | 138 | using System; 139 | 140 | class Program 141 | { 142 | static uint djb2(string str) 143 | { 144 | uint hash = 5381; 145 | 146 | foreach (char c in str) 147 | { 148 | hash = ((hash << 5) + hash) + c; 149 | } 150 | 151 | return hash; 152 | } 153 | 154 | static void Main(string[] args) 155 | { 156 | string str = "hello, world!"; 157 | uint hash_value = djb2(str); 158 | Console.WriteLine(hash_value); 159 | } 160 | } 161 | 162 | 163 | ### Hashing Collision Solutions 164 | 165 | 1. Open addressing: In open addressing, when a collision occurs, the algorithm searches for the next available slot in the hash table and places the item there. The slots are searched in a fixed sequence, which can be either linear or quadratic. This technique is called "open addressing" because it does not require the use of a separate data structure to store collided items. However, as the table fills up, the number of collisions can increase significantly, which can negatively impact performance. 166 | 167 | 1.1 Linear probing: In linear probing, when a collision occurs, the algorithm searches for the next available slot in the hash table by probing the slots one by one until it finds an empty slot. The slots are probed in a linear sequence, which means that the algorithm checks the next slot after the current slot until it finds an empty slot. This technique is easy to implement and can have good cache performance, but it can suffer from clustering, where items tend to cluster together in certain parts of the table. 168 | 169 | 170 | 1.2 Double hashing: In double hashing, when a collision occurs, the algorithm uses a secondary hash function to calculate an offset value that is added to the original hash index to find the next available slot. The offset value is calculated using a different hash function than the primary hash function, which helps to reduce clustering and improve performance. However, finding a good secondary hash function can be difficult, and the technique can still suffer from clustering if the hash functions are poorly chosen. 171 | 172 | 2. Chaining 173 | 174 | Chaining is another technique for resolving collisions in hash tables. In chaining, instead of storing items directly in the hash table, we use a linked list to store all the items that hash to the same index. When a collision occurs, the algorithm simply adds the new item to the end of the linked list at the appropriate index. 175 | 176 | The advantage of chaining is that it can handle a large number of collisions without degrading performance. The linked list provides a dynamic structure that can grow as needed to accommodate more items, without requiring any additional memory allocation. Additionally, because each slot in the table only needs to store a reference to the head of the linked list, the memory requirements for the hash table can be smaller than other techniques that require a slot for each item. 177 | 178 | However, chaining can suffer from poor cache performance, because the items that hash to the same index may not be contiguous in memory. This can lead to a high number of cache misses and degrade performance. 179 | -------------------------------------------------------------------------------- /Week 4 - Hashmap/hashmap: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // Define the hash map class 7 | class HashMap { 8 | private: 9 | // Each bucket contains a list of key-value pairs 10 | std::vector>> buckets; 11 | int numBuckets; 12 | int size; 13 | 14 | int hashFunction(int key) { 15 | return key % numBuckets; 16 | } 17 | 18 | public: 19 | HashMap(int numBuckets) : numBuckets(numBuckets), size(0) { 20 | buckets.resize(numBuckets); 21 | } 22 | 23 | void put(int key, int value) { 24 | int bucketIndex = hashFunction(key); 25 | auto& bucket = buckets[bucketIndex]; 26 | 27 | for (auto& pair : bucket) { 28 | if (pair.first == key) { 29 | pair.second = value; 30 | return; 31 | } 32 | } 33 | 34 | bucket.emplace_back(key, value); 35 | size++; 36 | } 37 | 38 | bool get(int key, int& value) { 39 | int bucketIndex = hashFunction(key); 40 | auto& bucket = buckets[bucketIndex]; 41 | 42 | for (const auto& pair : bucket) { 43 | if (pair.first == key) { 44 | value = pair.second; 45 | return true; 46 | } 47 | } 48 | 49 | return false; 50 | } 51 | 52 | bool remove(int key) { 53 | int bucketIndex = hashFunction(key); 54 | auto& bucket = buckets[bucketIndex]; 55 | 56 | for (auto it = bucket.begin(); it != bucket.end(); ++it) { 57 | if (it->first == key) { 58 | bucket.erase(it); 59 | size--; 60 | return true; 61 | } 62 | } 63 | 64 | return false; 65 | } 66 | 67 | int getSize() const { 68 | return size; 69 | } 70 | }; 71 | 72 | // Driver code to test the HashMap 73 | int main() { 74 | HashMap hashMap(10); 75 | 76 | // Insert key-value pairs 77 | hashMap.put(1, 100); 78 | hashMap.put(2, 200); 79 | hashMap.put(3, 300); 80 | hashMap.put(4, 400); 81 | 82 | // Retrieve values 83 | int value; 84 | if (hashMap.get(1, value)) { 85 | std::cout << "Key 1 has value " << value << std::endl; 86 | } else { 87 | std::cout << "Key 1 not found" << std::endl; 88 | } 89 | 90 | if (hashMap.get(2, value)) { 91 | std::cout << "Key 2 has value " << value << std::endl; 92 | } else { 93 | std::cout << "Key 2 not found" << std::endl; 94 | } 95 | 96 | if (hashMap.get(3, value)) { 97 | std::cout << "Key 3 has value " << value << std::endl; 98 | } else { 99 | std::cout << "Key 3 not found" << std::endl; 100 | } 101 | 102 | if (hashMap.get(5, value)) { 103 | std::cout << "Key 5 has value " << value << std::endl; 104 | } else { 105 | std::cout << "Key 5 not found" << std::endl; 106 | } 107 | 108 | // Remove a key-value pair 109 | if (hashMap.remove(2)) { 110 | std::cout << "Key 2 removed" << std::endl; 111 | } else { 112 | std::cout << "Key 2 not found" << std::endl; 113 | } 114 | 115 | if (hashMap.get(2, value)) { 116 | std::cout << "Key 2 has value " << value << std::endl; 117 | } else { 118 | std::cout << "Key 2 not found" << std::endl; 119 | } 120 | 121 | // Print the size of the hash map 122 | std::cout << "Size of the hash map: " << hashMap.getSize() << std::endl; 123 | 124 | return 0; 125 | } 126 | -------------------------------------------------------------------------------- /Week 4 - Hashmap/hashmapwithdjb2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | // Define the hash map class 8 | class HashMap { 9 | private: 10 | // Each bucket contains a list of key-value pairs 11 | std::vector>> buckets; 12 | int numBuckets; 13 | int size; 14 | 15 | // DJB2 hash function 16 | int hashFunction(int key) { 17 | unsigned long hash = 5381; 18 | hash = ((hash << 5) + hash) + key; // hash * 33 + key 19 | return hash % numBuckets; 20 | } 21 | 22 | public: 23 | HashMap(int numBuckets) : numBuckets(numBuckets), size(0) { 24 | buckets.resize(numBuckets); 25 | } 26 | 27 | void put(int key, int value) { 28 | int bucketIndex = hashFunction(key); 29 | auto& bucket = buckets[bucketIndex]; 30 | 31 | for (auto& pair : bucket) { 32 | if (pair.first == key) { 33 | pair.second = value; 34 | return; 35 | } 36 | } 37 | 38 | bucket.emplace_back(key, value); 39 | size++; 40 | } 41 | 42 | bool get(int key, int& value) { 43 | int bucketIndex = hashFunction(key); 44 | auto& bucket = buckets[bucketIndex]; 45 | 46 | for (const auto& pair : bucket) { 47 | if (pair.first == key) { 48 | value = pair.second; 49 | return true; 50 | } 51 | } 52 | 53 | return false; 54 | } 55 | 56 | bool remove(int key) { 57 | int bucketIndex = hashFunction(key); 58 | auto& bucket = buckets[bucketIndex]; 59 | 60 | for (auto it = bucket.begin(); it != bucket.end(); ++it) { 61 | if (it->first == key) { 62 | bucket.erase(it); 63 | size--; 64 | return true; 65 | } 66 | } 67 | 68 | return false; 69 | } 70 | 71 | int getSize() const { 72 | return size; 73 | } 74 | }; 75 | 76 | // Driver code to test the HashMap 77 | int main() { 78 | HashMap hashMap(10); 79 | 80 | // Insert key-value pairs 81 | hashMap.put(1, 100); 82 | hashMap.put(2, 200); 83 | hashMap.put(3, 300); 84 | hashMap.put(4, 400); 85 | 86 | // Retrieve values 87 | int value; 88 | if (hashMap.get(1, value)) { 89 | std::cout << "Key 1 has value " << value << std::endl; 90 | } 91 | else { 92 | std::cout << "Key 1 not found" << std::endl; 93 | } 94 | 95 | if (hashMap.get(2, value)) { 96 | std::cout << "Key 2 has value " << value << std::endl; 97 | } 98 | else { 99 | std::cout << "Key 2 not found" << std::endl; 100 | } 101 | 102 | if (hashMap.get(3, value)) { 103 | std::cout << "Key 3 has value " << value << std::endl; 104 | } 105 | else { 106 | std::cout << "Key 3 not found" << std::endl; 107 | } 108 | 109 | if (hashMap.get(5, value)) { 110 | std::cout << "Key 5 has value " << value << std::endl; 111 | } 112 | else { 113 | std::cout << "Key 5 not found" << std::endl; 114 | } 115 | 116 | // Remove a key-value pair 117 | if (hashMap.remove(2)) { 118 | std::cout << "Key 2 removed" << std::endl; 119 | } 120 | else { 121 | std::cout << "Key 2 not found" << std::endl; 122 | } 123 | 124 | if (hashMap.get(2, value)) { 125 | std::cout << "Key 2 has value " << value << std::endl; 126 | } 127 | else { 128 | std::cout << "Key 2 not found" << std::endl; 129 | } 130 | 131 | // Print the size of the hash map 132 | std::cout << "Size of the hash map: " << hashMap.getSize() << std::endl; 133 | 134 | return 0; 135 | } 136 | -------------------------------------------------------------------------------- /Week 4 - Hashmap/hello.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | vector msg {"Hello", "C++", "World", "from", "VS Code", "and the C++ extension!"}; 10 | 11 | for (const string& word : msg) 12 | { 13 | cout << word << " "; 14 | } 15 | cout << endl; 16 | } -------------------------------------------------------------------------------- /Week 4 - Hashmap/modulo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeez506/Data-Structures-Course/cc560e89afb62f378f83f8db3a2775a3eca4fdc1/Week 4 - Hashmap/modulo -------------------------------------------------------------------------------- /Week 4 - Hashmap/test.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeez506/Data-Structures-Course/cc560e89afb62f378f83f8db3a2775a3eca4fdc1/Week 4 - Hashmap/test.cpp -------------------------------------------------------------------------------- /Week 6 Dynamic Arrays or Lists/BasicDynamicArray.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | class AdvancedDynamicArray { 7 | private: 8 | std::unique_ptr array; 9 | int count; // 2 10 | int capacity; // 4 11 | 12 | static constexpr double GrowthFactor = 2; // 2 // 1.6 13 | 14 | 15 | static constexpr int InitialCapacity = 4; 16 | 17 | 18 | static constexpr int LinearGrowthThreshold = 20000; 19 | static constexpr int LinearGrowthAmount = 1000; 20 | 21 | //5 22 | void ensureCapacity(int minCapacity) { 23 | 24 | // 5 > 4 25 | if (minCapacity > capacity) { 26 | int newCapacity; 27 | 28 | if (capacity < LinearGrowthThreshold) { 29 | // Exponential growth 30 | // 8 4 * 2 31 | newCapacity = static_cast(capacity * GrowthFactor); 32 | } 33 | else { 34 | // Linear growth 35 | newCapacity = capacity + LinearGrowthAmount; 36 | } 37 | std::unique_ptr newArray = std::make_unique(newCapacity); 38 | for (int i = 0; i < count; ++i) { 39 | newArray[i] = array[i]; 40 | } 41 | array = std::move(newArray); 42 | capacity = newCapacity; 43 | } 44 | } 45 | 46 | void shrinkCapacity() { 47 | if (count < capacity / 4 && capacity > InitialCapacity) { 48 | int newCapacity = capacity / 2; 49 | if (newCapacity < InitialCapacity) { 50 | newCapacity = InitialCapacity; 51 | } 52 | std::unique_ptr newArray = std::make_unique(newCapacity); 53 | for (int i = 0; i < count; ++i) { 54 | newArray[i] = array[i]; 55 | } 56 | array = std::move(newArray); 57 | capacity = newCapacity; 58 | } 59 | } 60 | 61 | public: 62 | AdvancedDynamicArray(int initCapacity = InitialCapacity) 63 | : array(std::make_unique(initCapacity)), count(0), capacity(initCapacity) {} 64 | 65 | AdvancedDynamicArray(int initCapacity = InitialCapacity, int threshold = LinearGrowthThreshold, int growbynumber = LinearGrowthAmount) 66 | : array(std::make_unique(initCapacity)), count(0), capacity(initCapacity) { 67 | 68 | } 69 | 70 | int size() const { 71 | return count; 72 | } 73 | 74 | int getCapacity() const { 75 | return capacity; 76 | } 77 | 78 | int& operator[](int index) { 79 | if (index < 0 || index >= count) { 80 | throw std::out_of_range("Index out of range"); 81 | } 82 | return array[index]; 83 | } 84 | 85 | void add(int item) { 86 | ensureCapacity(count + 1); 87 | 88 | // count > 0 > index = 0 89 | //0 > 1 90 | 91 | array[count++] = item; 92 | } 93 | //5 94 | void insert(int index, int item) { 95 | if (index < 0 || index > count) { 96 | throw std::out_of_range("Index out of range"); 97 | } 98 | ensureCapacity(count + 1); 99 | for (int i = count; i > index; --i) { 100 | array[i] = array[i - 1]; 101 | } 102 | array[index] = item; 103 | ++count; 104 | } 105 | 106 | void removeAt(int index) { 107 | if (index < 0 || index >= count) { 108 | throw std::out_of_range("Index out of range"); 109 | } 110 | for (int i = index; i < count - 1; ++i) { 111 | array[i] = array[i + 1]; 112 | } 113 | array[--count] = 0; // Clear the last element 114 | shrinkCapacity(); 115 | } 116 | 117 | void clear() { 118 | array = std::make_unique(InitialCapacity); 119 | count = 0; 120 | capacity = InitialCapacity; 121 | } 122 | }; 123 | 124 | int main() { 125 | try { 126 | AdvancedDynamicArray arr; 127 | 128 | arr.add(10); 129 | arr.add(20); 130 | arr.add(30); 131 | arr.insert(1, 15); 132 | arr.removeAt(2); 133 | 134 | for (int i = 0; i < arr.size(); ++i) { 135 | std::cout << arr[i] << " "; 136 | } 137 | std::cout << std::endl; 138 | 139 | std::cout << "Current size: " << arr.size() << std::endl; 140 | std::cout << "Current capacity: " << arr.getCapacity() << std::endl; 141 | } 142 | catch (const std::exception& e) { 143 | std::cerr << e.what() << std::endl; 144 | } 145 | return 0; 146 | } 147 | -------------------------------------------------------------------------------- /Week 7 - Queue/concept-of-circular-queue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class Queue 5 | { 6 | private: 7 | int arr[5]; 8 | int front = -1, rear = -1; 9 | int capacity = sizeof(arr) / sizeof(arr[0]); 10 | 11 | public: 12 | /** isFull() 13 | * @return true if the queue is full 14 | */ 15 | bool isFull() 16 | { 17 | if ((rear + 1) % capacity == front) 18 | { 19 | return true; 20 | } 21 | else 22 | { 23 | return false; 24 | } 25 | } 26 | 27 | /** isEmpty 28 | * @return true if the queue is empty, 29 | */ 30 | bool isEmpty() 31 | { 32 | if (front == -1 && rear == -1) 33 | { 34 | return true; 35 | } 36 | else 37 | { 38 | return false; 39 | } 40 | } 41 | 42 | /** Enqueue 43 | * @return data {to input data into the queue at rear position} 44 | */ 45 | void Enqueue(int data) 46 | { 47 | if (isFull()) 48 | { 49 | cout << "Queue is full!" << endl; 50 | return; 51 | } 52 | else if (isEmpty()) 53 | { 54 | front = 0; 55 | rear = 0; 56 | } 57 | else 58 | { 59 | rear = (rear + 1) % capacity; 60 | } 61 | arr[rear] = data; 62 | cout << "Enqueued " << arr[rear] << endl; 63 | } 64 | 65 | /** Dequeue 66 | * @return it returns the data which is being removed from the queue 67 | */ 68 | int dequeue() 69 | { 70 | if (isEmpty()) 71 | { 72 | cout << "Queue is empty!" << endl; 73 | return -1; 74 | } 75 | int temp = arr[front]; 76 | if (front == rear) 77 | { 78 | front = -1; 79 | rear = -1; 80 | } 81 | else 82 | { 83 | front = (front + 1) % capacity; 84 | } 85 | 86 | cout << "Dequeueing..." << temp << endl; 87 | return temp; 88 | } 89 | 90 | /** peek 91 | * @return the value at the front of the queue 92 | */ 93 | int peek() 94 | { 95 | if (isEmpty()) 96 | { 97 | cout << "Queue is empty!" << endl; 98 | return -1; 99 | } 100 | return arr[front]; 101 | } 102 | }; 103 | 104 | int main() 105 | { 106 | Queue q; 107 | q.Enqueue(2); 108 | q.Enqueue(3); 109 | q.Enqueue(4); 110 | q.Enqueue(6); 111 | q.Enqueue(9); 112 | q.Enqueue(10); 113 | q.Enqueue(15); 114 | cout << q.peek() << endl; 115 | q.dequeue(); 116 | cout << q.peek() << endl; 117 | return 0; 118 | } -------------------------------------------------------------------------------- /Week 7 - Queue/implementation-of-queue-using-arrays.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class Queue 5 | { 6 | private: 7 | int arr[5]; 8 | int front = -1, rear = -1; 9 | int capacity = sizeof(arr) / sizeof(arr[0]); 10 | 11 | public: 12 | /** isFull() 13 | * @return true if the queue is full 14 | */ 15 | bool isFull() 16 | { 17 | if (rear == capacity - 1) 18 | { 19 | return true; 20 | } 21 | else 22 | { 23 | return false; 24 | } 25 | } 26 | 27 | /** isEmpty 28 | * @return true if the queue is empty, 29 | */ 30 | bool isEmpty() 31 | { 32 | if (front == -1 && rear == -1) 33 | { 34 | return true; 35 | } 36 | else 37 | { 38 | return false; 39 | } 40 | } 41 | 42 | /** Enqueue 43 | * @param data to input data into the queue at rear position 44 | */ 45 | void Enqueue(int data) 46 | { 47 | if (isFull()) 48 | { 49 | cout << "Queue is full!" << endl; 50 | return; 51 | } 52 | else if (isEmpty()) 53 | { 54 | front = 0; 55 | rear = 0; 56 | } 57 | else 58 | { 59 | rear++; 60 | } 61 | arr[rear] = data; 62 | cout << "Enqueued " << arr[rear] << endl; 63 | } 64 | 65 | /** Dequeue 66 | * @return it returns the data which is being removed from the queue 67 | */ 68 | int dequeue() 69 | { 70 | if (isEmpty()) 71 | { 72 | cout << "Queue is empty!" << endl; 73 | return -1; 74 | } 75 | int temp = arr[front]; 76 | if (front == rear) 77 | { 78 | front = -1; 79 | rear = -1; 80 | } 81 | else 82 | { 83 | front++; 84 | } 85 | 86 | cout << "Dequeueing..." << temp << endl; 87 | return temp; 88 | } 89 | 90 | /** peek 91 | * @return the value at the front of the queue 92 | */ 93 | int peek() 94 | { 95 | if (isEmpty()) 96 | { 97 | cout << "Queue is empty!" << endl; 98 | return -1; 99 | } 100 | return arr[front]; 101 | } 102 | }; 103 | 104 | int main() 105 | { 106 | Queue q; 107 | q.Enqueue(2); 108 | q.Enqueue(3); 109 | q.Enqueue(4); 110 | q.Enqueue(6); 111 | q.Enqueue(9); 112 | q.Enqueue(10); 113 | q.Enqueue(15); 114 | cout << q.peek() << endl; 115 | q.dequeue(); 116 | cout << q.peek() << endl; 117 | return 0; 118 | } -------------------------------------------------------------------------------- /Week 7 - Queue/implementation-of-queue-using-linked-list.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class Node 5 | { 6 | public: 7 | int data; 8 | Node *next; 9 | Node(int d) : data(d), next(nullptr) {} 10 | }; 11 | 12 | class Queue 13 | { 14 | Node *front; 15 | Node *rear; 16 | 17 | public: 18 | Queue() 19 | { 20 | front = rear = nullptr; 21 | } 22 | 23 | bool isEmpty() { 24 | return front == nullptr; 25 | } 26 | 27 | void enqueue(int item) 28 | { 29 | Node *newNode = new Node(item); 30 | if (rear == nullptr) 31 | { 32 | front = rear = newNode; 33 | return; 34 | } 35 | rear->next = newNode; 36 | rear = newNode; 37 | } 38 | 39 | void dequeue() 40 | { 41 | if (isEmpty()) 42 | { 43 | cout << "Queue is empty" << endl; 44 | return; 45 | } 46 | Node *temp = front; 47 | cout << temp->data << " dequeued from queue" << endl; 48 | front = front->next; 49 | if (front == nullptr) 50 | rear = nullptr; 51 | delete temp; 52 | } 53 | 54 | Node *peek() { 55 | if(isEmpty()) { 56 | cout << "Queue is empty" << endl; 57 | return nullptr; 58 | } 59 | 60 | return front; 61 | } 62 | }; 63 | 64 | int main() 65 | { 66 | Queue q; 67 | q.enqueue(10); 68 | q.enqueue(20); 69 | q.enqueue(30); 70 | q.dequeue(); 71 | q.dequeue(); 72 | q.dequeue(); 73 | 74 | // cout << q.peek()->data << endl; 75 | 76 | q.enqueue(40); 77 | q.enqueue(50); 78 | cout << q.peek()->data << endl; 79 | return 0; 80 | } --------------------------------------------------------------------------------