Skip to content

Fixing typos #136

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ Comparators are an inherent part of _class_. Suppose you design a new class, and
<details>
<summary>Structures Vs Class</summary>

# Strucutures vs Class
When you need to create your own data types, generally _structures_ suffice. However, there is no harm in using _classes_ to achieve the same task. Since we've only covered _classes_, we will base the entire discussion on it. However, keep in mind that everything can be equally applied to _structures_ as well. The bottomline is, if you want to create a new data type (containing heterogenous fields), you should use _class_ and if you are planning to deal with pointers a lot, use _structures_ as you are already familar with it.
# Structures vs Class
When you need to create your own data types, generally _structures_ suffice. However, there is no harm in using _classes_ to achieve the same task. Since we've only covered _classes_, we will base the entire discussion on it. However, keep in mind that everything can be equally applied to _structures_ as well. The bottom line is, if you want to create a new data type (containing heterogeneous fields), you should use _class_ and if you are planning to deal with pointers a lot, use _structures_ as you are already familiar with it.

---

Expand All @@ -25,7 +25,7 @@ When you need to create your own data types, generally _structures_ suffice. How
# The Default Comparator
Numbers are represented as bits in the computer. We've been using numbers a lot (along with their comparisons, such as `>`, `<`, `==`). To define their relative ordering, we have the concept of a comparator. **A comparator is a function which takes 2 objects as an argument and returns True if the first argument is smaller than the second, else it returns False**. (Notice that the order of arguments matter a lot).

So now, we need to tell the computer that `2 < 3`. How do we do this? Lucky for us, there is a default comparator in C++ which does the job. The **default** comparator is `lesser<int>`. Let us talk about what this is. First of all, `lesser<int>` is a function with a boolean return value. So far, we have only talked about the notation `<...>` in the context of containers. What does this symbol mean in terms of function? Well, it means the same. In containers, this notation was used to make the containers universal and accomodate any data type. You just needed to put the name of the data type inside `<...>`. It is the same thing as functions, it is written as a universal function which can accept any data type and perform the same type of operations on that data type. Makes sense, right? Because if you are creating a function that returns the absolute value, you wouldn't create a bunch of functions with different names. Rather you would want to create a function which can take `int`, `long int`, `long long int`, `float` , etc and just return the absolute value of these arguments. Hence, the data type of the input needs to be made universal. This is called **Templates** in C++.
So now, we need to tell the computer that `2 < 3`. How do we do this? Lucky for us, there is a default comparator in C++ which does the job. The **default** comparator is `lesser<int>`. Let us talk about what this is. First of all, `lesser<int>` is a function with a boolean return value. So far, we have only talked about the notation `<...>` in the context of containers. What does this symbol mean in terms of function? Well, it means the same. In containers, this notation was used to make the containers universal and accommodate any data type. You just needed to put the name of the data type inside `<...>`. It is the same thing as functions, it is written as a universal function which can accept any data type and perform the same type of operations on that data type. Makes sense, right? Because if you are creating a function that returns the absolute value, you wouldn't create a bunch of functions with different names. Rather you would want to create a function which can take `int`, `long int`, `long long int`, `float` , etc and just return the absolute value of these arguments. Hence, the data type of the input needs to be made universal. This is called **Templates** in C++.

**Caution** : Comparators are not exactly functions, as it is wrapped over a class. But, to keep the discussion less technical, we'll just assume that they are normal functions.

Expand All @@ -37,7 +37,7 @@ Similarly, there is a function called `greater<int>`. As you might have guessed
By default, C++ uses `lesser<int>` to compare 2 numbers. Hence, to know which of the numbers `7,5` is smaller, it would call `lesser(7,5)` and get the answer `false` which means `5` is smaller. Similarly, if it had accidentally called `lesser(5,7)`, it would get the answer `true` and it would still conclude that `5` is smaller.

