{"id":15047339,"url":"https://github.com/rajneesh069/dsa-cpp","last_synced_at":"2026-02-25T15:03:23.925Z","repository":{"id":251772066,"uuid":"838397274","full_name":"rajneesh069/DSA-CPP","owner":"rajneesh069","description":"This repo contains code for DSA in CPP.","archived":false,"fork":false,"pushed_at":"2024-10-24T09:50:37.000Z","size":476,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-24T20:31:15.726Z","etag":null,"topics":["competitive-programming","cpp11","dsa","dsa-practice","dsa-problems"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rajneesh069.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-05T14:58:16.000Z","updated_at":"2024-10-24T09:50:40.000Z","dependencies_parsed_at":"2024-09-29T00:40:38.371Z","dependency_job_id":"dd05590f-f30c-428f-8e89-b083c7695923","html_url":"https://github.com/rajneesh069/DSA-CPP","commit_stats":null,"previous_names":["rajneesh069/dsa-cpp"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rajneesh069%2FDSA-CPP","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rajneesh069%2FDSA-CPP/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rajneesh069%2FDSA-CPP/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rajneesh069%2FDSA-CPP/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rajneesh069","download_url":"https://codeload.github.com/rajneesh069/DSA-CPP/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243495495,"owners_count":20299923,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["competitive-programming","cpp11","dsa","dsa-practice","dsa-problems"],"created_at":"2024-09-24T20:56:46.946Z","updated_at":"2025-10-28T14:14:08.927Z","avatar_url":"https://github.com/rajneesh069.png","language":"C++","readme":"# C++ Standard Template Library(STL)\n\n## Strings\n\n- size(): returns size of the string\n- getline(cin, str): takes the whole line as input\n- To take very large data as input, use strings and then write proper algos to deal with them\n- Try not to add characters to string directly, instead use push_back() function to append characters to the string\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    string s1 = \"Hello\";\n    // string s2 = \"World\";\n    string s2 = \"Hello\";\n    cout \u003c\u003c s1 + \" \" + s2 \u003c\u003c endl;\n\n    if (s1 == s2) {\n        cout \u003c\u003c \"Equal\" \u003c\u003c endl;\n    }\n    else {\n        cout \u003c\u003c \"Not equal\" \u003c\u003c endl;\n    }\n    // to access elements we can use it by using the index\n    // each element is a character\n    s1[0] = 'c';\n    // we can re-assign individual characters of a string\n    cout \u003c\u003c s1.size() \u003c\u003c endl;\n\n    for (int i = 0; i \u003c s1.size(); i++) {\n        cout \u003c\u003c s1[i] \u003c\u003c \" \";\n    }\n    cout \u003c\u003c endl;\n    // to take the whole line as input\n    int t;\n    cin \u003e\u003e t;\n    cin.ignore(); // so that we can ignore extra space\n    while (t--)\n    {\n        string str;\n        getline(cin, str);\n        cout \u003c\u003c str \u003c\u003c endl;\n    }\n\n    // reverse a string\n    string ans;\n    cin \u003e\u003e ans;\n    for (int i = 0; i \u003c ans.size(); i++) {\n        ans.push_back(ans[i]); // don't add characters to string, not a good practice\n    }\n\n    return 0;\n}\n```\n\n## Vectors and Pairs in STL\n\n- Vectors are dynamic arrays with no fixed size.\n- v[i] isn't accessible until there's something inside the vector.\n- Pairs are containers used to store related data.\n- When a pair is swapped the whole pair is swapped.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvoid printVec(vector\u003cint\u003e\u0026 v) {  // passed by reference because otherwise it will pass a copy\n    // and that takes O(N) time complexity\n    for (int i = 0; i \u003c v.size(); i++) {\n        cout \u003c\u003c v[i] \u003c\u003c \" \";\n    }\n    cout \u003c\u003c endl;\n}\n\n\nint main() {\n    vector\u003cint\u003e v(10, -1); // size = 10, all values = -1\n    vector\u003cint\u003e v1 = v; // makes a copy of v into v1, takes O(N) time complexity\n    vector\u003cint\u003e\u0026 v2 = v; // makes a reference variable of v\n    printVec(v); //print the vector\n\n    pair\u003cint, int\u003e p;\n    // p = make_pair(2, 3);\n    p = { 2,3 }; // another way to initialize pair, more handy\n    int a = p.first; // gives the first value\n    int b = p.second; // gives the second value\n\n    // suppose we needed relation between elements of two arrays\n    int arr[3] = { 1,2,3 };\n    int brr[3] = { 4,5,6 };\n    pair\u003cint, int\u003e p1[3];\n    p1[0] = { arr[0],brr[0] };\n    p1[1] = { arr[1],brr[1] };\n    p1[2] = { arr[2],brr[2] };\n\n    swap(p1[0], p1[2]); // can swap easily obviously.\n\n    for (int i = 0; i \u003c 3; i++) {\n        cout \u003c\u003c p1[i].first \u003c\u003c \" \" \u003c\u003c p1[i].second \u003c\u003c endl;\n    }\n\n    return 0;\n}\n```\n\n## Nesting Vectors and Pairs\n\n- Pairs can be nested in the vectors to form vector of pair, where each element is a pair instead of 'int' or 'char' or 'bool'.\n- Vectors can be nested to form 2D dynamic arrays.\n- Remember, that in case of nested vectors each `v[i]` represents a vector, so to access a 2D or 3D vector using `v[i]` there needs to be some vector(s) inside it.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvoid printVec(vector\u003cpair\u003cint, int\u003e\u003e\u0026 v) {\n    cout \u003c\u003c \"size: \" \u003c\u003c v.size() \u003c\u003c endl;\n    for (int i = 0; i \u003c v.size(); i++) {\n        cout \u003c\u003c v[i].first \u003c\u003c \" \" \u003c\u003c v[i].second \u003c\u003c endl;\n    }\n}\n\nvoid printVec(vector\u003cint\u003e\u0026 v) {\n    cout \u003c\u003c \"size: \" \u003c\u003c v.size() \u003c\u003c endl;\n    for (int i = 0; i \u003c v.size(); i++) {\n        cout \u003c\u003c v[i] \u003c\u003c \" \";\n    }\n    cout \u003c\u003c endl;\n}\n\n\nint main() {\n    // vector of pairs\n    vector\u003cpair\u003cint, int\u003e\u003e v = {\n     {1,2}, {2,3}, {3,4}\n    };\n    printVec(v);\n\n    // array of vectors\n    int N; // number of vectors inside the array\n    cin \u003e\u003e N;\n    vector\u003cint\u003e v1[N];\n    for (int i = 0; i \u003c N; i++) {\n        int n; // size of each vector\n        cin \u003e\u003e n;\n        for (int j = 0; j \u003c n; j++) {\n            int x; // value inside each vector\n            cin \u003e\u003e x;\n            v1[i].push_back(x); // pushing x in the ith vector\n        }\n    }\n    for (int i = 0; i \u003c N; i++) {\n        printVec(v1[i]);\n    }\n\n    vector\u003cvector\u003cint\u003e\u003e v2; // Vector of vectors : v2[i] -\u003e vector\n    int K;\n    cin \u003e\u003e K;\n    // now v2[i] cannot be accessed until there's something inside it.\n    // so either create a temp vector and push everything in it and then\n    // push it in the v2 vector or v2.push_back(vector\u003cint\u003e ());\n    // Both will work\n    for (int i = 0; i \u003c K; i++) {\n        int n;\n        cin \u003e\u003e n;\n        vector\u003cint\u003e temp;\n        for (int j = 0; j \u003c n; j++) {\n            int x;\n            cin \u003e\u003e x;\n            temp.push_back(x);\n        }\n        v2.push_back(temp);\n    }\n\n    // print v2\n    cout \u003c\u003c \"v2: \" \u003c\u003c endl;\n    for (int i = 0; i \u003c v2.size(); i++) {\n        printVec(v2[i]);\n    }\n    return 0;\n}\n```\n\n## Iterators in STL\n\n- Iterators point to the elements of a container.\n- Syntax : `container_type :: iterator it`, 'it' is the name of iterator, it could be named anything obviously.\n- `begin()` points to the start position while `end()` points next to the last element of the container, NOT the last element but next to the last.\n- In case of iterators there's a difference between `it++` and `it+1`\n  - For vectors it's the same because vector has contiguous memory allocation,\n    but in case of maps and sets, the memory allocation couldn't be contiguous leading\n    to wrong memory locations, in case of 'it+1', because it will take the iterator\n    to the next memory location, whereas 'it++' or '++it' will take the iterator to the\n    location of the next iterator, that's why we use 'it++' or '++it' instead of\n    'it+1'.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    // iterators point to the elements of a container.\n    vector\u003cint\u003e v = { 2,3,6,7 };\n    for (int i = 0; i \u003c v.size(); i++) {\n        cout \u003c\u003c v[i] \u003c\u003c \" \";\n    }\n    cout \u003c\u003c \"\\n\";\n    vector\u003cint\u003e ::iterator it = v.begin(); // v.begin() points to v[0]\n    cout \u003c\u003c (*(it + 1)) \u003c\u003c endl; // prints the value 3 from v.\n    for (it = v.begin(); it != v.end(); ++it) { //v.end() points to the next position of the last element\n        cout \u003c\u003c *(it) \u003c\u003c endl;\n    }\n\n    // in case of iterators there's a difference between 'it++' and 'it+1'\n    /*\n        For vectors it's the same because vector has contiguous memory allocation,\n        but in case of maps and sets, the memory allocation couldn't be contiguous leading\n        to wrong memory locations, in case of 'it+1', because it will take the iterator\n        to the next memory location, whereas 'it++' or '++it' will take the iterator to the\n        location of the next iterator, that's why we use 'it++' or '++it' instead of\n        'it+1'.\n\n     */\n\n    vector\u003cpair\u003cint, int\u003e\u003e v_p = {\n        {1,2}, {2,3}, {3,4},{4,5}\n    };\n    vector\u003cpair\u003cint, int\u003e\u003e ::iterator it1;\n    // 'it1' is an iterator that will point to the pairs in the vector\n    for (it1 = v_p.begin(); it1 != v_p.end(); it++) {\n        cout \u003c\u003c (it1)-\u003efirst \u003c\u003c \" \" \u003c\u003c it1-\u003esecond \u003c\u003c endl;\n    }\n    for (it1 = v_p.begin(); it1 != v_p.end(); it++) {\n        cout \u003c\u003c (*it1).first \u003c\u003c \" \" \u003c\u003c (*it1).second \u003c\u003c endl;\n    }\n    return 0;\n}\n```\n\n## Concise Way of writing iterators using `auto` keyword and range based loops\n\n- 'auto' keyword assumes the data type of a variable automatically.\n- `Range based loops can iterate over the elements directly. It eliminates the need to dereference an iterator to get the value.`\n- Both of them could be used together in case of containers to make the code concise and neat.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n// iterators short forms and range based loops\n\nint main() {\n     // 'auto' keyword -\u003e it assumes/finds the data type of the variable automatically.\n    auto a = 1.0; // 'a' is assumed to be float now.\n    // in case of iterators it is particularly more useful because we don't have to write\n    // the whole syntax of iterators.\n\n    vector\u003cint\u003e v = { 2,3,6,7 };\n    // conditional loop\n    for (int i = 0; i \u003c v.size(); i++) {\n        cout \u003c\u003c v[i] \u003c\u003c \" \";\n\n    }\n    cout \u003c\u003c endl;\n\n    // vector\u003cint\u003e ::iterator it;\n    // for (it = v.begin(); it \u003c v.end(); it++) {\n    //     cout \u003c\u003c *(it) \u003c\u003c \" \";\n    // }\n    // cout \u003c\u003c endl;\n    // we can use auto here, instead of defining the iterator directly 'auto' can be used in the for loop\n    for (auto it = v.begin(); it != v.end(); it++)\n    {\n        cout \u003c\u003c *(it) \u003c\u003c \" \";\n    }\n    cout \u003c\u003c endl;\n\n    //range based loops directly iterate over elements and could be used on all containers\n    for (auto el : v) { // right now, 'el' is the copy of values in 'v'\n        el++; //-\u003e this line will have no effect on the elements of 'v'\n    }\n    for (auto\u0026 el : v) {\n        el++; // this will actually change the values of 'v' as it is a reference variable\n    }\n    for (auto el : v) {\n        cout \u003c\u003c el \u003c\u003c \" \";\n    }\n    cout \u003c\u003c endl;\n\n    vector\u003cpair\u003cint, int\u003e\u003e v_p = { {1,2}, {2,3},{3,4} };\n    for (auto\u0026 value : v_p) {\n        cout \u003c\u003c value.first \u003c\u003c \" \" \u003c\u003c value.second \u003c\u003c endl;\n    }\n\n\n\n    return 0;\n}\n```\n\n## Maps\n\n1. Maps : stores key-value pairs\n2. Normal maps(ordered maps) : sorted order -\u003e implemented using Red Black Trees\n3. Unordered maps : unsorted order.\n4. `*(iterator+1) cannot be done`, as there's no continguous memory allocation\n5. Maps(unordered/ordered) contain unique keys only, if we re-assign a value to the key of a map, it will change the value of that key then.\n\n### Ordered Maps: Insertion, Deletion and Accessing time complexity is O(logN)\n\n- Worst case, Best Case and Average Case all have O(logN), however it may worsen in case of strings of long length as they need to lexicographically put in the map, then it will depend on string length too\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n/*\n    1. maps : stores key-value pairs\n    2. normal maps : sorted order -\u003e implemented using Red Black Trees\n    3. unordered maps : unsorted\n    4. iterator+1 cannot be done, as there's no continguous memory allocation\n    5. maps(normal/ordered ones obviously) contain unique keys only, if we re-assign a value to the key\n    of a map it will change the value of that key then.\n*/\n\nint main() {\n    map\u003cint, string\u003e m;\n    m[1] = \"abc\"; // 1 is the key and \"abc\" is its value\n    m[5] = \"cdc\"; // insertion and accessing takes O(logN) because of sorting\n    m[3] = \"acd\";\n    m[6]; // even this takes O(logN), and default value is empty string for string type values,\n    // and for 'int' and 'float' its 0.\n    map \u003cint, string\u003e ::iterator it; // iterator for map, inside its a pair.\n    for (it = m.begin(); it != m.end(); it++) {\n        // 'it \u003c map.end()' doesn't make sense as there's no continuous memory location\n        cout \u003c\u003c it-\u003efirst \u003c\u003c \" \" \u003c\u003c it-\u003esecond \u003c\u003c endl;\n        // or cout \u003c\u003c (*it).first \u003c\u003c \" \" \u003c\u003c (*it).second \u003c\u003c endl;\n    }\n\n    // using auto keyword\n    for (auto\u0026 el : m) {\n        cout \u003c\u003c el.first \u003c\u003c \" \" \u003c\u003c el.second \u003c\u003c endl;\n    }\n\n    // these loops take N(logN) time complexity, as accessing take logN time and there's a loop which runs N times.\n\n    auto iter = m.find(3); // O(logN) time complexity.\n    if (iter == m.end()) {\n        cout \u003c\u003c \"No Value\";\n    }\n    else {\n        cout \u003c\u003c iter-\u003efirst \u003c\u003c \" \" \u003c\u003c iter-\u003esecond \u003c\u003c endl;\n    }\n    // returns m.end() if the value is not found.\n    m.erase(3); // takes key as well as iterator's value as well\n    auto iter1 = m.find(4);\n    if (iter1 != m.end()) {\n        m.erase(iter1);\n    }\n    m.clear(); // clears the whole map\n\n\n    map\u003cstring, string\u003e m1;\n    // insertion time complexity depends on the keys as well.\n    // so this time lexicographical comparison will happen and it will become s.size() * O(logN);\n    m1[\"abcd\"] = \"abc\";\n    return 0;\n}\n```\n\n#### Example\n\nGiven N strings, print unique strings in lexicographical order with their frequency.\n\n- Constraints:\n  - N \u003c= 10\u003csup\u003e5\u003c/sup\u003e\n  - s.length \u003c= 100\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    int N;\n    cin \u003e\u003e N;\n    map\u003cstring, int\u003e m; // map of strings and its frequency\n    for (int i = 0; i \u003c N; i++) {\n        string s;\n        cin \u003e\u003e s;\n        if (!s.empty()) m[s]++;\n    }\n    for (auto\u0026 el : m) {\n        cout \u003c\u003c el.first \u003c\u003c \" \" \u003c\u003c el.second \u003c\u003c endl;\n    }\n\n    return 0;\n}\n```\n\n- Input\n\n  8\n\n  abc\n\n  def\n\n  abc\n\n  ghj\n\n  jkl\n\n  ghj\n\n  ghj\n\n  abc\n\n- Output\n\n  abc 3\n\n  def 1\n\n  ghj 3\n\n  jkl 1\n\n### Unordered Maps : Average Insertion, Deletion and Accessing time complexity is O(1)\n\n- Worst case : O(n)\n- `Use unordered maps wherever possible to reduce time complexity.`\n- Can't use complex data types like pairs as keys because the hash functions aren't defined internally.\n- Basic data types are `int`, `float`, `string` etc. can be used.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n// all functions of ordered and unordered maps are same\n\nint main() {\n    unordered_map\u003cint, string\u003e m;\n    // 1. inbuilt implementation -\u003e uses hashing and hashtables\n    // 2. time complexity -\u003e O(1) is average.\n    // 3. valid keys datatype -\u003e complex datatype can't be keys\n    // unordered_map\u003cpair\u003cint, int\u003e, string\u003e m1; -\u003e can't compile\n    // because hash functions of these things aren't internally defined\n    m[1] = \"abc\";\n    m[3] = \"bce\";\n\n    //Example: given Q queries and N strings, print the frequency of the strings given in each query.\n    unordered_map\u003cstring, int\u003e m1;\n    int N;\n    cin \u003e\u003e N;\n    for (int i = 0; i \u003c N; i++) {\n        string s;\n        cin \u003e\u003e s;\n        m1[s]++;  // accessing and insertion is O(1)\n    }\n    int Q;\n    cin \u003e\u003e Q;\n    while (Q--) { //total time complexity for this loop is q*(length of string)\n        string s;\n        cin \u003e\u003e s;\n        cout \u003c\u003c m1[s] \u003c\u003c endl; // accessing and insertion is O(1)\n    }\n\n    // multimaps\n    multimap\u003cstring, int\u003e mm;\n\n   // Insert elements\n    mm.insert({ \"Alice\", 90 });\n    mm.insert({ \"Bob\", 85 });\n    mm.insert({ \"Alice\", 95 });\n\n    // Accessing elements\n    auto range = mm.equal_range(\"Alice\");\n    for (auto it = range.first; it != range.second; ++it) {\n        cout \u003c\u003c it-\u003efirst \u003c\u003c \": \" \u003c\u003c it-\u003esecond \u003c\u003c endl;\n    }\n\n    return 0;\n}\n```\n\n- Multimaps could be used to store multiple values with a single key. Not frequently used atleast in CP and we can use ordered maps with vector\u003cint/string\u003e as the value to store multiple instances.\n\n## Ordered, Unordered and Multi Sets\n\n- size: to get the size of sets and maps(ordered, unordered and multi)\n- Use them whenever you need to remove duplicate(or some form of duplicacy) elements.\n\n### Ordered Sets : Accessing, Deletion and Insertion Time Complexity is O(logN)\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvoid print_set(set\u003cstring\u003e\u0026 s) {\n    for (auto\u0026 el : s) {\n        cout \u003c\u003c el \u003c\u003c \" \";\n    }\n    cout \u003c\u003c endl;\n}\n\nint main() {\n    // ordered set: Everything is like map's time complexity, i.e., O(logN).\n    // sets only contain unique elements\n    set\u003cstring\u003e s;\n    s.insert(\"abc\");\n    s.insert(\"zsd\");\n    s.insert(\"bcd\");\n    // s[\"abc\"] -\u003e it doesn't exist, we use '.find()' method for this.\n    auto it = s.find(\"abc\"); // gives iterator if it exists or returns end iterator if it doesn't.\n    s.erase(\"abc\"); // it also takes iterators\n    if (it != s.end()) s.erase(it);\n    s.clear(); // clears the whole set\n    return 0;\n}\n```\n\n- Example\n  - Given N strings, print unique strings in lexicographical order.\n  - Constraints:\n    N \u003c= 10\u003csup\u003e5\u003c/sup\u003e, string.length=100000\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nint main() {\n    set\u003cstring\u003e s;\n    int N;\n    cin \u003e\u003e N;\n    for (int i = 0; i \u003c N; i++) {\n        string str;\n        cin \u003e\u003e str;\n        s.insert(str);\n    }\n    for (auto\u0026 el : s) {\n        cout \u003c\u003c el \u003c\u003c endl;\n    }\n\n    return 0;\n}\n```\n\n- Example : [Sets-STL](https://www.hackerrank.com/challenges/cpp-sets/problem?fbclid=IwAR1Z1fv5RnGAqByvADCRUv4pYQAAmQ_zV5rgVVCagY-DneWu6TSWENdncsY)\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\nint main() {\n    int q;\n    cin \u003e\u003e q;\n    set\u003cint\u003e s;\n    while (q--)\n    {\n        int y, x;\n        cin \u003e\u003e y \u003e\u003e x;\n        if (y == 1) {\n            s.insert(x);\n        }\n        else if (y == 2)\n        {\n            auto it = s.find(x);\n            if (it != s.end()) s.erase(it);\n        }\n        else if (y == 3)\n        {\n            auto it = s.find(x);\n            if (it != s.end()) {\n                cout \u003c\u003c \"Yes\" \u003c\u003c endl;\n            }\n            else {\n                cout \u003c\u003c \"No\" \u003c\u003c endl;\n            }\n        }\n    }\n    s.clear();\n    return 0;\n\n}\n```\n\n### Unordered Sets : Average Accessing, Deletion and Insertion Time Complexity is O(1)\n\n- Functions are same like ordered set, just the time complexity is different.\n- Similar to unordered maps, complex data types like pairs/sets/vectors can't be keys.\n- Following is the example and code for unordered set:\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n// Given N strings and Q queries, print yes if the string is present in the query. N \u003c= 10^5, string.length=100000\n\nint main() {\n    unordered_set\u003cstring\u003e us;\n    int N;\n    cin \u003e\u003e N;\n    for (int i = 0; i \u003c N; i++) {\n        string s;\n        cin \u003e\u003e s;\n        us.insert(s);\n    }\n    int Q;\n    cin \u003e\u003e Q;\n    while (Q--)\n    {\n        string s;\n        cin \u003e\u003e s;\n        auto it = us.find(s);\n        if (it != us.end()) {\n            cout \u003c\u003c \"yes\" \u003c\u003c endl;\n            continue;\n        }\n        cout \u003c\u003c \"no\" \u003c\u003c endl;\n\n    }\n\n    return 0;\n}\n```\n\n- (Unique Number of Occurences)[https://leetcode.com/problems/unique-number-of-occurrences/description/]\n\n  - unordered_set\u003cint\u003es; s.insert(2) returns a pair, in which first value is the iterator to that element in set and second is true/false depending on if the element was inserted.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nbool uniqueOccurrences(vector\u003cint\u003e\u0026 v) {\n    unordered_map\u003cint, int\u003e f;\n    for (auto\u0026 it : v) {\n        f[it]++;\n    }\n    unordered_set\u003cint\u003eo;\n    for (auto\u0026 el : f) {\n        if (!o.insert(el.second).second) {\n            return false;\n        }\n    }\n    return true;\n}\n\nint main() {\n\n\n    return 0;\n}\n```\n\n### Multisets : Allows multiple same values, O(logN) time complexity for everything generally.\n\n- Allows multiple keys in the set in sorted manner.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\nint main(){\n    multiset\u003cstring\u003e s;\n    s.insert(\"abc\"); // O(logN)\n    s.insert(\"bcd\");\n    s.insert(\"abc\");\n    s.insert(\"abc\");\n    s.insert(\"zsdf\");\n    auto it = s.find(\"abc\"); // O(logN), returns the iterator of the first instance it finds, else it returns 's.end()'\n    if(it!=s.end()) s.erase(it); // deletes just the first instance of \"abc\",\n    // which is being pointed by the iterator.\n    s.erase(\"abc\"); // deletes all instances of abc from the set.\n    return 0;\n\n}\n```\n\nExample : [The Monk and Class Marks](https://www.hackerearth.com/problem/algorithm/the-monk-and-class-marks/?fbclid=IwAR09BMLG-1NhqDlVQq0KIzSr8ZTgqrbJmdfnsXc7KnDiphgX5UmbFLoEYjE)\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    multiset\u003cpair\u003cint, string\u003e, function\u003cbool(pair\u003cint, string\u003e, pair\u003cint, string\u003e)\u003e\u003e m(\n        [](const pair\u003cint, string\u003e\u0026 a, const pair\u003cint, string\u003e\u0026 b) {\n            if (a.first != b.first) {\n                return a.first \u003e b.first;\n            }\n            else {\n                return a.second \u003c b.second;\n            }\n        }\n    );\n    for (int i = 0; i \u003c n; i++) {\n        string name;\n        int marks;\n        cin \u003e\u003e name \u003e\u003e marks;\n        m.insert({ marks, name });\n    }\n\n    for (auto\u0026 p : m) {\n        cout \u003c\u003c p.second \u003c\u003c \" \" \u003c\u003c p.first \u003c\u003c endl;\n    }\n\n    m.clear();\n\n\n    return 0;\n\n}\n```\n\n- Example: [Monk and the Magical Candies](https://www.hackerearth.com/practice/data-structures/trees/heapspriority-queues/practice-problems/algorithm/monk-and-the-magical-candy-bags/?fbclid=IwAR2kDiVkEaxu9dkCTCUhzXLuIccNn0Gz3dSfkaSUjlDE6Nb9UHMzt8HNDo4)\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nint main() {\n    int t;\n    cin \u003e\u003e t;\n    while (t--)\n    {\n        long long n, k;\n        cin \u003e\u003e n \u003e\u003e k;\n        multiset\u003clong long\u003e m;\n        for (int i = 0; i \u003c n; i++) {\n            long long x;\n            cin \u003e\u003e x;\n            m.insert(x);\n        }\n        long long sum = 0;\n        for (int i = 0; i \u003c k; i++) {\n            auto it = --m.end();\n            sum += *it;\n            m.erase(it);\n            m.insert((*it) / 2);\n        }\n        cout \u003c\u003c sum \u003c\u003c endl;\n        m.clear();\n    }\n\n    return 0;\n}\n```\n\n### Nesting in Sets and Maps\n\n- Only ordered sets and maps can be nested with complex data structures which could be compared somehow.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nint main() {\n    map\u003cpair\u003cstring, string\u003e, vector\u003cint\u003e\u003e m;\n    int n;\n    cin \u003e\u003e n;\n    for (int i = 0; i \u003c n; i++) {\n        string fn, ln;\n        int ct;\n        cin \u003e\u003e fn \u003e\u003e ln \u003e\u003e ct;\n        for (int j = 0; j \u003c ct; j++) {\n            int x;\n            cin \u003e\u003e x;\n            m[{fn, ln}].push_back(x);\n        }\n    }\n    for (auto\u0026 pr : m) {\n        auto\u0026 full_name = pr.first;\n        auto\u0026 list = pr.second;\n        cout \u003c\u003c full_name.first \u003c\u003c \" \" \u003c\u003c full_name.second \u003c\u003c endl;\n        cout \u003c\u003c list.size() \u003c\u003c endl;\n        for (auto\u0026 el : list)\n        {\n            cout \u003c\u003c el \u003c\u003c \" \";\n        }\n        cout \u003c\u003c endl;\n\n    }\n\n    return 0;\n}\n```\n\n## Stack and Queue in STL\n\n- Stack works on LIFO principle and the most handy functions it provides are as follows:\n\n  - top: to retreive(not remove) the topmost element\n  - push: to push elements onto the stack\n  - pop: to pop the elements off the stack\n  - size: to check the size of the stack\n\n- Queue works on FIFO principle and the most common functions are:\n  - front : to retrieve(not remove) the first element in the queue\n  - push: to push elements in the back of the queue\n  - pop: to pop elements from the front of the queue\n  - size: to check the size of the queue\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    // Stack works on LIFO principle\n    stack\u003cint\u003e s; // could be any data structure ofc\n    s.push(1);\n    s.push(2);\n    s.push(3);\n    s.push(4);\n    cout\u003c\u003cs.size()\u003c\u003cendl; //gives the size of the stack\n    while (!s.empty())\n    {\n        cout \u003c\u003c s.top() \u003c\u003c endl;\n        s.pop();\n    }\n\n    // Queue works on FIFO principle\n    queue\u003cstring\u003e q; // could be any data structure ofc\n    q.push(\"abc\");\n    q.push(\"def\");\n    q.push(\"ghi\");\n    q.push(\"jkl\");\n    cout\u003c\u003cq.size()\u003c\u003cendl; //gives the size of the queue\n    while (!q.empty())\n    {\n        cout \u003c\u003c q.front() \u003c\u003c endl;\n        q.pop();\n    }\n\n\n    return 0;\n}\n```\n\n### Examples for Stack and Queue along with concepts that will come in handy later\n\n1. [Balanced Brackets](https://leetcode.com/problems/valid-parentheses/description/)\n\n```cpp\n    #include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nbool isValid(string s) {\n    stack\u003cchar\u003e st;\n    unordered_map\u003cchar, int\u003e symbols = { {'[', -1}, {'(',-2}, {'{', -3}, {']', 1}, {')',2}, {'}', 3} };\n    for (char bracket : s)\n    {\n        if (symbols[bracket] \u003c 0) {\n            st.push(bracket);\n        }\n        else {\n            if (st.empty()) return false;\n            char top = st.top();\n            st.pop();\n            if (symbols[top] + symbols[bracket] != 0) return false;\n        }\n    }\n    return st.empty();\n}\n\n// balanced brackets\nint main() {\n\n    cout \u003c\u003c isValid(\"()\");\n    return 0;\n}\n```\n\n2. [Next Greater Element](https://www.hackerrank.com/contests/second/challenges/next-greater-element/problem)\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvector\u003cint\u003e NGE(vector\u003cint\u003e\u0026 v) {\n    stack\u003cint\u003e st;\n    vector\u003cint\u003e nge(v.size());\n    for (int i = 0; i \u003c v.size(); i++) {\n        while (!st.empty() \u0026\u0026 v[i] \u003e v[st.top()]) {\n            nge[st.top()] = i;\n            st.pop();\n        }\n        st.push(i);\n    }\n    while (!st.empty())\n    {\n        nge[st.top()] = -1;\n        st.pop();\n    }\n    return nge;\n}\n\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    vector\u003cint\u003e v(n);\n    for (int i = 0; i \u003c n; i++) {\n        cin \u003e\u003e v[i];\n    }\n    vector\u003cint\u003e nge = NGE(v);\n    for (int i = 0; i \u003c nge.size(); i++) {\n        cout \u003c\u003c v[i] \u003c\u003c \" \" \u003c\u003c (nge[i] == -1 ? -1 : v[nge[i]]) \u003c\u003c endl;\n    }\n    return 0;\n}\n```\n\n## Sorting(Introsort) in STL : O(NlogN) \u0026rarr; Time Complexity\n\n- `sort()` function takes the starting `address` and the `(ending+1) address` and can take a comparator function as well.\n\n1. Sorting on vectors and arrays\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    //Introsort -\u003e inbuilt sort algorithm = quick sort + heap sort + insertion sort\n    int n;\n    cin \u003e\u003e n;\n    // int a[n];\n    vector\u003cint\u003ea(n);\n    for (int i = 0; i \u003c n; i++) {\n        cin \u003e\u003e a[i];\n    }\n    // sort(a + 3, a + n); // takes starting address and (ending+1) address\n    sort(a.begin(), a.end());\n    for (int i = 0; i \u003c n; i++) {\n        cout \u003c\u003c a[i] \u003c\u003c \" \";\n    }\n    cout \u003c\u003c endl;\n\n\n    return 0;\n}\n```\n\n2. Sorting with comparator functions\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n//comparator function for bubble sort\n// bool should_i_swap(pair\u003cint, int\u003ea, pair\u003cint, int\u003e b) {\n//     if (a.first != b.first) {\n//         if (a.first \u003e b.first) return true;\n//     }\n//     else {\n//         if (a.second \u003c b.second) return true;\n//     }\n//     return false;\n// }\n\n//comparator function for inbuilt sort function\n// bool should_i_swap(pair\u003cint, int\u003ea, pair\u003cint, int\u003e b) {\n//     if (a.first != b.first) {\n//         if (a.first \u003e b.first) return false;\n//     }\n//     else {\n//         if (a.second \u003c b.second) return false;\n//     }\n//     return true;\n// }\n\n// comparator function for introsort but in a simpler way\n// return whatever you want the comparator function to do!\nbool should_i_swap(pair\u003cint, int\u003ea, pair\u003cint, int\u003e b) {\n    if (a.first != b.first) {\n        return a.first \u003c b.first;\n    }\n    return a.second \u003e b.second;\n}\n\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    vector\u003cpair\u003cint, int\u003e\u003ea(n);\n    for (int i = 0; i \u003c n; i++) {\n        cin \u003e\u003e a[i].first \u003e\u003e a[i].second;\n    }\n\n    // Bubble sort in O(n^2)\n    // for (int i = 0; i \u003c n; i++) {\n    //     for (int j = i + 1; j \u003c n; j++) {\n    //         if (should_i_swap(a[i], a[j])) swap(a[i], a[j]);\n    //     }\n    // }\n\n    sort(a.begin(), a.end(), should_i_swap); // return whatever you want the\n    // comparator function to do\n\n    for (int i = 0; i \u003c n; i++) {\n        cout \u003c\u003c a[i].first \u003c\u003c \" \" \u003c\u003c a[i].second \u003c\u003c endl;\n    }\n    cout \u003c\u003c endl;\n\n\n    return 0;\n}\n```\n\n## Upper and Lower Bounds using STL : Works in O(logN) on sorted Data Structures and in O(N) on unsorted ones\n\n### Lower Bound\n\n- Returns the iterator to the first element in the range that is not less than (i.e., greater than or equal to) the specified value.\n- Takes the range of addresses (start: inclusive, end: exclusive) on which the operation needs to be performed, and the value of which the lower bound needs to be found.\n- If no element is greater than or equal to the specified value, it returns the end iterator of the range.\n\n- Lower Bound on Arrays:\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    int a[n];\n    for (int i = 0; i \u003c n; i++) {\n        cin \u003e\u003e a[i];\n    }\n    sort(a, a + n); // works best on sorted data structures\n\n    for (int i = 0; i \u003c n; i++) {\n        cout \u003c\u003c a[i] \u003c\u003c \" \";\n    }\n    cout \u003c\u003c endl;\n\n    int* ptr = lower_bound(a, a + n, 26); // finds the pointer/iterator of that value or the value just greater than that\n    if (ptr == (a + n)) {\n        cout \u003c\u003c \"Not Found\" \u003c\u003c endl;\n\n    }\n    else {\n        cout \u003c\u003c (*ptr) \u003c\u003c endl;\n    }\n\n    int* ptr_restricted = lower_bound(a + 1, a + n, 5); // range can be restrictive too\n    if (ptr_restricted == (a + n)) {\n        cout \u003c\u003c \"Not Found\";\n    }\n    else {\n        cout \u003c\u003c (*ptr_restricted) \u003c\u003c endl;\n    }\n    return 0;\n}\n```\n\n- Lower bound on vectors\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    vector\u003cint\u003ea(n);\n    for (int i = 0; i \u003c n; i++) {\n        cin \u003e\u003e a[i];\n    }\n    sort(a.begin(), a.end());\n\n    for (int i = 0; i \u003c n; i++) {\n        cout \u003c\u003c a[i] \u003c\u003c \" \";\n    }\n    cout \u003c\u003c endl;\n\n    auto it = lower_bound(a.begin(), a.end(), 26); // finds the pointer/iterator of that value or the value just greater than that\n    if (it == (a.end())) {\n        cout \u003c\u003c \"Not Found\" \u003c\u003c endl;\n\n    }\n    else {\n        cout \u003c\u003c (*it) \u003c\u003c endl;\n    }\n\n    auto it_restricted = lower_bound(a.begin(), a.end(), 5); // range can be restrictive too\n    if (it_restricted == (a.end())) {\n        cout \u003c\u003c \"Not Found\";\n    }\n    else {\n        cout \u003c\u003c (*it_restricted) \u003c\u003c endl;\n    }\n    return 0;\n}\n```\n\n- Lower bound on sets and maps\n  1. Use set.lower_bound() function instead of regular lower_bound() function, same for maps as well.\n  2. Regular lower_bound() works as O(N) in case of sets and maps but map.lower_bound() function works in O(logN) as it uses trees internally to traverse through the map.\n  3. set.lower_bound() or map.lower_bound() just takes the value as input, and returns the iterator of either that value if its present in the set/map or of the first just greater element in it.\n  4. map.lower_bound() works just on the keys of the map and returns the iterator of the value in the map.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    set\u003cint\u003e s;\n    for (int i = 0; i \u003c n; i++) {\n        int x;\n        cin \u003e\u003e x;\n        s.insert(x);\n    }\n    // auto it = lower_bound(s.begin(), s.end(), 5); // this is NOT O(logN) but O(N)\n    // for sets use set.lower_bound() function, as it uses tree implementation to traverse\n    auto it_set = s.lower_bound(5);\n    if (it_set != s.end()) cout \u003c\u003c *it_set \u003c\u003c endl;\n    map\u003cint, int\u003em;\n    int k;\n    cin \u003e\u003e k;\n    for (int i = 0; i \u003c k; i++) {\n        int x;\n        int y;\n        cin \u003e\u003e x \u003e\u003e y;\n        m[x] = { y };\n    }\n    auto it_map = m.lower_bound(3); // works on keys only!\n    if (it_map != m.end()) cout \u003c\u003c (it_map)-\u003efirst \u003c\u003c \" \" \u003c\u003c it_map-\u003esecond \u003c\u003c endl;\n    return 0;\n}\n```\n\n### Upper Bound\n\n- Always returns the iterator of the first greater element than the current element. Works in the same way as lower bound.\n- Returns an iterator to the first element in the range that is greater than the specified value.\n- Takes the range of addresses (start: inclusive, end: exclusive) on which the operation needs to be performed, and the value of which the upper bound needs to be found.\n- If no element is greater than the specified value, it returns the end iterator of the range.\n\n- Example:\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nint main(){\n    map\u003cint, int\u003em;\n    int k;\n    cin \u003e\u003e k;\n    for (int i = 0; i \u003c k; i++) {\n        int x;\n        int y;\n        cin \u003e\u003e x \u003e\u003e y;\n        m[x] = { y };\n    }\n\n    auto it_map_upper_bound = m.upper_bound(4);\n    if (it_map_upper_bound != m.end()) cout \u003c\u003c it_map_upper_bound-\u003efirst \u003c\u003c \" \" \u003c\u003c it_map_upper_bound-\u003esecond \u003c\u003c endl;\n\n    return 0;\n}\n```\n\n### Some inbuilt algorithms and Lambda Functions in C++ STL\n\n- All of them take a range of starting(inclusive) and ending(exclusive) addresses to operate on.\n\n1. min_element() : returns the pointer/iterator of the minimum element in the range.\n2. max_element() : returns the pointer/iterator of the maximum element in the range.\n3. count() : counts the occurence of an element in the given range and returns the count.\n4. find() : returns the iterator/pointer of that element and if not found then returns the iterator/pointer of the next to the last element in the data structure(basically the end iterator/pointer), in the provided range.\n5. reverse() : reverses the elements of a data structure(like arrays, vectors and strings) in the provided range.\n6. accumulate(): sums the elements in the given range and takes the initial sum as the third argument as well.\n\n- Obviously, in case of arrays, instead of iterators we directly use the variable name(say a) for ranges like this : `sort(a, a+n)`, asssuming that there are 'n' elements in the array.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    vector\u003cint\u003e v(n);\n    for (int i = 0; i \u003c n; i++) {\n        cin \u003e\u003e v[i];\n    }\n    // all of these internal algorithms take up a range to operate in on a data structure.\n\n    int min = *min_element(v.begin(), v.end());\n    cout \u003c\u003c min \u003c\u003c endl;\n\n    int max = *max_element(v.begin(), v.end());\n    cout \u003c\u003c max \u003c\u003c endl;\n\n    int count_of_an_element = count(v.begin(), v.end(), 2);\n    cout \u003c\u003c count_of_an_element \u003c\u003c endl;\n\n    int sum = accumulate(v.begin(), v.end(), 0); // initial sum taken to be 0, if it is taken something else, it would be added to the final sum\n    cout \u003c\u003c sum \u003c\u003c endl;\n\n    auto it = find(v.begin(), v.end(), 6); //returns the iterator/pointer of that element, if not found then of the next to last element\n    if (it != v.end()) cout \u003c\u003c *it \u003c\u003c endl;\n    else cout \u003c\u003c \"Element Not Found\" \u003c\u003c endl;\n\n    // reverses the original data structure\n    reverse(v.begin(), v.end());\n    // comes in handy in case of arrays, vectors and strings especially\n    for (int i = 0; i \u003c n; i++) {\n        cout \u003c\u003c v[i] \u003c\u003c \" \";\n    }\n    cout \u003c\u003c endl;\n\n    string s = \"dfbhfew\";\n    reverse(s.begin() + 2, s.end()); // reverses from 2nd index to the last\n    cout \u003c\u003c s \u003c\u003c endl;\n\n    return 0;\n}\n```\n\n6. all_of(): returns true only if all the elements satisfy the condition.\n7. any_of(): returns true if atleast one of the elements satisfy the condition.\n8. none_of(): returns true if none of the elements satisfy the condition.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nbool is_positive(int x){\n    return x\u003e0;\n}\n\nint main() {\n\n    vector\u003cint\u003e v = { 2,4,6,7 };\n    //using regular function\n    cout \u003c\u003c all_of(v.begin(), v.end(), is_positive) \u003c\u003c endl;\n\n    //using lambda function\n    cout \u003c\u003c any_of(v.begin(), v.end(), [](int x) {return x \u003e 0;}) \u003c\u003c endl;\n    cout \u003c\u003c none_of(v.begin(), v.end(), [](int x) {return x \u003e 0;}) \u003c\u003c endl;\n\n    return 0;\n}\n```\n\n### Lambda function\n\n- This is a concise way of writing a function and could be assigned to a variable as well, like this:\n\n- Syntax : `[](int a, int b){ return a+b;}`, to call it, write parentheses just to the side of it like this :` [](int a, int b){ return a+b;}()`;\n  - `auto sum = [](int a, int b){ return a+b;};`\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    cout \u003c\u003c [](int x, int y) {return x + y;}(2, 3) \u003c\u003c endl; // calling the anonymous lambda function\n    auto sum = [](int x, int y) {return x + y;};\n    cout \u003c\u003c sum(2, 5) \u003c\u003c endl;\n\n    return 0;\n}\n```\n\n# Data Structures and Algorithms\n\n## Hashing and Pre-Computation\n\n- Formal Definition of hashing: Hashing is a technique used to map data from a large input space to a smaller, fixed-size range of integers (often referred to as \"hashes\"). `The goal is to efficiently store and retrieve data in a way that allows for quick lookups, insertions, and deletions.` Hashing is commonly used to implement data structures like hash tables, which are `key in solving problems involving frequent queries on large datasets.`\n\n- Formal Definition of Pre-computation : Pre-computation refers to the `process of computing and storing results in advance before they are needed during the actual query or operation phase`. This technique is especially useful in scenarios where the same computation may need to be repeated multiple times.\n\n- Here's an example: We reduced the time complexity by creating a hash array then did the pre-computation(in a frequency array and stored it) till the max size,i.e., 10\u003csup\u003e5\u003c/sup\u003e and simply looked up for the data in our hash vector.\n\n- This reduces the time complexity by a lot, especially for large datasets.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n/*\nGiven an array 'a' of N integers. Given Q queries and in each\nquery given a number X, print the count of that number in array.\n\nConstraints:\n1\u003c=N\u003c=10^5\n1\u003c=a[i]\u003c=10^7\n1\u003c=Q\u003c=10^5\n */\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    int a[n];\n    for (int i = 0; i \u003c n; i++) {\n        cin \u003e\u003e a[i];\n    }\n    int q;\n    cin \u003e\u003e q;\n    // while (q--) // O(q*n) == O(10^10) =\u003e this won't run in one second\n    // {\n    //     int x;\n    //     cin \u003e\u003e x;\n    //     int ct = 0;\n    //     for (int i = 0; i \u003c n; i++) {\n    //         if (a[i] == x) {\n    //             ct++;\n    //         }\n    //     }\n    //     cout \u003c\u003c ct \u003c\u003c endl;\n    // }\n\n    // Pre-computing the frequencies of the element\n    vector\u003cint\u003e freq(1e7 + 10); // hash vector(or array)\n    for (int i = 0; i \u003c n; i++) { // O(n)\n        freq[a[i]]++; // calculate frequency of each element in advance\n    }\n\n    while (q--) { // O(q)\n        int x;\n        cin \u003e\u003e x;\n        cout \u003c\u003c freq[x] \u003c\u003c endl;\n    }\n\n    // Total time complexity = O(n+q)\n\n    return 0;\n}\n```\n\n### [Two Sum](https://leetcode.com/problems/two-sum/)\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvector\u003cint\u003e twoSum(vector\u003cint\u003e\u0026 v, int target) {\n    unordered_map\u003cint, int\u003e m;\n\n    for (int i = 0; i \u003c v.size(); i++) {\n        int val = target - v[i];\n        if (m.find(val) != m.end()) {\n            return { m[val], i };\n        }\n        m[v[i]] = i;\n    }\n    return { -1, -1 };\n}\n\nint main() {\n    int n, target;\n    cin \u003e\u003e n \u003e\u003e target;\n    vector\u003cint\u003ev(n);\n    for (int i = 0; i \u003c n; i++) {\n        cin \u003e\u003e v[i];\n    }\n    vector\u003cint\u003e ans = twoSum(v, target);\n    for (int i = 0; i \u003c ans.size(); i++) {\n        cout \u003c\u003c ans[i] \u003c\u003c \" \";\n    }\n\n    return 0;\n}\n```\n\n### Prefix sum technique of Precomputation\n\n1. Prefix sum on 1D arrays\n\n- Use 1-based indexing the questions of prefix sum\n- To find occurences or sums in a range.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n/*\nGiven an array 'a' of N integers. Given Q queries and in each query given L\nand R, print sum of the array elements from L to R (both incluive).\n\nConstraints:\n1\u003c=N\u003c=10^5\n1\u003c=a[i]\u003c=10^9\n1\u003c=Q\u003c=10^5\n1\u003c=L,R\u003c=N\n*/\n\n// Use 1-based indexing in case of prefix sum\nint main() {\n    int N;\n    cin \u003e\u003e N;\n    vector\u003cint\u003e a(N + 1);\n    for (int i = 1; i \u003c= N; i++) {\n        cin \u003e\u003e a[i];\n    }\n\n    // pre-compute the prefix-sum in a pf vector, declare it vector\u003clong long\u003e\n    // because of the order of elements of the vector 'a'\n\n    // computing the prefix sum\n    vector\u003clong long\u003e pf(N + 1); // 'long long' because of the nature of the elements of vector 'a'\n    pf[1] = a[0];\n    for (int i = 2; i \u003c= N; i++) {\n        pf[i] = pf[i - 1] + a[i];\n    }\n\n    int q;\n    cin \u003e\u003e q;\n    while (q--) {\n        int l, r;\n        cin \u003e\u003e l \u003e\u003e r;\n        cout \u003c\u003c pf[r] - pf[l - 1] \u003c\u003c endl;\n    }\n\n    // O(N + Q)\n\n    return 0;\n}\n```\n\n2. Prefix sum on 2D arrays\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n/*\n    Given 2D array of N*N integers. Given Q queries and in each query given\n    a,b,c and d print sum of square represented by (a,b) as top left point and\n    (c,d) as top bottom right point.\n\n    Constraints:\n    1\u003c=N\u003c=10^3\n    1\u003c=a[i][j]\u003c=10^9\n    1\u003c=Q\u003c=10^5\n    1\u003c=a,b,c,d\u003c=N\n*/\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    vector\u003cvector\u003cint\u003e\u003ev(n + 1, vector\u003cint\u003e(n + 1, 0));\n    vector\u003cvector\u003clong long\u003e\u003epf(n + 1, vector\u003clong long\u003e(n + 1, 0));\n\n    for (int i = 1; i \u003c= n; i++) {\n        for (int j = 1; j \u003c= n; j++) {\n            cin \u003e\u003e v[i][j];\n        }\n    }\n\n    for (int i = 1; i \u003c= n; i++) {\n        for (int j = 1; j \u003c= n; j++) {\n            pf[i][j] = v[i][j] + pf[i - 1][j] + pf[i][j - 1] - pf[i - 1][j - 1];\n        }\n    }\n\n    int q;\n    cin \u003e\u003e q;\n    while (q--)\n    {\n        int a, b, c, d;\n        cin \u003e\u003e a \u003e\u003e b \u003e\u003e c \u003e\u003e d;\n        cout \u003c\u003c pf[c][d] - pf[a - 1][d] - pf[c][b - 1] + pf[a - 1][b - 1] \u003c\u003c endl;\n    }\n\n\n    return 0;\n}\n```\n\n3. [Prefix Sum with a twist](https://www.hackerrank.com/challenges/crush/problem)\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n// L to R addition type problem\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    vector\u003clong long\u003e v(n + 1, 0);\n    int t;\n    cin \u003e\u003e t;\n    vector\u003cvector\u003clong long\u003e\u003e q(t, vector\u003clong long\u003e(3));\n    for (int i = 0; i \u003c t; i++) {\n        for (int j = 0; j \u003c 3; j++) {\n            cin \u003e\u003e q[i][j];\n        }\n    }\n\n    // Setting the elements cleverly\n    for (int i = 0; i \u003c t; i++) {\n        int a = q[i][0], b = q[i][1], k = q[i][2];\n        v[a] += k;\n        if (b + 1 \u003c= n) v[b + 1] -= k;\n    }\n\n    // performing prefix sum to pre-compute the answer\n    for (int i = 1; i \u003c= n; i++) {\n        v[i] += v[i - 1];\n    }\n\n    long long max_el = v[1];\n    for (int i = 2; i \u003c= n; i++) {\n        if (max_el \u003c v[i]) {\n            max_el = v[i];\n        }\n    }\n\n    cout \u003c\u003c max_el;\n    return 0;\n}\n\n```\n\n4. Prefix Sum and Hashing both\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n// find in the range L to R if the string is palindromic?\n/*\nInput:\n2\n5 5\nabcec\n1 2\n2 5\n3 5\n1 5\n1 4\n5 5\naabbc\n1 2\n2 5\n3 5\n1 5\n1 4\n\nOutput:\nNO\nNO\nYES\nNO\nNO\nYES\nNO\nYES\nYES\nYES\n\n\n*/\n// prefix sum and hashing\nint main() {\n    int t;\n    cin \u003e\u003e t;\n    while (t--)\n    {\n        int n, q;\n        cin \u003e\u003e n \u003e\u003e q;\n        string s;\n        cin \u003e\u003e s;\n        // hashing\n        vector\u003cvector\u003cint\u003e\u003ev(s.size() + 1, vector\u003cint\u003e(26, 0));\n        for (int i = 0; i \u003c n; i++) {\n            v[i + 1][s[i] - 'a']++;\n        }\n        // prefix sum\n        for (int i = 0; i \u003c 26; i++) {\n            for (int j = 1; j \u003c= n; j++) {\n                v[j][i] += v[j - 1][i];\n            }\n        }\n        while (q--)\n        {\n            int l, r;\n            cin \u003e\u003e l \u003e\u003e r;\n            int oddCt = 0;\n            for (int i = 0; i \u003c 26; i++) {\n                int charCt = v[r][i] - v[l - 1][i];\n                if (charCt % 2 != 0) oddCt++;\n            }\n            if (oddCt \u003e 1) cout \u003c\u003c \"NO\\n\";\n            else cout \u003c\u003c \"YES\\n\";\n        }\n\n    }\n\n\n    return 0;\n}\n\n\n\n\n```\n\n## Number Theory\n\n### Factors and Sum of Divisors\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;x = p\u003csub\u003e1\u003c/sub\u003e\u003csup\u003en\u003csub\u003e1\u003c/sub\u003e\u003c/sup\u003e \u0026times;p\u003csub\u003e2\u003c/sub\u003e\u003csup\u003en\u003csub\u003e2\u003c/sub\u003e\u003c/sup\u003e \u0026times;...p\u003csub\u003et\u003c/sub\u003e\u003csup\u003en\u003csub\u003et\u003c/sub\u003e\u003c/sup\u003e, where p\u003csub\u003ek\u003c/sub\u003e is a prime factor of the number x.\n\n- Count of divisors = (n\u003csub\u003e1\u003c/sub\u003e + 1) \u0026times; (n\u003csub\u003e2\u003c/sub\u003e+1) \u0026times; (n\u003csub\u003e3\u003c/sub\u003e+1)... \u0026times; (n\u003csub\u003et\u003c/sub\u003e+1)\n- Sum of divisors = ((p\u003csub\u003e1\u003c/sub\u003e\u003csup\u003en\u003csub\u003e1\u003c/sub\u003e+1\u003c/sup\u003e)/(p\u003csub\u003e1\u003c/sub\u003e-1)) + ((p\u003csub\u003e2\u003c/sub\u003e\u003csup\u003en\u003csub\u003e2\u003c/sub\u003e+1\u003c/sup\u003e)/(p\u003csub\u003e2\u003c/sub\u003e-1)) + ....\n\n1. Finding all the factors of a number, their count and sum as well\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    int ct = 0;   // count of divisors\n    int sum = 0;  // sum of divisors\n    /* 1. naive approach : O(N) method\n    for (int i = 1; i \u003c= n; i++) {\n        if (n % i == 0) cout \u003c\u003c i \u003c\u003c endl;\n    }\n    */\n\n    // 2. O(sqrt(n)) method\n    for (int i = 1; i * i \u003c= n; i++) {\n        if (n % i == 0) {\n            cout \u003c\u003c i \u003c\u003c \" \" \u003c\u003c n / i \u003c\u003c \"\\n\";\n            ct++;\n            sum += i;\n            if (n / i != i) {\n                ct++;\n                sum += n / i;\n            }\n        }\n    }\n    cout \u003c\u003c \"ct: \" \u003c\u003c ct \u003c\u003c \", sum: \" \u003c\u003c sum \u003c\u003c \"\\n\";\n\n\n    return 0;\n}\n```\n\n2. Checking if a number is prime or not\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    bool is_prime = true;\n    // 1. O(N) - naive approach\n    /* for (int i = 2; i \u003c n; i++) {\n        if (n == 1) {\n            is_prime = false;\n            break;\n        }\n        if (n % i == 0) {\n            is_prime = false;\n            break;\n        }\n    } */\n\n   //2. O(sqrt(N))\n    for (int i = 2; i * i \u003c= n; i++) {\n        if (n == 1) {\n            is_prime = false;\n            break;\n        }\n        if (n % i == 0) {\n            is_prime = false;\n            break;\n        }\n    }\n\n    cout \u003c\u003c is_prime \u003c\u003c \"\\n\";\n\n\n    return 0;\n}\n```\n\n3. Finding all the prime factors of a number\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    vector\u003cint\u003e prime_factors;\n    // 1. O(N) approach\n    /* for (int i = 2; i \u003c= n; i++) {\n        while (n % i == 0) {\n            prime_factors.push_back(i);\n            n /= i;\n        }\n    } */\n\n   // 2. O(sqrt(N)) approach\n    for (int i = 2; i * i \u003c= n; i++) {\n        while (n % i == 0) {\n            prime_factors.push_back(i);\n            n /= i;\n        }\n    }\n\n    if (n \u003e 1) { // the last prime number which would be left will be caught by this\n        prime_factors.push_back(n);\n    }\n\n    for (int prime : prime_factors) {\n        cout \u003c\u003c prime \u003c\u003c \" \";\n    }\n\n    return 0;\n}\n```\n\n### Sieve of Eratostheneses: Finding all the primes in a range\n\n- A form of `pre-computation` in a given range.\n\n```cpp\n// pre-compute all the numbers\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nconst int N = 1e7 + 10;\nvector\u003cbool\u003e isPrime(N, 1);\n\nint main() {\n    isPrime[0] = isPrime[1] = false;\n    // sieve algorithm -\u003e precompute all the primes in the given range\n    // O(NloglogN) -\u003e time complexity, smaller than O(logN)\n    for (int i = 2; i \u003c N; i++) {\n        if (isPrime[i] == true) {\n            for (int j = 2 * i; j \u003c N; j += i) {\n                isPrime[j] = false;\n            }\n        }\n    }\n\n    for (int i = 1; i \u003c 100; i++) {\n        cout \u003c\u003c i \u003c\u003c \": \" \u003c\u003c (isPrime[i] == true ? \"true\" : \"false\") \u003c\u003c \"\\n\";\n    }\n\n    return 0;\n}\n```\n\n## Bit Manipulation\n\n- Number of digits in a binary number = (int)(log\u003csub\u003e2\u003c/sub\u003e(N)) + 1.\n- `n \u0026 (-n) isolates the rightmost set bit of n. It doesn't give the position but rather a number where only the rightmost set bit of n is set.`\n\n  Example: let n = 10010, then (10010) \u0026 (01110) = 00010, here 01110 is the 2's complement(negative) of 10010.\n\n- `rightmost_unset_bit = (~n) \u0026 (n + 1). rightmost_unset_bit is a value that has only one bit set at the position of the rightmost unset bit in n.`\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nint setBit(int n) {\n    if (n == 0) return 1;\n\n    int rightmost_unset_bit = (~n) \u0026 (n + 1);\n    return n | rightmost_unset_bit;\n}\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    cout \u003c\u003c setBit(n);\n    return 0;\n}\n```\n\n- n \u0026 (n-1) clears the rightmost set bit.\n\n  Example: let n = 10010, then\n  (10010) \u0026 (10010-1) = (10010) \u0026 (10001) = 10000\n\n- (1 \u003c\u003c i) \u0026 n tells if the ith bit is set in a number or not. If 1-based indexing then (1\u003c\u003c(i-1)) \u0026 n would give the same result.\n\n- 1 \u003c\u003c i = 2\u003csup\u003ei\u003c/sup\u003e, it would overflow after the 31st bit, as the limit is 2\u003csup\u003e31\u003c/sup\u003e-1. Left shifting a number means multiplying by 2.\n\n- 1 \u003e\u003e i = 2\u003csup\u003e-i\u003c/sup\u003e. Right shifting a number means dividing by 2.\n\n- 1 ^ bit = flipped bit.\n\n  - 1 ^ 0 = 1\n  - 1 ^ 1 = 0\n\n- 1 \u0026 bit = bit.\n  - 1 \u0026 1 = 1\n  - 1 \u0026 0 = 0\n- 1 | bit = 1\n  - 1 | 1 = 1\n  - 1 | 0 = 1\n- 0 \u0026 bit = 0 \u0026rarr; This is used for masking unwanted bits and set them to 0.\n\n- Find sum of set bits upto a number N\n\n```cpp\n\nint countSetBits(int n) {\n    int count = 0;\n    for (int i = 0; (1 \u003c\u003c i) \u003c= n; ++i) {\n        int bitMask = (1 \u003c\u003c (i + 1)); // Size of full cycles\n        int completeCycles = n / bitMask; // Number of complete cycles\n        int remaining = n % bitMask; // Remaining numbers after full cycles\n\n        count += completeCycles * (bitMask / 2) + max(0, remaining - (bitMask / 2) + 1);\n    }\n    return count;\n}\n```\n\n- Dividing two integers using bit manipulation !!!IMPORTANT!!!\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nint divide(int dividend, int divisor) {\n    bool is_negative = (dividend \u003c 0) ^ (divisor \u003c 0);\n\n    if (divisor == -1) {\n        if (dividend == INT_MIN) return INT_MAX;\n        return -dividend;\n    }\n    if (dividend == 0)\n        return 0;\n    if (dividend == divisor)\n        return 1;\n    if (divisor == 1)\n        return dividend;\n\n    long long q = 0;\n    long long d1 = abs(divisor);  // divisor\n    long long d2 = abs(dividend); // dividend\n\n    // what we need to find is d2/d1\n\n    while (d2 \u003e= d1) {\n        long long temp = d1, multiple = 1;\n        while (d2 \u003e= (temp \u003c\u003c 1)) {\n            temp \u003c\u003c= 1;\n            multiple \u003c\u003c= 1;\n        }\n        d2 -= temp;\n        q += multiple;\n    }\n\n    if (is_negative) {\n        q = -q;\n    }\n\n    if (q \u003e INT_MAX) {\n        return INT_MAX;\n    }\n\n    if (q \u003c (INT_MIN)) {\n        return INT_MIN;\n    }\n\n    return q;\n}\n\nint main() {\n    int dividend, divisor;\n    cin \u003e\u003e dividend \u003e\u003e divisor;\n    cout \u003c\u003c divide(dividend, divisor);\n\n    return 0;\n}\n```\n\n- XOR from L To R, both inclusive, i.e., [L,R]\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nint xorUpto(int a) { // xor from 0 to a(both inclusive)\n    switch (a % 4) {\n    case 0: return a;\n    case 1: return 1;\n    case 2: return a + 1;\n    case 3: return 0;\n    }\n    return 0;\n}\n\nint xor_from_l_to_r(int l, int r) { // both inclusive\n    return xorUpto(l - 1) ^ xorUpto(r);\n}\n\n\nint main() {\n    int l, r;\n    cin \u003e\u003e l \u003e\u003e r;\n    cout \u003c\u003c xor_from_l_to_r(l, r);\n    return 0;\n}\n```\n\n## Binary Search(Works for sorted arrays, monotonic and predicate functions)\n\n0. Binary Search\n   - Time Complexity: O(log(n))\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nint main(){\n    int n, target;\n    cin \u003e\u003e n \u003e\u003e target;\n    int v[n];\n\n    int start =0, end = n-1;\n    while(start\u003c=end){\n        int mid = start + (end-start)/2;\n        if(v[mid]==target){\n           return mid;\n        }else if(v[mid]\u003ctarget){\n            start = mid+1;\n        }else{\n            end = mid-1;\n        }\n    }\n\n    return -1;\n}\n```\n\n### Monotonic functions\n\n- Functions which are either increasing or decreasing and NOT both.\n\n### Predicate Functions\n\n- Functions which return a `boolean` and change the nature once at a point.\n- Example:\n  - Suppose some function is in a given range x\u003csub\u003e1\u003c/sub\u003e to x\u003csub\u003e2\u003c/sub\u003e and suppose there's a point x\u003csub\u003e0\u003c/sub\u003e, in the range x\u003csub\u003e1\u003c/sub\u003e to x\u003csub\u003e2\u003c/sub\u003e, then if the function returns just `true` till x\u003csub\u003e0\u003c/sub\u003e and then returns `false` after it or vice-versa is called a predicate function.\n\n1. Floor of a number\n   - It's the largest number less than or equal to the given target.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    // works for sorted array ofc\n    int n, target;\n    cin \u003e\u003e n \u003e\u003e target;\n    int v[n];\n    for (int i = 0; i \u003c n; i++) {\n        cin \u003e\u003e v[i];\n    }\n\n    int start = 0, end = n - 1, f = -1;\n    while (start \u003c= end) {\n        int mid = start + (end - start) / 2;\n        if (v[mid] == target) {\n            f = mid;\n            break;\n        } else if (v[mid] \u003e target) {\n            end = mid - 1;\n        } else {\n            f = mid; // potential floor\n            start = mid + 1;\n        }\n    }\n    cout \u003c\u003c f \u003c\u003c (f == -1 ? -1 : v[f]) \u003c\u003c \"\\n\";\n\n    return 0;\n}\n```\n\n2. Ceil of a number\n   - It's the smallest number greater than or equal to the given target.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    // works for sorted array ofc\n    int n, target;\n    cin \u003e\u003e n \u003e\u003e target;\n    int v[n];\n    for (int i = 0; i \u003c n; i++) {\n        cin \u003e\u003e v[i];\n    }\n\n    int start = 0, end = -1, c = -1;\n    while (start \u003c= end) {\n        int mid = start + (end - start) / 2;\n        if (v[mid] == target) {\n            c = mid;\n            break;\n        } else if (v[mid] \u003c target) {\n            start = mid - 1;\n        } else {\n            c = mid; // potential ceil\n            end = mid - 1;\n        }\n    }\n\n    cout \u003c\u003c c \u003c\u003c \" \" \u003c\u003c (c == -1 ? -1 : v[c]);\n\n    return 0;\n}\n```\n\n3. Find the first and last occurence of a number\n   - To find the first occurrence always break the loop with `start = mid+1`.\n   - To find the last occurrence always break the loop with `end = mid-1`.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n// to get the last position break the loop with start=mid+1\n// to get the first position break the loop with end = mid-1\n\nvector\u003cint\u003e searchRange(vector\u003cint\u003e\u0026 nums, int target) {\n    vector\u003cint\u003e v(2, -1);\n    int n = nums.size();\n    int start = 0, end = n - 1;\n    int ans = -1;\n    // finds first occurence\n    while (start \u003c= end) {\n        int mid = start + (end - start) / 2;\n        if (nums[mid] == target) {\n            ans = mid;\n            start = mid + 1; // always break it with start=mid+1;\n        } else if (nums[mid] \u003e target) {\n            end = mid - 1;\n        } else {\n            start = mid + 1; // always break it with start=mid+1;\n        }\n    }\n    v[1] = ans;\n    start = 0;\n    end = n - 1;\n    ans = -1;\n\n    //finds last occurence\n    while (start \u003c= end) {\n        int mid = start + (end - start) / 2;\n        if (nums[mid] == target) {\n            ans = mid;\n            end = mid - 1; // always break it with end = mid-1;\n        } else if (nums[mid] \u003c target) {\n            start = mid + 1;\n        } else {\n            end = mid - 1; // always break it with end = mid-1;\n        }\n    }\n    v[0] = ans;\n    return v;\n}\n\nint main() {\n\n\n    return 0;\n}\n```\n\n### Advance Binary Search Problems/Binary Search on Answers\n\n- Here we will use the concept of predicate function and monotonic functions.\n- We create an `is_possible` predicate function which gives us a `bool` as an output till a certain point and reverses it's nature for the remaining range, i.e., `true` for a given range and then `false` for the remaining range or vice-versa.\n- `start = mid+1` or `end = mid-1` is set accordingly if we want to find the first `true` value or the first `false` value or the last `true` value or the last `false` value, depending on the question.\n\n0. Finding square root of a number\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nclass Solution {\nprivate:\n    bool is_possible(long long int x, long long int mid) {\n        return mid * mid \u003c= x;\n    }\n\npublic:\n    int mySqrt(int x) {\n        long long int ans = -1;\n        long long int start = 0;\n        long long int end = x;\n        while (start \u003c= end) {\n            long long int mid = start + (end - start) / 2;\n\n            if (is_possible(x, mid)) {\n                ans = mid;\n                start = mid + 1;\n            } else {\n                end = mid - 1;\n            }\n        }\n        return ans;\n    }\n};\n\nint main() {\n\n\n    return 0;\n}\n```\n\n1. [Koko Eating Bananas](https://leetcode.com/problems/koko-eating-bananas/)\n\n```cpp\nclass Solution {\nprivate:\n    bool is_possible(vector\u003cint\u003e\u0026 piles, int h, int mid) {\n        int n = piles.size();\n        for (int i = 0; i \u003c n; i++) {\n            if (mid \u003e= piles[i]) {\n                h--;\n            } else {\n                if (piles[i] % mid == 0) {\n                    h -= piles[i] / mid;\n                } else {\n                    h -= (piles[i] / mid) + 1;\n                }\n            }\n        }\n\n        return h\u003e=0;\n    }\n\npublic:\n    int minEatingSpeed(vector\u003cint\u003e\u0026 piles, int h) {\n        int start = 1;\n        int end = *max_element(piles.begin(), piles.end());\n        int ans = -1;\n        while(start\u003c=end){\n            int mid = start + (end-start)/2;\n\n            if(is_possible(piles, h, mid)){\n                ans = mid;\n                end = mid-1;\n            }else{\n                start = mid+1;\n            }\n        }\n\n        return ans;\n    }\n};\n```\n\n2. [Find the smallest divisor given a threshold](https://leetcode.com/problems/find-the-smallest-divisor-given-a-threshold/description/)\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nclass Solution {\nprivate:\n    bool is_possible(vector\u003cint\u003e\u0026 v, int threshold, int mid) {\n        long long int n = v.size();\n        long long int sum = 0;\n        for (int i = 0; i \u003c n; i++) {\n            if (v[i] % mid == 0) {\n                sum += v[i] / mid;\n            } else {\n                sum += v[i] / mid + 1;\n            }\n        }\n        if (sum \u003c= threshold) return true;\n        return false;\n    }\npublic:\n    int smallestDivisor(vector\u003cint\u003e\u0026 nums, int threshold) {\n        long long int start = 1;\n        long long int end = *max_element(nums.begin(), nums.end());\n        long long int ans = -1;\n\n        while (start \u003c= end) {\n            long long int mid = start + (end - start) / 2;\n\n            if (is_possible(nums, threshold, mid)) {\n                ans = mid;\n                end = mid - 1;\n            } else {\n                start = mid + 1;\n            }\n        }\n        return ans;\n    }\n};\n\nint main() {\n\n\n    return 0;\n}\n```\n\n3. [Kth Missing Positive Number](https://leetcode.com/problems/kth-missing-positive-number/)\n\n```cpp\n int findKthPositive(vector\u003cint\u003e\u0026 v, int k) {\n        int start = 0, end = v.size() - 1;\n\n        while (start \u003c= end) {\n            int mid = start + (end - start) / 2;\n            int missing = v[mid] - (mid + 1);\n\n            if (missing \u003c k) {\n                start = mid + 1;\n            } else {\n                end = mid - 1;\n            }\n        }\n        return start + k;\n    }\n```\n\n## Two Pointer and Sliding Window\n\n1. Whenever you get the problem of finding max/min substring think of two pointer and sliding window approach.\n2. These algos are more of a constructive approach and the only thing which remains constant is the window and it keeps moving across the string.\n3. How the window is moved, depends on the problem.\n\n- We start out with an empty window, i.e., `l and r` would be at the same position then we keep expanding the window until some condition is violated and at that point we simply move the window ahead, i.e., move `l` to a new position.\n\n- `l`: moves the window, `r` expands the window.\n\n### Examples:\n\n1. [Longest Substring Without Repeating Characters](https://leetcode.com/problems/longest-substring-without-repeating-characters/description/)\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    string s;\n    cin \u003e\u003e s;\n    int n = s.size();\n    vector\u003cint\u003em(256, -1); // hash array for 250 characters\n    int l = 0, r = 0;\n    int max_length = 0;\n    while (r \u003c n) {\n        int length = 0;\n\n        if (m[s[r]] != -1) { // check if the character is already in the hash array\n            if (m[s[r]] \u003e= l) { // check if that character is in our window\n                l = m[s[r]] + 1; // move the window if it is in the window\n\n            }\n        }\n        m[s[r]] = r; //re-assign new value to the position of that character\n        length = r - l + 1;\n        max_length = max(max_length, length);\n        r++;\n    }\n    cout \u003c\u003c \"max length: \" \u003c\u003c max_length;\n    return 0;\n}\n```\n\n## Recursion\n\n### When to apply recursion?\n\n- It breaks large problems into smaller ones, and once we devise a solution for the smaller one then it eventually adds upto the solution of large problems.\n- To explore all the possibilities \u0026rarr; use recursion.\n- To count the number of ways.\n- If there are multiple ways of doing something, then minimum or maximum number of ways are asked.\n\n- Try to write the function in its own terms.\n  For example : digit_sum(num)\n\n  - `digit_sum(num) = last_digit + digit_sum(num_with_its_last_digit_removed);`\n\n    Let's say, num = 1234.\n\n    digit_sum(1234) = 4 + digit_sum(123);\n\n    digit_sum(123) = 3 + digit_sum(12);\n\n    digit_sum(12) = 2 + digit_sum(1);\n\n    digit_sum(1) = 1 + digit_sum(0);\n\n    digit_sum(0) = 0; -\u003e base condition to terminate.\n\nHence, `digit_sum(num) = (num%10) + digit_sum(num/10)` -\u003e from the above pattern.\n\n### Example code :\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nint digit_sum(int num)\n{\n    if (num == 0)\n        return 0;\n    return (num % 10) + digit_sum(num / 10);\n}\n\nint main()\n{\n    int num;\n    cin \u003e\u003e num;\n    cout \u003c\u003c \"Hello world\";\n    cout \u003c\u003c num;\n    // this is the recursive part when you go down the tree\n    digit_sum(num);\n    // this is the part when you come back up in the tree\n    return 0;\n}\n```\n\n### Time Complexity of Recursion\n\n1. `Compute the total number of function calls.`\n2. `Compute the time complexity of each function.`\n\n- In the above example, for each digit the function call happens once, so the total number of function calls = number of digits(say, n). In each function call, the operations have O(1) time complexity as there's no loop, rather just a simple if statement and a function call.\n\n  Hence the total time complexity is given by : O(1 \\* n) = O(n)\n\n- If the number is taken to be 'n', then the number of digits will be: log(n) + 1. Then the time complexity will be : O(log(n) \\* 1) = O(log(n)).\n\n- Less significant terms and constants are ignored in the Big-O notation. (That's why O(log(n)) in the above example.)\n\n#### Backtracking in Recursion\n\n- Backtracking is simply used to maintain the state of recursion, i.e., for the same function when the recursion comes back up to it from the stack then the variables in the body/parameters need to be same.\n\n- For example, when we pass some string/array using reference then the actual string/array is being modified in each function call hence when the recursion comes back up in the tree to run some code below the call then the actual string/array for that function would have been modified which would result in unexpected behavior. So to reset it to the original state, i.e., to the state in which the recursion started for that string/array we revert the changes.\n\nThis preserves the actual state of the recursion and allows us to traverse through the recursive tree properly.\n\n- Maze traversal is the best example for this.\n\n- Or when we pass some array/string/variable(by reference) and we need to come back up in the function to perform some operation on it then we might need to use backtracking if the operations are needed to be performed on the previous version of the variable, i.e., the one with which the recursion was called.\n\n- `It's nothing different from recursion, just a fancy name.`\n\n## Some important pointers to remember while writing recursive functions\n\n- Variable number of recursive calls at a single level \u0026rarr; use `for loop` and put the recursion inside it.\n\n- Use the `void` return type to explore all the possibilities.\n\n- Return `1` or `0` if you want to count then add all the recursive calls and return them. Return `0` when the condition isn't satisified and if it's satisified return `1`.\n\n- Return `true` or `false` if you need to break the recursion after the condition is `once satisfied`. Return `true` for satisified conditions else return `false`.\n\n## Patterns In Recursion\n\n1. Unique Elements in an array: Use the `take/not-take technique`, no `for loop` will be required and terminate the recursion using the base case/termination conditions yourself.\n\n   - Entirely Based on `take/not-take` technique: [Generate all binary strings](#generate-all-binary-strings)\n   - [Taking the same element unlimited number of times](#combination-sum-taking-the-same-element-multiple-times)\n   - [Taking an element only once](#combination-sum-variation-taking-an-element-just-once)\n\n2. Duplicate Elements in an array: Sort the array first, use the `for loop` and inside it put the recursion, `for loop` will automatically do the `take/not-take` and will implicitly terminate(when `for loop` condition will eventually be unsatisfied), so we don't necessarily need a base case to terminate the recursion for preventing stack overflow because of infinite loop condition, rather terminate it when the conditions are satisfied.\n\n   - [Taking the element only once and skipping the duplicates](#combination-sum-ii-taking-an-element-just-once)\n   - Take an element unlimited number of times then simply remove the duplicate ones and solve it like [Combination Sum I](#combination-sum-taking-the-same-element-multiple-times)\n\n3. Permutations: We use the for loop method because of the variable number of choices to start with and put the recursion inside the for loop which eventually picks up the elements provided the same element hasn't been picked already. If there are duplicate elements use the way taught in [Combination Sum II](#combination-sum-ii-taking-an-element-just-once) and add the `f[i-1]==0` along with it.\n\n### [Generate all binary strings](https://www.geeksforgeeks.org/problems/generate-all-binary-strings/0)\n\n```cpp\nclass Solution{\nprivate:\n    void fn(int n, int i, string \u0026ds, vector\u003cstring\u003e\u0026ans){\n        if(i==n){\n            ans.push_back(ds);\n            return;\n        }\n\n        if(i\u003e0 \u0026\u0026 ds[i-1]=='0'){\n            // take '0'\n            ds.push_back('0');\n            fn(n, i+1, ds, ans);\n            ds.pop_back();\n\n            // not take '0', i.e., take '1'\n            ds.push_back('1');\n            fn(n, i+1, ds, ans);\n            ds.pop_back();\n\n        }else if(i\u003e0 \u0026\u0026 ds[i-1]=='1'){\n            // cannot take '1' due to constraints\n            ds.push_back('0');\n            fn(n, i+1, ds, ans);\n            ds.pop_back();\n        }\n    }\npublic:\n    vector\u003cstring\u003e generateBinaryStrings(int num){\n        vector\u003cstring\u003e ans;\n        string ds;\n\n        // take '0'\n        ds.push_back('0');\n        fn(num, 1, ds, ans);\n        ds.pop_back();\n\n        // not take '0', i.e., take '1'\n        ds.push_back('1');\n        fn(num, 1, ds, ans);\n        ds.pop_back();\n\n\n\n        return ans;\n    }\n};\n```\n\n### [Combination Sum: Taking the same element multiple times](https://leetcode.com/problems/combination-sum/)\n\n- Remember this pattern that when we have to pick elements from an array which consists of unique elements then we use the `pick/not-pick` method without the `for loop`!\n\n```cpp\nclass Solution {\nprivate:\n    void solve(vector\u003cint\u003e\u0026 candidates, int target, vector\u003cvector\u003cint\u003e\u003e\u0026 ans,\n               vector\u003cint\u003e\u0026 current, int n, int i) {\n        if (i \u003e= n) {\n            if (target == 0) {\n                ans.push_back(current);\n            }\n            return;\n        }\n\n        // take\n        if (target \u003e 0) { // important line\n            current.push_back(candidates[i]);\n            solve(candidates, target - candidates[i], ans, current, n, i);\n            current.pop_back();\n        }\n\n        // not take\n        solve(candidates, target, ans, current, n, i + 1);\n    }\n\npublic:\n    vector\u003cvector\u003cint\u003e\u003e combinationSum(vector\u003cint\u003e\u0026 candidates, int target) {\n        vector\u003cvector\u003cint\u003e\u003e ans;\n        vector\u003cint\u003e current;\n        int n = candidates.size();\n        solve(candidates, target, ans, current, n, 0);\n        return ans;\n    }\n};\n```\n\n- In the above question we stop when the target becomes negative, i.e, we can take the elements as many times as we want but if the target becomes negative we stop because then no combination of it would sum upto the target.\n\n### Combination Sum Variation: Taking an element just once\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\nvoid solve(vector\u003cint\u003e\u0026 candidates, int target, vector\u003cvector\u003cint\u003e\u003e\u0026 ans,\n               vector\u003cint\u003e\u0026 current, int n, int i) {\n        if (i \u003e= n) {\n            if (target == 0) {\n                ans.push_back(current);\n            }\n            return;\n        }\n\n        // take\n        if (target \u003e 0) { // important line\n            current.push_back(candidates[i]);\n            solve(candidates, target - candidates[i], ans, current, n, i+1);\n            current.pop_back();\n        }\n\n        // not take\n        solve(candidates, target, ans, current, n, i + 1);\n    }\n\nint main(){\n    int n, target;\n    cin \u003e\u003e n \u003e\u003e target;\n    vector\u003cint\u003e ds;\n    vector\u003cint\u003e candidates(n);\n    for(int i=0; i\u003cn; i++){\n        cin \u003e\u003e candidates[i];\n    }\n    vector\u003c\u003cvector\u003cint\u003e\u003e ans;\n    solve(candidates, target, ans, ds, n, 0);\n    return 0;\n}\n```\n\n- Example: [Combination Sum III](https://leetcode.com/problems/combination-sum-iii/)\n\n```cpp\nclass Solution {\nprivate:\n    void fn(vector\u003cint\u003e\u0026v, int target, int k,int i, vector\u003cint\u003e\u0026ds, vector\u003cvector\u003cint\u003e\u003e\u0026ans){\n        if(target\u003c0) return;\n        // no need of  the above condition, because if the target even becomes negative then also recursion will eventually stop as we are not taking the same element multiple times hence the third condition of if(i\u003e=v.size()) will save us eventually unlike Combination Sum I.\n\n        if(ds.size()==k){\n            if(target==0){\n                ans.push_back(ds);\n            }\n            return;\n        }\n\n        if(i\u003e=v.size()) return;\n\n        ds.push_back(v[i]);\n        target-=v[i];\n        fn(v, target, k, i+1, ds, ans);\n        target+=v[i];\n        ds.pop_back();\n\n        fn(v, target, k, i+1, ds, ans);\n    }\npublic:\n    vector\u003cvector\u003cint\u003e\u003e combinationSum3(int k, int n) {\n        vector\u003cint\u003e v;\n        vector\u003cint\u003e ds;\n        vector\u003cvector\u003cint\u003e\u003e ans;\n        for(int i=0; i\u003c9; i++){\n            v.push_back(i+1);\n        }\n        fn(v, n, k, 0, ds, ans);\n        return ans;\n    }\n};\n```\n\n### [Combination sum II: Taking an element just once!](https://leetcode.com/problems/combination-sum-ii/description/)\n\n- First sort the original array.\n\n- Remember this pattern, where when we have to choose `non-duplicate` elements from an array having duplicate elements ofcourse, then we use `for loop` along with the `pick/not-pick` technique and put the recursion inside it, as done below.\n\n- `No explicit base condition`(like ind\u003e=n) because the `for loop` does it implicitly anyway.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvoid f(int ind, int target, int\u0026 n, vector\u003cint\u003e\u0026 ds,\n    vector\u003cvector\u003cint\u003e\u003e\u0026 ans, vector\u003cint\u003e\u0026 v) {\n    if (target == 0) {\n        ans.push_back(ds);\n        return;\n    }\n\n    // recursion inside the for loop and we moved ahead as we can't pick the same element unlimited number of times\n    for (int i = ind; i \u003c n; i++) {\n        if (i \u003e ind \u0026\u0026 v[i] == v[i - 1])\n            continue;\n        if (v[i] \u003e target)\n            break;\n        ds.push_back(v[i]);\n        f(i + 1, target - v[i], n, ds, ans, v);\n        ds.pop_back();\n    }\n}\n\n\nint main() {\n    int n, target;\n    cin \u003e\u003e n, target;\n\n    vector\u003cint\u003e v;\n    vector\u003cvector\u003cint\u003e\u003e ans;\n    vector\u003cint\u003e current;\n\n    for (int i = 0; i \u003c n; i++) {\n        cin \u003e\u003e v[i];\n    }\n\n    sort(v.begin(), v.end()); // sort the original array\n\n    f(0, target, n, current, ans, v);\n\n    return 0;\n}\n```\n\n- We stop when the target becomes 0, that means we got the answer and we either store it or print it. To check for the duplicate elements we resort back to the for loop and `if(i\u003eind \u0026\u0026 v[i]==v[i-1])` we skip that iteration, if the target becomes negative/ `v[i]\u003etarget` we can `break/return` the/from the loop.\n\n### [Subsets I: Printing the subsets of an array with unique elements](https://leetcode.com/problems/subsets/description/)\n\n- Similar to Combination Sum I\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvoid f(int ind, int sum, int n, vector\u003cint\u003e\u0026 v, vector\u003cint\u003e\u0026 current) {\n    if (ind \u003e= n) {\n        if (current.size() == 0) cout \u003c\u003c \"{}\";\n        for (auto\u0026 it : current) {\n            cout \u003c\u003c it \u003c\u003c \" \";\n        }\n        cout \u003c\u003c \"\\n\" \u003c\u003c \"sum: \" \u003c\u003c sum \u003c\u003c \"\\n \\n\";\n        return;\n    }\n\n    current.push_back(v[ind]);\n    f(ind + 1, sum + v[ind], n, v, current);\n    current.pop_back();\n\n    f(ind + 1, sum, n, v, current);\n}\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n\n    vector\u003cint\u003e v(n);\n    vector\u003cint\u003e current;\n    for (int i = 0; i \u003c n; i++) {\n        cin \u003e\u003e v[i];\n    }\n\n    f(0, 0, n, v, current);\n\n    return 0;\n}\n```\n\n### [Subsets II: Ignoring the dupilcates and printing all the subsets](https://leetcode.com/problems/subsets-ii/description/)\n\n- Similar to Combination Sum II\n\n- Here we don't need fully formed subsets till `n` rather we want all the unique subsets, that's why `no explicit base condition` because the `for loop` does it implicitly anyway.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvoid f(int ind, int n, vector\u003cint\u003e\u0026 v, vector\u003cint\u003e\u0026 current) {\n    // Include the current subset in the output immediately\n    for (auto\u0026 it : current) {\n        cout \u003c\u003c it \u003c\u003c \" \";\n    }\n    cout \u003c\u003c \"\\n\";\n\n    // Explore further elements starting from the current index\n    for (int i = ind; i \u003c n; i++) {\n        if (i \u003e ind \u0026\u0026 v[i] == v[i - 1]) {\n            continue;  // Skip duplicates\n        }\n        current.push_back(v[i]);\n        f(i + 1, n, v, current);\n        current.pop_back();\n    }\n}\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n\n    vector\u003cint\u003e v(n);\n    vector\u003cint\u003e current;\n    for (int i = 0; i \u003c n; i++) {\n        cin \u003e\u003e v[i];\n    }\n    sort(v.begin(), v.end());  // Sort to handle duplicates\n    f(0, n, v, current);\n\n    return 0;\n}\n\n```\n\n### [Permutations I: Array has unique elements](https://leetcode.com/problems/permutations/description/)\n\n- Approach 1\n  - We go until we have all the elements in the data structure.\n  - Remember this pattern and there's for loop and inside it the recursion because of variable number of function calls at each step.\n  - `i=0` in each case because again for every element previous elements need to be considered.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvoid f(int ind, int n, vector\u003cint\u003e\u0026 v, int freq[], vector\u003cint\u003e\u0026 ds) {\n    if (ds.size() == n) { // we will go till we have all the three elements\n        for (auto\u0026 i : ds) {\n            cout \u003c\u003c i \u003c\u003c \" \";\n        }\n        cout \u003c\u003c endl;\n        return;\n    }\n\n    for (int i = 0; i \u003c n; i++) { // for each element I have to check from i=0 only\n    // like in case of [1,2,3] if we take 2 first then [2, 1, 3] is also possible, hence we need i=0.\n        if (!freq[i]) {\n            freq[i] = 1;\n            ds.push_back(v[i]);\n            f(i + 1, n, v, freq, ds);\n            ds.pop_back();\n            freq[i] = 0;\n        }\n    }\n\n\n}\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n\n    vector\u003cint\u003e v(n);\n    vector\u003cint\u003e current;\n    for (int i = 0; i \u003c n; i++) {\n        cin \u003e\u003e v[i];\n    }\n\n    int freq[n] = { 0 };\n    f(0, n, v, freq, current);\n\n    return 0;\n}\n\n```\n\n### [Permutations II: Skipping the duplicate elements](https://leetcode.com/problems/permutations-ii/description/)\n\n- We skip it just like we did it in Subets II and Combination Sum II.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvoid permutations(int j, vector\u003cint\u003e\u0026 v, vector\u003cint\u003e\u0026 ds, int f[]) {\n    if (ds.size() == v.size()) {\n        for (auto\u0026\u0026 it : ds) {\n            cout \u003c\u003c it \u003c\u003c \" \";\n        }\n        cout \u003c\u003c \"\\n\";\n    }\n\n    for (int i = 0; i \u003c v.size(); i++) {\n        if (i \u003e 0 \u0026\u0026 v[i] == v[i - 1] \u0026\u0026 f[i - 1] == 0) {\n            continue;\n        }\n        if (f[i] != 1) {\n            f[i] = 1;\n            ds.push_back(v[i]);\n            permutations(i + 1, v, ds, f);\n            ds.pop_back();\n            f[i] = 0;\n        }\n    }\n\n}\n\n\nint main() {\n    vector\u003cint\u003e v = { 1,2,2 };\n    vector\u003cint\u003e ds;\n    int f[v.size()] = { 0 };\n    permutations(0, v, ds, f);\n    return 0;\n}\n```\n\n## Some Miscellaneous Questions\n\n0. [Reverse a stack using recursion](https://www.geeksforgeeks.org/problems/reverse-a-stack/1)\n\n- Note: Using IBH technique taught by Aditya Verma THE MAN\n- Recursive function wo kaam kar dega tum toh ye socho ki kaise sambhaloge use.\n\n```cpp\nclass Solution{\nprivate:\n    void insert_at_bottom(stack\u003cint\u003e \u0026st, int el){\n            if(st.empty()){\n                st.push(el);\n                return;\n            }\n\n            int top = st.top();\n            st.pop();\n            insert_at_bottom(st, el); // le daal diya bottom pe\n            st.push(top); // hai himmat? hai himmat sambhaalne ki?\n    }\n\n    void reverse(stack\u003cint\u003e \u0026st){\n        if(st.empty()){\n            return;\n        }\n\n        int top = st.top();\n        st.pop();\n        reverse(st); // kam kar diya\n        insert_at_bottom(st, top); // sambhaal bsdk\n    }\npublic:\n    void Reverse(stack\u003cint\u003e \u0026st){\n        reverse(st);\n    }\n};\n```\n\n0.1. [Count Good Numbers](https://leetcode.com/problems/count-good-numbers/)\n\n- Focus on how modulo is being handled in this question, baaki toh maths hai 11th ki(PnC).\n\n```cpp\nint m = (1e9+7);\n\nclass Solution {\nprivate:\n    int power(long long int a, long long b){\n        if(a==1) return 1; // agar base hi 1 hai toh execute hi mat karo aage\n\n        if(b==0){\n            return 1; // kisi ki power zero toh 1\n        }\n\n        int temp = power(a, b/2)%m;\n        if(b%2==0){\n            return (1LL*temp*temp)%m;\n        }\n\n       return (1LL*a*temp*temp)%m;\n    }\npublic:\n    int countGoodNumbers(long long n) {\n        long long int even = ceil(n/2.0);\n        long long int odd = n/2;\n        return ((1LL * power(5, even))%m * (1LL * power(4, odd))%m)%m;\n    }\n};\n```\n\n1. [Letter Combinations of a Phone Number](https://leetcode.com/problems/letter-combinations-of-a-phone-number/description/)\n\n- Since there are multiple/variable(depending on the size of vector) recursive calls hence we need to use a `for loop` and put the recursion inside it.\n\n```cpp\nclass Solution {\nprivate:\n    void fn(string \u0026s, int i, string \u0026ds, vector\u003cstring\u003e\u0026ans, unordered_map\u003cint, vector\u003cchar\u003e\u003e \u0026m){\n        if(i\u003e=s.size()){\n            ans.push_back(ds);\n            return;\n        }\n\n        int digit = s[i] - '0';\n\n        for(int j=0; j\u003cm[digit].size(); j++){\n            ds.push_back(m[digit][j]);\n            fn(s, i+1, ds, ans, m);\n            ds.pop_back();\n        }\n    }\n\npublic:\n    vector\u003cstring\u003e letterCombinations(string \u0026s) {\n        if(s.size()==0) return {};\n        unordered_map\u003cint, vector\u003cchar\u003e\u003e m;\n        m[2] = {'a', 'b', 'c'};\n        m[3] = {'d', 'e', 'f'};\n        m[4] = {'g', 'h', 'i'};\n        m[5] = {'j', 'k', 'l'};\n        m[6] = {'m', 'n', 'o'};\n        m[7] = {'p', 'q', 'r', 's'};\n        m[8] = {'t', 'u', 'v'};\n        m[9] = {'w', 'x', 'y', 'z'};\n\n        vector\u003cstring\u003e ans;\n        string ds;\n        fn(s, 0, ds, ans, m);\n\n        return ans;\n    }\n};\n```\n\n- `unordered_map` has been used to reduce Time Complexity to O(1) on an average.\n\n- Extract the digit, get the vector using the map and simply push it into the `ds` string to get the combinations and since `ds` has been passed on using reference hence backtrack to maintain recursive state.\n\n2. [Nim Game](https://leetcode.com/problems/nim-game/description/)\n\n- To win, the other has to lose in every scenario.\n\n```cpp\nclass Solution {\nprivate:\n    bool fn(int n, int me){\n         if (n == 1 || n == 2 || n == 3)\n            return me;\n        if (me) {\n            return fn(n - 1, !me) || fn(n - 2, !me) || fn(n - 3, !me);\n        } else { // important\n            return fn(n - 1, !me) \u0026\u0026 fn(n - 2, !me) \u0026\u0026 fn(n - 3, !me);\n        }\n    }\npublic:\n    bool canWinNim(int n) {\n        // bool me = true;\n        // return fn(n, me);\n        return n % 4 != 0;\n    }\n};\n```\n\n## Graphs : Contd. after the Java notes, but in C++\n\n### What is a graph?\n\n- Collection of nodes/vertices and/or edges.\n- Generally in questions, N : Number of vertices and M: Number of edges.\n- And in M lines we are given the edges between nodes(will make more sense in the graph representation section).\n\nExample:\n\n        6 9 -\u003e N = 6, M = 9\n        In rest of the M lines, we are given the configuration of nodes\n        1 3\n        1 5\n        3 5\n        3 4\n        3 6\n        3 2\n        2 6\n        4 6\n        5 6\n\n### Types of graph\n\n1. Undirected : no arrows to a node, i.e., no bi-directional edge.\n2. Directed : edges have arrows, and graphs can be traversed in a specific direction.\n3. Acyclic : graphs with no cycles.\n4. Cyclic : graphs with cycles.\n\n### What are trees?\n\n- Graphs with no cycles. Acyclic undirected graphs are called trees as well.\n- Number of edges(m) = Number of nodes(n) - 1.\n- Root node: Could be any node, we consider rest of the tree hanging from it.\n- Leaf node: Nodes without any children.\n- Depth of a node: Distance of a node from the root node.\n- Height of a node: Max number of edges starting from any leaf node to that node.\n- LCA: The first common node of 2 or more nodes is called lowest common ancestor.\n\n### What are connected components? (Related to graphs)\n\n- For undirected graph:\n  - If from one node, every other node in that component can be traversed, then it's connected component.\n  - Sometimes, multiple connected components together are called a forest, its a graph too but with multiple connected components.\n  - Number of connected Components : The nummber of time DFS runs.\n- For directed graph: Could be cyclic or acyclic depending on the direction\n  - We define strongly connected components here, instead of just connected components.\n  - Strongly connected component : It should be possible to reach at every node from the starting node.\n\n### Graph Representation\n\n- Input:\n\n        6 9\n        1 3\n        1 5\n        3 5\n        3 4\n        3 6\n        3 2\n        2 6\n        4 6\n        5 6\n\n1. Adjacency Matrix\n2. Adjacency List \u0026rarr; mostly used because of less space complexity\n\n   1. Adjacency Matrix\n\n   - Make a matrix of n\\*n(n = number of vertices, m = number of edges).\n   - If 1-based graph then make (n+1)\\*(n+1).\n   - a[i][j] = 1 \u0026\u0026 a[j][i] = 1, if i and j are connected, else it's 0 \u0026rarr; for undirected graph.\n   - a[i][j] = 1, if i and j are connected for directed ones(depending on the direction)\n   - if edges have weights, a[i][j] = w \u0026rarr; w is the weight.\n   - Can get and edge and weight between edges in O(1)\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    int n, m;\n    cin \u003e\u003e n \u003e\u003e m;\n    // adjacency matrix -\u003e too much space complexity(O(N^2))\n    vector\u003cvector\u003cint\u003e\u003egraph(n + 1, vector\u003cint\u003e(n + 1, 0)); // initialized a 2D vector\n    for (int i = 0; i \u003c m; i++) {\n        int v1, v2;\n        cin \u003e\u003e v1 \u003e\u003e v2;\n        graph[v1][v2] = 1;\n        graph[v2][v1] = 1;\n    }\n    for (int i = 1; i \u003c= n; i++) {\n        for (int j = 1; j \u003c= n; j++) {\n            cout \u003c\u003c graph[i][j] \u003c\u003c \" \";\n        }\n        cout \u003c\u003c \"\\n\";\n    }\n    return 0;\n}\n```\n\n- Output of adjacency matrix:\n\n        0 0 1 0 1 0\n        0 0 1 0 0 1\n        1 1 0 1 1 1\n        0 0 1 0 0 1\n        1 0 1 0 0 1\n        0 1 1 1 1 0\n\n  2. Adjacency List\n\n  - Make number of lists(arrays/vectors) = number of nodes(+1 if 1-based).\n  - In each list store, the nod with which it is connected.\n  - Space Complexity = O(V+2E) ~ O(V+E)\n  - To find weight and edge, we need to run a loop, in O(N).\n\n1. Unweighted graph\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    int n, m;\n    cin \u003e\u003e n \u003e\u003e m;\n    // adjacency list : O(V+E)\n    vector\u003cvector\u003cint\u003e\u003e graph(n + 1);\n    for (int i = 0; i \u003c m; i++) {\n        int v1, v2;\n        cin \u003e\u003e v1 \u003e\u003e v2;\n        graph[v1].push_back(v2);\n        graph[v2].push_back(v1);\n    }\n\n    // N = 10^5, M\u003c= 10^7\n\n    for (const auto\u0026 row : graph) {\n        for (const auto\u0026 el : row) {\n            cout \u003c\u003c el \u003c\u003c \" \";\n        }\n        cout \u003c\u003c \"\\n\";\n    }\n\n    return 0;\n}\n```\n\n2. Weighted Graph\n\n- Input: last elements are the weights\n\n        6 9\n        1 3 4\n        1 5 3\n        3 5 2\n        3 4 7\n        3 6 8\n        3 2 9\n        2 6 1\n        4 6 2\n        5 6 3\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nint main() {\n    int n, m;\n    cin \u003e\u003e n \u003e\u003e m;\n    // adjacency list : O(V+E)\n    vector\u003cvector\u003cpair\u003cint, int\u003e\u003e\u003e graph(n + 1);\n    for (int i = 0; i \u003c m; i++) {\n        int v1, v2, wt;\n        cin \u003e\u003e v1 \u003e\u003e v2 \u003e\u003e wt;\n        graph[v1].push_back({ v2, wt });\n        graph[v2].push_back({ v1, wt });\n    }\n\n    // N = 10^5, M\u003c= 10^7\n\n    for (const auto\u0026 row : graph) {\n        for (const auto\u0026 el : row) {\n            cout \u003c\u003c \"{node: \" \u003c\u003c el.first \u003c\u003c \" wt:\" \u003c\u003c el.second \u003c\u003c \"}, \";\n        }\n        cout \u003c\u003c \"\\n\";\n    }\n\n    return 0;\n}\n```\n\n- Output:\n\n        {node: 3 wt:4}, {node: 5 wt:3},\n        {node: 3 wt:9}, {node: 6 wt:1},\n        {node: 1 wt:4}, {node: 5 wt:2}, {node: 4 wt:7}, {node: 6 wt:8},{node: 2 wt:9},\n        {node: 3 wt:7}, {node: 6 wt:2},\n        {node: 1 wt:3}, {node: 3 wt:2}, {node: 6 wt:3},\n        {node: 3 wt:8}, {node: 2 wt:1}, {node: 4 wt:2}, {node: 5 wt:3},\n\n### Significance of Visited Array\n\n- Helps us in traversing each and every node of a forest/graph.\n- Prevents infinite loops by making the node be visited only once.\n- `Length of visited array = Length of adjacency list = Length of Adjacency Matrix = Number of nodes(if 0-based indexed graph) or Number of nodes+1(if 1-based indexed graph)`\n\n### Depth First Search(DFS)\n\n- `Goes in-depth of the graph/tree and visits/explores every node.`\n- `We do come back to the node from which we started.`\n- `Even if a node has been visited by some other node already, but it would be checked out by the parent node again, i.e., suppose 3 was visited by 2 already, but if 3 is a child of 1, it will atleast be checked out by 1 and then it'll do nothing as it will be visited already.`\n- Uses recursion.\n- Used to find the number of connected components in a graph.\n- Used to find cycles in a graph.\n- Time Complexity: O((Number of vertices) + 2\\*(Number Of Edges)) ~ O(N+M)\n- Code: Do remember the four areas and their significance in the code\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nvoid dfs(int vertex, vector\u003cint\u003e g[], vector\u003cbool\u003e\u0026 vis) {\n    // take action on vertex after entering the vertex\n    vis[vertex] = true;\n    cout \u003c\u003c vertex \u003c\u003c \"\\n\";\n    for (int child : g[vertex]) {\n        // take action on child before entering the child node(haven't called dfs yet)\n        cout \u003c\u003c \"par: \" \u003c\u003c vertex \u003c\u003c \", child: \" \u003c\u003c child \u003c\u003c \"\\n\";\n        if (vis[child]) continue;\n        dfs(child, g, vis);\n        // take action on child after exiting the child node(called dfs on child)\n    }\n    // take action on vertex before exiting the vertex\n}\n\n\n\nint main() {\n    int n, m;\n    cin \u003e\u003e n \u003e\u003e m;\n    vector\u003cint\u003e g[n + 1];\n    vector\u003cbool\u003evis(n + 1, false);\n    for (int i = 0; i \u003c m; i++) {\n        int v1, v2;\n        cin \u003e\u003e v1 \u003e\u003e v2;\n        g[v1].push_back(v2);\n        g[v2].push_back(v1);\n    }\n\n    for (int i = 0; i \u003c n + 1; i++) {\n        if (vis[i]) continue;\n        dfs(i, g, vis);\n    }\n\n    return 0;\n}\n```\n\n- Output:\n\n        1\n        par: 1, child: 3\n        3\n        par: 3, child: 1\n        par: 3, child: 5\n        5\n        par: 5, child: 1\n        par: 5, child: 3\n        par: 5, child: 6\n        6\n        par: 6, child: 3\n        par: 6, child: 2\n        2\n        par: 2, child: 3\n        par: 2, child: 6\n        par: 6, child: 4\n        4\n        par: 4, child: 3\n        par: 4, child: 6\n        par: 6, child: 5\n        par: 3, child: 4\n        par: 3, child: 6\n        par: 3, child: 2\n        par: 1, child: 5\n\n#### Finding Number of Connected Components using DFS\n\n- Input:\n\n        8 5\n        1 2\n        2 3\n        2 4\n        3 5\n        6 7\n\n- Output : 3\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nvoid dfs(int vertex, vector\u003cint\u003e g[], vector\u003cbool\u003e\u0026 vis) {\n    // take action on vertex after entering the vertex\n    vis[vertex] = true;\n    for (int child : g[vertex]) {\n        // take action on child before entering the child node(haven't called dfs yet)\n        if (vis[child]) continue;\n        dfs(child, g, vis);\n        // take action on child after exiting the child node(called dfs on child)\n    }\n    // take action on vertex before exiting the vertex\n}\n\n\n\nint main() {\n    int n, m;\n    cin \u003e\u003e n \u003e\u003e m;\n    vector\u003cint\u003e g[n + 1];\n    vector\u003cbool\u003evis(n + 1, false);\n    for (int i = 0; i \u003c m; i++) {\n        int v1, v2;\n        cin \u003e\u003e v1 \u003e\u003e v2;\n        g[v1].push_back(v2);\n        g[v2].push_back(v1);\n    }\n    int count = 0;\n    for (int i = 1; i \u003c n + 1; i++) {\n        if (vis[i]) continue;\n        count++;\n        dfs(i, g, vis);\n    }\n\n    cout \u003c\u003c count \u003c\u003c \"\\n\";\n\n    return 0;\n}\n```\n\n### Storing the connected components\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nvoid dfs(int vertex, vector\u003cint\u003e g[], vector\u003cbool\u003e\u0026 vis, vector\u003cint\u003e\u0026 ccc) {\n    // take action on vertex after entering the vertex\n    vis[vertex] = true;\n    ccc.push_back(vertex);\n    for (int child : g[vertex]) {\n        // take action on child before entering the child node(haven't called dfs yet)\n        if (vis[child]) continue;\n        dfs(child, g, vis, ccc);\n        // take action on child after exiting the child node(called dfs on child)\n    }\n    // take action on vertex before exiting the vertex\n}\n\n\n\nint main() {\n    int n, m;\n    cin \u003e\u003e n \u003e\u003e m;\n    vector\u003cint\u003e g[n + 1];\n    vector\u003cbool\u003evis(n + 1, false);\n    vector\u003cvector\u003cint\u003e\u003e cc;\n    for (int i = 0; i \u003c m; i++) {\n        int v1, v2;\n        cin \u003e\u003e v1 \u003e\u003e v2;\n        g[v1].push_back(v2);\n        g[v2].push_back(v1);\n    }\n    int count = 0;\n    for (int i = 1; i \u003c n + 1; i++) {\n        if (vis[i]) continue;\n        vector\u003cint\u003e ccc; // initialize a new current connected component vector\n        count++;\n        dfs(i, g, vis, ccc);\n        cc.push_back(ccc); // push it back after the dfs completes for each connected component\n    }\n\n    for (auto\u0026 row : cc) {\n        for (auto\u0026 el : row) {\n            cout \u003c\u003c el \u003c\u003c \" \";\n        }\n        cout \u003c\u003c \"\\n\";\n    }\n\n    return 0;\n}\n```\n\n- Output:\n  1 2 3 5 4\n  6 7\n  8\n\n### Detecting cycles using DFS\n\n- If there's a cycle, we reach a node which is already visited but it is not the parent node from which we came from.\n\n```cpp\n// Cycle detection\n/*\nIf there's a cycle, we reach a node which is already visited but it is not the\nparent node from which we came from.\n*/\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nbool dfs(int v, int par, vector\u003cint\u003eg[], vector\u003cbool\u003e\u0026 vis) {\n    vis[v] = true;\n    bool does_loop_exist = false;\n    for (int child : g[v]) {\n        if (vis[child] \u0026\u0026 child == par) continue;\n        if (vis[child]) {\n            return true;\n        };\n        does_loop_exist |= dfs(child, v, g, vis);\n    }\n    return does_loop_exist;\n}\n\n\nint main() {\n    int n, m;\n    cin \u003e\u003e n \u003e\u003e m;\n    vector\u003cint\u003eg[n + 1];\n    for (int i = 0; i \u003c m; i++) {\n        int v1, v2;\n        cin \u003e\u003e v1 \u003e\u003e v2;\n        g[v1].push_back(v2);\n        g[v2].push_back(v1);\n    }\n\n    vector\u003cbool\u003evis(n + 1, false);\n    for (int i = 0; i \u003c vis.size(); i++) {\n        if (vis[i]) continue;\n        if (dfs(i, 0, g, vis)) {\n            cout \u003c\u003c \"true\" \u003c\u003c \"\\n\";\n            return 0;\n        };\n    }\n\n    cout \u003c\u003c \"false\" \u003c\u003c \"\\n\";\n\n    return 0;\n}\n```\n\n### Graph Matrix Problems: [Flood Fill Problem](https://leetcode.com/problems/flood-fill/description/)\n\n- Assume all 1's to be the nodes of a graph and that way we'll have components.\n- DFS needs to be done in either 4 directions or 8(including diagonals).\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvoid dfs(int i, int j, int initialColor, int newColor, vector\u003cvector\u003cint\u003e\u003e\u0026 image) {\n    int n = image.size();\n    int m = image[0].size();\n    if (i \u003c 0 || j \u003c 0) return;\n    if (i \u003e= n || j \u003e= m) return;\n    if (image[i][j] != initialColor) return;\n\n    image[i][j] = newColor;\n\n    dfs(i - 1, j, initialColor, newColor, image);\n    dfs(i + 1, j, initialColor, newColor, image);\n    dfs(i, j - 1, initialColor, newColor, image);\n    dfs(i, j + 1, initialColor, newColor, image);\n}\n\n\nvector\u003cvector\u003cint\u003e\u003e floodFill(vector\u003cvector\u003cint\u003e\u003e\u0026 image, int sr, int sc, int newColor) {\n    int initialColor = image[sr][sc];\n    if (initialColor != newColor)\n        dfs(sr, sc, initialColor, newColor, image);\n    return image;\n}\n\n\nint main() {\n    // Flood fill\n\n\n    return 0;\n}\n```\n\n### [Number of Islands](https://leetcode.com/problems/number-of-islands/)\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nclass Solution {\nprivate:\n    void dfs(int i,int j,  vector\u003cvector\u003cchar\u003e\u003e\u0026g, vector\u003cvector\u003cbool\u003e\u003e\u0026vis){\n        if(i\u003c0 || j\u003c0 || i\u003e= g.size() || j\u003e= g[0].size()|| g[i][j]=='0'||vis[i][j]) return;\n        vis[i][j] = true;\n        dfs(i+1, j, g, vis);\n        dfs(i-1, j, g, vis);\n        dfs(i, j+1, g, vis);\n        dfs(i, j-1, g, vis);\n    }\npublic:\n    int numIslands(vector\u003cvector\u003cchar\u003e\u003e\u0026 grid) {\n        int m = grid.size(), n = grid[0].size();\n        vector\u003cvector\u003cbool\u003e\u003evis(m, vector\u003cbool\u003e(n, false));\n        int count = 0;\n        for(int i=0; i\u003cm; i++){\n            for(int j=0; j\u003cn; j++){\n                if(!vis[i][j] \u0026\u0026 grid[i][j]=='1'){\n                    count++;\n                    dfs(i, j, grid, vis);\n                }\n            }\n        }\n\n        return count;\n    }\n\n};\n\nint main(){\n    return 0;\n}\n```\n\n### !!! LEVEL OF A NODE = DEPTH OF A NODE FROM ROOT NODE IN A TREE !!!\n\n### DFS in trees\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvoid dfs(int vertex, int par, vector\u003cvector\u003cint\u003e\u003e\u0026g){\n    for(int child: g[vertex]){\n        if(child==par) continue;\n        dfs(child, par, g);\n    }\n}\n\nint main(){\n    int n;\n    cin \u003e\u003e n;\n    vector\u003cvector\u003cint\u003e\u003egraph(n + 1);\n\n    vector\u003cint\u003e depth(n + 1, 0);\n    vector\u003cint\u003e height(n + 1);\n\n\n    for (int i = 0; i \u003c n - 1; i++) {\n        int x, y;\n        cin \u003e\u003e x \u003e\u003e y;\n        graph[x].push_back(y);\n        graph[y].push_back(x);\n    }\n\n    dfs(1, 0, graph);\n}\n```\n\n### Height and Depth of a tree\n\n- Height is calculated when coming up in the tree and depth is calculated when going down the tree.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvoid dfs(int v, int par, vector\u003cvector\u003cint\u003e\u003e\u0026 g, vector\u003cint\u003e\u0026 depth, vector\u003cint\u003e\u0026 height) {\n\n    // going down into the vertex\n    for (int child : g[v]) {\n        // going down into the child\n        if (child == par) continue;\n        depth[child] = depth[v] + 1;\n        dfs(child, v, g, depth, height);\n        height[v] = max(height[child] + 1, height[v]);\n        // coming up from the child\n    }\n    // coming up from the vertex\n}\n\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    vector\u003cvector\u003cint\u003e\u003egraph(n + 1);\n\n    vector\u003cint\u003e depth(n + 1, 0);\n    vector\u003cint\u003e height(n + 1);\n\n\n    for (int i = 0; i \u003c n - 1; i++) {\n        int x, y;\n        cin \u003e\u003e x \u003e\u003e y;\n        graph[x].push_back(y);\n        graph[y].push_back(x);\n    }\n\n    dfs(1, 0, graph, depth, height);\n\n    for (int i = 1; i \u003c= n; i++) {\n        cout \u003c\u003c depth[i] \u003c\u003c \" \" \u003c\u003c height[i] \u003c\u003c \"\\n\";\n    }\n\n\n    return 0;\n}\n```\n\n### Precomputation in Trees\n\n- Precomputation happens when you come back up from the child because you need the children's value first.\n\n1. Sum of the subtree and even number count\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvoid dfs(int v, int par, vector\u003cvector\u003cint\u003e\u003e\u0026 g, vector\u003cint\u003e\u0026 subtree_sum, vector\u003cint\u003e\u0026 even_ct) {\n    // take action while going down the vertex\n    subtree_sum[v] += v;\n    if (v % 2 == 0) even_ct[v]++;\n    for (int child : g[v]) {\n        if (child == par) continue;\n    // take action while going down the child\n        dfs(child, v, g, subtree_sum, even_ct);\n        subtree_sum[v] += subtree_sum[child];\n        even_ct[v] += even_ct[child];\n    // take action while coming up from the child\n    }\n    // take action while coming up from the vertex\n}\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    vector\u003cvector\u003cint\u003e\u003eg(n + 1);\n\n    for (int i = 1; i \u003c= n - 1; i++) {\n        int x, y;\n        cin \u003e\u003e x \u003e\u003e y;\n        g[x].push_back(y);\n        g[y].push_back(x);\n    }\n\n    vector\u003cint\u003e subtree_sum(n + 1);\n    vector\u003cint\u003e even_ct(n + 1);\n    dfs(1, 0, g, subtree_sum, even_ct);\n    for (int i = 1; i \u003c= n; i++) {\n        cout \u003c\u003c subtree_sum[i] \u003c\u003c \" \" \u003c\u003c even_ct[i] \u003c\u003c \"\\n\";\n    }\n    return 0;\n}\n```\n\n### Diameter of a tree\n\n- Find the max depth by traversing the tree through any node as root node.\n- Then the node which gives the max depth,i.e., the max_depth_node use it as a root node and find the max depth again.\n- These two nodes(max_depth_node and max_depth_node_1) are the two ends of the diameter and the newly calculated max_depth is the diameter.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvoid dfs(int v, int p, vector\u003cint\u003e\u0026 d, vector\u003cvector\u003cint\u003e\u003e\u0026 g) {\n    for (int c : g[v]) {\n        if (c == p) continue;\n        d[c] = d[v] + 1;\n        dfs(c, v, d, g);\n    }\n}\n\nvoid reset(vector\u003cint\u003e\u0026 d) {\n    for (int i = 0; i \u003c d.size(); i++) {\n        d[i] = 0;\n    }\n}\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    vector\u003cvector\u003cint\u003e\u003eg(n + 1);\n    for (int i = 0; i \u003c n - 1; i++) {\n        int x, y; cin \u003e\u003e x \u003e\u003e y;\n        g[x].push_back(y);\n        g[y].push_back(x);\n    }\n\n    vector\u003cint\u003ed(n + 1, 0);\n\n    dfs(1, -1, d, g);\n\n    int max_depth_node = -1;\n    int max_depth = -1;\n    for (int i = 1; i \u003c= n; i++) {\n        if (max_depth \u003c= d[i]) {\n            max_depth = d[i];\n            max_depth_node = i;\n        }\n    }\n    cout \u003c\u003c max_depth_node \u003c\u003c \" \" \u003c\u003c max_depth \u003c\u003c \"\\n\";\n\n    reset(d);\n\n    dfs(max_depth_node, 0, d, g);\n\n    int max_depth_node_1 = -1;\n    int max_depth_1 = -1;\n    for (int i = 1; i \u003c= n; i++) {\n        if (max_depth_1 \u003c= d[i]) {\n            max_depth_1 = d[i];\n            max_depth_node_1 = i;\n        }\n    }\n\n    cout \u003c\u003c max_depth_node_1 \u003c\u003c \" \" \u003c\u003c max_depth_1 \u003c\u003c \"\\n\";\n    int diameter = max_depth_1;\n    cout \u003c\u003c diameter;\n    // max_depth_node and max_depth_node_1 are the two ends of the diameter.\n    return 0;\n}\n```\n\n### LCA of two nodes in a tree\n\n- Store the parents in a parents array and then using that parents array climb back to the root node and store the path of nodes from root node and then simply traverse through both the path array and wherever the equality the node just before it is the LCA.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nvoid dfs(int v, int p, vector\u003cvector\u003cint\u003e\u003e\u0026 g, vector\u003cint\u003e\u0026 par) {\n    par[v] = p;\n    for (int c : g[v]) {\n        if (c == p) continue;\n        dfs(c, v, g, par);\n    }\n}\n\nvector\u003cint\u003e path(int v, vector\u003cint\u003e\u0026 par) {\n    vector\u003cint\u003e p;\n    while (true) {\n        if (v == -1) break;\n        p.push_back(v);\n        v = par[v];\n    }\n    reverse(p.begin(), p.end());\n    return p;\n}\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    vector\u003cvector\u003cint\u003e\u003eg(n + 1);\n    vector\u003cint\u003e par(n + 1, -1);\n    for (int i = 0; i \u003c n - 1; i++) {\n        int x, y; cin \u003e\u003e x \u003e\u003e y;\n        g[x].push_back(y);\n        g[y].push_back(x);\n    }\n\n    // take any 2 nodes for their LCA, suppose 2 and 12 -\u003e their LCA is 2\n    dfs(1, -1, g, par);\n\n    vector\u003cint\u003ep1 = path(12, par);\n    vector\u003cint\u003ep2 = path(2, par);\n\n    for (auto\u0026 it : p1) {\n        cout \u003c\u003c it \u003c\u003c \" \";\n    }\n    cout \u003c\u003c \"\\n\";\n\n    for (auto\u0026 it : p2) {\n        cout \u003c\u003c it \u003c\u003c \" \";\n    }\n    cout \u003c\u003c \"\\n\";\n\n    int LCA = -1;\n    for (int i = 0; i \u003c n-1; i++) {\n        if (p1[i] != p2[i]) break;\n        LCA = p1[i];\n    }\n\n    cout \u003c\u003c LCA;\n    return 0;\n}\n```\n\n### Edge Deletion Questions\n\n1. Given a tree with `n` nodes, where each node is labeled with a unique integer from 1 to `n`, you need to compute the maximum possible product formed by deleting a single edge in the tree. When an edge is deleted, the tree is divided into two separate subtrees. The product is calculated as the product of the sums of the node values in each of these two subtrees.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvoid dfs(int v, int par, vector\u003cvector\u003cint\u003e\u003e\u0026 g, vector\u003cint\u003e\u0026 subtree_sum) {\n    subtree_sum[v] = v;\n    for (int c : g[v]) {\n        if (c == par) continue;\n        dfs(c, v, g, subtree_sum);\n        subtree_sum[v] += subtree_sum[c];\n    }\n}\n\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    vector\u003cvector\u003cint\u003e\u003eg(n + 1);\n    for (int i = 0; i \u003c n - 1; i++) {\n        int x, y; cin \u003e\u003e x \u003e\u003e y;\n        g[y].push_back(x);\n        g[x].push_back(y);\n    }\n    vector\u003cint\u003esubtree_sum(n + 1, 0);\n    dfs(1, -1, g, subtree_sum);\n\n    // delete edge: Delete the top edge of the node\n    long long ans = 1;\n    for (int i = 2; i \u003c= n; i++) {\n        int part_1 = subtree_sum[i];\n        int part_2 = subtree_sum[1] - subtree_sum[i];\n        ans = max(ans, part_1 * 1LL * part_2);\n    }\n    cout \u003c\u003c ans \u003c\u003c \"\\n\";\n    return 0;\n}\n```\n\n2. Given a tree with `n` nodes, where each node is labeled with a unique integer from 1 to `n`, your task is to:\n\n   1. Count how many prime numbers exist in the subtree of each node, including the node itself.\n   2. Find the maximum possible product formed by deleting a single edge in the tree, where the product is computed as the number of prime numbers in the two resulting subtrees after the deletion.\n\n   - Input:\n     1. The first line contains a single integer n representing the number of nodes in the tree.\n     2. The next n-1 lines each contain two integers x and y, representing an undirected edge\n        between node x and node y.\n   - Output:\n     1. For each node from 1 to n, print the count of prime numbers in its subtree.\n     2. Output the maximum product that can be obtained by deleting exactly one edge, where the product is the multiplication of prime counts in the two resulting subtrees.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nvoid dfs(int v, int par, vector\u003cvector\u003cint\u003e\u003e\u0026 g, vector\u003cint\u003e\u0026 subtree_prime_count, vector\u003cbool\u003e\u0026 isPrime) {\n    if (isPrime[v])\n        subtree_prime_count[v]++;\n    for (int c : g[v]) {\n        if (c == par) continue;\n        dfs(c, v, g, subtree_prime_count, isPrime);\n        subtree_prime_count[v] += subtree_prime_count[c];\n    }\n}\n\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    vector\u003cvector\u003cint\u003e\u003eg(n + 1);\n    for (int i = 0; i \u003c n - 1; i++) {\n        int x, y; cin \u003e\u003e x \u003e\u003e y;\n        g[y].push_back(x);\n        g[x].push_back(y);\n    }\n    vector\u003cint\u003esubtree_prime_count(n + 1, 0);\n    vector\u003cbool\u003eisPrime(n + 1, true);\n\n    isPrime[1] = isPrime[0] = 0;\n    for (int i = 2; i \u003c n + 1; i++) {\n        if (isPrime[i]) {\n            for (int j = 2 * i; j \u003c n + 1; j += i) {\n                isPrime[j] = 0;\n            }\n        }\n    }\n\n    dfs(1, -1, g, subtree_prime_count, isPrime);\n\n    for (int i = 1; i \u003c= n; i++) {\n        cout \u003c\u003c subtree_prime_count[i] \u003c\u003c \"\\n\";\n    }\n\n    // delete edge: Delete the top edge of the node\n    long long ans = 1;\n    for (int i = 2; i \u003c= n; i++) {\n        int part_1 = subtree_prime_count[i];\n        int part_2 = subtree_prime_count[1] - subtree_prime_count[i];\n        ans = max(ans, part_1 * 1LL * part_2);\n    }\n    cout \u003c\u003c \"ans: \" \u003c\u003c ans \u003c\u003c \"\\n\";\n    return 0;\n}\n```\n\n### Breadth First Search(BFS) in Trees and Graphs\n\n- Goes level wise.\n- `There are two levels at a time in the queue, the current one and the next one.`\n- `Time Complexity is O(V+E).`\n- Each node is visited once, because of the visited array ofcourse.\n- `In an equally weighted graph, the path given from the source node is the shortest.`\n- The smaller level will always be accessed by the BFS firstly then it goes to the greater ones!\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\nvoid bfs(int source, vector\u003cvector\u003cint\u003e\u003e\u0026 g, vector\u003cint\u003e\u0026 b, vector\u003cbool\u003e\u0026 vis, int n) {\n    queue\u003cint\u003eq;\n    q.push(1);\n    b.push_back(1);\n    vis[1] = true;\n    vector\u003cint\u003elevel(n + 1, 0);\n    while (!q.empty()) {\n        int current_node = q.front();\n        q.pop();\n        b.push_back(current_node);\n        for (int child : g[current_node]) {\n            if (vis[child]) continue;\n            q.push(child);\n            vis[child] = true;\n            level[child] = level[current_node] + 1;\n        }\n    }\n\n    for (int i = 1; i \u003c= n; i++) {\n        cout \u003c\u003c b[i] \u003c\u003c \", level[\" \u003c\u003c b[i] \u003c\u003c \"]: \" \u003c\u003c level[i] \u003c\u003c \"\\n\";\n    }\n}\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    vector\u003cvector\u003cint\u003e\u003eg(n + 1);\n\n    for (int i = 0; i \u003c n - 1; i++) {\n        int x, y; cin \u003e\u003e x \u003e\u003e y;\n        g[x].push_back(y);\n        g[y].push_back(x);\n    }\n\n    vector\u003cbool\u003evis(n + 1, 0);\n    vector\u003cint\u003eb;\n    bfs(1, g, b, vis, n);\n\n    return 0;\n}\n```\n\n#### [Minimum Distance Question using BFS](https://www.spoj.com/problems/NAKANJ/)\n\n- Find the minimum number of moves a knight takes to reach from one square to another square of a chess board (8 × 8).\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nconst int INF = 1e9 + 10;\n\nint getX(string s) {\n    return s[0] - 'a';\n}\nint getY(string s) {\n    return s[1] - '1';\n}\n\nint vis[8][8];\nint lev[8][8];\n\nvector\u003cpair\u003cint, int\u003e\u003e movements = {\n    {1,2}, {-1,2},\n    {2,1}, {2,-1},\n    {-2,-1}, {-2,1},\n    {1,-2}, {-1,-2}\n};\n\nbool isValid(int x, int y) {\n    return x \u003e= 0 \u0026\u0026 y \u003e= 0 \u0026\u0026 x \u003c 8 \u0026\u0026 y \u003c 8;\n}\n\nint bfs(string src, string dest) {\n    int srcX = getX(src);\n    int srcY = getY(src);\n    int destX = getX(dest);\n    int destY = getY(dest);\n    queue\u003cpair\u003cint, int\u003e\u003e q;\n    q.push({ srcX, srcY });\n    vis[srcX][srcY] = 1;\n\n    while (!q.empty()) {\n        pair\u003cint, int\u003e p = q.front();\n        q.pop();\n        int x = p.first;\n        int y = p.second;\n        for (auto movement : movements) {\n            int childX = movement.first + x;\n            int childY = movement.second + y;\n            if (!isValid(childX, childY)) continue;\n            if (vis[childX][childY]) continue;\n            q.push({ childX, childY });\n            lev[childX][childY] = lev[x][y] + 1;\n            vis[childX][childY] = 1;\n        }\n        if (lev[destX][destY] != INF) break;\n    }\n    return lev[destX][destY];\n\n}\n\nvoid reset() {\n    for (int i = 0; i \u003c 8; i++) {\n        for (int j = 0; j \u003c 8; j++) {\n            lev[i][j] = INF;\n            vis[i][j] = 0;\n        }\n    }\n}\n\nint main() {\n    int t;\n    cin \u003e\u003e t;\n    while (t--) {\n        reset();\n        string s1, s2;\n        cin \u003e\u003e s1 \u003e\u003e s2;\n        cout \u003c\u003c bfs(s1, s2);\n    }\n\n    return 0;\n}\n```\n\n### [0-1 BFS: For finding shortest path if the weights are only 0 and 1](https://vjudge.net/problem/CodeChef-REVERSE)\n\n- We process the node again(two times) even if it has been processed once, i.e., went into the queue once already, that's why no visited array as we need to process the path with wt = 0(which could result in the even shorter path), that's why we used the level technique, the level technique can be used in regular BFS(here, the nodes are processed only once) too, by setting the level once and then skipping the nodes whose level isn't INF.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\nconst int INF = 1e9 + 10;\n\nint bfs(vector\u003cvector\u003cpair\u003cint, int\u003e\u003e\u003e\u0026 g, vector\u003cint\u003e\u0026 lev, int n) {\n    deque\u003cint\u003e q;\n    q.push_back(1);\n    lev[1] = 0;\n    while (!q.empty()) {\n        int cur_v = q.front();\n        q.pop_front();\n        for (auto child : g[cur_v]) {\n            int child_v = child.first;\n            int wt = child.second;\n            if (lev[cur_v] + wt \u003c lev[child_v]) {\n                lev[child_v] = lev[cur_v] + 1;\n            /* to process the node again even if it has been\n            processed already, that's why no visited array as we need to process the path with\n            wt = 0, that's why we used the level technique, it can be used in regular BFS too, by\n            setting the level once and then skipping the nodes whose level isn't INF.\n            */\n                if (wt == 0) {\n                    q.push_front(child_v);\n                } else {\n                    q.push_back(child_v);\n                }\n            }\n        }\n    }\n    return lev[n] == INF ? -1 : lev[n]; // lev[n] because we need to check for the shortest path between 1 to N\n}\n\nint main() {\n    int n, m;\n    cin \u003e\u003e n \u003e\u003e m;\n    vector\u003cvector\u003cpair\u003cint, int\u003e\u003e\u003eg(n + 1);\n    for (int i = 0; i \u003c m; i++) {\n        int x, y;\n        cin \u003e\u003e x \u003e\u003e y;\n        if (x == y) continue; // do avoid self loops, i.e., edge between the same element\n        g[x].push_back({ y,0 });\n        g[y].push_back({ x,1 });\n    }\n    vector\u003cint\u003e lev(n + 1, INF);\n    cout \u003c\u003c bfs(g, lev, n) \u003c\u003c \" \";\n    return 0;\n}\n```\n\n### Multi Source BFS: Starting the BFS from multiple source nodes\n\n- Multi-source BFS basically gives us the idea that if we start from multiple sources at once then which one will lead us to our destination first and its then marked visited ofcourse.\n\n- We basically put all the sources into the queue all at once and run the BFS.\n\n- Why it works?\n\n  - When we put multiple sources into the queue and initialize them with level = 0, then all the nodes other\n    than the sources would be reached by the ones already in the queue and will be marked as level = 1 and so on.\n\n  - Even if a node was visitable by a source node but was at a farther distance/level it won't be visited again, because that node would already have been marked visited/the level would be set to 1 which won't allow other farther source nodes to intefere.\n\n- Examples could include the following:\n  1. Reaching at the destination node in shortest time.\n  2. Which node could lead us to the destination node faster.\n  3. Finding the shortest time to reach a node when started with multiple nodes.\n  4. Questions could be on simultaneity of a situation, i.e., the values increase/decrease/change simultaneously in a grid.\n\n```cpp\n\n```\n\n## Dynamic Programming\n\n- Recursion \u0026rarr; Memoization(for time complexity optimization) \u0026rarr; Tabulation(for eliminating space complexity of the stack space) \u0026rarr; Space Optimization to O(1)\n- Overlapping sub-problems: we store(`memoize`) the results of sub-problems in a map/table and then simply retrieve it, when they overlap.\n- Memoization: Top\u0026rarr;Down \u0026rarr; build from the top(required solution) to the base case\n- Tabulation: Bottom\u0026rarr;up \u0026rarr; build from base case till the required solution\n- Space Optimization: Eliminating the `dp` array altogether and make it O(1).\n  - If there is (index-1) and (index-2) involved, we can always optimize the space.\n\n### Fibonacci Numbers\n\n- Recursive way : Time Complexity \u0026rarr; O(2\u003csup\u003eN\u003c/sup\u003e), Space Complexity \u0026rarr; O(N)\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nint fibo(int n) {\n    // recursion\n    if (n \u003c 2) {\n        return n;\n    }\n    return fibo(n - 1) + fibo(n - 2); // recurrence relation\n}\n\n\nint main() {\n\n    cout \u003c\u003c fibo(4) \u003c\u003c \"\\n\";\n    return 0;\n}\n```\n\n- Memoization: Time Complexity \u0026rarr; O(N), Space Complexity \u0026rarr; O(2N) = Stack Space + Array Space\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n// memoization: Time Complexity -\u003e O(N), Space Complexity -\u003e O(2N) = Stack Space + Array Space\nint f_memo(int n, vector\u003cint\u003e\u0026 dp) {\n    if (n \u003c= 1) {\n        return n;\n    }\n    if (dp[n] != -1) return dp[n];\n    return dp[n] = f_memo(n - 1, dp) + f_memo(n - 2, dp);\n}\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    vector\u003cint\u003e dp(n + 1, -1);\n    cout \u003c\u003c f_memo(n, dp) \u003c\u003c \"\\n\";\n\n\n\n    return 0;\n}\n```\n\n- Tabulation: Eliminating stack space in this case\n  - Time Complexity \u0026rarr; O(N), Space Complexity \u0026rarr; O(N) = Array Space\n  - `Convert the recurrence relation from f(n-1) + f(n-2)` \u0026rarr; `dp[i-1] + dp[i-2].`\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n\n//tabulation: Time Complexity -\u003e O(N), Space Complexity -\u003e O(N) = Array Space\nint f_tabulated(int n, vector\u003cint\u003e\u0026 dp) {\n    dp[0] = 0; dp[1] = 1;\n    for (int i = 2; i \u003c= n; i++) {\n        dp[i] = dp[i - 1] + dp[i - 2];\n    }\n    return dp[n];\n}\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    vector\u003cint\u003e dp(n + 1, -1);\n    cout \u003c\u003c f_tabulated(n, dp);\n\n    return 0;\n}\n```\n\n- Making the space complexity = O(1), by using `prev`, `prev2` and `curi` pointers \u0026rarr; Remember this pattern as it will be used or its variations would be used at many places\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n// space optimization: Time Complexity -\u003e O(N), Space Complexity -\u003e O(1)\nint f_space_optimized(int n) {\n    int prev2 = 0, prev = 1;\n    if (n \u003c 2) return n;\n    for (int i = 2; i \u003c= n; i++) {\n        int curi = prev2 + prev;\n        prev2 = prev;\n        prev = curi;\n    }\n    return prev;\n}\n\nint main() {\n    int n;\n    cin \u003e\u003e n;\n    cout \u003c\u003c f_space_optimized(n) \u003c\u003c \"\\n\";\n\n    return 0;\n}\n\n```\n\n### How to identify a DP/Recursion question?\n\n1. Count the number of ways\n2. Multiple ways of doing something, then minimum or maximum number of ways are asked\n\nRecursion helps you explore all the possibilities.\n\n## How to write recurrence relations in an easy way?\n\n1. Try to represent the problem in terms of indices(even if there is no array).\n2. Do all possible things on that index according to the problem statement.\n3. Think of edge cases.\n4. If you need to do the following:\n   - Count all ways: Sum up all the things\n   - Min(of all things): Find Min\n   - Max(of all things): Find Max\n\n- Example 1: [Climbing Stairs](https://leetcode.com/problems/climbing-stairs/description/)\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\n// this is the recursive way(btw it looks like fibonacci)\nint climb_stairs(int i) { // we'll jump down\n    if (i == 0) return 1;\n    // however, what if i=1, then we'll need to handle the edge case of i = 1\n    if (i == 1) return 1;\n    int left = climb_stairs(i - 1);\n    int right = climb_stairs(i - 2);\n\n    return left + right;\n\n}\n\n// let's memoize it\nint f(int i, vector\u003cint\u003e\u0026 dp) {\n    if (i == 0) return 1;\n    if (i == 1) return 1;\n    if (dp[i] != -1) return dp[i];\n    int left = f(i - 1, dp);\n    int right = f(i - 2, dp);\n\n    return dp[i] = left + right;\n}\n\n// let's tabulate this\nint t(int n, vector\u003cint\u003e\u0026 dp) { // size of dp vector would be n+1, for 1-based indexing in this case\n    if (n == 0) return 1;\n    if (n == 1) return 1;\n    for (int i = 2; i \u003c= n; i++) {\n        dp[i] = dp[i - 1] + dp[i - 2];\n    }\n    return dp[n];\n}\n\n//let's do space optimization\nint s(int n) {\n    if (n == 0) return 1;\n    if (n == 1) return 1;\n    int prev = 1, prev2 = 1;\n    for (int i = 0; i \u003c= n; i++) {\n        int curi = prev2 + prev;\n        prev2 = prev;\n        prev = curi;\n    }\n\n    return prev;\n}\n\n\nint main() {\n    // Represent the problem in terms of indices.\n    // We'll consider the stairs to be indices from 0 to n.\n    // Then either we can jump 1 step or 2 steps -\u003e the things we can do with the index.\n\n    return 0;\n}\n```\n\n- Example 2: [Frog Jump](https://www.geeksforgeeks.org/problems/geek-jump/1)\n  - If there is (index-1) and (index-2) involved, we can always optimize the space.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nint min_energy_recursive(int ind, vector\u003cint\u003e\u0026 heights) {\n    if (ind == 0) return 0;\n    if (ind == 1) return abs(heights[1] - heights[0]);\n    int left = min_energy_recursive(ind - 1, heights) + abs(heights[ind] - heights[ind - 1]);\n    int right = min_energy_recursive(ind - 2, heights) + abs(heights[ind] - heights[ind - 2]);\n\n    return (left, right);\n}\n\n\nint min_energy_dp(int ind, vector\u003cint\u003e\u0026 dp, vector\u003cint\u003e\u0026 heights) {\n    if (ind == 0) return 0;\n    if (ind == 1) return abs(heights[1] - heights[0]);\n    if (dp[ind] != -1) return dp[ind];\n    int left = min_energy_dp(ind - 1, dp, heights) + abs(heights[ind] - heights[ind - 1]);\n    int right = min_energy_dp(ind - 2, dp, heights) + abs(heights[ind] - heights[ind - 2]);\n\n    return dp[ind] = min(left, right);\n\n}\n\nint min_energy_tabulated(int ind, vector\u003cint\u003e\u0026 dp, vector\u003cint\u003e\u0026 heights) {\n    if (ind == 0) return 0;\n    if (ind == 1) return abs(heights[1] - heights[0]);\n    dp[0] = 0; dp[1] = abs(heights[1] - heights[0]);\n    for (int i = 2; i \u003c= ind; i++) {\n        dp[i] = min(dp[i - 1] + abs(heights[i] - heights[i - 1]), dp[i - 2] + abs(heights[i] - heights[i - 2]));\n    }\n    return dp[ind];\n}\n\nint min_energy_space_optimized(int ind, vector\u003cint\u003e\u0026 heights) {\n    if (ind == 0) return 0;\n    if (ind == 1) return abs(heights[1] - heights[0]);\n    int prev = abs(heights[1] - heights[0]), prev2 = 0;\n    for (int i = 2; i \u003c= ind; i++) {\n        int curi = min(prev + abs(heights[i] - heights[i - 1]), prev2 + abs(heights[i] - heights[i - 2]));\n        prev2 = prev;\n        prev = curi;\n    }\n    return prev;\n}\n\nint main() {\n   // Express the question in terms of an index\n   // Then do everything with the index as per the question\n   // Think of the edge cases, like ind == 1, in this case.\n   // Then return the minimum of the things you did on the index\n    return 0;\n}\n```\n\n- Example 3: [Frog Jump with K steps](https://atcoder.jp/contests/dp/tasks/dp_b)\n- It demonstrates how 2 loops are required in the tabulated format.\n\n```cpp\n#include \u003cbits/stdc++.h\u003e\nusing namespace std;\n\nint jump_with_k_steps(int n, int k, vector\u003cint\u003e\u0026 arr) {\n    if (n == 0) return 0;\n    int min_steps = INT_MAX;\n    for (int i = 1; i \u003c= k; i++) {\n        if (n - i \u003e= 0) {\n            int jump = jump_with_k_steps(n - i, k, arr);\n            min_steps = (min_steps, jump);\n        }\n    }\n    return min_steps;\n}\n\nint jump_with_k_steps_memoized(int i, int k, vector\u003cint\u003e\u0026 arr, vector\u003cint\u003e\u0026 dp) {\n    if (i == 0) return 0;\n    if (dp[i] != -1) return dp[i];\n    int min_steps = INT_MAX;\n    for (int j = 1; j \u003c= k; j++) {\n        if (i - j \u003e= 0) {\n            int jump = jump_with_k_steps_memoized(i - j, k, arr, dp) + abs(arr[i - j] - arr[i]);\n            min_steps = (min_steps, jump);\n        }\n    }\n    return dp[i] = min_steps;\n}\n\nint jump_with_k_steps_tabulated(int n, int k, vector\u003cint\u003e\u0026 arr, vector\u003cint\u003e\u0026 dp) {\n    if (n == 0) return 0;\n    dp[0] = 0;\n    for (int i = 1; i \u003c= n; i++) {\n        int min_steps = INT_MAX;\n        for (int j = 1; j \u003c= k; j++) {\n            if (i - j \u003e= 0) {\n                int jump = dp[i - j] + abs(arr[i - j] - arr[i]);\n                min_steps = min(jump, min_steps);\n            }\n        }\n        dp[i] = min_steps;\n    }\n\n    return dp[n];\n}\n\n\nint main() {\n    int n, k;\n    cin \u003e\u003e n \u003e\u003e k;\n    vector\u003cint\u003e arr(n);\n    for (int i = 0; i \u003c n; i++) {\n        cin \u003e\u003e arr[i];\n    }\n    vector\u003cint\u003e dp(n + 1, -1);\n    cout \u003c\u003c jump_with_k_steps_tabulated(n - 1, k, arr, dp);\n    return 0;\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frajneesh069%2Fdsa-cpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frajneesh069%2Fdsa-cpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frajneesh069%2Fdsa-cpp/lists"}