**Tricking the Computer**
C++ would **always** expect the comparator to behave as `lesser<int>`. Hence, no matter what comparator you desgin, if you return `true` from that comparator, C++ would automatically think that the first argument is `smaller`. (As it would expect it to behave as `lesser<int>`). Using this idea, how do we trick the computer to sort the numbers in descending order? Suppose, there was a way to change `lesser<int>` to any other function that you want. Can you do it now? Yes, we can just replace it with `greater<int>`. Now, when C++ calls the comparator with the arguments `(7,5)` , it would get the answer as `true`. Hence it would assume `7 < 5` (as we discussed earlier). Similarly, if it accidentally calls the comparator on `(5,7)`, it would get `false`. It would still conclude that `7 < 5`. I hope you see the underlying trick here. We have fooled the computer into believing that numbers with large magnitude should be seen as smaller numbers. Hence, in the sorted order, we'll have the largest number first (as the computer thinks it to be the smallest number). In this manner, we can sort it in descending order.
C++ would **always** expect the comparator to behave as `lesser<int>`. Hence, no matter what comparator you design, if you return `true` from that comparator, C++ would automatically think that the first argument is `smaller`. (As it would expect it to behave as `lesser<int>`). Using this idea, how do we trick the computer to sort the numbers in descending order? Suppose, there was a way to change `lesser<int>` to any other function that you want. Can you do it now? Yes, we can just replace it with `greater<int>`. Now, when C++ calls the comparator with the arguments `(7,5)` , it would get the answer as `true`. Hence it would assume `7 < 5` (as we discussed earlier). Similarly, if it accidentally calls the comparator on `(5,7)`, it would get `false`. It would still conclude that `7 < 5`. I hope you see the underlying trick here. We have fooled the computer into believing that numbers with large magnitude should be seen as smaller numbers. Hence, in the sorted order, we'll have the largest number first (as the computer thinks it to be the smallest number). In this manner, we can sort it in descending order.

Now, recall the **Merge Sort** algorithm. While manually merging the 2 sorted array, there was just one instance where we used `<`. So, if we want to sort custom objects, we need to clarify what is meant by one object being `<` than the second. There are 2 options, either include this as a blueprint in the source code of your object or pass an overloaded optional third parameter to the **sort** function. We'll discuss what the first option means. But for the second option, we just need to create a function that returns `true` when the first arguments is `greater` than the second (to imitate the reverse of `lesser<int>`). If we pass this optional parameter, all usage of `lesser` would be replaced by this function. Here's an example with numbers.
[Playground](https://ide.geeksforgeeks.org/lxIMuLVyov)
Expand Down Expand Up @@ -100,7 +100,7 @@ using namespace std;
/* Note that if you aren't dealing with pointers,
it is a good idea to do everything with class */

/* Definiton for struct */
/* Definition for struct */
struct S_Node
{
int data;
Expand Down Expand Up @@ -389,13 +389,13 @@ int main()
# Making our lives simpler
To create custom containers, there is a lot of work involved. You need to create a new class, put a new function, remember the difference in the syntax between `priority_queue` and `set`, etc. Plus, we still don't know how to implement custom maps.

Let's think about this a bit. When you create a container of integers, do you do all this? No, right! This is beacause all the comparators are already hidden inside the integers. Hence, we don't have to worry about them. Can we do the same for objects? Can we inject something in the blueprint of the object so that compiler would treat it as integers. If so, than our lives would become much simpler. Turns out, there is such a way and I'll let you in on this secret in a few moments.
Let's think about this a bit. When you create a container of integers, do you do all this? No, right! This is because all the comparators are already hidden inside the integers. Hence, we don't have to worry about them. Can we do the same for objects? Can we inject something in the blueprint of the object so that compiler would treat it as integers. If so, than our lives would become much simpler. Turns out, there is such a way and I'll let you in on this secret in a few moments.

In Java, there is one superclass, and every class inherits from it. What's more, you can also over ride the inherited functions. In C++, when defining any class, there is a hidden boolean function called `operator<` which takes a single parameter and determines whether the current object of the class is smaller than the incoming object. This is the default comparator. If you write this function precisely, then you won't have to use comparators with this class, not even in sorting. To sort, you can just do `sort(customVec.begin(), customVec.end())`. To create a set, jsut do, `set<customClass>`. To create heaps, just do `priority_queue<cusomClasss>`. To create maps, just do `map<customClass, ValueDataType>>`. As you can see, we can now use it like any other data type because we have embedded the comparator in the blue print. So, all that remains is to modify the blue print.
In Java, there is one superclass, and every class inherits from it. What's more, you can also over ride the inherited functions. In C++, when defining any class, there is a hidden boolean function called `operator<` which takes a single parameter and determines whether the current object of the class is smaller than the incoming object. This is the default comparator. If you write this function precisely, then you won't have to use comparators with this class, not even in sorting. To sort, you can just do `sort(customVec.begin(), customVec.end())`. To create a set, just do, `set<customClass>`. To create heaps, just do `priority_queue<customClass>`. To create maps, just do `map<customClass, ValueDataType>>`. As you can see, we can now use it like any other data type because we have embedded the comparator in the blue print. So, all that remains is to modify the blue print.

To do so, just create a public function with this template
```
boool operator < (const &IncomingObject) const
bool operator < (const &IncomingObject) const
{
// Return true if you see current object is smaller than incoming one
// Don't forget to return false explicitly if it is bigger or equal
Expand All @@ -404,7 +404,7 @@ boool operator < (const &IncomingObject) const

**Notice the extra const at the end. Weird syntax, but it is what it is**

Although it looks like it takes 1 argument, it actually takes 2 under the hood. It's just like `lesser<int>`. So now, we want to know what is the first argument and what is the second argument. (Remember, the ordering matters a lot). Well, it turns out, that **The first argument is the object of the class that you are currently standing at and the second is the incoming object**. Hence, the comparator expects that if the object that you are standing at is smaller than the incoming object, then it is your duty to return true. Now, how to access the instance variables of the object that you are standing at? It's simple. Either use `this->VariableName` or just use `instanceVariableName` . This is because there is no name collisons and we don't really require `this`. How to access the variables of incoming object? Use the dot notation.
Although it looks like it takes 1 argument, it actually takes 2 under the hood. It's just like `lesser<int>`. So now, we want to know what is the first argument and what is the second argument. (Remember, the ordering matters a lot). Well, it turns out, that **The first argument is the object of the class that you are currently standing at and the second is the incoming object**. Hence, the comparator expects that if the object that you are standing at is smaller than the incoming object, then it is your duty to return true. Now, how to access the instance variables of the object that you are standing at? It's simple. Either use `this->VariableName` or just use `instanceVariableName` . This is because there is no name collisions and we don't really require `this`. How to access the variables of incoming object? Use the dot notation.

After we are done, we don't have to worry about using any function / container which uses ordering. This is the template that I use (and prefer). It's not as difficult as it seems

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
**Intuition**
* Create a helper function `minSteps` that takes as input 2 vectors and a `candidate` and returns the minimum steps to convert every element in the `target` array to `candidate`. It returns -1 if the target vector cannot be converted in the desired fashion. This function is used to remove code redundancy.
* Create a frquency array and update the frequency of each element (as every element is in the range `[1,6]`.)
* Traverse the frequency array and capture the `candidates`, i.e, elements which occur atleast half the time [inclusive]. Note that this is not the same as majority element as majority element should occur strictly more than `n/2` times(and hence Moore's Algorithm won't work). However, there can be atmost 2 candidates.
* Create a frequency array and update the frequency of each element (as every element is in the range `[1,6]`.)
* Traverse the frequency array and capture the `candidates`, i.e, elements which occur at least half the time [inclusive]. Note that this is not the same as majority element as majority element should occur strictly more than `n/2` times(and hence Moore's Algorithm won't work). However, there can be at most 2 candidates.
* If there is no candidate, return -1
* For each of the candidate, try to adjust it in both the top and bottom half and take the best outcome of the two.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ int Solution :: minSteps(vector<int>& source, vector<int>& target, int candidate
/* Returns the min steps to equalize each element in any vector */
int Solution :: minDominoRotations(vector<int>& a, vector<int>& b)
{
// Get the size, Create the frequncy and candidate vector
// Get the size, Create the frequency and candidate vector
int n = a.size();
vector<int> freq(7,0);
vector<int> candidate;
Expand All @@ -35,7 +35,7 @@ int Solution :: minDominoRotations(vector<int>& a, vector<int>& b)
for(int i=0; i<n; i++)
freq[a[i]]++, freq[b[i]]++;

// Fill the candidate vectpr
// Fill the candidate vector
for(int i=1; i<=6; i++)
if(freq[i]>=n)
candidate.push_back(i);
Expand All @@ -46,7 +46,7 @@ int Solution :: minDominoRotations(vector<int>& a, vector<int>& b)
// Variable to store the min steps
int minCount = INT_MAX;

// Try all the candidate elements (atmost 2)
// Try all the candidate elements (at most 2)
for(int i=0; i<candidate.size(); i++)
{
// Try to fill the candidate in the top and bottom
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ any of the questions. I didn't even realize that the time complexity of the 4th
solutions received bad reviews too. I need to focus more on writing quality codes with optimal complexity along with a thorough explanation. This
would benefit me more than anyone else, as it would be a great help during my revision. I was going through the solution of the top 10 people
in the contest and I was literally amazed by the elegance of their solution. Now I realize why are they able to complete the contest within 10
to 15 minutes. **I have to see the codes of atleast top 10 people from the next contest**.
to 15 minutes. **I have to see the codes of at least top 10 people from the next contest**.
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ var numPairsDivisibleBy60 = function(time)
// The reference for modular arithmetic
const ref=60;

// Initilize the map
// Initialize the map
var count = [];
for(let i=0; i<ref; i++)
count.push(0);

// Populate the map in modular arithemtic
// Populate the map in modular arithmetic
for(let i=0; i<time.length; i++)
count[time[i]%ref]++;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ int Solution :: numPairsDivisibleBy60(vector<int>& a)
// The reference for modular arithmetic
int ref=60;

// Populate the map in modular arithemtic
// Populate the map in modular arithmetic
unordered_map<int,int> count;
for(auto ele : a)
count[ele%ref]++;
Expand Down
Loading