Repository: Utkarsh1504/DSA-Java Branch: main Commit: bedc4e3c0632 Files: 94 Total size: 313.3 KB Directory structure: gitextract_himew_8z/ ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── config.yml │ │ ├── documentation_request.yml │ │ ├── improvement_request.yml │ │ └── other.yml │ ├── pull_request-template.md │ └── workflows/ │ └── gatsby.yml ├── .gitignore ├── .prettierrc ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── csv.js ├── gatsby-config.js ├── gatsby-node.js ├── lessons/ │ ├── arraylist.md │ ├── arrays.md │ ├── assignment.md │ ├── backtrack-maze.md │ ├── backtrack-nknight.md │ ├── backtrack-sudoku.md │ ├── backtracking.md │ ├── binarysearch.md │ ├── bitwise-operator.md │ ├── bmmv-algorithm.md │ ├── bracktrack-nqueen.md │ ├── bubblesort.md │ ├── countsort.md │ ├── cyclesort.md │ ├── dataTypes.md │ ├── firstjavaprogram.md │ ├── flow-of-recursion.md │ ├── flowchart.md │ ├── functions.md │ ├── greedy.md │ ├── insertion.md │ ├── intro-binarytree.md │ ├── intro-bst.md │ ├── intro-complexity.md │ ├── intro-dp.md │ ├── intro-ds.md │ ├── intro-graph.md │ ├── intro-hashmap.md │ ├── intro-heap.md │ ├── intro-linkedlist.md │ ├── intro-maths.md │ ├── intro-oop.md │ ├── intro-priorityqueues.md │ ├── intro-programming.md │ ├── intro-recursion.md │ ├── intro-stacks.md │ ├── intro-string.md │ ├── intro-trees.md │ ├── intro-tries.md │ ├── introduction.md │ ├── io-conditionals.md │ ├── jagged-array.md │ ├── java-setup.md │ ├── jumps.md │ ├── linearsearch.md │ ├── loops.md │ ├── mergesort.md │ ├── num-one.md │ ├── num-three.md │ ├── num-two.md │ ├── operators.md │ ├── practise-question.md │ ├── print-patterns.md │ ├── properties.md │ ├── quicksort.md │ ├── radixsort.md │ ├── recurrence.md │ ├── recursion-arrays.md │ ├── recursion-practise.md │ ├── recursion-string.md │ ├── selectionsort.md │ ├── space-complexity.md │ ├── string-builder.md │ ├── subarrays.md │ ├── this-constructor.md │ ├── time-complexity.md │ └── time_space_tradeoff.md ├── package.json ├── src/ │ ├── components/ │ │ └── TOCCard.js │ ├── layouts/ │ │ ├── Footer.css │ │ ├── Footer.js │ │ ├── index.css │ │ ├── index.js │ │ └── variables.css │ ├── pages/ │ │ ├── 404.js │ │ └── index.js │ ├── templates/ │ │ └── lessonTemplate.js │ └── util/ │ └── helpers.js └── static/ └── theme.css ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false ================================================ FILE: .github/ISSUE_TEMPLATE/documentation_request.yml ================================================ name: Docs request description: Suggest lesson, propose new data-structure and algorithms, discuss new ideas title: "new lesson: " labels: ["⭐ goal: addition"] body: - type: textarea id: requesttype attributes: label: ⭐ Request Type description: describe the name of the lesson or section you want to add. validations: required: true - type: textarea id: location attributes: label: 💻 Location description: | Where you think your lesson should be placed(location) so that there will be ease in understanding for new comers. validations: required: true - type: textarea id: addtionalinfo attributes: label: ❌ Additional Info description: | If you have any additional information that you think will help the community. validations: required: false - type: markdown attributes: value: | You can also join the Discord community [here](#) ================================================ FILE: .github/ISSUE_TEMPLATE/improvement_request.yml ================================================ name: Improvement request description: propose improvements, adding new code, or any new features title: "improve: " labels: ["⭐ goal: addition"] body: - type: textarea id: summary attributes: label: ⭐ Summary description: A brief summary of what you'd like to see added or improved. validations: required: true - type: textarea id: location attributes: label: 💻 Location description: | Describe where or in which section/lesson you want to do improvements. validations: required: true - type: textarea id: additionalinfo attributes: label: ❌ Additional Info description: | Any additional information you'd like to provide. validations: required: false - type: markdown attributes: value: | You can also join the Discord community [here](#) ================================================ FILE: .github/ISSUE_TEMPLATE/other.yml ================================================ name: Other description: Use this for any other issues. PLEASE do not create blank issues title: "[OTHER]" labels: ["🛠 status: fix"] body: - type: markdown attributes: value: "# Other issue" - type: textarea id: issuedescription attributes: label: Other description: Provide a clear and concise explanation of your issue. validations: required: true - type: textarea id: extrainfo attributes: label: Additional information description: Is there anything else we should know about this issue? validations: required: false ================================================ FILE: .github/pull_request-template.md ================================================ Fixes # #### Short description of what this resolves: #### What Changes proposed in this pull request: - - - #### Checklist - [ ] Added description of change - [ ] Added file name matches [File name guidelines](https://github.com/Utkarsh1504/DSA-Java/blob/main/CONTRIBUTING.md#requesting-a-lesson) - [ ] Added code examples, test must pass - [ ] Added documentation so that the program is self-explanatory and educational. - [ ] Relevant documentation/comments is changed or added - [ ] PR title follows semantic [commit guidelines](https://github.com/Utkarsh1504/DSA-Java/blob/main/CONTRIBUTING.md#requesting-a-lesson) - [ ] Search previous suggestions before making a new one, as yours may be a duplicate. - [ ] I acknowledge that all my contributions will be made under the project's license. Notes: ================================================ FILE: .github/workflows/gatsby.yml ================================================ name: Deploy Gatsby Site to GitHub Pages on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@master - name: npm install, build, and csv run: | npm install npm run build npm run csv - name: Deploy site to gh-pages branch uses: crazy-max/ghaction-github-pages@v2 with: target_branch: gh-pages build_dir: public env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ================================================ FILE: .gitignore ================================================ # Project dependencies # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git node_modules .cache/ # Build directory public/ .DS_Store yarn-error.log /.idea ================================================ FILE: .prettierrc ================================================ {} ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: - Using welcoming and inclusive language - Being respectful of differing viewpoints and experiences - Gracefully accepting constructive criticism - Focusing on what is best for the community - Showing empathy towards other community members Examples of unacceptable behavior by participants include: - The use of sexualized language or imagery and unwelcome sexual attention or advances - Trolling, insulting/derogatory comments, and personal or political attacks - Public or private harassment - Publishing others' private information, such as a physical or electronic address, without explicit permission - Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a maintainer of the [project team members](https://github.com/orgs/dsa-java) or write a email to 'utkarshmishra73444@gmail.com'. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing to DSA-Java First of all, thanks for taking the time to contribute! This project can only grow and live by your countless contributions. To keep this project maintainable, we have developed some guidelines for our contributors. Please note that by participating, you are expected to uphold the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md). ## Table of Content - [Terms](#terms) - [Lesson](#lesson) - [Requesting A Lesson](#requesting-a-lesson) - [Fixing Typos](#fixing-typos) - [Improving Lesson](#improving-lesson) - [Our Standards](#our-standards) - [Markdown Format](#markdown-format) - [Communication](#communication) --- ## Terms Here are some terms that we will use in this repo: - `path` needs a leading slash. This will be slug of the lesson - `title`- will be the title displayed on the `Table of Contents` and on the page itself - `order`- the order of which the item should appear in the table of contents. It should be in `` format where the number corresponds to the section itself and the letter corresponds to the order of the lesson inside the section, e.g. 3B means under the section 3 and the order of the lesson will be B(second) - `section` - the title of the section that the article is in. Only the first lesson for each section will be used. - `description` - a one-to-three sentence summary of the lesson. Used for the meta tag for social shares and SEO. If no description is given, the siteMetadata.description for the site is used. - `icon` the Font Awesome icon you want for the home page of the site ## Lesson The crux of this site is are the `lesson`. Provided are two examples. Each lesson needs a frontmatter path, order, and title. Generally you should make the path and the file name match for ease of finding it. - In `Lesson` directory there are various sections. You can start contributing from there. - Inside each of the sections `lesson` present in the form of markdown. If you wanted to add a new lesson make a new file with `.md` extension and add at the top it. ```yml --- path: "/pathName" title: "TitleName" order: "" section: "SectionName" description: "Learn DSA-Java" --- ``` - Modify this according to your contribution and go ahead - For writing concepts, take a look at the other [lessons]('lesson/Learn-Programming-Language/operator.md') markdown and make sure it is written in a similar way. ## Requesting A Lesson for requesting a lesson simply raise a new issue in the `Issues` section. - Search for other issues already requesting the lesson. - If an issue doesn't exist, create an issue naming it `new lesson: ` - provide description as mentioned in issue template. - Please create separate issues for any concept or lesson that you want to add. ## Fixing Typos for fixing typo just make a pull request with your fixes, naming it: - `fixed typo: ` - provide description as mentioned in pull request template. ## Improving lesson for any improvement in the lesson raise a new issue in the Issues section, Naming it: - `improvement: ` - provide description as mentioned in issue template. - also one thing to keep in mind, if you wanted to do improvement in the lesson, It should be clear and easy to understand. ## Our Standards Before you submit your PR, please ensure that they meet the following standard: - For writing the concept, take a look at the other [lessons]('lesson/Learn-Programming-Language/operator.md') markdown and make sure it is written in a similar way. - Content inside the lesson should not be copied or plagarized from any other resources, you need to write your own content using your understanding about the concept. - Code example should not copied from anywhere else, you should set example by your own. - for adding images and gifs related to the lesson, make sure it is copyright free and not used for commercial purpose. but in case you don't find any image or gif on internet, you can use the [draw.io](draw.io) to make your own images. Images and gif used should be kept in `lesson/images/` directory. ## Markdown Format Here are some guidelines for writing markdown, In the same fashion you have to write the markdown for the lessons: - All the main headings should be in `##` or `

` format. - please do not use any heading at the start of the lesson, it will be used by default by the frontmatters, so don't start writing your lesson with a heading. - All the subheadings should be in `###` or `

` or `####`, `

` format and so on. ## Communication We are running a communication channel. You can go here to talk, discuss, and more with the maintainers and other people, too. Here's the invitation: [discord](#) ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================

Getting Started with Data Structures and Algorithms


[![Welcome to my profile](https://img.shields.io/badge/Hello,Programmer!-Welcome-blue.svg?style=flat&logo=github)](https://github.com/utkarsh1504) [![Open Source Love](https://badges.frapsoft.com/os/v2/open-source.svg?v=103)](https://github.com/utkarsh1504/DSA-Java) ![Lines of code](https://img.shields.io/tokei/lines/github/utkarsh1504/DSA-Java?color=red&label=Lines%20of%20Code) ![License](https://img.shields.io/badge/License-Apache-red.svg) ![Stars](https://img.shields.io/github/stars/utkarsh1504/DSA-Java?style=flat&logo=github) ![Forks](https://img.shields.io/github/forks/utkarsh1504/DSA-Java?style=flat&logo=github)
ds-algo

html css C++ js os check

A learning purpose website for everyone to learn Data Structures and Algorithms at one place in a very simple way using the language Java.

Table of Contents

  1. About
  2. Getting Started
  3. Lesson Requests
  4. Contributing
  5. Pull Requests
  6. License
## **About** We are building a site which will contain all the DS-Algo related things. It will contain just the relevent concepts which are needed to get started from scratch to go upto its hard parts. It will also contains some assigment question from different-different platforms. It is completely free, open-sourced, everyone can use it to learn, taking notes, doing revision, making tutorial etc. That's all the goal is. ## **Getting Started** You are just 11 step away from making your contribution to this repo. For the quick start, you can follow the steps below: 1. Star this repository. 2. Fork this repository. 3. Clone the **forked** repository. ```yml git clone https://github.com//DSA-Java ``` 4. Set this repository as upstream repository. ```yml git remote add upstream https://github.com/Utkarsh1504/DSA-Java.git ``` 5. Navigate to the project directory. ```yml cd DSA-Java ``` 6. Pull upstream commits(changes). Always keep your **main** branch updated with the project's **main/master** branch(updated repository). ```yml git pull upstream main ``` 7. Create a new branch. ```yml git checkout -b ``` #### **Project Setup:** Run the following command to install the required dependencies. 1. `npm install --global gatsby-cli` - make sure you're on Gatsby v2+ - See [docs here](https://next.gatsbyjs.org/docs/) if you need help 2. `npm install` - install the required dependencies 3. `npm run dev` - start the development server 4. Open http://localhost:8000 in your browser 5. Contribute
8. Stage your changes. ```yml git add . ``` 9. Commit your changes. ```yml git commit -m "" ``` 10. Push your local commits to the remote repo. ```yml git push -u origin ``` 11. Create a Pull-Request to `main`. 12. Congratulations! 🎉 you've made your contribution to DSA-Java. ✌️ ❤️ 💥

Contributing

Thank you for your interest in contributing to our Repo! Pull requests are welcome. For fixing typos, please make a PR with your fixes. For other contributions, we suggest you to read our contribution guidelines to see how you can contribute to this project. We are happy for every contribution.

Issues & Pull Requests

Before making pull requests please look at our contributing guidelines. You can start working on the issue which are mentioned in issues section. Just drop a comment before working on the issue. Thank you!

License

The **code** is this repo is licensed under the Apache 2.0 license. Feel free to use and share it as per the license. ## Thanks to all the contributors ❤️
love how
================================================ FILE: csv.js ================================================ const fs = require("fs").promises; const path = require("path"); const fm = require("front-matter"); const isUrl = require("is-url-superb"); const parseLinks = require("parse-markdown-links"); const { sorter } = require("./src/util/helpers"); const mdDir = process.env.MARKDOWN_DIR || path.join(__dirname, "lessons/"); const outputPath = process.env.OUTPUT_CSV_PATH || path.join(__dirname, "public/lessons.csv"); const linksOutputPath = process.env.LINKS_CSV_PATH || path.join(__dirname, "public/links.csv"); async function createCsv() { console.log(`making the markdown files into a CSV from ${mdDir}`); // get paths const allFiles = await fs.readdir(mdDir); const files = allFiles.filter(filePath => filePath.endsWith(".md")); // read paths, get buffers const buffers = await Promise.all( files.map(filePath => fs.readFile(path.join(mdDir, filePath))) ); // make buffers strings const contents = buffers.map(content => content.toString()); // make strings objects let frontmatters = contents.map(fm); // find all attribute keys const seenAttributes = new Set(); frontmatters.forEach(item => { Object.keys(item.attributes).forEach(attr => seenAttributes.add(attr)); }); const attributes = Array.from(seenAttributes.values()); if (attributes.includes("order")) { frontmatters = frontmatters.sort(sorter); } // get all data into an array let rows = frontmatters.map(item => { const row = attributes.map(attr => item.attributes[attr] ? JSON.stringify(item.attributes[attr]) : "" ); return row; }); // header row must be first row rows.unshift(attributes); // join into CSV string const csv = rows.map(row => row.join(",")).join("\n"); // write file out await fs.writeFile(outputPath, csv); console.log(`Wrote ${rows.length} rows to ${outputPath}`); // make links csv let longestLength = 0; let linksArray = frontmatters.map(row => { const links = parseLinks(row.body).filter(isUrl); longestLength = longestLength > links.length ? longestLength : links.length; const newRow = [row.attributes.order, row.attributes.title, ...links]; return newRow; }); if (longestLength) { // add title row linksArray = linksArray.map(array => { const lengthToFill = longestLength + 2 - array.length; return array.concat(Array.from({ length: lengthToFill }).fill("")); }); linksArray.unshift( ["order", "title"].concat( Array.from({ length: longestLength }).map((_, index) => `link${index}`) ) ); // join into CSV string const linksCsv = linksArray.map(row => row.join(",")).join("\n"); // write file out await fs.writeFile(linksOutputPath, linksCsv); console.log(`Wrote ${linksArray.length} rows to ${linksOutputPath}`); } } createCsv(); ================================================ FILE: gatsby-config.js ================================================ module.exports = { siteMetadata: { title: "Data Structures & Algorithms", subtitle: "Using Java", courseImage: "algorithms.png", // this also should go in /static twitter: "https://twitter.com/umishra1504", // make empty string to omit socials linkedin: "https://www.linkedin.com/in/umishra-1504", github: "https://github.com/utkarsh1504", description: "Learn all the data-structures and algorithm using the language Java", keywords: ["java", "markdown", "algorithms", "data-structures"], }, pathPrefix: "/DSA-Java", // if you're using GitHub Pages, put the name of the repo here with a leading slash plugins: [ { resolve: "gatsby-plugin-react-svg", options: { rule: { include: /src/, }, }, }, `gatsby-plugin-sharp`, `gatsby-plugin-layout`, { resolve: `gatsby-source-filesystem`, options: { path: `${__dirname}/lessons`, name: "markdown-pages", }, }, `gatsby-plugin-react-helmet`, { resolve: `gatsby-transformer-remark`, options: { plugins: [ `gatsby-remark-autolink-headers`, `gatsby-remark-copy-linked-files`, `gatsby-remark-prismjs`, { resolve: `gatsby-remark-images`, options: { maxWidth: 800, linkImagesToOriginal: true, sizeByPixelDensity: false, }, }, ], }, }, ], }; ================================================ FILE: gatsby-node.js ================================================ const path = require("path"); exports.createPages = ({ actions, graphql }) => { const { createPage } = actions; const lessonTemplate = path.resolve(`src/templates/lessonTemplate.js`); return graphql(` { allMarkdownRemark( sort: { order: DESC, fields: [frontmatter___order] } limit: 1000 ) { edges { node { excerpt(pruneLength: 250) html id frontmatter { order path title } } } } } `).then(result => { if (result.errors) { return Promise.reject(result.errors); } result.data.allMarkdownRemark.edges.forEach(({ node }) => { createPage({ path: node.frontmatter.path, component: lessonTemplate }); }); }); }; ================================================ FILE: lessons/arraylist.md ================================================ --- path: "/arraylist" title: "ArrayList In Java" order: "4B" section: "Arrays" description: "learn arrays" --- The ArrayList class is in implementation of the list interface that allow us to create resizable array. In simple term we can say that ArrayList in java is dynamic array for storing the elements. It is just like the vector in c++. ## Creating An ArrayList ```java ArrayListarraylist = new ArrayList<> ; //here type define any type of ArrayList. Example: ArrayList arrlist = new ArrayList(n); ``` ## Code Snippet to demonstrate the working of ArrayList in Java ```java import java.io.*; import java.util.*; class ArrayListExample { public static void main(String[] args) { //create array ArrayList arr = new ArrayList(n); arr.add(1); arr.add(2); arr.add(3); arr.add(4); System.out.println("List: " + arr ); } } ``` ## Output ```java List : [1, 2, 3, 4] ``` ## Methods OF ArrayList : Some Commonly used Methods Method | Detail ------------- | ------------- size() | give the size of the ArrayList sort() | to sort the elements in the list isEmpty() | Checks if the arraylist is empty. indexOf() | to find index of any element. ## Basic Operation in Java ArrayList : The ArrayList class have some methods to perform different operations on arraylists. Let's see some of most used methods. - Add elements - Access elements - Change elements - Remove elements ### Add Elements: - add() : This is the method to insert any elements at the end of the list. ```java import java.util.ArrayList; class Main { public static void main(String[] args){ ArrayList playerName = new ArrayList<>(); // add() method playerName.add("Virat"); playerName.add("Dhoni"); playerName.add("Sachin"); //print System.out.println("ArrayList: " + playerName); } } ``` ### Output: ``` ArrayList : [Virat,Dhoni,Sachin] ``` - get() : This method is used to acess the elements from the list. ```java import java.util.ArrayList; class Main { public static void main(String[] args){ ArrayList playerName = new ArrayList<>(); playerName.add("Virat"); playerName.add("Dhoni"); playerName.add("Sachin"); System.out.println("ArrayList: " + playerName); // get() method String name1 = playerName.get(1); System.out.println(name1); } } ``` ### Output: ``` ArrayList : [Virat,Dhoni,Sachin]; Dhoni ``` - set(): This method is used to set any elements at any position. ```java import java.util.ArrayList; class Main { public static void main(String[] args) { ArrayList playerName = new ArrayList<>(); // add() method without the index parameter playerName.add("Virat"); playerName.add("Dhoni"); playerName.add("Sachin"); System.out.println("ArrayList: " + playerName); // change the element of the array list playerName.set(2, "Rohit"); System.out.println("New ArrayList: " + playerName); } } ``` ### Output: ``` ArrayList : [Virat,Dhoni,Sachin] New ArrayList : [Virat,Dhoni,Rohit] ``` - remove() : To remove the elements from the list ```java import java.util.ArrayList; class Main { public static void main(String[] args) { ArrayList playerName = new ArrayList<>(); // add() method without the index parameter playerName.add("Virat"); playerName.add("Dhoni"); playerName.add("Sachin"); System.out.println("ArrayList: " + playerName); // remove element String name1 = playerName.remove(2); //print list after removal System.out.println("New ArrayList: " + playerName); //removed elements System.out.println("Removed: " + name1); } } ``` ### Output: ``` ArrayList : [Virat,Dhoni,Sachin] New ArrayList : [Virat,Dhoni] Removed: Sachin ``` ## Some remembering points about ArrayList - It comes under java.util package. - This class maintains insertion order. - It allows random access. - ArrayList is not Synchronized - To convert ArrayList into an array we use toArray() method. - To convert array into an arraylist we use asList() method. ================================================ FILE: lessons/arrays.md ================================================ --- path: "/arrays" title: "Introduction to Arrays" order: "4A" section: "Arrays" description: "arrays" icon: "map" --- It was simple when we used to store just a couple of numbers, we just make some variables for that and store respectively. But what if we want to store 50 numbers? Ofcource, we can make 50 variables and store but that would be very childish approach and inappropriate. And now assume we have to 5000 numbers, we can't make just 5000 variables. To handle this situation, in almost all programming languages we have a data structure called `Arrays`. ## **What is an Array ?** An array is a data structure used to store a collection of data of the same data type. Normally, an array is a collection of similar type of elements which has contiguous memory location. Java array is an object which contains elements of a similar data type. Additionally, The elements of an array are stored in a contiguous memory location. It is a data structure where we store similar elements. We can store only a fixed set of elements in a Java array. Array in Java is index-based, the first element of the array is stored at the 0th index, 2nd element is stored on 1st index and so on. ![Array Indicing.png](https://github.com/shoebxsiddiqui/DSA-Java/blob/shoebxsiddiqui-Arrays/lessons/images/Array%20Indicing.png) Unlike C/C++, we can get the length of the array using the `length` member. In C/C++, we need to use the `sizeof` operator. In Java, array is an object of a dynamically generated class. Java array inherits the Object class, and implements the Serializable as well as Cloneable interfaces. We can store primitive values or objects in an array in Java. Like C/C++, we can also create single dimentional or multidimentional arrays in Java. Moreover, Java provides the feature of anonymous arrays which is not available in C/C++. ```java datatype[] variablename = new datatype[size]; ``` eg, we want to store roll numbers: ```java int[] rollnos = new int[5]; OR int[] rollnos = {51, 82, 13, 15, 16}; ``` `int` represents the type of data, all the elements in the array should be of same data type, here it is int so the elements in the should be of int data type. ```java int[] rollnow; //declaration of arrays //rollnos get defined in stack ``` There are `two types` of Arrays: * Single Dimensional Arrays * Multidimentional Arrays Let's understand these in detail: ## **1.One-Dimensional Arrays** The general form of a one-dimensional array declaration is ```java type var-name[]; OR type[] var-name; ``` An array declaration has two components: the type and the name. type declares the element type of the array. The element type determines the data type of each element that comprises the array. Like an array of integers, we can also create an array of other primitive data types like char, float, double, etc. or user-defined data types (objects of a class). Thus, the element type for the array determines what type of data the array will hold Example: ```java // both are valid declarations int intArray[]; or int[] intArray; byte[] byteArray; short[] shortsArray; boolean[] booleanArray; long[] longArray; float[] floatArray; double[] doubleArray; char[] charArray; // an array of references to objects of // the class MyClass (a class created by // user) MyClass myClassArray[]; Object[] ao, // array of Object Collection[] ca; // array of Collection // of unknown type ``` Although the first declaration above establishes the fact that intArray is an array variable, no actual array exists. It merely tells the compiler that this variable (intArray) will hold an array of the integer type. To link intArray with an actual, physical array of integers, you must allocate one using new and assign it to intArray. ### **Instantiating an Array in Java** When an array is declared, only a reference of array is created. To actually create or give memory to array, you create an array like this:The general form of new as it applies to one-dimensional arrays appears as follows: ```java var-name = new type [size]; ``` Here, type specifies the type of data being allocated, size specifies the number of elements in the array, and var-name is the name of array variable that is linked to the array. That is, to use new to allocate an array, you must specify the type and number of elements to allocate. ### **Example:** ```java int intArray[]; //declaring array intArray = new int[20]; // allocating memory to array OR int[] intArray = new int[20]; // combining both statements in one ``` ![One Dimensional Array.jpeg](https://github.com/shoebxsiddiqui/DSA-Java/blob/shoebxsiddiqui-Arrays/lessons/images/One%20Dimensional%20Array.jpeg) ### **Note :** 1. The elements in the array allocated by new will automatically be initialized to zero (for numeric types), false (for boolean), or null (for reference types).Refer Default array values in Java 2. Obtaining an array is a two-step process. First, you must declare a variable of the desired array type. Second, you must allocate the memory that will hold the array, using new, and assign it to the array variable. Thus, in Java all arrays are dynamically allocated. ```java rollnos = new int[5]; //initialisation //Actual memory allocation happens here. Here, Object is being created in Heap memory. ``` ```java Declaration of array Initialisation (compile time) (run-time) | | ____\ /_____ ___\ /____ | | | | int[] arr = new int[5]; ^ ^ ^ / \ / \ / \ | | | | | | | ref var | | | | creating Object in Heap memory DataType ``` This above concept is known as `Dynamic memory allocation` which means at runtime OR execution time is allocated. ### **Array Literal** In a situation, where the size of the array and variables of array are already known, array literals can be used. ```java int[] intArray = new int[]{ 1,2,3,4,5,6,7,8,9,10 }; // Declaring array literal ``` * The length of this array determines the length of the created array. * There is no need to write the new int[] part in the latest versions of Java ### **Accessing Java Array Elements using for Loop** Each element in the array is accessed via its index. The index begins with 0 and ends at (total array size)-1. All the elements of array can be accessed using Java for Loop. ```java // accessing the elements of the specified array for (int i = 0; i < arr.length; i++) System.out.println("Element at index " + i + " : "+ arr[i]); ``` ```java // Java program to illustrate creating an array // of integers, puts some values in the array, // and prints each value to standard output. class Main { public static void main (String[] args) { // declares an Array of integers. int[] arr; // allocating memory for 5 integers. arr = new int[5]; // initialize the first elements of the array arr[0] = 10; // initialize the second elements of the array arr[1] = 20; //so on... arr[2] = 30; arr[3] = 40; arr[4] = 50; // accessing the elements of the specified array for (int i = 0; i < arr.length; i++) System.out.println("Element at index " + i + " : "+ arr[i]); } } ``` ### **Output:** ``` Element at index 0 : 10 Element at index 1 : 20 Element at index 2 : 30 Element at index 3 : 40 Element at index 4 : 50 ``` ### **Arrays of Objects** An array of objects is created just like an array of primitive type data items in the following way. ```java Student[] arr = new Student[7]; //student is a user-defined class ``` The Student array `arr` contains seven memory spaces each of the size of student class in which the address of seven Student objects can be stored. The Student objects have to be instantiated using the constructor of the Student class and their references should be assigned to the array elements in the following way. ```java Student[] arr = new Student[5]; ``` ```java // Java program to illustrate creating an array of // objects class Student { public int roll_no; public String name; Student(int roll_no, String name) { this.roll_no = roll_no; this.name = name; } } // Elements of the array are objects of a class Student. public class GFG { public static void main (String[] args) { // declares an Array of integers. Student[] arr; // allocating memory for 5 objects of type Student. arr = new Student[5]; // initialize the first elements of the array arr[0] = new Student(1,"aman"); // initialize the second elements of the array arr[1] = new Student(2,"vaibhav"); // so on... arr[2] = new Student(3,"shikar"); arr[3] = new Student(4,"dharmesh"); arr[4] = new Student(5,"mohit"); // accessing the elements of the specified array for (int i = 0; i < arr.length; i++) System.out.println("Element at " + i + " : " + arr[i].roll_no +" "+ arr[i].name); } } ``` ### **Output:** ``` Element at 0 : 1 aman Element at 1 : 2 vaibhav Element at 2 : 3 shikar Element at 3 : 4 dharmesh Element at 4 : 5 mohit ``` ### **What happens if we try to access element outside the array size?** JVM throws **ArrayIndexOutOfBoundsException** to indicate that array has been accessed with an illegal index. The index is either negative or greater than or equal to the size of an array. ```java class GFG { public static void main (String[] args) { int[] arr = new int[2]; arr[0] = 10; arr[1] = 20; for (int i = 0; i <= arr.length; i++) System.out.println(arr[i]); } } ``` ### **Runtime error** ``` Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2 at GFG.main(File.java:12) ``` ### **Output:** ``` 10 20 ``` ## **2. Multidimensional Arrays** Multidimensional arrays are arrays of arrays with each element of the array holding the reference of other array. These are also known as Jagged Arrays. A multidimensional array is created by appending one set of square brackets ([]) per dimension. Examples: ```java int[][] intArray = new int[10][20]; //a 2D array or matrix int[][][] intArray = new int[10][20][10]; //a 3D array ``` ![Two Dimensional Array.jpeg](https://github.com/shoebxsiddiqui/DSA-Java/blob/shoebxsiddiqui-Arrays/lessons/images/Two%20Dimensional%20Array.jpeg) ```java class multiDimensional { public static void main(String args[]) { // declaring and initializing 2D array int arr[][] = { {2,7,9},{3,6,1},{7,4,2} }; // printing 2D array for (int i=0; i< 3 ; i++) { for (int j=0; j < 3 ; j++) System.out.print(arr[i][j] + " "); System.out.println(); } } } ``` ### **Output:** ``` 2 7 9 3 6 1 7 4 2 ``` ### **Passing Arrays to Methods** Like variables, we can also pass arrays to methods.For example, below program pass array to method sum for calculating sum of array’s values. ```java // Java program to demonstrate // passing of array to method class Test { // Driver method public static void main(String args[]) { int arr[] = {3, 1, 2, 5, 4}; // passing array to method m1 sum(arr); } public static void sum(int[] arr) { // getting sum of array values int sum = 0; for (int i = 0; i < arr.length; i++) sum+=arr[i]; System.out.println("sum of array values : " + sum); } } ``` ### **Output :** ``` sum of array values : 15 ``` ### **Returning Arrays from Methods** As usual, a method can also return an array. For example, below program returns an array from method m1. ```java // Java program to demonstrate // return of array from method class Test { // Driver method public static void main(String args[]) { int arr[] = m1(); for (int i = 0; i < arr.length; i++) System.out.print(arr[i]+" "); } public static int[] m1() { // returning array return new int[]{1,2,3}; } } ``` ### **Output:** ``` 1 2 3 ``` ### **Class Objects for Arrays** Every array has an associated Class object, shared with all other arrays with the same component type. ```java // Java program to demonstrate // Class Objects for Arrays class Test { public static void main(String args[]) { int intArray[] = new int[3]; byte byteArray[] = new byte[3]; short shortsArray[] = new short[3]; // array of Strings String[] strArray = new String[3]; System.out.println(intArray.getClass()); System.out.println(intArray.getClass().getSuperclass()); System.out.println(byteArray.getClass()); System.out.println(shortsArray.getClass()); System.out.println(strArray.getClass()); } } ``` ### **Output:** ``` class [I class java.lang.Object class [B class [S class [Ljava.lang.String; ``` ### **Explanation :** 1. The string “[I” is the run-time type signature for the class object “array with component type int“. 2. The only direct superclass of any array type is java.lang.Object. 3. The string “[B” is the run-time type signature for the class object “array with component type byte“. 4. The string “[S” is the run-time type signature for the class object “array with component type short“. 5. The string “[L” is the run-time type signature for the class object “array with component type of a Class”. The Class name is then followed. --- ================================================ FILE: lessons/assignment.md ================================================ --- path: "/assignment" title: "Assignments" order: "24A" section: "Assignments & Practise Question" description: "practise some standard question" icon: "question" --- This section will consist some leetcode questions and some practise questions. All the solutions will be in [LeetCode](https://github.com/utkarsh1504/leetcode-solutions) repository. ## Leetcode Question The following is a list of leetcode questions. ### Arrays - - [1. Two Sum](https://leetcode.com/problems/two-sum/) ================================================ FILE: lessons/backtrack-maze.md ================================================ --- path: "/backtrack-maze" title: "Maze Problems" order: "9E" section: "BackTracking In Java" description: "learn about backtracking algorithms" --- ================================================ FILE: lessons/backtrack-nknight.md ================================================ --- path: "/backtrack-nknight" title: "N Knights" order: "9D" section: "BackTracking In Java" description: "learn about backtracking algorithms" --- ================================================ FILE: lessons/backtrack-sudoku.md ================================================ --- path: "/backtrack-sudoku" title: "Sudoku Solver" order: "9B" section: "BackTracking In Java" description: "learn about backtracking algorithms" --- ================================================ FILE: lessons/backtracking.md ================================================ --- path: "/backtracking" title: "Introduction to Backtracking" order: "9A" section: "BackTracking In Java" description: "learn about backtracking algorithms" icon: "sitemap" --- ================================================ FILE: lessons/binarysearch.md ================================================ --- path: "/binarysearch" title: "Binary Search" order: "5B" section: "Searching & Sorting" description: "learn Searching algorithms" --- ================================================ FILE: lessons/bitwise-operator.md ================================================ --- path: "/bitwise-operator" title: "Complete Bitwise Operators" order: "10B" section: "Maths for DSA" description: "learn maths required in DSA" --- In this lesson, we are going to learn about the bit-wise operators, and some Bit-manipulation techniques to get optimized solutions. These concepts are very important from competitive programming as well as interviews point of view. Okay, so let's learn these techniques: In this lesson, we are going to learn about the bit-wise operators, and some Bit-manipulation techniques to get optimized solutions. These concepts are very important from competitive programming as well as interviews point of view. Okay, so let's learn these techniques: ## Bit Manipulation Bit manipulation is the process of applying logical operations on a sequence of bits, the smallest form of data in a computer, to achieve a required result. Bit manipulation has constant time complexity and process in parallel, meaning it is very efficient on all systems. Most programming languages will have you work with abstractions, like objects or variables, rather than the bits they represent. However, direct bit manipulation is needed to improve performance and reduce error in certain situations. Bit manipulation requires a strong knowledge of binary and binary conversion. Here’s a few examples of tasks that require bit manipulation: * Low-level device control * Error detection and correction algorithms * Data compression * Encryption algorithms * Optimization ## Bitwise Manipulation and Coding Interviews Bit manipulation is also a common topic in coding interviews, especially with FAANG companies. These interviewers expect you to have a basic understanding of bits, fundamental bit operators, and generally understand the thought process behind bit manipulation. > Having this knowledge demonstrates that you’re a well-rounded developer who understands both the specific tools and the foundation of computer science. If you’re applying for a role that will work with embedded systems or other low-level systems, you’ll encounter more bit questions. In short, the closer your role is to machine level, the more bit manipulation questions you’ll encounter. The best way to prepare for bit manipulation questions is to practice using each bitwise operator and brush up on your binary to decimal conversions. ## Bitwise Operators In Java You are no doubt familiar with the arithmetic operators such as + - * / or %. You are also aware of logical operators such as & or |. Turns out there is another, a slightly less known set of operators, which manipulate numbers on bit level. Internally, every number is stored in a binary format - that is 0 and 1. Bitwise operators are used for performing manipulation of bits of a number. These can be used with any type of integer data types (char, short, int, etc). These operators can be performed on integer types - * byte (8 bit) * short (16 bit) * int (32 bit) * long (64 bit), and even * char (16 bit) Now let's see its type one by one: ## 1. Unary bitwise complement [~] This fancy name basically means bit negation. It takes every single bit of the number and flips its value,i.e, ~0 becomes 1 and vice versa. It is the 1's complement of the number. Unary means that it needs just one operand. The operator is `~` and it is just placed before the number: ```java a = 5 = 0101 (In Binary) Bitwise Complement Operation of 5 ~ 0101 ________ 1010 = 10 (In decimal) ``` ## 2. Bitwise AND [&] Unlike bitwise complement operator, other bitwise operators need two operands. A & B means that all the bits of both numbers are compared one by one and the resulting number is calculated based on values of the bits from numbers A and B. Bitwise AND is similar to logical AND in a sense that it results in 1 only when the two compared bits are both equal to 1. Otherwise, it results in 0. For example: 1010 & 1100 would result in 1000 as the first bit from the left is the only one where both operands contain 1. ```java a = 5 = 0101 (In Binary) b = 7 = 0111 (In Binary) Bitwise AND Operation of 5 and 7 0101 & 0111 ________ 0101 = 5 (In decimal) ``` ## 3. Bitwise OR [ | ] Bitwise OR results in 1 when at least one of the compared bits is 1 (or both), otherwise it results in 0. ```java a = 5 = 0101 (In Binary) b = 7 = 0111 (In Binary) Bitwise OR Operation of 5 and 7 0101 | 0111 ________ 0111 = 7 (In decimal) ``` ## 4. Bitwise Exclusive OR (XOR) [^] xclusive OR (XOR) results in 1 only if both the compared bits have a different value, otherwise, it results in 0. ```java a = 5 = 0101 (In Binary) b = 7 = 0111 (In Binary) Bitwise XOR Operation of 5 and 7 0101 ^ 0111 ________ 0010 = 2 (In decimal) ``` |A |B |A AND B |A B |A XOR B | |-----|----|----------|---------|----------| |1 |0 |0 |1 |1 | |0 |1 |0 |1 |1 | |1 |1 |1 |1 |0 | |0 |0 |0 |0 |0 | ```java // Java program to illustrate // bitwise operators public class operators { public static void main(String[] args) { // Initial values int a = 5; int b = 7; // bitwise and // 0101 & 0111=0101 = 5 System.out.println("a&b = " + (a & b)); // bitwise or // 0101 | 0111=0111 = 7 System.out.println("a|b = " + (a | b)); // bitwise xor // 0101 ^ 0111=0010 = 2 System.out.println("a^b = " + (a ^ b)); // bitwise not // ~0101=1010 // will give 2's complement of 1010 = -6 System.out.println("~a = " + ~a); // can also be combined with // assignment operator to provide shorthand // assignment // a=a&b a &= b; System.out.println("a= " + a); } } ``` ### Output: ``` a&b = 5 a|b = 7 a^b = 2 ~a = -6 a= 5 ``` ## 5. Signed Left Shift [<<] Signed Left Shift takes two operands. It takes the bit pattern of the first operand and shifts it to the left by the number of places given by the second operand. For example 5 << 3: What happens in this case - Every bit in the binary representation of the integer 5 is shifted by 3 positions to the left. All the places on the left are padded by zeros. That is: `00000101` becomes `00101000`. You can note that the integer result of 5 << 3 is 40. That shows that shifting a number by one is equivalent to multiplying it by 2, or more generally left shifting a number by n positions is equivalent to multiplication by `2^n`. In this case, it is 5*2^3 = 40. * Even though you can use shifting of byte, short or char, they are promoted to 32-bit integer before the shifting * Bit-shift operators never throw an exception * The right operand (the number of positions to shift) is reduced to modulo 32. That is 5 <<35 is equivalent to 5 << 3. ```java a = 5 = 0000 0101 b = -10 = 1111 0110 a << 1 = 0000 1010 = 10 a << 2 = 0001 0100 = 20 b << 1 = 1110 1100 = -20 b << 2 = 1101 1000 = -40 ``` ## 6. Signed Right Shift [>>] Signed right shift moves all the bits by given number of positions to the right. However, it preserves the sign. Positive numbers remain positive and negative ones remain negative. Similar to left shift, the right shift of n positions is equivalent to division by 2^n. Or division by 2^n -1 in case of odd numbers. ```java a = 10 a>>1 = 5 Example 2: a = -10 a>>1 = -5 We preserve the sign bit. ``` ## 7. Unsigned Right Shift [>>>] Unlike the signed shift, the unsigned one does not take sign bits into consideration, it just shifts all the bits to the right and pads the result with zeros from the left. That means that for negative numbers, the result is always positive. Signed and unsigned right shifts have the same result for positive numbers. ```java a = 10 a>>>1 = 5 a = -10 a>>>1 = 2147483643 DOES NOT preserve the sign bit. ``` This operator shifts the first operand to the specified number of bits to the right. Excess bits shifted off to the right are `discarded`. Zero bits are shifted in from the left. The sign bit becomes 0, so the result is `always non-negative`. Unlike the other bitwise operators, zero-fill right shift returns an unsigned 32-bit integer. For non-negative numbers, zero-fill right shift and sign-propagating right shift yield the same result. For example, 9 >>> 2 yields 2, the same as 9 >> 2: ## 8. Unsigned Left Shift [<<<] Unlike unsigned Right Shift, there is no “<<<” operator in Java, because the logical (<<) and arithmetic left-shift (<<<) operations are identical. ```java 9 (base 10): 00000000000000000000000000001001 (base 2) 9 >>> 2 (base 10): 00000000000000000000000000000010 (base 2) = 2 (base 10) ``` However, this is not the case for negative numbers. For example, -9 >>> 2 yields 1073741821, which is different than -9 >> 2 (which yields -3): ```java -9 (base 10): 11111111111111111111111111110111 (base 2) -9 >>> 2 (base 10): 00111111111111111111111111111101 (base 2) = 1073741821 (base 10) ``` |Operator |Example |Is equivalent to | |----------|------------|------------------| |OR= |x OR= 5 |x = x OR 5 | |^= |x ^= 5 |x = x ^ 5 | |&= |x &= 5 |x = x & 5 | |<<= |x <<= 5 |x = x << 5 | |>>= |x >>= 5 |x = x >> 5 | |>>>= |x >>>= 5 |x = x >>> 5 | ```java // Java program to illustrate // shift operators public class operators { public static void main(String[] args) { int a = 5; int b = -10; // left shift operator // 0000 0101<<2 =0001 0100(20) // similar to 5*(2^2) System.out.println("a<<2 = " + (a << 2)); // right shift operator // 0000 0101 >> 2 =0000 0001(1) // similar to 5/(2^2) System.out.println("b>>2 = " + (b >> 2)); // unsigned right shift operator System.out.println("b>>>2 = " + (b >>> 2)); } } ``` ### Output: ``` a<<2 = 20 b>>2 = -3 b>>>2 = 1073741821 ``` ## Bitwise Tricks And Some Questions Now, let’s look at a few tricks you can do using bitwise operators. These are often used as interview questions to check if you’ve reviewed basic bit manipulation and can apply it to day-to-day coding tasks. ### Q1. Check for EVEN / ODD To check a number is even or odd, we need to look at the number in its binary form first, lets take an eg, 4 ,i.e, `0100`, if we look carefully then we will find out that the 1 present in the number is at `power of 2` position, lets take another example now, 6 ,i.e, `0110`, here both the 1's are at `power of 2` position and now we can conclude that in binary form if the number is at power of 2 position the it is even. Lets check for odd no. now, eg, 5 ,i.e, `0101` here the least significant digit(or `LSD`) is `not` at the `power of 2` position and thus it is odd. Now, lets look how to solve this, if we and a number with one then we know we get back that original number, so if we and the last digit with one and if we get 1 then it would be a odd number else it would be even. ```java if (x & 1 ) == 0 return true; else return false; ``` ### Q2. Convert characters to Uppercase/Lowercase This trick tests your knowledge of uppercase and lowercase characters in binary. You can convert any character, `ch`, to the opposite case using `ch ^= 32`. This is because the binary representation of lowercase and uppercase letters are nearly identical, with only 1 bit of difference. Using the XOR operation lets us toggle that single bit and swap it to the opposite value, therefore making a lowercase character uppercase or vice versa. ```java public class Test { static int x=32; // tOGGLE cASE = swaps CAPS to lower // case and lower case to CAPS static String toggleCase(char[] a) { for (int i=0; i 0) { n &= (n - 1); count++; } return count; } public static void main(String[] args) { int number = 125; System.out.println("SetBit Count is : " + helper(number)); } } ``` ### Output: ``` SetBit Count is : 6 ``` In this approach, we count only the set bits. So, * If a number has 2 set bits, then the while loop runs two times. * If a number has 4 set bits, then the while loop runs four times. ### Q4. Single Number You are given an array in which every number appears twice except one number, return that number. ```java class SingleNumber { private static int singleNumber(int[] nums) { int xor = 0; for (int num : nums) { xor ^= num; } return xor; } public static void main(String[] args) { int[] nums = {4, 1, 2, 9, 1, 4, 2}; System.out.println("Element appearing one time is " + singleNumber(nums)); } } ``` ### Output: ``` Element appearing one time is 9 ``` This solution relies on the following logic: * If we take XOR of zero and some bit, it will return that bit: a ^ 0 = a * If we take XOR of two same bits, it will return 0: a ^ a = 0 * For n numbers, the below math can be applied: a ^ b ^ a = (a ^ a) ^ b = 0 ^ b = b Therefore, we can XOR all bits together to find the unique number. ### Q5. Get First Set Bit ```java class FirstSetBitPosition { private static int helper(int n) { if (n == 0) { return 0; } int k = 1; while (true) { if ((n & (1 << (k - 1))) == 0) { k++; } else { return k; } } } public static void main(String[] args) { System.out.println("First setbit position for number: 18 is -> " + helper(18)); System.out.println("First setbit position for number: 5 is -> " + helper(5)); System.out.println("First setbit position for number: 32 is -> " + helper(32)); } } ``` ### Output: ``` First setbit position for number: 18 is -> 2 First setbit position for number: 5 is -> 1 First setbit position for number: 32 is -> 6 ``` The logic of this solution relies on a combination of left shifting and the AND operation. Essentially, we first check if the rightmost significant bit is the set bet using `bit & 1`. If not, we keep shifting left and checking until we find the bit that makes our AND operation yield 1. The number of shifts is tracked by our pointer, k. Once we do find the set bit, we return k as our answer. --- ================================================ FILE: lessons/bmmv-algorithm.md ================================================ --- path: "/bmmv-algorithm" title: "Boyer-Moore Majority Voting Algorithm" order: "4D" section: "Arrays" description: "arrays" icon: "map" --- The Boyer-Moore voting algorithm is used to find the majority element among the given elements that have more than N/2 occurrences. This algorithm works on the fact that if an element occurs more than N/2 times, it means that the remaining elements other than this would definitely be less than N/2. For finding the majority element it takes exactly 2 traversals over the given elements, and works in O(N) time complexity and O(1) space complexity. It's also quite simple to implement, though a little trickier to understand how it works. ## Working This algorithm processes each element one at a time. We first choose a candidate from the given set of elements. If it is same as the candidate element, increase the votes. Otherwise decrease the votes. If votes become 0, take another new element as the new candidate. ## Pseudo Code 1. Traverse through array and assume first element of array is the majority element. 2. Take a counter variable to count frequency of majority element. 3. As you traverse through array, if the current element of the array is same as majority element, increment the counter variable. 4. If the current element is not same as majority element, decrement the counter variable. This is done so that one vote of the majority element gets nullified. 5. If counter reaches 0, then change the majority element to current element and set the counter variable to 1. 6. Now again traverse through the array and find the count of majority element found. 7. If the counter is greater than half the size of the array, that is the majority element. Print the element. 8. Else print that there is no majority element. ## Algorithm ```java majorityElement(int[] nums) maj_ele = nums[0], count = 0, i=0 Traverse through the array from i=0 to i< nums.length using loop if count = 0, maj_ele = nums[i], count = 1 else if current element == maj_ele count++ else count-- Traverse through the array from start to end using loop if count > N/2 return maj_ele else return -1 ``` ## Understand through Example ``` nums[ ]: 1, 1, 1, 1, 2, 3, 5 ``` ``` count = 0: 1, 2, 3, 4, 3, 2, 1 ``` ``` maj_ele = 1: 1, 1, 1, 1, 1, 1, 1 ``` maj_ele = 1 after first traversal and count is ``` count: 1, 2, 3, 4, 4, 4, 4 ``` maj_ele = 1 count > 7/2 i.e 3 So majority element is 1. ## Code Implementation ```java import java.io.*; class Main { // Function to find majority element public static int majorityElement(int nums[]) { int count = 0, maj_ele = nums[0]; // Finding majority element for (int i = 0; i < nums.length; i++) { if (count == 0) { maj_ele = nums[i]; count = 1; } else { if (nums[i] == maj_ele) count++; else count--; } } // Checking if majority element occurs more than N/2 times for (int i = 0; i < nums.length; i++) { if (nums[i] == maj_ele) count++; } if (count > (nums.length / 2)) return maj_ele; return -1; } // Driver code public static void main(String[] args) { int arr[] = { 1, 1, 1, 1, 2, 3, 5 }; int majority = majorityElement(arr); System.out.println(" The majority element is " + majority); } } ``` ### Output The majority element is 1 ## Complexity Analysis ### Time Complexity Two traversal through the array has occured, so the time complexity is linear i.e O(n). ### Space Complexity No extra space is required so space complexity is O(1). ## Problems Based on Boyer-Moore Majority Voting Algorithm - Majority Element : https://leetcode.com/problems/majority-element/solution/ - Majority Element II : https://leetcode.com/problems/majority-element-ii/ ================================================ FILE: lessons/bracktrack-nqueen.md ================================================ --- path: "/backtrack-nqueen" title: "N Queens" order: "9C" section: "BackTracking In Java" description: "learn about backtracking algorithms" --- ================================================ FILE: lessons/bubblesort.md ================================================ --- path: "/bubblesort" title: "Bubble Sort" order: "5C" section: "Searching & Sorting" description: "learn Searching n sorting algorithms" --- Sorting is an everyday tool for programmers.We need to sort many things for many reasons.Like sorting to age,price etc.So there are many sorting algorithms like Merge Sort , Quick Sort, Bubble sort etc. ## **Stable & Unstable Sorting** If Two elements in array has same value, After sorting two things can happen. 1. They exchange their relative position. 2. They don't exchange their relative position. ![Stable Sorting](./images/stableSort.jpeg) From this example we can see that two '26' doesn't replace their relative positions.Hence it is stable sorting algorithms. Merge Sort ,Bubble Sort, insertion sort are actually stable sorting algorithm. On the other hand,Heap Sort, Quick Sort etc are unstable sorting algorithms. ## **Bubble Sort** Bubble Sort is the simplest algorithm. This is named Bubble Sort because its element just swap one by one. It doesn't have any special use in sorting.It is actually used for educational purposes to introduces sorting algorithms. I'm actually sorry if I disappointed you. Sort your emotions then.
    Suppose we have an array of 3 numbers [3,6,2] which should be sorted in incrementing order. We can use Bubble Sort Algorithms to do so.
  • At first, we have to take the first element of the array and compare it to the rest of the elements.If we get any elements lower than it, we will swap the position. Comparison 1: 3 > 6 ->NO
  • Comparison 2: 3 > 2 ->YES swap the positions Then the array will be [2,6,3]
  • Comparison 3: 6>3 -> YES swap the positions Then the array will be [2,3,6]
Boom, We have sorted the array.Now let's try to do this in Java. ## **Bubble Sort Function** ```java void bubbleSort(int array[], int length){ for(int i = 0; i < length-1; i++){ for(int j = i+1; j < length-1; j++){ //first loop is used to check to the (length-1)th index of the aray //second loop is used to check the following items of the arrays int temp; if(array[i] array[j]) { temp = array[i]; array[i] = array[j]; array[j] = temp; } } } //for printing for (int i = 0; i < length; i++) { System.out.println(array[i]); } } } ``` ## **Time Complexity** Now talk about the time complexity of this algorithm.From the coding algorithm that is clear that we have to use a loop and a nested loop. So the complexity becomes O(n*n). Now, let's see the time complexity of bubble sort in the best case, average case, and worst case. We will also see the space complexity of bubble sort. - Best Case Complexity - This case occurs when no sorting is needed, i.e. the array is already sorted. The best-case time complexity of bubble sort is O(n). - Average Case Complexity - It occurs when the array elements are in jumbled order that is not properly ascending and not properly descending. The average case time complexity of bubble sort is O(n^2). - Worst Case Complexity - It occurs when the array elements are required to be sorted in reverse order. That means suppose you have to sort the array elements in ascending order, but its elements are in descending order. The worst-case time complexity of bubble sort is O(n^2). ## **Space Complexity** Here Space complexity is O(1). We just have to make a temp variable which is updated throughout the loop and doesn't need to create anything new. ## Bubble short is majorly used where - - complexity does not matter - simple and shortcode is preferred Now, let's discuss the optimized bubble sort algorithm. ## **Optimized Bubble sort Algorithm** In the bubble sort algorithm, comparisons are made even when the array is already sorted. Because of that, the execution time increases. To solve it, we can use an extra variable swapped. It is set to true if swapping requires; otherwise, it is set to false. It will be helpful, as suppose after an iteration, if there is no swapping required, the value of variable swapped will be false. It means that the elements are already sorted, and no further iterations are required. This method will reduce the execution time and also optimizes the bubble sort. ## Program for optimized implementation of bubble sort in Java. public class Bubble { static void print(int a[]) // function to print array elements { int n = a.length; int i; for (i = 0; i < n; i++) { System.out.print(a[i] + " "); } } static void bubbleSort(int a[]) // function to implement bubble sort { int n = a.length; int i, j, temp; for (i = 0; i < n; i++) { for (j = i + 1; j < n; j++) { if (a[j] < a[i]) { temp = a[i]; a[i] = a[j]; a[j] = temp; } } } } public static void main(String[] args) { int a[] = { 35, 10, 31, 11, 26 }; Bubble b1 = new Bubble(); System.out.println("Before sorting array elements are - "); b1.print(a); b1.bubbleSort(a); System.out.println(); System.out.println("After sorting array elements are - "); b1.print(a); } } ``` ## Usage:- - Due to its simplicity, bubble sort is often used to introduce the concept of a sorting algorithm. - In computer graphics it is popular for its capability to detect a very small error (like swap of just two elements) in almost-sorted arrays and fix it with just linear complexity (2n). For example, it is used in a polygon filling algorithm, where bounding lines are sorted by their x coordinate at a specific scan line (a line parallel to x axis) and with incrementing y their order changes (two elements are swapped) only at intersections of two lines ================================================ FILE: lessons/countsort.md ================================================ --- path: "/countsort" title: "Count Sort" order: "5F" section: "Searching & Sorting" description: "learn Sorting algorithms" --- Counting sort is a sorting algorithm that sorts the elements of an array by counting the number of occurrences of each unique element in the array. In Counting sort, we maintain an auxiliary array which drastically increases space requirement for the algorithm implementation. It works just like hashing, first, we calculate the max value in the input array, the array to be sorted. Then we count the number of occurrences of each array element from 0 to length-1 and assign it into the auxiliary array. This array is used again to retrieve the sorted version of the input array. It actually has linear time complexity but we can’t say that it’s the best algorithm because the space complexity is quite high and it is only suitable to use in a scenario where input array element range is close to the size of the array. ## **Pseudo-Code** 1. Iterate the input array and find the maximum value present in it. 2. Declare a new array of size max+1 with value 0 3. Count each and every element in the array and increment its value at the corresponding index in the auxiliary array created 4. Find cumulative sum is the auxiliary array we adding curr and prev frequency 5. Now the cumulative value actually signifies the actual location of the element in the sorted input array 6. Start iterating auxiliary array from 0 to max 7. Put 0 at the corresponding index and reduce the count by 1, which will signify the second position of the element if it exists in the input array 8. Now transfer array received in the above step in the actual input array ## **Algorithm** ```java countingSort(array, size) max <- find largest element in array initialize count array with all zeros for j <- 0 to size find the total count of each unique element and store the count at jth index in count array for i <- 1 to max find the cumulative sum and store it in count array itself for j <- size down to 1 restore the elements to array decrease count of each element restored by 1 ``` ## **Example for better understanding** Consider the data in the range 0 to 9. Input data: 1, 4, 1, 2, 7, 5, 2 1. Take a count array to store the count of each unique object. Index: 0 1 2 3 4 5 6 7 8 9 Count: 0 2 2 0 1 1 0 1 0 0 2. Modify the count array such that each element at each index stores the sum of previous counts. Index: 0 1 2 3 4 5 6 7 8 9 Count: 0 2 4 4 5 6 6 7 7 7 The modified count array indicates the position of each object in the output sequence. 3. Rotate the array clockwise for one time. Index: 0 1 2 3 4 5 6 7 8 9 Count: 0 0 2 4 4 5 6 6 7 7 4. Output each object from the input sequence followed by increasing its count by 1. Process the input data: 1, 4, 1, 2, 7, 5, 2. Position of 1 is 0. Put data 1 at index 0 in output. Increase count by 1 to place next data 1 at an index 1 greater than this index. ## **Code Implementation** ```java // Counting sort in Java import java.util.*; class Solution { static void countSort(int[] arr) { int max = Arrays.stream(arr).max().getAsInt(); int min = Arrays.stream(arr).min().getAsInt(); int range = max - min + 1; int count[] = new int[range]; int output[] = new int[arr.length]; for (int i = 0; i < arr.length; i++) { count[arr[i] - min]++; } for (int i = 1; i < count.length; i++) { count[i] += count[i - 1]; } for (int i = arr.length - 1; i >= 0; i--) { output[count[arr[i] - min] - 1] = arr[i]; count[arr[i] - min]--; } for (int i = 0; i < arr.length; i++) { arr[i] = output[i]; } } static void printArray(int[] arr) { for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } System.out.println(""); } // Driver code public static void main(String[] args) { int[] arr = { -5, -10, 0, -3, 8, 5, -1, 10 }; countSort(arr); printArray(arr); } } ``` ### **Output** -10 -5 -3 -1 0 5 8 10 ## **Limitations of Count Sort** 1. It is effective when range is not greater than number of object. 2. It is not comparison based complexity. 3. It is also used as sub-algorithm for different algorithm. 4. It uses partial hashing technique to count the occurrence. ## **Complexity Analysis** ### Time Complexity Best : O(n+k) Worst : O(n+k) Average : O(n+k) Stability : Yes In all cases, the complexity is the same because no matter how the elements are placed in the array, the algorithm goes through n+k times, where k is the range of input. There is no comparison between any elements, so it is better than comparison based sorting techniques. But, it is bad if the integers are very large because the array of that size should be made. ### Space Complexity The space complexity of Counting Sort is O(max). Larger the range of elements, larger is the space complexity. ## **Problems Based on Count Sort** 1. Shil and Birthday Present : https://www.hackerearth.com/problem/algorithm/shil-and-birthday-present/ 2. Finding Pairs : https://www.hackerearth.com/problem/algorithm/finding-pairs-4/ 3. Counting Sort : https://practice.geeksforgeeks.org/problems/counting-sort/1 ================================================ FILE: lessons/cyclesort.md ================================================ --- path: "/cyclesort" title: "Cyclic Sort" order: "5H" section: "Searching & Sorting" description: "learn Sorting algorithms" --- Cycle sort is a comparison sorting algorithm which forces array to be factored into the number of cycles where each of them can be rotated to produce a sorted array. It is theoretically optimal in the sense that it reduces the number of writes to the original array. It is an in-place and unstable sorting algorithm. It is optimal in terms of number of memory writes. It minimizes the number of memory writes to sort. Each value is either written zero times, if it’s already in its correct position, or written one time to its correct position. ## Algorithm Consider an array of `n` distinct elements. An element `a` is given, index of `a` can be calculated by counting the number of elements that are smaller than `a`. 1. If the element is found to be at its correct position, simply leave it as it is. 2. Otherwise, find the correct position of `a` by counting the total number of elements that are less than `a` . where it must be present in the sorted array. The other element `b` which is replaced is to be moved to its correct position. This process continues until we got an element at the original position of `a`. ## Code Implementation ```java //Java program for implementation of Cyclic Sort import java.util.Arrays; public class CyclicSort { public static void main(String[] args) { int[] arr = {5, 4, 3, 2, 1}; sort(arr); System.out.println(Arrays.toString(arr)); } //Function to sort array using Cyclic sort public static void sort(int[] arr) { int i = 0; while (i < arr.length) { int correct = arr[i] - 1; if (arr[i] != arr[correct]) { swap(arr, i , correct); } else { i++; } } } //Function to swap two elements public static void swap(int[] arr, int first, int second) { int temp = arr[first]; arr[first] = arr[second]; arr[second] = temp; } } ``` ### Explanation of the example arr [] = {5, 4, 3, 2, 1} Step 1: Count the number of elements less than 5, there are 4 elements less than 5 . move `5` to 5th place in the array ( Index = 4 ). Step 2: So, 5 will take the position of 1 and then count the number of elements less than 1, there are no elements less than 1 . move `1` to 1st place in the array ( Index = 0 ). Step 3: The original position of 5 is acquired and one cycle is completed Step 5: Repeat same for all elements. ## Complexity analysis The time complexity of the cyclic sort is **O(n)**. The while loop, in the worst case, can iterate a maximum of `2n-1` times. As you can see, we are not incrementing the index `i` when swapping the numbers, this will result in more than `n` iterations of the loop, but in the worst-case scenario, the while loop will swap a total of `n-1` numbers and once a number is at its correct index, we will move on to the next number by incrementing `i`. So overall, our algorithm will take **O(n) + O(n-1)** or we can say **O(2n-1)** which is asymptotically equivalent to **O(n)**. ================================================ FILE: lessons/dataTypes.md ================================================ --- path: "/dataTypes" title: "Learn Data Types" order: "3A" section: "Learn Java" description: "Learn java" icon: "coffee" --- So before knowing what are data types. First let's know what are variable and Constants. ## Variable Simply, Variable are placeholder for some data values. when we are creating a variable we are just reserving some memory locations or reserving some space in memory to store values. In C++, there are different types of variables,eg: - **int** stores integers such as 7 or -3. - **float** - stores decimal numbers, such as 7.33 or -3.77. etc. ## Constant As its name suggest **constant**- which does not change, they remain fixed. Basically these are fixed values which do not change and it must have to be initialized at the time of creation, we can not assign any new values to it later. That's why these are called **literals**, cuz it can not be modified. ## Data Types Data types are important because each programming language needs different types of data like integers and strings, and these data are stored as that data type. Data types are used to define a variable before to use in a program, its a constrains that a expression, such as variable or a function, might take. In Java, whenever a variable is defined, the compiler(which compiles source code written in a high-level language(Java) into a set of machine-language that can be understood by a digital computer's CPU) allocates some memory for that variable based on their data-type. It has some types: ![data-types](./images/dataTypes.png) There are two types of data types in Java: 1. **Primitive data types**: The primitive data types include boolean, char, byte, short, int, long, float and double. These are pre defined or they are the most basic structure for building more sophisicated data types.they always have a value. 2. **Non-primitive data types**: The non-primitive data types or reference data types include Classes, Objects, Interfaces, Strings, and Arrays. They have null as default value. In Java, all variables must be declared first before they can be used. # Primitive Data-Type These are the building blocks of data manipulation. In Java, these are the most basic data types. These are of `8 types`: |Data Types |Default Value |Default Size | |-------------|-----------------|---------------| |boolean |false |1 bit | |char |'\u0000' |2 byte | |byte |0 |1 byte | |short |0 |2 byte | |int |0 |4 byte | |long |0L |8 byte | |float |0.0f |4 byte | |double |0.0d |8 byte | 1. **Boolean Data Type** : Variables declared with boolean data type can store only true/false. These are used as flag which checks for a particular conditions. Its size is only 1 bit. ```java boolean a = false; ``` 2. **Byte Data Type** : It is 8-bit signed 2's complement integer. Its value-range lies between -128 to 127 (inclusive). Its default value is 0. The byte data type is used to save memory in large arrays where the memory savings is most required. It saves space because a byte is 4 times smaller than an integer. It can also be used in place of "int" data type. ```java byte a = 10; byte b = -20; ``` 3. **Short Data Type** : It is a 16-bit signed 2's complement integer. Its value-range lies between -32,768 to 32,767 (inclusive). Its default value is 0. A short data type is 2 times smaller than an integer. ```java short a = 10000; short b = -5000; ``` 4. **Int Data Type** : It is a 32-bit signed 2's complement integer. Its value-range lies between - 2,147,483,648 (-2^31) to 2,147,483,647 (2^31 -1) (inclusive). Its default value is 0. It is generally used as a default data type for integral values. ```java int a = 100000; int b = -200000; ``` 5. **Long Data Type** : It is a 64-bit 2's complement integer. Its value-range lies between -9,223,372,036,854,775,808(-2^63) to 9,223,372,036,854,775,807(2^63 -1)(inclusive). Its default value is 0. The long data type is generally used when the integer that we have to store exceeds the range provided by int data type. ```java long a = 100000L; long b = -200000L; ``` 6. **Float Data Type** : It is a single-precision 32-bit IEEE 754 floating point.Its value range is unlimited. It is recommended that we should use float (instead of double) if yweou need to save memory in large arrays of floating point numbers. It should never be used for precise values, such as currency. Its default value is 0.0F. ```java float f1 = 234.5f ; ``` 7. **Double Data Type** : It is a double-precision 64-bit IEEE 754 floating point. Its value range is unlimited. This is also generally used for decimal values just like float. The double data type also should never be used for precise values, such as currency. Its default value is 0.0d. ```java double d1 = 12.3; ``` 8. **Char Data Type** : It is a single 16-bit Unicode character. Its value-range lies between '\u0000' (or 0) to '\uffff' (or 65,535 inclusive). It is used to store characters. ```java char letterA = 'A'; ``` # Non-Primitive Data-Type These are created by programmers, unlike primitive data types which are already built-in. These are used to store a group of values for eg, Arrays, in arrays we store a group of data, another eg is list. Therefore, these are also known as advanced data types in Java. When we define a variable of non-primitive data types, it references a memory location where data is stored in the heap memory. That's why, a non-primitive data type is also known as reference data type in Java or simply object reference variable. Non-Primitive data types are created by instantiation, i.e, an object is created. This object reference variable lives on the stack memory and the object to which it points always lives on the heap memory. The stack holds a pointer to the object on the heap. This object can have more than one reference variable, and if we make changes on the data of the object through one reference variable the actual object gets changed and this changed objects's data is changed in all the variables that are pointing(or referencing) to this object. Let's see some of its types: 1. **Class** : Every class is considered as user-defined data type as a user creates a class. In Java programming, a class is basically a user-defined data type that act as a template for creating objects of identical type. It represents the common properties and actions (functions) of an object. ```java public class GitHub { // class body. } ``` 2. **Object** : An object is any real-world thing that has some properties and actions. In other words, an entity that has state and behavior is known as an object. An Object has three characterstics - State, Behaviour and Identity. ```java Person p = new Person(); ``` 3. **String** : A String is also a class. It represents a sequence of characters like Shuaib, A123, etc. The simplest way to create a string object is by storing sequence of characters into string type variable. ```java String str = "India"; ``` 4. **Arrays** : It is an Object which is used to store multiple data of same data type. It can store Primitive as well as Non-Primitive data in it. ```java int [] numbers; Student [] x; // Student is a name of class. ``` 5. **Interface** : An interface is declared like a class but the only difference is that it contains only final variables and method declarations. It is a fully abstract class. It is blue print of a class. It is mechanism in Java to achieve abstraction and multiple inheritance. There can only be abstract methods and variables and no method body. ```java interface printnum{ void print(); } ``` ================================================ FILE: lessons/firstjavaprogram.md ================================================ --- path: "/firstjavaprogram" title: "First Java Program" order: "2C" section: "Basics" description: "run java" --- Create a fresh new java class file in the `src/` directory with **.java** extension. Don't worry we'll explain this in detail later and start writing the following code in it. ```java // Create a hello world program public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } } ``` OKay so lots of horrible looking code, but it's not that bad, we'll get it line by line. - The first line is the class declaration. It tells the compiler what the class is called and what it does (in this case it's a HelloWorld class). - The 2nd line is the main method. This is where the program starts. `public` is the access modifier, `static` is the modifier, `void` is the return type, `main` is the method name, and `(String[])` is the parameter list. The parameter list is a list of strings, which are the arguments passed to the program. This is basically the terminology. - The 3rd line is the `System.out.println` statement. This is a method call. `System` is the class, `out` is the object, `.` is the dot operator, `println` is the method name, and inside the parentheses we pass the string `Hello World!`. ================================================ FILE: lessons/flow-of-recursion.md ================================================ --- path: "/flow-of-recursion" title: "Flow of Recursion" order: "8B" section: "Recursion" description: "learn Recursion from scratch" --- ================================================ FILE: lessons/flowchart.md ================================================ --- path: "/flowchart" title: "Flowchart & Pseudocode" order: "2A" section: "Basics" description: "this is the description that will show up in social shares" icon: "code" --- Through this journey we will be learning problem solving approaches, skills and their associated tools. If we have given any problem what we'll do first? we first understand the problem and its context and then we try to think of the solution and write down the steps of solution and then we try to convert our solution(idea) into the code. So for writing down the solution we will use flow chart and pseudocode. ## **Flowchart** - It is a visual representation of the solution to a given problem. - It allows us to see the solution step by step by breaking them into smaller steps. #### Flowchart Components - **Start**: The starting point of the flowchart. similarly `End` is the end point where the flowchart ends. - **Input/Output**: The input and output of the flowchart. - **Process**: The process of the flowchart. - **Decision**: The decision of the flowchart. - **Arrow**: The arrow that connects the process to the decision. Lets understand the flowchart by looking at the following flowchart. [img](#flowchart) [img](#flowchart) ## **Decision Making** Decision making is a process of making a choice based on the available options. we have decision box, it kind of looks like a kite shape. so lets see an example: - check whether number is Odd or even - Find largest of three numbers ## **Understanding Loops** So let suppose we have to print numbers from 1 to n. then how do we do it? Obivously we will start from 1 and then after priting 1 we have to think the next number of the sequence, so we'll basically add 1 in the previous number and we'll get the next number, this process will keep repeating until we reach n. and when we reach n then we have to check that we don't write the number which comes after the n. Here you will see you are repeating the process and a loop is formed. eg: - find if a given number is prime or not. - find the prime numbers till N. Let's solve a problem. ```java // find largest of N numbers 10, 8, 15, 6, 20 ``` ================================================ FILE: lessons/functions.md ================================================ --- path: "/functions" title: "Function & Scope" order: "3F" section: "Learn Java" description: "Learn how to use functions and scope" --- Whether you a professional programmer or just a beginner it is always better to break your programme into blocks, or functions. It will help you later, first of all in debugging, secondly, it is just better to have an elegant, readable and organized code. A function is a part of a program that has its own name. This name can be used in the program as a command (this command is called a function call). When a function is called, the commands of which it consists are executed. A function call can return a value (similar to an operation) and therefore can be used in an expression along with operations. In java, **Method** is also called as **Behaviour**. And **Variables** are also called as **States**. ### **Syntax** ```java public static int function() { //your function Body here// } ``` ### **Example** ```java public static void function() { System.out.println("Hello World"); } ``` The main function which calls the above function is as follows: ```java public static void main(String []args) { //function() called below to print "Hello World" function(); } ``` The **output** is as follows ```js Hello World ``` ## **Return type + program examples** Whenever you define a method in java, you specify a return type i.e. that can be any data type, whether primitive or non-primitive and if you don't want to return a data-type you mark it as void (that means you dont want to return anything from the method). To return a something from a method you need to use "**return**" keyword followed by the name of the variable or object. The below example depicts to return a **Integer(int)** value. ```java public static int function() { int count = 0; //your code here //returning count return count; } ``` Make sure that you return the integer value or else, **Compilation fails**. ## **Parameters and Pass-By-Value** ## **Scope** **Scope** of a variable is the part of the program where the variable is **accessible**. Like C/C++, in Java, all identifiers are lexically (or statically) scoped, i.e.scope of a variable can determined at compile time and independent of function call stack. Java programs are organized in the form of classes. Every class is part of some package. Java scope rules can be covered under following categories. 1. **Member Variables** - Scope of member variable is all over the class. You can use it anywhere but inside the class. 2. **Local Variables** - Scope of Local variable is between the methods not outside the method, if you do so compiler throws an exception. 3. **Block Variables** - The variables declared inside the block level statements cannot be accessed from outside the block. These blocks includes different types of loops, if else statements, etc. ```java class Scope { static int c = 10; //the reason to make c as static is that if we want //to use a variable inside a static method then it //should be static public static void main(String []args) { //below both are local variables. int a = 10; int b = 20; //Block Statement if(a > b) { //here variable d is block variable //so d cannot be used outside if statement int d = a + b ; } //if i try to print value of variable d below //it will throw an error. //System.out.pritnln(d); //but we can print c here because c is a global variable //and its scope is all ove the class. System.out.println(c); }// end of main function }//end of class Scope ``` ## **Shadowing** Shadowing in Java is the practice of using variables in overlapping scopes with the **same** **name** where the variable in low-level scope overrides the variable of high-level scope. Here the variable at high-level scope is shadowed by the low-level scope variable. In other words we can also say that it will use the global variable untill it finds local variable i.e it will use the local variable when **overlapping** is met. You can get it well by refering to the below example ```java class shadow { static int x = 20; public static void main(String []args) { //here it preints the global variable System.out.println(x); int x = 40; //here the overlapping is met //so it will print the local variable System.out.println(x); } } ``` The output is as follows: ``` 20 40 ``` ## **Overloading** - In method overloading, we can create methods that have the same name, but the methods differ in type, number and/or sequence of parameters. - When an overloaded method is invoked, Java uses the type, number and/or sequence of arguments as its guide to determine which version of the overloaded method to actually call. - When java encounters a call to an overloaded method, it simplyexecutes the version of the method whose parameters match the arguments used in the call. **Rules of Overloading** - Overloaded methods must change the **arguments** list i.e numbers, datatye or sequence. - Overloaded methods can change the **return** type. - overloaded methods can change the **access modifier**. The below example depicts the concept of method overloading. ```java class Adder { static int add(int a,int b) { return a+b; } static int add(int a,int b,int c) { return a+b+c; } } class TestOverloading { public static void main(String[] args) { System.out.println(Adder.add(11,11)); System.out.println(Adder.add(11,11,11)); } } ``` The output is as follows ``` 22 33 ``` ## **Conclusion** Hence after refering the above topics, we can conclude that if you need some code to be executed again again then we must use methods to increase the code reusability and increase the performance of the program. And also seen that how important is, the concept of overloading and the rules for it. Shadowing is also a great and unique concept where, whenever the variables overlaps then the latest one is considered. ## **Some Examples to practice** - Write a java program to find the area of different shapes by using the concept of method overloading. - Write a suitable java program which depicts the concept of shadowing. ================================================ FILE: lessons/greedy.md ================================================ --- path: "/greedy" title: "Introduction to Greedy Algorithms" order: "20A" section: "Greedy Algorithms" description: "complete greedy algorithm" --- ================================================ FILE: lessons/insertion.md ================================================ --- path: "/insertion" title: "Insertion Sort" order: "5E" section: "Searching & Sorting" description: "learn Sorting algorithms" --- Insertion sort is the sorting mechanism where the sorted array is built having one item at a time. The array elements are compared with each other sequentially and then arranged simultaneously in some particular order. ## Explanation The first element of the array forms the sorted subarray while the rest create the unsorted subarray from which we choose an element one by one and **insert** the same in the sorted subarray. The same procedure is followed until we reach the end of the array. In each iteration, we extend the sorted subarray while shrinking the unsorted subarray. The array is searched sequentially and unsorted items are moved and inserted into the sorted sub-list (in the same array). * If it is the first element, it is already sorted. return 1; * Pick next element * Compare with all elements in the sorted sub-list * Shift all the elements in the sorted sub-list that is greater than the value to be sorted * Insert the value * Repeat until list is sorted ## Pseudocode ```pseudocode procedure insertionSort( A : array of items ) int holePosition int valueToInsert for i = 1 to length(A) inclusive do: /* select value to be inserted */ valueToInsert = A[i] holePosition = i /*locate hole position for the element to be inserted */ while holePosition > 0 and A[holePosition-1] > valueToInsert do: A[holePosition] = A[holePosition-1] holePosition = holePosition -1 end while /* insert the number at hole position */ A[holePosition] = valueToInsert end for end procedure ``` ## Complexity analysis Insertion sort runs in *O*(*n*) time in its best case and runs in *O*(*n*²) in its worst and average cases. ### Best case Insertion sort performs two operations: it scans through the list, comparing each pair of elements, and it swaps elements if they are out of order. Each operation contributes to the running time of the algorithm. If the input array is already in sorted order, insertion sort compares *O*(*n*) elements and performs no swaps. Therefore, in the best case, insertion sort runs in O(*n*) time. ### Worst case The worst case for insertion sort will occur when the input list is in decreasing order. To insert the last element, we need at most *n*−1 comparisons and at most *n*−1 swaps. To insert the second to last element, we need at most *n*−2 comparisons and at most *n*−2 swaps, and so on. The number of operations needed to perform insertion sort is therefore: 2 × (1+2+⋯+*n* −2+*n* −1) . This is in the order of sum of first n-1 numbers which is quadratic in nature. therefore, in the worst case, insertion sort runs in O(*n*²) time. > The average case and the worst case have the same time complexity. Try to think why is this happening. ## Code Implementation ```java // Java program for implementation of Insertion Sort public class InsertionSort { public static void insertionSort(int[] input) { for (int i = 1; i < input.length; i++) { int j = i - 1; int temp = input[i]; for (; j >= 0 && input[j] > temp; j--) { input[j + 1] = input[j]; } input[j + 1] = temp; } } public static void main(String[] args) { int[] input = { 1, 5, 4, 2, 3 }; insertionSort(input); for (int j : input) { System.out.print(j + " "); } } } ``` > > >Explanation of the example arr [] = {1 , 5 , 4 , 2 , 3 } > >Step 1 : No element on the left side of 1. so, no change in position. > >Step 2 : As 1 < 5. so no change in position. > >Step 3 : As 5 > 4. 4 and 5 will swap. now 1 < 4. so no change in postion. > >Step 4 : As 5 > 2. 2 and 5 will swap. now 4 > 2 so 2 and 4 will swap. now 1 < 2, so no change in position. > >Step 5: As 5 > 3. 3 and 5 will swap. now 4 > 3 so 3 and 4 will swap. now 2 < 3, so no change in position. Now our array is sorted. you can visualize this at [hackerearth](https://www.hackerearth.com/practice/algorithms/sorting/insertion-sort/visualize/) ## Advantages - Simple and easy to understand implementation - Efficient for small data - If the input list is sorted beforehand (partially) then insertions sort takes `**O(n+d)**` where d is the number of inversions - Chosen over bubble sort and selection sort, although all have worst case time complexity as `**O(n^2)**` - Maintains relative order of the input data in case of two equal values (stable) - It requires only a constant amount `**O(1)**` of additional memory space (in-place Algorithm) ## Applications - It could be used in sorting small lists. - It could be used in sorting "almost sorted" lists. - It could be used to sort smaller sub problem in Quick Sort. ================================================ FILE: lessons/intro-binarytree.md ================================================ --- path: "/intro-binarytree" title: "Intro to Binary Tree" order: "15A" section: "Binary Tree" description: "learn about Binary Tree from scratch" icon: "tree" --- ================================================ FILE: lessons/intro-bst.md ================================================ --- path: "/intro-bst" title: "Intro to BST" order: "16A" section: "Binary Search Tree" description: "learn about Binary Search Tree from scratch" icon: "search" --- ### Binary Search Tree A Binary Search Tree is a binary tree that additionally satisfies the binary search property. ### Binary Tree Property This property states that the key in each node must be greater than or equal to any key stored in the left sub-tree and less than or equal to any key stored in the right sub-tree. ![BinarySearchTree_diagram](images/BinarySearchTree_diagram.png) ## Operations In BST ### Searching 1. We begin by examining the root node. If the tree is null , the key we are searching for does not exist in the tree. 2. If the key equals that of the root If the key is equal that of route the search is successful and we return the node . 3. If the key is less than that of the root we search the left subtree. Similarly, if the key is greater than that of the root, we search the right subtree. 4. This process is repeated until the key is found or the remaining subtree is null. 5. If the search key is not found after a null subtree is reached, then the key is not present in the tree. ### Insertion To insert for a key in the tree , we follow the binary search property and insert accordingly. 1. Compare the key to be searched with the root key. 2. If the key is lesser than the roots value, we return the left subtree of the node. 3. If the key is greater than the roots value, we return the right subtree of node. 4. This process continued until we hit a leaf node. The new node is inserted to this location as a new node. ### Deletion When removing a node from a binary search tree it is mandatory to maintain the in-order sequence of the nodes. There are three possible cases to consider: 1. Deleting a node with no childeren :simply remove the node from the tree 2. Deleting a node with one child: remove the node and replace it with its child. 3. Deleting a node with two children: First we find the inorder successor of the node.
Then the contents of this in-order successor are copied to the node to be deleted. Finally, the in-order successor is deleted
Let's see the implementation of Binary Search Tree using an example: ```java // Java implementation of recursive Binary Search class BinarySearch { // Returns index of x if it is present in arr[l..r], // else return -1 int binarySearch(int arr[], int l, int r, int x) { if (r >= l) { int mid = l + (r - l) / 2; // If the element is present at the // middle itself if (arr[mid] == x) return mid; // If element is smaller than mid, then // it can only be present in left subarray if (arr[mid] > x) return binarySearch(arr, l, mid - 1, x); // Else the element can only be present // in right subarray return binarySearch(arr, mid + 1, r, x); } // We reach here when element is not present // in array return -1; } // Driver method to test above public static void main(String args[]) { BinarySearch ob = new BinarySearch(); int arr[] = { 2, 3, 4, 10, 40 }; int n = arr.length; int x = 10; int result = ob.binarySearch(arr, 0, n - 1, x); if (result == -1) System.out.println("Element not present"); else System.out.println("Element found at index " + result); } } ``` Output : ``` Element is present at index 3 ``` ## Visualisations [BinarySearch Visualisation](https://www.cs.usfca.edu/~galles/visualization/BST.html) ================================================ FILE: lessons/intro-complexity.md ================================================ --- path: "/intro-complexity" title: "Complexity Analysis" order: "7A" section: "Space & Time Complexity" description: "learn about time and space complexity for various algorithms" icon: "flask" --- Ok so till now we have just learn some algorithm and tried to solve some problems based on them. Now an important question arise while programming is: How efficient is an algorithm or piece of code? How much time and space does it take to run? ## *What is Complexity analysis* It's really important to understand the real-world significance of **algorithms and its properties** because using different ideas one can design many algorithms for computing a solution to a given problem. Key important questions in algorithms are : - How do we design **good** algorithms? - How do we know that our algorithm is **efficient**? - How to efficiently implement algorithms in a programming language? > **Interviewer** *often checks your ideas and coding skills by asking you to write a code giving restrictions on its* **time or space complexities.** ## *Why to do Complexity analysis* We already know there are tools to measure how fast a program runs. There are programs called *profilers* which measure running time in milliseconds and can help us optimize our code by spotting bottlenecks. While this is a useful tool, it isn't really relevant to algorithm complexity. Algorithm complexity is something designed to compare two algorithms at the idea level — ignoring low-level details such as the implementation programming language, the hardware the algorithm runs on, or the instruction set of the given CPU. We want to compare algorithms in terms of just what they are: Ideas of how something is computed. Counting milliseconds won't help us in that. It's quite possible that a bad algorithm written in a low-level programming language such as [assembly](http://en.wikipedia.org/wiki/Assembly_language) runs much quicker than a good algorithm written in a high-level programming language such as [Python](http://www.python.org/) or [Ruby](http://www.ruby-lang.org/en/). ### *Memory* Memory in a computer is just a sequential set of "buckets" that can contain numbers, characters, or Boolean values. By using several buckets in a row, we get arrays. By giving names to a set of contiguous buckets, we get a "structure". But at its core, a computer memory is a very simple list of numbers. Everything else must be built up upon this. 1. Memory is laid out in sequential order basically from 0 on up (one byte at a time). Each position in memory has a number (called its address!). 2. The compiler (or interpreter) associates your variable names with memory addresses. 3. In some languages like C, you can actually ask the computer for the address of a variable in memory. In C this is done using the ampersand & In many languages, the actual address is hidden from you and is of little use to you, as all the access methods "abstract" the details of the computer hardware away, allowing the programmer to concentrate on the algorithm, and not the details. 4. Arrays variables simply contain the address of the first element of the array. Arrays are zero based so the address simply becomes the base address plus the index. 5. Structure variables simply contain the address of the first element of the structure, and each "named" field of the structure forms an offset from the first bucket. The computer keeps track of this offset so that the programmer can use symbolic names instead of numbers. 6. Memory buckets are 8 bits long (or one byte). A character (char) is one byte. An integer is (usually) four bytes. A float is four bytes. A double is 8 bytes. ### **Performance** It conclude on the basis of time/memory/disk/etc. usage when we run the code. It depends on the machine, compiler, OS, etc as well as the code itself. ### **Complexity** We are typically interested in the execution time of large instances of a problem, e.g., when 𝑛 → ∞, (asymptotic complexity). _for this we introduce the big O notation._ **Big O notation** is a mathematical notation that describes the limiting behavior of a function when the argument tends towards a particular value or infinity. big O notation is used to classify algorithms according to how their run time or space requirements grow as the input size grows. In analytic number theory, big O notation is often used to express a bound on the difference between an arithmetical function and a better understood approximation. Big O notation characterizes functions according to their growth rates: different functions with the same growth rate may be represented using the same O notation. The letter O is used because the growth rate of a function is also referred to as the **order of the function**. A description of a function in terms of big O notation usually only provides an upper bound on the growth rate of the function. | Function | common name | | :------: | :----------: | | N! | factorial | | 2^n | exponential | | n³ | cubic | | n² | quadratic | | n log n | quasi-linear | | n | linear | | log n | logarithmic | | 1 | constant | ## Different types of complexity There are several different types of complexities , we will only be looking into the more popular and the most commonly used ones. ### Constant Time Complexity: O(1) Complexity **O(1)** is the best, it’s not always achievable, but if it is, then your code is *independent* of the input size. Other operations that have complexity **O(1)** are the print function, simple arithmetic — addition, subtraction, and multiplication and division in the case of integers. ### Linear Time Complexity: O(n) When time complexity grows in direct proportion to the size of the input, you are facing Linear Time Complexity, or O(n). Algorithms with this time complexity will process the input (n) in “n” number of operations. This means that as the input grows, the algorithm takes proportionally longer to complete. Linear running time algorithms are very common, and they relate to the fact that the algorithm visits every element from the input. ### Logarithmic Time Complexity: O(log n) Algorithms with this complexity make computation amazingly fast. An algorithm is said to run in logarithmic time if its time execution is proportional to the logarithm of the input size. This means that instead of increasing the time it takes to perform each subsequent step, the time is decreased at a magnitude that is inversely proportional to the input “n”. ### Quadratic Time Complexity: O(n²) In this type of algorithms, the time it takes to run grows directly proportional to the square of the size of the input (like linear, but squared). Nested **For Loops** run on quadratic time, because you’re running a linear operation within another linear operation, or *n* which equals *n².* If you face these types of algorithms, you’ll either need a lot of resources and time, or you’ll need to come up with a better algorithm. ### O(n log(n)) If we have a code or an algorithm with complexity **O(log(n))** that gets repeated multiple times, then it becomes **O(n log(n))**. Famous examples of this are __merge sort and quicksort__. # Big O rules Going through the above examples, you might have figured out some rules for calculating Big O, but let’s sum them up: 1. Reading, writing an item in a list or a dictionary has **O(1)**. 2. Going through an iterable is **O(n)**. 3. Nested loops lead to **O(n²)** complexity. 4. Any divide and concur approach or loops handling binary numbers have **O(n log(n))** complexity. 5. We sum up the complexity of sequential loops and multiply the complexity of nested loops. ================================================ FILE: lessons/intro-dp.md ================================================ --- path: "/intro-dp" title: "Introduction to DP" order: "19A" section: "Dynamic Programming" description: "learn about Dynamic Programming" icon: "sitemap" --- ================================================ FILE: lessons/intro-ds.md ================================================ --- path: "/intro-ds" title: "Introduction to Data Structures" order: "12A" section: "Linked Lists" description: "complete intro to data structures" icon: "link" --- ================================================ FILE: lessons/intro-graph.md ================================================ --- path: "/intro-graphs" title: "Introduction to Graphs" order: "22A" section: "Graphs" description: "learn about graph data-structure from scratch" icon: "map-signs" --- ================================================ FILE: lessons/intro-hashmap.md ================================================ --- path: "/intro-hashmap" title: "Introduction to Hashmap" order: "18A" section: "Hashmap" description: "learn about hashmap from scratch" icon: "book" --- ================================================ FILE: lessons/intro-heap.md ================================================ --- path: "/intro-heap" title: "Introduction to Heaps" order: "17A" section: "Heaps" description: "complete introduction to heaps" icon: "object-ungroup" --- ================================================ FILE: lessons/intro-linkedlist.md ================================================ --- path: "/intro-linkedlist" title: "Introduction to Linked List" order: "12B" section: "Linked Lists" description: "learn Linked list from scratch" --- ================================================ FILE: lessons/intro-maths.md ================================================ --- path: "/intro-maths" title: "Introduction to Maths in DSA" order: "10A" section: "Maths for DSA" description: "learn maths required in DSA" icon: "plus" --- ================================================ FILE: lessons/intro-oop.md ================================================ --- path: "/intro-oop" title: "Introduction" order: "11A" section: "Object Oriented Programming" description: "complete introduction to object oriented programming" icon: "object-ungroup" --- Having learned the material in the preceding chapters, you are able to solve many programming problems using selections, loops, methods, and arrays. However, these Java features are not sufficient for developing graphical user interfaces and large-scale software systems. Suppose you want to develop a graphical user interface (GUI, pronounced goo-ee) for Calculator. How would you program it? Okay so, In this lesson we'll be talking about OOP(Object Oriented Porgramming) concepts.Object-Oriented Programming paradigm is a popular programming paradigm which is used to write to good quality code and this is the paradigm which is the default choice everywhere whether you want to do web or android development or any sort of development from now onwards, OOP concepts are the concepts that will be most useful to you. So before we go in detail of the OOPs, let's try to understand why OOP is the most popular choice. Basically Object-Oriented Programming is actually inspired by the real life problems that you're trying to solve. The intent behind OOP is whatever your problem is, your code should be looks similar to the problem that you are trying to solve. When you are solving a problem then you would find that your code also revolves around **Objects**. An **object** represents an entity in the real world that can be distinctly identified. For example, a student, a desk, a circle, and button can all be viewed as objects. An object has a unique identity, state, and behavior. So In OOP, what we do is, we identify which are objects to which our problem will revolves around and then we try writing code assimilating the problem that we're trying to solve. Let's understand this by an example. Suppose you have given a project from college which is college management system, now In this project, what all do you think will be key entities around which this system will revolve. I think the key entities will be teachers, students, departments, batches, courses, etc will be objects for us to work with. Now we have Objects, then obiviously they'll have proeperties associated with themselves. Now as you move forward you'll realise that OOP is revolving around two major terms which is basically Objects and Classes. So what exactly is an object, let's we have some students S1, S2, S3, S4, so each student is our object, now each student will have certain set properties associated and functionality with them such as name, uid, phone number, address, email etc. and functionality let's say isEligibleForScholarhip, getBatch, getDepartment, etc. Now S1, S2, S3, S4 all are have these properties, so when you're creating an object you would not want to write that list of properties everytime, instead you would want that I just create an object and I can expect that object will have all the set of properties and functionality, So this is where Classes come in. **Class** is basically a template of properties of an object. So, if you have a student S1, S2, S3, S4, then you can create a class called Student and then create an object of that class called S1, S2, S3, S4. Now, S1, S2, S3, S4 will have all the properties and functionality of the Student class. Now a class will only indicate the list of properties that a student should have not values. Actual values of these properties will be the once that you will specify once you create an object of that class. For example, S1 and S2 will both have a property name, but their values(names may be different) will be different. So this is the difference b/w classes and objects. Objects are actually is an instance of a class Now I hope you've got the idea of how OOP works, so let's move further. ================================================ FILE: lessons/intro-priorityqueues.md ================================================ --- path: "/intro-priorityqueues" title: "Introduction to Priority Queues" order: "21A" section: "Priority Queues" description: "learn about Priority Queues from scratch" icon: "braille" --- ================================================ FILE: lessons/intro-programming.md ================================================ --- path: "/intro-programming" title: "Intro to Programming" order: "1B" section: "Introduction" description: "learn Java" --- There is a question comes in everyone's mind before getting started with coding or ds algo or Competitive Programming(**cp**) - Which is the best programming language to get started with? And truly it's quite important to figure out the language which is most suitable for you. So we're just going to recommend you two languages- 1. C++ 2. Java Now, If you are interested in doing some development and also wanted to learn ds algo and _cp_, definitely choose `Java`. But if your main focus is _cp_ and wanted to do game development or likes to work on Operating System then choose `C++`. ## **C++** C++ is a programming language which can be used to develop games, operating systems, Graphical User Interfaces(GUI) etc. It supports procedural programming object-oriented programming (**OOPs**), functional programming(**FP**), etc. C++, developed by `Bjarne Stroustrup`, is a relatively faster programming language in comparison with other and That's why it is most recommended and widely used in Competitive coding rounds. It consists some rich libraries like Standard Template Library(**STL**) which includes template classes that has various data structures such as stacks,lists,trees,graphs, arrays, etc ## **Java** **JAVA** another most recommended programming language for Competitive Programming. It is developed by Sun Microsystems and is used to build large class applications. Java works great within corporate environments, although it can be used for small tasks, it's less suited for that. Many popular IDE's and tools are are written and developed in Java such Eclipse, IntelliJ IDEA and NetBeans IDE. In this course I will pick Java as a programming language for learning data structures and algorithms. It has various features like OOPs, Functional Programming, Generics, etc. It is relatively more stable than other and it also has multi-threading support. Java is very efficient at memory management and it is very fast. #### **Java Plateform Independent** As you may have hear from others that Java is a platform independent language, so what does it mean basically lets understand. lets we have, ```java code machine c = a + b --> Binary (human-readable) (base-2) /\ 0 1 ``` Binary is base-2 number system. which is basically 0 and 1. We write the code which is by the way human readable, computer can not understand it that's why we need to convert it into binary. so somehow we need to bridge this gap. Now it's like there are two people talking in different languages and they wanted to communicate with each other. Similarly here at the one end we have a high-level language like **Java** & **C++** and on the other hand a hardware which understand only binary therefore we need a sort of imediator to bridge this gap. This imediator comes into the picture is called **Compiler**. so this conversion(Human-readable to binary) done by this compiler okay. Now Let's talk about both the languages C++ and Java and how the compiler works. ```cpp code (.cpp) ↓ compile ↓ (.exe or a.out) machine ``` In case of C++, first our code which is in **.cpp** file is compiled and then a new **.exe or a.out** file generated by compiler. And that .exe or a.out file is run on the machine or Plateform. Now the binary outcome(compiled outcome) is different on different plateforms means if we are using Windows, then the compiled outcome is an .exe file. If we are using Linux or Mac, then the compiled outcome is an a.out file. Now this brings us to a problem which is if we want to share the compiled ooutcome with someone, we cannot directly do that because that compiled code might not work on the other machinne or plateform. now the question arises how do we share our code with someone? well we can share the source-code (.cpp) file but generally we don't do that cuz we don't want to share our private code. This is a problem with **C++**. Now **Java** is different from **C++** in that this problem is something delt in java and you don't have to worry about it. ```java code (.java) ↓ ←-------compile-----------→ | | (.class) | | | | | | | ↓ ↓ ↓ Plateform1 Plateform2 Plateform3 ``` In case of Java the compiler compiles the .java file and generates a .class file. So the compiled outcome is the same on all plateforms. we can share that .class file with anyone without sharing our actual source-code. Now how is that happen in java? Does that mean that all plateforms understand the same binary outcome? No all plateforms have their own binary outcome and it's different. so how is that happen? okay so **JVM(Java Virtual Machine)** comes into the action. JVM is another layer which is there in between compiler and plateform. JVM is a virtual machine which is a program which runs on the plateform and it's responsible for converting the human-readable outcome into the binary outcome. So different plateforms have different JVM's and it converts .class file into the relevant binary outcome that need to run on particular hardware. Now I think you got the point. This is why Java is called **Plateform Independent**. Now lets move further. ================================================ FILE: lessons/intro-recursion.md ================================================ --- path: "/intro-recursion" title: "Intro to Recursion" order: "8A" section: "Recursion" description: "learn Recursion from scratch" icon: "redo" --- Recursion is a technique that leads to elegant solutions to problems that are difficult to solve using simple iteration(loops). In some cases, it enables you to develop a natural, straightforward, simple solution to an otherwise difficult problem. > Recursion in Computer Science is a method where the solution to a problem depends on the solution to smaller instances of the same problem. This lesson introduces the concepts and techniques of recursive programming and illustrates with examples of how to **“think recursively”**. Let's understand this by a simple example: ```java Calculate factorial of a number by using recursion ``` Now, How do you find `n!` of a given number? - To find `1!` is easy, because you know that `0!` is 1, and 1! is 1 × 0!. - Assuming that you know `(n - 1)!`, you can obtain n! immediately by using `n × (n - 1)!`. Thus, the problem of computing n! is reduced to computing (n - 1)!. When computing `(n - 1)!`, you can apply the same idea recursively until n is reduced to 0. - Let factorial(n) be the method for computing n!. If you call the method with n = 0, it immediately returns the result. The method knows how to solve the simplest case, which is referred to as the **base case** or the stopping condition. - If you call the method with n > 0, it reduces the problem into a subproblem for computing the factorial of n - 1. - The subproblem is essentially the same as the original problem, but it is simpler or smaller. Because the sub-problem has the same property as the original problem, you can call the method with a different argument, which is referred to as a recursive call. - The recursive algorithm for computing factorial(n) can be simply described as follows: ```java if(n == 0){ return 1; }else{ return n * factorial(n - 1); } ``` A recursive call can result in many more recursive calls, because the method keeps on dividing a subproblem into new subproblems. For a recursive method to terminate, the problem must eventually be reduced to a stopping case, at which point the method returns a result to its caller. The caller then performs a computation and returns the result to its own caller. This process continues until the result is passed back to the original caller. The original problem can now be solved by multiplying `n` by the result of **factorial(n - 1)**. ```java import java.util.Scanner; public class CalculateFactorial { /** Main method */ public static void main(String[] args) { // Create a Scanner Scanner input = new Scanner(System.in); System.out.print("Enter a nonnegative integer: "); int n = input.nextInt(); // Display factorial System.out.println("Factorial of " + n + " is " + factorial(n)); } /** Return the factorial for the specified number */ public static long factorial(int n) { if (n == 0) // Base case return 1; else return n * factorial(n - 1); // Recursive call } } ``` ##### Output: ```yml eg-1: Enter a nonnegative integer: 4 Factorial of 4 is 24 eg-2: Enter a nonnegative integer: 10 Factorial of 10 is 3628800 ``` The `factorial` method is essentially a direct translation of the recursive mathematical definition for the factorial into Java code. The call to factorial is recursive because it calls itself. The parameter passed to factorial is decremented until it reaches the base case of 0. You see how to write a recursive method. How does recursion work behind the scenes? Below diagram illustrates the execution of the recursive calls, starting with n = 4. ![fact](./images/fact.png) ```java public static long factorial(int n) { return n * factorial(n - 1); } ``` The example discussed in this section shows a recursive method that invokes itself. This is known as direct recursion. It is also possible to create indirect recursion. This occurs when method A invokes method B, which in turn invokes method A. There can even be seeral more methods involved in the recursion. For example, method A invokes method B, which invoke method C, which invokes method A. Let'seee one more another example to grasp it better. ## Computing Fibonacci Numbers As I mentioned that Recursion enables we to create an intuitative straightforward, simple solution to a problem. In this section, we'll be looking an example for creating an intuitive solution to a problem using recursion. Consider the well-known Fibonacci-series problem: ```java The series: 0 1 1 2 3 5 8 13 21 34 55 89 … (indexes): 0 1 2 3 4 5 6 7 8 9 10 11 ``` The Fibonacci series begins with 0 and 1, and each subsequent number is the sum of the preceding two. The series can be recursively defined as: ```java fib(0) = 0; fib(1) = 1; fib(index) = fib(index - 2) + fib(index - 1); for index >= 2 ``` So now the problem is: How do we find `fib(index)` for a given index? It is easy to find `fib(2)`, because we know `fib(0)` and `fib(1)`. Assuming that we know `fib(index - 2)` and `fib(index - 1)`, we can obtain `fib(index)` immediately. Thus, the problem of computing `fib(index)` is reduced to computing `fib(index - 2)` and `fib(index - 1)`. When doing so, we apply the idea recursively until index is reduced to `0` or `1`. The base case is index = `0` or index = `1`. One thing here to keep in mind that we can have more than one **Base case** also. If we call the method with index = `0` or index = `1`, it immediately returns the result. If we call the method with index >= `2`, it divides the problem into two subproblems for computing `fib(index - 1)` and `fib(index - 2)` using recursive calls. The recursive algorithm for computing `fib(index)` can be simply described as follows: ```java if (index == 0) { return 0; } else if (index == 1) { return 1; } else { return fib(index - 1) + fib(index - 2); } ``` let's see how we can implement this recursive technique into the code: ```java import java.util.Scanner; public class ComputeFibonacci { // Main method public static void main(String[] args) { // Create a Scanner Scanner input = new Scanner(System.in); System.out.print("Enter an index for a Fibonacci number: "); int index = input.nextInt(); // Find and display the Fibonacci number System.out.println("The Fibonacci number at index " + index + " is " + fib(index)); } // The method for finding the Fibonacci number public static long fib(long index) { if (index == 0) {// Base case return 0; } else if (index == 1) {// Base case return 1; } else {// Reduction and recursive calls return fib(index - 1) + fib(index - 2); } } } ``` ##### Output: ```java Enter an index for a Fibonacci number: 1 (entered by user) The Fibonacci number at index 1 is 1 Enter an index for a Fibonacci number: 6 (entered by user) The Fibonacci number at index 6 is 8 Enter an index for a Fibonacci number: 7 (entered by user) The Fibonacci number at index 7 is 13 ``` A little mind-melting, right? Let's break it down really quick. ![fibonacci](./images/fibonacci.png) The successive recursive calls for evaluating `fib(4)`. The original method, `fib(4)`, makes two recursive calls, `fib(3)` and `fib(2)`, and then returns `fib(3) + fib(2)`. But in what order are these methods called? In Java, operands are evaluated from left to right, so `fib(2)` is called after `fib(3)` is completely evaluated. There are many duplicated recursive calls. For instance, `fib(2)` is called twice, `fib(1)` three times, and `fib(0)` twice. In general, computing `fib(index)` requires roughly twice as many recursive calls as does computing `fib(index - 1)`. As you try larger index values, the number of calls substantially increases, see below: ```java Table: Number of Recursive Calls in fib(index) index: 2 3 4 10 20 30 40 50 number of calls: 3 5 9 177 21891 2,692,537 331,160,281 2,075,316,483 ``` Okay so I hope you will able to understand the idea of Recursion and why it is used, so let's move forward to the next lesson to know more about the Recursion. ================================================ FILE: lessons/intro-stacks.md ================================================ --- path: "/intro-stacks" title: "Intro to Stack" order: "13A" section: "Stacks & Queues" description: "learn stack data-structure from scratch" icon: "align-justify" --- ================================================ FILE: lessons/intro-string.md ================================================ --- path: "/intro-string" title: "Intro to Strings" order: "6A" section: "Strings In Depth" description: "learn strings in depth" icon: "road" --- ================================================ FILE: lessons/intro-trees.md ================================================ --- path: "/intro-trees" title: "Intro to Trees" order: "14A" section: "Trees" description: "learn Tree data-struture from scratch" icon: "seedling" --- Tree is a non-linear data structure which organises data in hierarchical form and is recursive in nature. It is a popular data structure used in wide range of applications. Every element is considered as a node which has a predecessor and a successor. Trees are further classified into many types I.e, Binary Tree, Complete Binary Tree, Perfect Binary Tree etc. ## Structure of Tree Structure of this Data Structure is clearly mentioned by its name which is in the form of a Tree. Every circle here represents a node. Let’s understand them better with the help of the diagram below ![binary_tree](./images/binary_tree.jpeg) **Root** - Initial node of a tree , which divides the tree into n numbers. **Parent Node** - The Predecessor of every node is its parent node. As D here is the parent of H & I. **Child Node** - The successor of every node is its child node. Here, H & I are the successors of D. **Siblings** - Nodes at the same levels are considered as siblings. **Leaf nodes** - The nodes having no successors are the one’s which are considered as leaves. **Right Sub-tree** - Nodes at the right side of the root node are the one’s of right sub-tree. **Left Sub-tree** - Nodes at the left side of the root node are the one’s of left sub tree. ## Types of Trees Their are in basic 4 types of Trees * Binary tree * Binary Search tree * AVL tree * B-tree ### Binary Tree Binary tree is the one whose every parent node has atmost 2 children. Number of child nodes can be either 0,1 or 2. Binary Trees can further be classified into more types given below in the diagram. ![binary_type](./images/binary_type.png) ### Binary Search Tree BST is a lot similar to a binary tree in which every parent node has at most 2 children. Other than that, BST follows few properties which makes it different from a binary tree. The properties are - * Value in all the nodes of a left subtree should be lesser than the value in the root node. * Value in all the nodes of a right subtree should be larger than the value in the root node. The pictorial representation of BST is ![binary_search_tree](./images/binary_search_tree.png) ### AVL Tree AVL trees are considered as the variants of binary tree which have the characteristics of both Binary tree and Binary search tree. These trees are self-balanced which means the height of left sub tree and right are sub tree are equal. This balanced is measured in terms of balancing factor. ![AVL](./images/AVL.png) Now, let’s understand what is a balancing factor - * It is the difference between the left sub tree and right sub tree. * The value of balancing factor must be 0 , -1 and 1 , which means each node will be having a balancing factor of 0,1 and -1. * Values of nodes other than -1, to 1 in an AVL tree will represent an unbalanced tree that needs to be balanced. * If a node has a balance factor of 1, it means that the left subtree is one level higher than the right subtree. * If a node has a balance factor of 0, it means that the height of the left subtree and the right subtree is equal. * If a node has a balance factor of -1, it means that the right subtree is one level higher than the left subtree or the left subtree is one level lower than the right subtree. ### B-Tree It is also known as height-balanced m way tree, where m is the order of the tree. B-tree is more generalised form of a binary search tree.  In the case of a binary tree, the leaf nodes might not be at the same level. However, in the case of a B Tree, all the leaf nodes should be at the same level.  Properties of B-Tree are - * The root may have between 2 and m children. * All other nodes must have between [M/2] and m children. * A node that has k children will have k-1 key values. * Thus, the root may have only 2 children; all other nodes must be at least half full . ## Traversals in Trees Tree traversals means traversing or visiting each node of the tree. Other than tree data structure, Stack , Queue and Linked List only have one way for traversing which makes Trees different from them also. Traversals are of 3 types 1. **In-order Traversal** - This traversal calls for the sequence of LEFT, ROOT, RIGHT. 2. **Pre-order Traversal** - This traversal calls for the sequence of ROOT ,LEFT, RIGHT. 3. **Post-order Traversal** - This traversal calls for the sequence of LEFT, RIGHT, ROOT. Now let’s understand these a help of an example ![traversal](./images/traversal.png) Taking the above tree into consideration let's understand how traversing is done **In-order Traversal (LEFT , ROOT, RIGHT)** - Traverse the left sub-tree , visit the root , traverse the right sub-tree which makes the sequence (1,5,6,10,17,19,21) **Pre-order traversal (ROOT, LEFT , RIGHT)** - Visit the root , Traverse the left sub tree , Traverse the right sub tree which makes the sequence (10,5,1,6,19,17,21) **Post-order traversal (LEFT,RIGHT,ROOT)** - Traverse the left sub tree , Traverse the right sub-tree , visit the root which makes the sequence (1,6,5,17,21,19,10) ================================================ FILE: lessons/intro-tries.md ================================================ --- path: "/intro-tries" title: "Introduction to Tries" order: "23A" section: "Tries" description: "learn about tries from scratch" icon: "share-alt" --- ================================================ FILE: lessons/introduction.md ================================================ --- path: "/introduction" title: "Welcome" order: "1A" section: "Introduction" description: "this is the introduction to the website" icon: "search" --- Hi there! We have made this website for the learning purpose for all those students out there who wanted to enhance there knowledge learning Data-Structure and Algorithms. This website contains all the data structures and algorithms in very simple way such that anyone can learn. The DS Algo will be oriented towards the language Java. Okay! ## Motivations So why should you care to learn DS Algo? So the simple answer is that the skills here you will gain, will help you to enhance your problem-solving skills and in your interview for tech jobs since a lot of the questions asked by big tech companies are either directly related or derived from these classic algorithms and data structures. ## Tips to Get Started > This course is hard. Like, really hard. Even if you've done all these things before, there is so much brain power to get through questions of these platform mentioned below. Don't expect to get everything on the first try. Don't get frustrated with yourself. - Solve Daily 5-10 Question. - If you are solving question on plateforms like Leetcode, CodeChef, Top-Coder etc.Keep the following points in mind: - Don't give more than 45 mins to a Problem.(Leetcode) - First Try to Solve Problem for 15 mins by Own. - If you get stuck, Look for hints after trying 15 min by your own. - If you unable to solve the problem check the solution, and then after few days try to solve again. ## Where to File Issues We have written this kind of like blog-site for Java and ds-algo and tried our best to not make mistakes. However when writing hours of material, mistakes are inevitable, both here in the grammar and in the course with the material. However We are constantly correcting the mistakes so that those of you that come later get the best material possible. If you find a mistake we'd love to fix it. The best way to do this is to open a pull request or [file an issue](https://www.github.com/utkarsh1504/DSA-Java) on the GitHub repo. ## Prerequisites This course requires some of the prerequisite knowledge of the following: - Basic knowledge of any programming language (Like C, C++, Java, etc.). but if you don't that's completely fine. we'll be firstly going to learn Java then we'll move to data structures and algorithms. - One thing I'll recommend is to follow the [DSA-Bootcamp-Java](https://www.youtube.com/playlist?list=PL9gnSGHSqcnr_DxHsP7AW9ftq0AtAyYqJ) course because most of the notes and the material are based on that. So definitely you should watch that course. ## Special Thanks A big shout out to [Kunal](https://twitter.com/kunalstwt) for his [DSA-Bootcamp-Java](https://www.youtube.com/playlist?list=PL9gnSGHSqcnr_DxHsP7AW9ftq0AtAyYqJ) course. On his Youtube channel, he is teaching this quality-loaded course completely for free. I also want to thank [Brian Holt](https://twitter.com/holtbt) for the idea of this course-site and for allowing me to use his starter. He's a great instructor at [Frontend Masters](https://frontendmasters.com/teachers/brian-holt/), if you want to learn some react and javascript related stuffs go checkout his courses. I'm really grateful for his support. ================================================ FILE: lessons/io-conditionals.md ================================================ --- path: "/io-conditionals" title: "Input/Output & Conditionals" order: "3C" section: "Learn Java" description: "Learn java" --- Okay so let's learn about the control flow of a Java program. ```java // Java program to demonstrate the control flow public class { public static void main(String[] args){ System.out.println("Hello World"); } } ``` Let's go through the code line by line. - **``public static void main(String[] args)``** Java main method is the entry point of any Java program. You can only change the name of String array argument, for example you can change ``args`` to ``myStringArgs``. - **``public``** This is the access modifier of the main method. It has to be ``public`` so that Java Runtime Environment(JRE) can execute this method. Remember that if you make any method non-public then it’s not allowed to be executed by any program, there are some access restrictions applied. So it means that the main method has to be public. - **``Static``** When JRE starts, there is no object of the class present. That’s why the main method has to be static so that JVM can load the class into memory and call the main method. If the main method won’t be static, JVM would not be able to call it because there is no object of the class is present. - **``Void``** Java programming mandates that every method provide the return type. Java main method doesn’t return anything, that’s why it’s return type is void. This has been done to keep things simple because once the main method is finished executing, java program terminates. So there is no point in returning anything, there is nothing that can be done for the returned object by JVM. If we try to return something from the main method, it will give compilation error as an unexpected return value. - **``Main``** method is similar to the main function in C and C++. The ``main`` method accepts a single argument: an array of elements of type String. - **``String[] args``** Java main method accepts a single argument of type String array. This is also called as java command line arguments. - **``System.out.println("Hello, World");``** Outputs the string “Hello, World” followed by a new line on the screen.Output is actually accomplished by the built-in println( ) method. ``System`` is a predefined class that provides access to the system, and ``out`` is the variable of type output stream that is connected to the console. > System, out, println these are default classes and methods built into Java. If you want to read docs do a `ctrl+click` (IntelliJ Idea) on them. > Okay that's a lot of information to digest and it is the basic for a Java program. Now let's move on to the next section. ## **If-Else Statements** If-else statements are used to execute different code depending on the value of a variable. We use If-else statements for the condition based problem solving. If we have given a choice, then we can use if-else statements to decide which code to execute and it is called conditional execution. It will be really easy to understand as we will see in the following example. #### Syntax if-else statements are written as follows. ```java // syntax if (condition) { // Code to execute if condition is true } else { // Code to execute if condition is false } ``` so above is the basic syntax of if-else statements. let's see some of the examples to understand it better. we will see some simple examples and in last of this section i will link some more question so you can practise them on your own. ```java // program to check the greater number of the two. public class { public static void main(String[] args){ int a = 10; int b = 20; if(a > b){ System.out.println("a is greater than b"); } else{ System.out.println("b is greater than a"); } } } ``` Lets go through the if-else code line by line. - `if` is the keyword that indicates that the code block is an if statement. `(a > b)` is the condition. we can have multiple conditions in a single if statement. we're checking if `a` is greater than `b` if this turn out to be true then the code block under the if statement will be executed, if not then we'll move on the next statement. - `else if` is the keyword that indicates that the code block is an else if statement. `(a < b)` is the condition. else if is used to check if the condition is true then the code block under the if statement will be executed, if not then we'll move on the next statement. it is used when we have multiple conditions in a single if statement. - `else` is the keyword that indicates that the code block is an else statement. if the condition from the above statements are turn out to be false then the code block under the else statement will be executed. ok so that's all. now let's see some more examples. ```java //A Java Program to demonstrate the use of if-else statement. //It is a program of odd and even number. public class IfElseClass { public static void main(String[] args) { //defining a variable int number = 13; //Check if the number is divisible by 2 or not if(number % 2 == 0){ System.out.println("even number"); } else{ System.out.println("odd number"); } } } ``` Let's go through the code line by line. - `if` is the keyword that indicates that the code block is an if statement. `(number%2==0)` is the condition. we can have multiple conditions in a single if statement. we're checking if ``number`` is divisible by ``2`` if this turn out to be true then the code block under the if statement will be executed, if not then we'll move on the next statement. - `else` is the keyword that indicates that the code block is an else statement. if the condition from the above statements are turn out to be false then the code block under the else statement will be executed. ## **Switch Statements** Switch statements are used to execute different code depending on the value of a variable. We use Switch statements for the condition based problem solving. Switch statements are used when we have multiple conditions in a single if statement. It is just a substitute for multiple if-else statements. In this a variable is compared to multiple cases one by one and when the case is matched then the code block under that case will be executed. #### Syntax ```java // syntax switch (expression) { case value1: // code to execute if expression is value1 break; case value2: // code to execute if expression is value2 break; default: // code to execute if expression is not value1 or value2 break; } ``` Above is the basic syntax of switch statements. This is how it works: - The switch expression is only evaluated `once`. - The value of the expression is `compared` with the values of each case value. - If there is a `match`, ie. the case value and the switch expression are same, the associated block of code with the case value is executed. - The `break` and `default` keywords are optional and will be explained ahead. Now, let us see a diagramtic workflow of the Java Switch statement for a better understanding. ![java-switch-statement](./images/java-switch-statement.png) Let us see an example to understand it better. ```java // Program to check Vowel or Consonant: // It is not case-sensitive. public class { public static void main(String[] args){ char ch='O'; switch(ch) { case 'a': System.out.println("Vowel"); break; case 'e': System.out.println("Vowel"); break; case 'i': System.out.println("Vowel"); break; case 'o': System.out.println("Vowel"); break; case 'u': System.out.println("Vowel"); break; case 'A': System.out.println("Vowel"); break; case 'E': System.out.println("Vowel"); break; case 'I': System.out.println("Vowel"); break; case 'O': System.out.println("Vowel"); break; case 'U': System.out.println("Vowel"); break; default: System.out.println("Consonant"); break; } } } Output : Vowel ``` #### The 'break' Keyword - When the Java compiler reaches a `break` keyword, it breaks out of the switch block. - This will stop the execution of more code and case testing inside the block. - Basically it means that When a match is found, and the job is done, there is no need for more testing. Hence we break out of the switch statement. #### The 'default' Keyword - The `default` keyword specifies some code to run if there is no case match: Now let us see another example where there are no break statements present: ```java //switch cases without break statements public class SwitchExample2 { public static void main(String[] args) { int num = 20; switch(num){ case 10: System.out.println("10"); case 20: System.out.println("20"); case 30: System.out.println("30"); default: System.out.println("The number is not 10, 20 or 30"); } } } Output : 20 30 The number is not 10, 20 or 30 ``` Remember that the switch statement is `fall-through`. That's why all the statements got executed after the first match because the break statement is NOT present. #### Points to Remember - There can be 1 or N number of `case values` for a switch expression. - The `case values` must be `literal` or `constant`. It doesn't allow variables. - The `case values` must be `unique`. In case of duplicate value, it renders compile-time error. - The Java `switch expression` must be of `byte, short, int, long` (with its Wrapper type), `enums and string`. - Each case statement can have a `break` statement which is `optional`. When control reaches to the break statement, it jumps the control after the switch expression. If a break statement is `not found`, it executes the next case. - The case value can have a `default` label which is `optional`. - The Java switch statement is `fall-through`. It means it executes all statements after the first match if a break statement is NOT present. #### Java Nested Switch Statements We can use switch statement inside other switch statement in Java. It is known as nested switch statement. ```java //Java Program to demonstrate the use of Java Nested Switch public class NestedSwitchExample { public static void main(String args[]) { //C - CSE, E - ECE, M - Mechanical char branch = 'C'; int collegeYear = 4; switch(collegeYear) { case 1: System.out.println("English, Maths, Science"); break; case 2: switch( branch ) { case 'C': System.out.println("Operating System, Java, Data Structure"); break; case 'E': System.out.println("Micro processors, Logic switching theory"); break; case 'M': System.out.println("Drawing, Manufacturing Machines"); break; } break; case 3: switch(branch) { case 'C': System.out.println("Computer Organization, MultiMedia"); break; case 'E': System.out.println("Fundamentals of Logic Design, Microelectronics"); break; case 'M': System.out.println("Internal Combustion Engines, Mechanical Vibration"); break; } break; case 4: switch(branch) { case 'C': System.out.println("Data Communication and Networks, MultiMedia"); break; case 'E': System.out.println("Embedded System, Image Processing"); break; case 'M': System.out.println("Production Technology, Thermal Engineering"); break; } break; } } } Output : Data Communication and Networks, MultiMedia ``` ================================================ FILE: lessons/jagged-array.md ================================================ --- path: "/jagged-array" title: "Jagged Arrays" order: "4F" section: "Arrays" description: "arrays" --- > A jagged array is an array of arrays such that the member arrays can be of different sizes. We can create a 2-D(multi-dimensional) array but with a variable number of columns in each row. These types of arrays are known as Jagged arrays. ![java-jaggedarray](./images/java-jagged-array.png) #### Declaration and Initialization of Jagged array : ##### Syntax : ```java data_type array_name[][] = new data_type[n][]; //n: no. of rows array_name[] = new data_type[n1]; //n1= no. of colmuns in row-1 array_name[] = new data_type[n2]; //n2= no. of colmuns in row-2 array_name[] = new data_type[n3]; //n3= no. of colmuns in row-3 . . . array_name[] = new data_type[nk]; //nk=no. of colmuns in row-n ``` #### Alternative, ways to Initialize a Jagged array : ```java int arr_name[][] = new int[][] { new int[] {15, 7, 22}, new int[] {67, 81}, new int[] {12, 91, 1, 17} }; ``` OR ```java int[][] arr_name = { new int[] {15, 7, 22}, new int[] {67, 81}, new int[] {12, 91, 1, 17} }; ``` OR ```java int[][] arr_name = { {15, 7, 22}, {67, 81}, {12, 91, 1, 17} }; ``` ```java class Main { public static void main(String[] args) { // Declaring 2-D array with 2 rows int arr[][] = new int[2][]; // Making the above array Jagged // First row has 3 columns arr[0] = new int[3]; // Second row has 2 columns arr[1] = new int[2]; // Initializing array int count = 0; for (int i = 0; i < arr.length; i++) for (int j = 0; j < arr[i].length; j++) arr[i][j] = count++; // Displaying the values of 2D Jagged array System.out.println("Contents of 2D Jagged Array"); for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr[i].length; j++) System.out.print(arr[i][j] + " "); System.out.println(); } } } ``` ##### Output Contents of 2D Jagged Array 0 1 2 3 4 Following is another example where i’th row has i columns, i.e., the first row has 1 element, the second row has two elements and so on. ```java // Another Java program to demonstrate 2-D jagged // array such that first row has 1 element, second // row has two elements and so on. class Main { public static void main(String[] args) { int r = 5; // Declaring 2-D array with 5 rows int arr[][] = new int[r][]; // Creating a 2D array such that first row // has 1 element, second row has two // elements and so on. for (int i = 0; i < arr.length; i++) arr[i] = new int[i + 1]; // Initializing array int count = 0; for (int i = 0; i < arr.length; i++) for (int j = 0; j < arr[i].length; j++) arr[i][j] = count++; // Displaying the values of 2D Jagged array System.out.println("Contents of 2D Jagged Array"); for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr[i].length; j++) System.out.print(arr[i][j] + " "); System.out.println(); } } } ``` ##### Output Contents of 2D Jagged Array 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ### Applications After having learnt about Jagged Arrays, you must be wondering, where you should use them? Well, continue reading.... A matrix is typically stored as a 2D arrays. It may be called as a "dense" representation. It's called dense because it stores each and every element of the array. But in some cases many elements of the array are 0 (or perhaps some other value) and it doesn't make sense to store them explicitly. These are called "sparse" matrix. Now coming to the applications and uses- - A lot of sparse matrix representations use a small number of 1D arrays. Really jagged arrays are definitely useful in situations where you don't want each 1D array to have the same length. Jagged arrays also make it somewhat easier to swap out entire "rows". - It should be noted that, jagged arrays usually have better performance than multidimensional arrays. - When using jagged arrays you can easily perform operations like row swap and row resize. Maybe in some cases usage of multidimensional arrays will be more safe, but jagged arrays should be used instead of multidimensional when you use it for analysis purposes. ================================================ FILE: lessons/java-setup.md ================================================ --- path: "/java-setup" title: "Java Development Setup" order: "2B" section: "Basics" description: "Intro to java" --- ## Tools You Will Need For setting up environment for performing java codes you need with a minimum of 64 MB of RAM. You will also need the following softwares: - Linux 5.14 or Windows XP/7/8/10 operating system - [Java JDK 16](https://www.oracle.com/java/technologies/javase-jdk16-downloads.html) - IDEs ## Java Architecture Java Architecture combines the process of compilation and interpretation. It explains the various processes involved whilst formulating a Java program The explaination of the java architecture in simple steps are as follows: - In Java, there is a process of compilation and interpretation. - The code written in Java, is converted into byte codes which is done by the Java Compiler. - The byte codes, then are converted into machine code by the JVM. - The Machine code is executed directly by the machine. ### Components of Java Architecture There are three main components of Java language: - **JVM:** Java Virtual Machine - **JRE:** Java Runtime Environment - **JDK:** Java Development Kit ### Java Virtual Machine: Java applications are called WORA(Write Once, Run Anywhere) because of their ability to run a code on any platform. This is done only because of JVM. The JVM is a Java platform component that provides an environment for executing Java programs. JVM interprets the bytecode into machine code which is executed in the machine in which the Java program runs. So, in a nutshell, JVM performs the following functions: - Loads the code - Verifies the code - Executes the code - Provides runtime environment ### Java Runtime Environment: The JRE software builds a runtime environment in which Java programs can be executed. The JRE is the on-disk system that takes your Java code, combines it with the needed libraries, and starts the JVM to execute it. The JRE contains libraries and software needed by your Java programs to run. JRE is a part of JDK but can be downloaded separately. ### Java Development Kit: The Java Development Kit is a software development environment used to develop Java applications and applets. It contains JRE and several development tools, an interpreter/loader (java), a compiler (javac), an archiver (jar), a documentation generator (javadoc) accompanied with another tool. ## Setting up Java development environment Java SE is freely available from the link [Download Java](https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html). You can download a version based on your operating system. Follow the instructions to download Java and run the `.exe` to install Java on your machine. Once Java is installed on your machine, you will need to set environment variables to point to correct installation directories: ### Setting Up the Path for Windows: Assuming you have installed Java in *`C:\Program Files\Java\JDK* directory`:* - Right-click on `This PC` and select `Properties`. - Click the `Environment variables` button under the `Advanced` tab. - Now, alter the `PATH` variable so that it also contains the path to the Java executable. Example, if the path is currently set to *`C:\WINDOWS\SYSTEM32`*, then change your path to read *`C:\WINDOWS\SYSTEM32;C:\Program Files\Java\JDK\bin`* ### Setting Up the Path for Linux, UNIX: Environment variable `PATH` should be set to point to where the Java binaries have been installed. Refer to your shell documentation, if you have trouble doing this. Example, if you use bash as your shell, then you would add the following line to the end of your *`.bashrc: export PATH = /path/to/java:$PATH`*. ## IDEs It is a software development environment for writing, debugging, and testing Java programs. we can write code very smoothly using IDE. There are many IDE's available for java. for example, **[IntelliJ IDEA](https://www.jetbrains.com/idea/)**, [Eclipse](https://www.eclipse.org/downloads/), [Netbeans](https://netbeans.apache.org/download/nb120/nb120.html), etc. After setting up JDK, install anyone of the of your favorite IDE just by clicking on the link and install it. *It's really Simple!* ================================================ FILE: lessons/jumps.md ================================================ --- path: "/jumps" title: "Jumps Statements" order: "3E" section: "Learn Java" description: "Learn Java" --- Jumps statements are used to jump to a specific line in a program. Java supports three jump statements. - `break` - `continue` - `return` These three statements transfer control to other part of the program. Let's see one by one how it works. ## **Break statements** Break Statement is a loop control statement that is used to terminate the loop. As soon as the `break` statement is encountered from within a loop, the loop iterations stop there, and control returns from the loop immediately to the first statement after the loop. Example. ```java public class HelloWorld { public static void main(String[] args) { // Initially loop is set to run from 1-5 for(int i=1; i<=5; i++){ // terminate loop when i is 4. if(i=4){ break; System.out.print(i); } } } } ``` Output: `1 2 3` In Java, `break` is majorly used for: - To exit a loop. - Terminate a sequence in a `switch` statement. ## **Continue Statements** Sometimes you doesn't want to execute a particular iteration in a loop. That is, you might want to continue running the loop but stop processing the particular iteration. Then `continue` statement performs such an action. Example. ```java public class HelloWorld { public static void main(String[] args) { // Initially loop is set to run from 1-5 for(int i=1; i<=6; i++){ // terminate loop when i is 4. if(i=4){ continue; System.out.print(i); } } } } ``` Output: `1 2 3 5 6` ## **Break vs Continue** Let's us see how these two jump statements are different from each other. | break | continue | | ----------------- | --------------- | |The break statement is used to terminate the loop immediately. | The continue statement is used to skip the current iteration of the loop.| | break keyword is used to indicate break statements in java programming. | continue keyword is used to indicate continue statement in java programming.| | We can use a break with the switch statement. | The continue statement brings the next iteration early. | | It stops the execution of the loop. | It does not stop the execution of the loop.| ## **Return Statement** The `return` statement is used to explicitly return from a method. That is, it causes a program control to transfer back to the caller of the method. It is used to **exit** from a method, with or without a value. Usage of **return keyword** as there exist two ways as listed below as follows: - **Case 1:** Methods returning a value - **Case 2:** Methods not returning a value ## **Methods returning a value** ```java // Main method class CodeExample { // Method 1 public static int sumFunction(int a, int b) { int sum = a + b; // Since return type of sunFunction method is integer so this method should return integer value return sum; } // Main driver method public static void main(String[] args){ int a = 5; int b = 8; // here ans variable will receive sum from sumFunction int ans = sumFunction(a, b); // print statement System.out.println(ans); } } ``` Output: `13` **Output explanation:** When we are calling a class CodeExample method that has **return sum** which returns the value of sum and that’s value gets displayed on the console. ## **Methods not returning a value** For methods that do not return a value, `return` statement in Java can be skipped. Here there arise two cases when there is no value been returned by the user as listed below as follows: - Method not using return statement in void function - Methods with return type void #### Method not using return statement in void function ```java // Main method class CodeExample { // Method 1 public static void sumFunction(int a, int b) { int sum = a + b; // Since return type of sunFunction method is void so this method should not return any value. System.out.println(sum); } // Main driver method public static void main(String[] args){ int a = 5; int b = 8; // Here, we will just call the function and the program will execute successfully. sumFunction(a, b); } } ``` Output: `13` #### Method with return type void ```java // Main method class CodeExample { // Method 1 public static void demoFunction(int n) { if(n<10) { // return statement below(only using return statement and not returning anything) // control exits the method if this condition(i.e, n<9) is true. return; } else { n++; } } // Main driver method public static void main(String[] args){ int n = 8; // calling the function sumFunction(n); } } ``` Program executed successfully. ================================================ FILE: lessons/linearsearch.md ================================================ --- path: "/linearsearch" title: "Linear Search" order: "5A" section: "Searching & Sorting" description: "learn Searching algorithms" icon: "sort" --- ## **What is Searching ?** Searching is the process of finding some particular element in the list. If the element is present in the list, then the process is called successful and the process returns the location of that element, otherwise the search is called unsuccessful. ## **What is Linear Search ?** Linear search is the simplest search algorithm and often called sequential search. In this type of searching, we simply traverse the list completely and match each element of the list with the item whose location is to be found. If the match found then location of the item is returned otherwise the algorithm return NULL. ## **Linear Search Algorithm :** ***LINEAR_SEARCH(ARR, N, VAL)*** - **Step 1:** [INITIALIZE] SET POS = -1 - **Step 2:** [INITIALIZE] SET I = 1 - **Step 3:** Repeat Step 4 while I<=N - **Step 4:** IF ARR[I] = VAL
SET POS = I
PRINT POS
Go to Step 6
[END OF IF]
SET I = I + 1
[END OF LOOP] - **Step 5:** IF POS = -1
PRINT " VALUE IS NOT PRESENTIN THE ARRAY "
[END OF IF] - **Step 6:** EXIT ![linear-search](./images/linear-search.png) ## **Complexity of Algorithm :** - **Time Complexity :** O(n) - **Space Complexity :** O(1) ## **Code :** ```java class LinearSearch { // linear search algorithm public static int linearSearch(int arr[], int n, int val) { for (int i = 0; i < n; i++) { if (arr[i] == val) return i; } return -1; } // driver code main method public static void main(String args[]) { int arr[] = { 12, 25, 8, 10, 32 }; int x = 8; // function call int result = linearSearch(arr, arr.length, x); if (result == -1) System.out.print("Element is not present in array"); else System.out.print("Element is present at index : "+ result); } } ``` ## **Output :** ``` Element is present at index : 2 ``` ================================================ FILE: lessons/loops.md ================================================ --- path: "/loops" title: "Loops In Java" order: "3D" section: "Learn Java" description: "Learn java" --- Loops are a way to repeat a block of code. It is used to remove repetitive code and to make code more readable. It is a way to write iterative code. There are three types of loops in Java. - For - While - Do-While ## **For Loops** For loops are used to iterate over a range of numbers. In this loop, the range is defined by the `for` keyword. It needs a variable to store the current value and a condition to check if the loop should continue or not and a block of code to be executed for each value in the range of numbers (from the first to the last). #### Semantics ```java // syntax for (initialization; condition; update){ // block of code } ``` ##### FlowChart ![ForLoop](../images/forLoop.png) Ok so let's see how to use for loops in writing a program. ```java //program to find sum upto n numbers public class { public static void main(String[] args) { int sum = 0; for (int i = 0; i < 10; i++) { sum += i; } System.out.println("Sum of numbers upto 10 is " + sum); } } ``` so let's analyze the code. - we have initialized the variable `sum` to 0. - then we used `for` loop: - In the initialization, we have initialized the variable `i` to 0(`int i=0;`). This step is completely optional. You can also do the initialization before the loop. In that that would be look like: ```java int sum = 0; int i = 0; for (; i < 10; i++) { .... ``` or something like that. ```java int i; for (i = 0; i < 10; i++) { ``` - In the condition, it checks if `i` is less than 10. The condition checks if the loop should continue or not and this is not optional, you have to provide condition. In this case we have given a sigle condition `i < 10`. we can also have multiple conditions like `i < 10 && i > 0`. for multiple conditions, we need to use logical operator to combine them. ```java int sum = 0; for(int i=0; i<10 && i%2==0; i++) { ``` - In the update, it updates the value of `i` by 1. This is optional too. you can have the update like: i++, i--, i+=2, i-=2 etc. ```java int sum = 0; for(int i=0; i<10;) { sum += i; i++; } ``` - Okay so these are the variation of for loops. let's understand how this for loop works. So `i=0;`, i is assigned to 0. now it checks is `i`(0) is less than `10`, the answer is yes(true). if condition comes true, it executes the block of code. so inside the body, `sum += i;`, expression is evaluated. `sum` is assigned to 0 as sum = sum + i(0). so `sum` is assigned to 0. This is the first iteration. - Now `i` get updated to 1. now it checks if `i` is less than 10, the answer is yes(true). if condition comes true, it executes the block of code. so inside the body, `sum += i;`, expression is evaluated. `sum` is assigned to 0 as sum = sum + i(1). so `sum` is assigned to 1. This is the second iteration. - This iteration continues until `i` is less than 10. As `i` reaches 10, the condition becomes false and the loop stops. - So the final value of `sum` is 10, which will be printed on the console. And that's all. You can see that the for loop is very simple and easy to understand. You can practise some questions based on for loops in the [Assignment Section](./assignment.md). ## **While Loops** While Loops are used to iterate over a range of numbers. In this loop, the range is defined by the `while` keyword. It needs a condition to check if the loop should continue or not and a block of code to be executed for each value in the range of numbers (from the first to the last). #### Semantics ```java // syntax while(condition) { // block of code } ``` ##### FlowChart ![WhileLoop](./images/whileLoop.png) Let's see how to use while loops in writing a program. ```java // Program to demonstrate while loop public class { public static void main(String[] args) { int i = 0; while (i < 10) { System.out.println("i is " + i); i++; } } } ``` let's analyze the code. - In line six, we have used `while` to iterate over the range of numbers and we have put condition `n > 0` because we want to iterate over the numbers from the first to the last. - Inside the loop we have used `n--` which is another way of writing `n = n - 1`, we're decrementing the value of `n` by 1 each time till it reaches zero and it reaches zero, condition will be false and the loop will break. - Lastly we print the value of `sum` to the screen. I think that's easy to understand. So let's move to our next loop. ## **Do-While Loops** Do-While loops are used to iterate over a range of numbers. In this loop, the range is defined by the `do-while` keyword. It needs a condition to check if the loop should continue or not and a block of code to be executed for each value in the range of numbers (from the first to the last). The main difference between do-while and while loop is that the do-while loop is iterates _atleast once_ whether the condition is true or not it will execute the block of code atleast once which is not true in case of while loop. `While` loop firstly checks the condition and then it works according to the condition but `Do-while` loop first execute the code inside the body of the loop then checks the condition. #### Semantics ```java // syntax do { // block of code } while(condition); ``` ##### FlowChart ![DoWhileLoop](./images/doWhileLoop.png) Let's see how to apply do-while loop in writing a program. ```java // Program to demonstrate do-while loop public class { public static void main(String[] args) { int i = 0; do { System.out.println("i is " + i); i++; } while (i < 10); } } ``` Lets analyze the code. - we have used `do` keyword to execute the block of code firstly. firstly this loop will start executing the block of code and print the value of `i` to the console. - after that we're incrementing the value of `i` by 1 and then we check the condition `i < 10` and if the condition is true then we execute the loop again and print the value of `i` to the console. - and if the condition is false then we break the loop. - so the conclusion is that we first, atleast once execute the block of code and then we'll check the condition and according to the condition we'll work further. > There may be a question when to use which loop? Okay so it depends on the situation. It completey depends on the problem you are solving. - **`for` and `while`** - you can use both loop as per your requirement, but there is one thing which recommended by all is you should use `while` loop when you don't know how many times you have to iterate and use a `for` loop when you know how many times you have to iterate. suppose you have to print numbers from 1 to 10 then you know how many times you have to run the loop so use `for` loop. And if you have given that keep taking input from a user till user doesn't press x, here you don't know how many times you have to iterate so use `while` loop. - **`while` and `do-while`** - so in situations like, when you atleast once want to run the loop, irrespective of the condition, then you should use `do-while` loop and rest in all other cases either use `while` loop or `for` loop. ================================================ FILE: lessons/mergesort.md ================================================ --- path: "/mergesort" title: "Merge Sort" order: "8E" section: "Recursion" description: "learn Recursion from scratch" --- ================================================ FILE: lessons/num-one.md ================================================ --- path: "/num-one" title: "Number Theory Part-A" order: "10C" section: "Maths for DSA" description: "learn maths required in DSA" --- ================================================ FILE: lessons/num-three.md ================================================ --- path: "/num-three" title: "Number Theory Part-C" order: "10E" section: "Maths for DSA" description: "learn maths required in DSA" --- In this article we will cover the remaining and some advanced concepts of number theory. ## **Mathmatical Exceptation** Mathematical Expectation is an important concept in Probability Theory.This article attempts to throw some light on this topic by discussing few related mathematical and programming problems. Mathematical expectation, also known as the expected value, which is the summation of all possible values from a random variable.It is also known as the product of the probability of an event occurring, denoted by P(x), and the value corresponding with the actually observed occurrence of the event. The mathematical expectation is denoted by the formula: > E(X)= Σ (x1p1, x2p2, …, xnpn) It is important to understand that **"expected value"** is not same as **"most probable value"** - rather, it need not even be one of the probable values. For example, in a dice-throw experiment, the expected value, is not one of the possible outcomes at all. > The rule of **"linearity of of the expectation"** says that E[x1+x2] = E[x1] + E[x2]. ## **Fermat's Theorem** It is also known as Fermat's little theorem. Fermat’s little theorem states that if p is a prime number, then for any integer a, the number a^(p) – a is an integer multiple of p. > Here p is a prime number ap ≡ a (mod p) >Let's see an Example How Fermat’s little theorem works **Examples:** P = an integer Prime number a = an integer which is not multiple of P Let a = 2 and P = 17 According to Fermat's little theorem 2^(17 - 1) ≡ 1 mod(17) we got 65536 % 17 ≡ 1 that mean (65536-1) is an multiple of 17 ```java // Java program to find modular // inverse of a under modulo m // using Fermat's little theorem. // This program works only if m is prime. class Main { static int __gcd(int a, int b) { if (b == 0) { return a; } else { return __gcd(b, a % b); } } // To compute x^y under modulo m static int power(int x, int y, int m) { if (y == 0) { return 1; } int p = power(x, y / 2, m) % m; p = (p * p) % m; return (y % 2 == 0) ? p : (x * p) % m; } // Function to find modular // inverse of a under modulo m // Assumption: m is prime static void modInverse(int a, int m) { if (__gcd(a, m) != 1) { System.out.print("Inverse doesn't exist"); } else { // If a and m are relatively prime, then // modulo inverse is a^(m-2) mode m System.out.print("Modular multiplicative inverse is " + power(a, m - 2, m)); } } // Driver code public static void main(String[] args) { int a = 3, m = 11; modInverse(a, m); } } ``` ## **Wilson's Theorem** Wilson’s theorem states that a natural number p > 1 is a prime number if and only if **(p-1) ! ≡ -1 mod p**
OR **(p-1) ! ≡ (p-1) mod p** **Examples:** p = 5 (p-1)! = 24 24 % 5 = 4 p = 7 (p-1)! = 6! = 720 720 % 7 = 6 **Proof:** It is easy to check the result when n is 2 or 3, so let us assume n > 3. If n is composite, then its positive divisors are among the integers 1, 2, 3, 4, ... , n-1 and it is clear that gcd( (n-1)! , n) > 1, so we can not have (n-1)! = -1 (mod n). However if n is prime, then each of the above integers are relatively prime to n. So for each of these integers a there is another b such that ab = 1 (mod n). It is important to note that this b is unique modulo n, and that since n is prime, a = b if and only if a is 1 or n-1. Now if we omit 1 and n-1, then the others can be grouped into pairs whose product is one showing 2.3.4.....(n-2) = 1 (mod n) (or more simply (n-2)! = 1 (mod n)). Finally, multiply this equality by n-1 to complete the proof. ## **Lucas Theorem** Lucas theorem basically suggests that the value of nCr can be computed by multiplying results of niCri where ni and ri are individual same-positioned digits in base p representations of n and r respectively.. The idea is to one by one compute niCri for individual digits ni and ri in base p.Since these digits are in base p, we would never need more than O(p) space and time complexity of these individual computations would be bounded by O(p2). ```java // A Lucas Theorem based solution to compute nCr % p class Lucas { // Returns nCr % p. In this Lucas Theorem based program, // this function is only called for n < p and r < p. static int nCrModpDP(int n, int r, int p) { // The array C is going to store last row of // pascal triangle at the end. And last entry // of last row is nCr int[] C = new int[r + 1]; C[0] = 1; // Top row of Pascal Triangle // One by constructs remaining rows of Pascal // Triangle from top to bottom for (int i = 1; i <= n; i++) { // Fill entries of current row using previous // row values for (int j = Math.min(i, r); j > 0; j--) // nCj = (n-1)Cj + (n-1)C(j-1); C[j] = (C[j] + C[j - 1]) % p; } return C[r]; } // Lucas Theorem based function that returns nCr % p // This function works like decimal to binary conversion // recursive function. First we compute last digits of // n and r in base p, then recur for remaining digits static int nCrModpLucas(int n, int r, int p) { // Base case if (r == 0) { return 1; } // Compute last digits of n and r in base p int ni = n % p; int ri = r % p; // Compute result for last digits computed above, and // for remaining digits. Multiply the two results and // compute the result of multiplication in modulo p. return (nCrModpLucas(n / p, r / p, p) * // Last digits of n and r nCrModpDP(ni, ri, p)) % p; // Remaining digits } // Driver program public static void main(String[] args) { int n = 1000, r = 900, p = 13; System.out.println("Value of nCr % p is " + nCrModpLucas(n, r, p)); } } ``` ## **Chinese Remainder Theorem** **Chinese Remainder Theorem states that there always exists an x that satisfies given congruences.** Let num[0], num[1], …num[k-1] be positive integers that are pairwise coprime. Then, for any given sequence of integers rem[0], rem[1], … rem[k-1], there exists an integer x solving the following system of simultaneous congruences. A Naive Approach to find x is to start with 1 and one by one increment it and check if dividing it with given elements in num[] produces corresponding remainders in rem[]. Once we find such an x, we return it. ```java // A Java program to demonstrate the working of Chinese remainder theorem class ChineseRemainderTheorem { // k is size of num[] and rem[]. Returns the smallest // number x such that: // x % num[0] = rem[0], // x % num[1] = rem[1], // .................. // x % num[k-2] = rem[k-1] // Assumption: Numbers in num[] are pairwise coprime // (gcd for every pair is 1) static int findMinX(int num[], int rem[], int k) { int x = 1; // Initialize result // As per the Chinese remainder theorem, // this loop will always break. while (true) { // Check if remainder of x % num[j] is // rem[j] or not (for all j from 0 to k-1) int j; for (j = 0; j < k; j++) if (x % num[j] != rem[j]) { break; } // If all remainders matched, we found x if (j == k) { return x; } // Else try next number x++; } } // Driver method public static void main(String args[]) { int num[] = { 3, 4, 5 }; int rem[] = { 2, 3, 1 }; int k = num.length; System.out.println("x is " + findMinX(num, rem, k)); } } ``` ## **NP-Completeness** A problem is in the class NPC if it is in NP and is as hard as any problem in NP. A problem is NP-hard if all problems in NP are polynomial time reducible to it, even though it may not be in NP itself. **NP-Hard** If a polynomial time algorithm exists for any of these problems, all problems in NP would be polynomial time solvable. These problems are called NP-complete. The phenomenon of NP-completeness is important for both theoretical and practical reasons. ##### Definition of NP-Completeness A language B is NP-complete if it satisfies two conditions: - B is in NP. - Every A in NP is polynomial time reducible to B. If a language satisfies the second property, but not necessarily the first one, the language B is known as NP-Hard. Informally, a search problem B is NP-Hard if there exists some NP-Complete problem A that Turing reduces to B. The problem in NP-Hard cannot be solved in polynomial time, until P = NP. If a problem is proved to be NPC, there is no need to waste time on trying to find an efficient algorithm for it. Instead, we can focus on design approximation algorithm. **NP-Completeness Problems**: > Following are some NP-Complete problems, for which no polynomial time algorithm is known. - Determining whether a graph has a Hamiltonian cycle - Determining whether a Boolean formula is satisfiable, etc. **NP-Hard Problems > The following problems are NP-Hard - The circuit-satisfiability problem - Set Cover - Vertex Cover - Travelling Salesman Problem In this context, now we will discuss TSP is NP-Complete: **TSP is NP-Complete** The traveling salesman problem consists of a salesman and a set of cities. The salesman has to visit each one of the cities starting from a certain one and returning to the same city. The challenge of the problem is that the traveling salesman wants to minimize the total length of the trip Okay so let's move to some more advanced concepts: ## 1. Bit Masking + Dynamic Programming First thing to make sure before using bitmasks for solving a problem is that it must be having small constraints, as solutions which use bitmasking generally take up exponential time and memory. Let's first try to understand what Bitmask means. Mask in Bitmask means hiding something. Bitmask is nothing but a binary number that represents something. Let's take an example. Consider the set *A={1,2,3,4,5}*. We can represent any subset of *A* using a bitmask of length *5*, with an assumption that if *ith(0<=i<=4)* bit is set then it means ith element is present in subset. So the bitmask *01010* represents the subset *{2,4}* *Now the benefit of using bitmask. We can set the ith bit, unset the ith bit, check if ith bit is set in just one step each. Let's say the bitmask b = 01010.* ***Set the ith bit*** : b|(1<= val count = count + 1 return count ``` To iterate over all the subsets we are going to each number from *0 to 2^(set_size)-1*. The above problem simply uses bitmask and complexity is *O(N2^(N))*. ##### Assignment Problem: *There are N persons and N tasks, each task is to be alloted to a single person. We are also given a matrix cost of size NxN , where cost[i][j] denotes, how much person i is going to charge for task j. Now we need to assign each task to a person in such a way that the total cost is minimum. Note that each task is to be alloted to a single person, and each person will be alloted only one task.* The brute force approach here is to try every possible assignment. Algorithm is given below: ``` assign(N, cost) for i = 0 to N assignment[i] = i //assigning task i to person i res = INFINITY for j = 0 to factorial(N) total_cost = 0 for i = 0 to N total_cost = total_cost + cost[i][assignment[i]] res = min(res, total_cost) generate_next_greater_permutation(assignment) return res ``` The complexity of above algorithm is *O(N!)*, well that's clearly not good. Let's try to improve it using dynamic programming. Suppose the state of dp is *(k,mask)* , where k represents that person 0 to k-1 have been assigned a task, and mask is a binary number, whose ith bit represents if the ith task has been assigned or not. Now, suppose, we have answer(k,mask), we can assign a task i to person k, iff ith task is not yet assigned to any peron i.e. *mask&(i< ## 2. Extended Euclidean Algorithm While the Euclidean algorithm calculates only the greatest common divisor (GCD) of two integers a and b, the extended version also finds a way to represent GCD in terms of a and b, i.e. coefficients x and y for which: ax+by=gcd(a,b) It's important to note, that we can always find such a representation, for instance, gcd(55,80)=5 therefore we can represent 5 as a linear combination with the terms 55 and 80, 55x3+80x(−2)=5. #### Algorithm We will denote the GCD of a and b with g in this section. The changes to the original algorithm are very simple. If we recall the algorithm, we can see that the algorithm ends with b=0 and a=g. For these parameters, we can easily find coefficients, namely gx1+0x0=g. Starting from these coefficients (x,y)=(1,0), we can go backwards up the recursive calls. All we need to do is to figure out how the coefficients x and y change during the transition from (a,b) to (b, a mod b). Let us assume we found the coefficients (x1,y1) for (b,amodb): *b⋅x1+(amodb)⋅y1=g* and we want to find the pair (x,y) for (a,b): *a⋅x+b⋅y=g* We can represent amodb as: *amodb=a−⌊a/b⌋⋅b* Substituting this expression in the coefficient equation of (x1,y1) gives: *g=b⋅x1+(amodb)⋅y1=b⋅x1+(a−⌊a/b⌋⋅b)⋅y1* and after rearranging the terms: *g=a⋅y1+b⋅(x1−y1⋅⌊a/b⌋)* We found the values of x and y: *x=y1* *y=x1−y1⋅⌊a/b⌋* #### Implementation ```java class Extended { // extended Euclidean Algorithm public static int gcdExtended(int a, int b, int x, int y) { // Base Case if (a == 0) { x = 0; y = 1; return b; } int x1 = 1, y1 = 1; // To store results of recursive call int gcd = gcdExtended(b % a, a, x1, y1); // Update x and y using results of recursive // call x = y1 - (b / a) * x1; y = x1; return gcd; } // Driver Program public static void main(String[] args) { int x = 1, y = 1; int a = 35, b = 15; int g = gcdExtended(a, b, x, y); System.out.print("gcd(" + a + ", " + b + ") = " + g); } } ``` ## 3. Modulo Multiplicative Inverse In modular arithmetic we do not have a division operation. However, we do have modular inverses. - The modular inverse of A (mod C) is A^-1 - (A * A^-1) ≡ 1 (mod C) or equivalently (A * A^-1) mod C = 1 - Only the numbers coprime to C (numbers that share no prime factors with C) have a modular inverse (mod C) ##### Example: A=3, C=7 - 3 * 0 ≡ 0 (mod 7) - 3 * 1 ≡ 3 (mod 7) - 3 * 2 ≡ 6 (mod 7) - 3 * 3 ≡ 9 ≡ 2 (mod 7) - 3 * 4 ≡ 12 ≡ 5 (mod 7) - 3 * 5 ≡ 15 (mod 7) ≡ 1 (mod 7) <------ ​*FOUND INVERSE!* - 3 * 6 ≡ 18 (mod 7) ≡ 4 (mod 7) #### Implementation -1 (Naive) A Naive method is to try all numbers from 1 to m. For every number x, check if (a*x)%m is 1. Time Complexity: O(m). ````java class Modulo{ static int modInverse(int a, int m) { for (int x = 1; x < m; x++) if (((a%m) * (x%m)) % m == 1) return x; return 1; } public static void main(String args[]) { int a = 3, m = 11; // Function call System.out.println(modInverse(a, m)); } } ```` #### Implementation -2 (Extended Euler’s GCD algorithm - Iterative) The idea is to use Extended Euclidean algorithms that takes two integers ‘a’ and ‘b’, finds their gcd and also find ‘x’ and ‘y’ such that ax + by = gcd(a, b) Time Complexity: O(Log m) ````java class Modulo{ // Returns modulo inverse of a with // respect to m using extended Euclid // Algorithm Assumption: a and m are // coprimes, i.e., gcd(a, m) = 1 static int modInverse(int a, int m) { int m0 = m; int y = 0, x = 1; if (m == 1) return 0; while (a > 1) { // q is quotient int q = a / m; int t = m; // m is remainder now, process // same as Euclid's algo m = a % m; a = t; t = y; // Update x and y y = x - q * y; x = t; } // Make x positive if (x < 0) x += m0; return x; } // Driver code public static void main(String args[]) { int a = 3, m = 11; // Function call System.out.println("Modular multiplicative " + "inverse is " + modInverse(a, m)); } } ```` #### Implementation-3 (Works when m is prime) If we know m is prime, then we can also use Fermats’s little theorem to find the inverse. am-1 ≅ 1 (mod m) Time Complexity: O(Log m) ````java class Modulo{ // Function to find modular inverse of a // under modulo m Assumption: m is prime static void modInverse(int a, int m) { int g = gcd(a, m); if (g != 1) System.out.println("Inverse doesn't exist"); else { // If a and m are relatively prime, then modulo // inverse is a^(m-2) mode m System.out.println( "Modular multiplicative inverse is " + power(a, m - 2, m)); } } static int power(int x, int y, int m) { if (y == 0) return 1; int p = power(x, y / 2, m) % m; p = (int)((p * (long)p) % m); if (y % 2 == 0) return p; else return (int)((x * (long)p) % m); } // Function to return gcd of a and b static int gcd(int a, int b) { if (a == 0) return b; return gcd(b % a, a); } // Driver Code public static void main(String args[]) { int a = 3, m = 11; // Function call modInverse(a, m); } } ```` ## 4. Linear Diophantine Equations A Diophantine equation is a polynomial equation, usually in two or more unknowns, such that only the integral solutions are required. An Integral solution is a solution such that all the unknown variables take only integer values. Given three integers a, b, c representing a linear equation of the form : ax + by = c. Determine if the equation has a solution such that x and y are both integral values. ``` Input : a = 3, b = 6, c = 9 Output: Possible Explanation : The Equation turns out to be, 3x + 6y = 9 one integral solution would be x = 1 , y = 1 Input : a = 3, b = 6, c = 8 Output : Not Possible Explanation : o integral values of x and y exists that can satisfy the equation 3x + 6y = 8 Input : a = 2, b = 5, c = 1 Output : Possible Explanation : Various integral solutions possible are, (-2,1) , (3,-1) etc. ``` #### Solution: For linear Diophantine equation equations, integral solutions exist if and only if, the GCD of coefficients of the two variables divides the constant term perfectly. In other words the integral solution exists if, GCD(a ,b) divides c. Thus the algorithm to determine if an equation has integral solution is pretty straightforward. - Find GCD of a and b - Check if c % GCD(a ,b) ==0 - If yes then print Possible - Else print Not Possible Below is the implementation of above approach. ````java class Equation { // Utility function to find the GCD // of two numbers static int gcd(int a, int b) { return (a % b == 0) ? Math.abs(b) : gcd(b,a%b); } // This function checks if integral // solutions are possible static boolean isPossible(int a, int b, int c) { return (c % gcd(a, b) == 0); } // Driver function public static void main (String[] args) { // First example int a = 3, b = 6, c = 9; if(isPossible(a, b, c)) System.out.println( "Possible" ); else System.out.println( "Not Possible"); // Second example a = 3; b = 6; c = 8; if(isPossible(a, b, c)) System.out.println( "Possible") ; else System.out.println( "Not Possible"); // Third example a = 2; b = 5; c = 1; if(isPossible(a, b, c)) System.out.println( "Possible" ); else System.out.println( "Not Possible"); } } ```` ```` Output : Possible Not Possible Possible ```` ## 5. Matrix Exponentiation The concept of matrix exponentiation in its most general form is very useful in solving questions that involve calculating the nth term of a linear recurrence relation in time of the order of log(n). ```` For solving the matrix exponentiation we are assuming a linear recurrence equation like below: F(n) = a*F(n-1) + b*F(n-2) + c*F(n-3) for n >= 3 . . . . . Equation (1) where a, b and c are constants. For this recurrence relation, it depends on three previous values. Now we will try to represent Equation (1) in terms of the matrix. [First Matrix] = [Second matrix] * [Third Matrix] | F(n) | = Matrix 'C' * | F(n-1) | | F(n-1) | | F(n-2) | | F(n-2) | | F(n-3) | Dimension of the first matrix is 3 x 1 . Dimension of the third matrix is also 3 x 1. So the dimension of the second matrix must be 3 x 3 [For multiplication rule to be satisfied.] Now we need to fill the Matrix 'C'. So according to our equation. F(n) = a*F(n-1) + b*F(n-2) + c*F(n-3) F(n-1) = F(n-1) F(n-2) = F(n-2) C = [a b c 1 0 0 0 1 0] Now the relation between matrix becomes : [First Matrix] [Second matrix] [Third Matrix] | F(n) | = | a b c | * | F(n-1) | | F(n-1) | | 1 0 0 | | F(n-2) | | F(n-2) | | 0 1 0 | | F(n-3) | Lets assume the initial values for this case :- F(0) = 0 F(1) = 1 F(2) = 1 So, we need to get F(n) in terms of these values. So, for n = 3 Equation (1) changes to | F(3) | = | a b c | * | F(2) | | F(2) | | 1 0 0 | | F(1) | | F(1) | | 0 1 0 | | F(0) | Now similarly for n = 4 | F(4) | = | a b c | * | F(3) | | F(3) | | 1 0 0 | | F(2) | | F(2) | | 0 1 0 | | F(1) | - - - - 2 times - - - | F(4) | = | a b c | * | a b c | * | F(2) | | F(3) | | 1 0 0 | | 1 0 0 | | F(1) | | F(2) | | 0 1 0 | | 0 1 0 | | F(0) | So for n, the Equation (1) changes to - - - - - - - - n -2 times - - - - - | F(n) | = | a b c | * | a b c | * ... * | a b c | * | F(2) | | F(n-1) | | 1 0 0 | | 1 0 0 | | 1 0 0 | | F(1) | | F(n-2) | | 0 1 0 | | 0 1 0 | | 0 1 0 | | F(0) | | F(n) | = [ | a b c | ] ^ (n-2) * | F(2) | | F(n-1) | [ | 1 0 0 | ] | F(1) | | F(n-2) | [ | 0 1 0 | ] | F(0) | ```` So we can simply multiply our Second matrix n-2 times and then multiply it with the third matrix to get the result. Multiplication can be done in (log n) time using Divide and Conquer algorithm for power. Let us consider the problem of finding n’th term of a series defined using below recurrence. ```` n'th term, F(n) = F(n-1) + F(n-2) + F(n-3), n >= 3 Base Cases : F(0) = 0, F(1) = 1, F(2) = 1 ```` We can find n’th term using following : ````Putting a = 1, b = 1 and c = 1 in above formula | F(n) | = [ | 1 1 1 | ] ^ (n-2) * | F(2) | | F(n-1) | [ | 1 0 0 | ] | F(1) | | F(n-2) | [ | 0 1 0 | ] | F(0) | ```` ##### Java Implementation Time Complexity: O(logN) Auxiliary Space: O(logN) ````java // JAVA program to find value of f(n) where // f(n) is defined as // F(n) = F(n-1) + F(n-2) + F(n-3), n >= 3 // Base Cases : // F(0) = 0, F(1) = 1, F(2) = 1 class Matrix { // A utility function to multiply two // matrices a[][] and b[][]. // Multiplication result is // stored back in b[][] static void multiply(int a[][], int b[][]) { // Creating an auxiliary matrix to // store elements of the // multiplication matrix int mul[][] = new int[3][3]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { mul[i][j] = 0; for (int k = 0; k < 3; k++) mul[i][j] += a[i][k] * b[k][j]; } } // storing the multiplication // result in a[][] for (int i=0; i<3; i++) for (int j=0; j<3; j++) // Updating our matrix a[i][j] = mul[i][j]; } // Function to compute F raise to // power n-2. static int power(int F[][], int n) { int M[][] = {{1, 1, 1}, {1, 0, 0}, {0, 1, 0}}; // Multiply it with initial values // i.e with F(0) = 0, F(1) = 1, // F(2) = 1 if (n == 1) return F[0][0] + F[0][1]; power(F, n / 2); multiply(F, F); if (n%2 != 0) multiply(F, M); // Multiply it with initial values // i.e with F(0) = 0, F(1) = 1, // F(2) = 1 return F[0][0] + F[0][1] ; } // Return n'th term of a series defined // using below recurrence relation. // f(n) is defined as // f(n) = f(n-1) + f(n-2) + f(n-3), n>=3 // Base Cases : // f(0) = 0, f(1) = 1, f(2) = 1 static int findNthTerm(int n) { int F[][] = {{1, 1, 1}, {1, 0, 0}, {0, 1, 0}} ; return power(F, n-2); } // Driver code public static void main (String[] args) { int n = 5; System.out.println("F(5) is " + findNthTerm(n)); } } //This code is contributed by vt_m. ```` ## 6. Combinatorics Combinatorial mathematics, the field of mathematics concerned with problems of selection, arrangement, and operation within a finite or discrete system. Included is the closely related area of combinatorial geometry. One of the basic problems of combinatorics is to determine the number of possible configurations (e.g., graphs, designs, arrays) of a given type. Even when the rules specifying the configuration are relatively simple, enumeration may sometimes present formidable difficulties. The mathematician may have to be content with finding an approximate answer or at least a good lower and upper bound. In mathematics, generally, an entity is said to “exist” if a mathematical example satisfies the abstract properties that define the entity. In this sense it may not be apparent that even a single configuration with certain specified properties exists. This situation gives rise to problems of existence and construction. There is again an important class of theorems that guarantee the existence of certain choices under appropriate hypotheses. Besides their intrinsic interest, these theorems may be used as existence theorems in various combinatorial problems. *Here we will be discussing a few problems that can be implemented using the concepts of Combinatorics* #### Generating Permutations A permutation is an act of rearranging a sequence in such a way that it has a different order. As we know from math, for a sequence of n elements, there are n! different permutations. n! is known as a factorial operation: ``` n! = 1 * 2 * … * n ``` #### Algorithm It's a good idea to think about generating permutations in a recursive manner. Let's introduce the idea of the state. It will consist of two things: the current permutation and the index of the currently processed element. The only work to do in such a state is to swap the element with every remaining one and perform a transition to a state with the modified sequence and the index increased by one. Let's illustrate with an example. We want to generate all permutations for a sequence of four elements – [1, 2, 3, 4]. So, there will be 24 permutations. The illustration below presents the partial steps of the algorithm: ![image](images/permutation.png) Each node of the tree can be understood as a state. The red digits across the top indicate the index of the currently processed element. The green digits in the nodes illustrate swaps. So, we start in the state [1, 2, 3, 4] with an index equal to zero. We swap the first element with each element – including the first, which swaps nothing – and move on to the next state. ##### Java Impelementation ```java private static void permutationsInternal(List sequence, List> results, int index) { if (index == sequence.size() - 1) { permutations.add(new ArrayList<>(sequence)); } for (int i = index; i < sequence.size(); i++) { swap(sequence, i, index); permutationsInternal(sequence, permutations, index + 1); swap(sequence, i, index); } } ``` ### Generating the Powerset of a Set Powerset (or power set) of set S is the set of all subsets of S including the empty set and S itself So, for example, given a set [a, b, c], the powerset contains eight subsets: ``` [] [a] [b] [c] [a, b] [a, c] [b, c] [a, b, c] ``` ##### Java Implementation ```java private static void powersetInternal( List set, List> powerset, List accumulator, int index) { if (index == set.size()) { results.add(new ArrayList<>(accumulator)); } else { accumulator.add(set.get(index)); powerSetInternal(set, powerset, accumulator, index + 1); accumulator.remove(accumulator.size() - 1); powerSetInternal(set, powerset, accumulator, index + 1); } } ``` #### Generating Combinations Now, it's time to tackle combinations. We define it as follows: *k-combination of a set S is a subset of k distinct elements from S, where an order of items doesn't matter* The number of k-combinations is described by the binomial coefficient: ![image](images/combination_equation.png) So, for example, for the set [a, b, c] we have three 2-combinations: ``` [a, b] [a, c] [b, c] ``` ##### Java Implementation ``` java private static void combinationsInternal( List inputSet, int k, List> results, ArrayList accumulator, int index) { int needToAccumulate = k - accumulator.size(); int canAcculumate = inputSet.size() - index; if (accumulator.size() == k) { results.add(new ArrayList<>(accumulator)); } else if (needToAccumulate <= canAcculumate) { combinationsInternal(inputSet, k, results, accumulator, index + 1); accumulator.add(inputSet.get(index)); combinationsInternal(inputSet, k, results, accumulator, index + 1); accumulator.remove(accumulator.size() - 1); } } ``` ================================================ FILE: lessons/num-two.md ================================================ --- path: "/num-two" title: "Number Theory Part-B" order: "10D" section: "Maths for DSA" description: "learn maths required in DSA" --- ================================================ FILE: lessons/operators.md ================================================ --- path: "/operators" title: "Operators in Java" order: "3B" section: "Learn Java" description: "Learn java" --- Operators are symbols that tell the compiler to perform some specfic operations. In JAVA, there are many operators, and they are grouped into several categories. We are going to learn some of the important operators only. You will see these operators in most of the section and this will cover almost every problem you will encounter in your programming journey. Ok, So there are basically 6 categories of operators: - Arithmetic Operators - Relational Operators - Logical Operators - Assignment Operators - Bitwise Operators - Other Operators In the last one _Other Operators_ I have put the miscellaneous operators, which are not grouped into any of the above categories. Ok so let's learn them one by one. ## **Arithmetic Operators** Arithmetric operators are used to perform arithmetic operations. They are used to perform addition, subtraction, multiplication, division, modulus, exponentiation, and negation. That's all you need to know. It has some types: - `Binary Operator`: used to perform addition(**+**), subtraction(**-**), multiplication(**\***), division(**/**), modulus(**%**), exponentiation(**\*\***) etc. - `Unary Operator`: used to perform operation using the single operand. like Incrementer(**++**), Decrementer(**--**), negation(**!**), Complement(**~**), etc. Ok so let's learn about the incrementer and decrementer operators now because they are very important. ### Incrementer and Decrementer Operators/ Unary Operators In Java there are two types of incrementer and decrementer operators: - **Incrementer Operator**: used to increment the value of the operand by 1. - **Decrementer Operator**: used to decrement the value of the operand by 1. --- There are two types to each of them: - **Prefix Incrementer Operator**: used to increment the value of the operand by 1. - **Postfix Incrementer Operator**: used to increment the value of the operand by 1. - **Prefix Decrementer Operator**: used to decrement the value of the operand by 1. - **Postfix Decrementer Operator**: used to decrement the value of the operand by 1. now do some question based on the above operators. | **Operators** | **Representation** | **Description** | **Example** | | ----------------- | ------------------ | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | | Prefix Increment | **++x** | Increment `x` instantly | int x = 10; int y; y = ++x; `System.out.println(x+" , "+y)` **Output: 11 , 11** | | Postfix Increment | **x++** | Current value of `x` is preserved temporarily. `x` will get incremented before next statement is executed. | int x = 10; int y; y = x++; `System.out.println(x+" , "+y)` **Output: 11 , 10** | | Prefix Decrement | **--x** | Decrement `x` instantly | int x = 10; int y; y = --x; `System.out.println(x+" , "+y)` **Output: 9 , 9** | | Postfix Decrement | **x--** | Current value of `x` is preserved temporarily. `x` will get decremented before next statement is executed. | int x = 10; int y; y = x--; `System.out.println(x+" , "+y)` **Output: 9 , 10** | ## **Relational Operators** Relational operators are used to compare the values of two operands. They are used to compare the values of two operands using the following operators: - `== or = =`: used to compare two operands if they are equal. It gives true if both the operands have equal values. - `!= or ! =`: used to compare two operands if they are not equal. It gives true if both the operands have not same values. - `<`: used to compare two operands if the first operand is less than the second operand. It gives true if the first operand is less than the second operand. - `>`: used to compare two operands if the first operand is greater than the second operand. It gives true if the first operand is greater than the second operand. - `<=`: used to compare two operands if the first operand is less than or equal to the second operand. It gives true if the first operand is less than or equal to the second operand. - `>=`: used to compare two operands if the first operand is greater than or equal to the second operand. It gives true if the first operand is greater than or equal to the second operand. ## **Logical Operators** Logical operators are used to perform logical operations. They are used to perform the following operations: - `&&` and `&`: Java unlike many other languages has two AND operators to perform logical AND operation. It returns true if both the operands (being compared) have a truthy value. Even though both the `&` and `&&` operators perform the same AND operation; the `&&` operator is a logical operator and it can improve the efficiency of your code since it evaluates the second expression only if the first expression is true unlike the bitwise `&` operator which evaluates the second expression nonetheless. - `||` and `|`: OR is used to perform logical OR operation. It returns true if either of the operands have a truthy value. The difference between `|` and `||` is that the `|` operator is a bitwise operator and it compares each operand bitwise whereas the `||` operator is the logical OR operator. It operates on both the operands and returns true if either of the operands have a truthy value. - `!`: NOT used to perform logical NOT operation. It gives true if the operand has false value. let's see an example: ```Java // program to find whether a number is divible by both 3 and 5 // or divisible by only one of them import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("Enter a number: "); int a = sc.nextInt(); if (a % 3 == 0 && a % 5 == 0) System.out.println("The number is divisible by both 3 and 5"); else if (a % 3 == 0 || a % 5 == 0) System.out.println("The numbers is divisible by only one of them"); else System.out.println("The numbers is not divisible by any of them"); } } ``` let's see the explanation: - `a%3==0 && a%5==0`: it checks whether the value of `a` is divisible by both 3 and 5. if its divisible by both 3 and also divisible by 5 then it gives true. that's why we use `&&` operator here. - `a%3==0 || a%5==0`: it checks whether the value of `a` is divisible by either 3 or 5. if its divisible by 3 or 5 then it gives true. if its divisible by 5 then it gives true. that's why we use `||` operator here. - but `a` is neither divisible by 3 nor divisible by 5. so it gives false. so we'll be priting `the numbers is not divisible by any of them`. ## **Assignment Operators** Assignment operators are used to assign the value of one operand to another. They are used to assign the value of one operand to another using the following operators: - `=`: used to assign the value of one operand to another. It assigns the value of the right operand to the left operand. - `+=`: used to add the value of one operand to another. It adds the value of the right operand to the left operand and assigns the result to the left operand. - `-=`: used to subtract the value of one operand from another. It subtracts the value of the right operand from the left operand and assigns the result to the left operand. - `*=`: used to multiply the value of one operand with another. It multiplies the value of the right operand with the left operand and assigns the result to the left operand. - `/=`: used to divide the value of one operand with another. It divides the value of the right operand with the left operand and assigns the result to the left operand. - `%=`: used to find the remainder of the division of one operand with another. It divides the value of the right operand with the left operand and assigns the remainder to the left operand. ## **Bitwise Operators** Bitwise operators are operatr on bits and perform bit-by-bit operations. They are used to perform the following operations: - `&`: **AND operator**. It gives the value of the left operand if it is set in the right operand. eg: let a=5, b=6 then a&b==? | Variable | Value | Binary | |:--------:|:-----:|:------:| | a | 5 | 0101 | | b | 6 | 0110 | | a&b | 4 | 0100 |
- `|`: **OR operator**. It gives the value of the left operand if it is set in the right operand. eg: let a=5, b=6 then a|b==? | Variable | Value | Binary | |:--------:|:-----:|:------:| | a | 5 | 0101 | | b | 6 | 0110 | | a|b | 7 | 0111 |
- `^`: **XOR operator**. It gives the value of the left operand if it is set in the right operand. eg: let a=5, b=6 then a^b==? | Variable | Value | Binary | |:--------:|:-----:|:------:| | a | 5 | 0101 | | b | 6 | 0110 | | a^b | 3 | 0011 | - `~`: **NOT operator**. It gives the value of the left operand if it is set in the right operand. eg: let a=5, ~a==? | Variable | Value | Binary | |:--------:|:-----:|:------:| | a | 5 | 0101 | | ~a | | 1010 | - `<<`: **LEFT SHIFT operator**. It shifts the bits of the left operand to the left and assigns the result to the left operand. ```js eg: let 8 << 1 == ? (01000) << 1 == (10000) ==> 16 ``` - `>>`: **RIGHT SHIFT operator**. It shifts the bits of the left operand to the right and assigns the result to the left operand. ```js eg: let 8 >> 1 == ? (1000) >> 1 == (0100) ==> 4 ``` here one thing to keep in mind that `>>` operator shifts the bits to the right and `<<` shifts the bits to the left. there is a way to find right shift and left shift of a number. ```java Right Shift --> a >> n ==> a * 2^n Left Shift --> a << n ==> a / 2^n ``` ## **Other Operators** This category contains the following operators: - `condition ? true_expression : false_expression`: it evaluates the true_expression if the condition is true and false_expression if the condition is false. ```java // syntax // variable = Expression1 ? Expression2 : Expression3; public class Main { public static void main(String[] args) { int num = 15; String msg = num > 10 ? "Number is greater than 10" : "Number is less than or equal to 10"; System.out.println(msg); } } ``` - `typecasting`: it converts the value of the operand to the type of the right operand. eg: ```java public class Main { public static void main(String[] args) { char ch = 'a'; int typecasted_character = (int) 'a'; System.out.println(ch); System.out.println(typecasted_character); } } ``` ## **Operators Precedence** Operators Precedence is the order in which the operators are evaluated. Below is the precedence of the operators. ![precedence](./images/precedence_java.jpg) ```java public class Main { public static void main(String[] args) { int a = 2, b = 10, c = 0, d = 40, e = 40, f = 30; // precedence rules for arithmetic operators. // (* = / = %) > (+ = -) // prints a+(b/d) System.out.println("a+b/d = " + (a + b / d)); // if same precendence then associative // rules are followed (evaluation occurs by the order //in which the operators are present from left to right) // e/f -> b*d -> a+(b*d) -> a+(b*d)-(e/f) System.out.println("a+b*d-e/f = " + (a + b * d - e / f)); } } ``` Output: ``` a+b/d = 2 a+b*d-e/f = 401 ``` ================================================ FILE: lessons/practise-question.md ================================================ --- path: "/practise-question" title: "Practise Questions" order: "5I" section: "Searching & Sorting" description: "learn Searching & sorting algorithms" --- **Q1) Move All Zeros to End of an Array**
You have been given a random integer array of size N. You have been required to push all the zeros that are present in the array to the end of it such that the relative order of the non-zero elements should be maintained. ```java Sample Input/Output ​Input: arr[]={3,0,1,5,0,5} Output: arr[]={3,1,5,5,0,0} ``` ## Approach Before we discuss the approach for this question let’s see what exactly the question requires us to do. It seems that we have to push all the 0s in the array towards the end of the array. It can also be looked at as pushing all the non-zero elements in the array towards the beginning of the array.
First, traverse the whole array and initialize a variable count whose value should be equal to zero. Now, check each element of the array whether it is equal to zero or not. If the element is not equal to zero,put that element at the count position of the array(arr[count]) and increment the value of count by one.
Now, after traversing the whole array fill the remaining positions of the array with zeroes. ## Program ```java package main; import java.util.*; public class Main { public static void pushZerosToEnd(int[] arr, int n) { int count=0; for(int i=0;i - Make a function named pushZeroToEnd and input an array.
- Traverse through the array and check each element whether it is equal to zero or not.
- If the element is not equal to zero, put the element at the countth position of the array.
- Increase the value of count by 1.
- At last, fill the remaining positions of the array with 0.
## Time Complexity Since we will be traversing the whole array twice therefore the time complexity of algorithm would be: - **Time complexity of first loop O(N) + Time complexity of second loop O(N) = O(N)**, where n is number of elements in input array. ================================================ FILE: lessons/print-patterns.md ================================================ --- path: "/print-patterns" title: "Printing Patterns" order: "4C" section: "Arrays" description: "learn Arrays" --- Java pattern program enhances the coding skill, logic, and looping concepts. It is mostly asked in Java interview to check the logic and thinking of the programmer. We can print a Java pattern program in different designs. To learn the pattern program, we must have a deep knowledge of the Java loop, such as for loop do-while loop. In this section, we will learn how to print a pattern in Java. ## **We have classified the Java pattern program into three categories:** - Star Pattern - Number Pattern - Character Pattern ### **Here we explain each category with examples :** ## **Star Pattern :** _**Qn1 : Right Triangle Star Pattern**_ ### **Code :** ```java public class RightTriangleStarPattern { public static void main(String args[]) { //i for rows and j for columns //row denotes the number of rows you want to print int i, j, row = 4; //outer loop for rows for(i=0; i Happy Learning 👍 ================================================ FILE: lessons/properties.md ================================================ --- path: "/properties" title: "Properties of OOP" order: "11C" section: "Object Oriented Programming" description: "complete introduction to object oriented programming" icon: "object-ungroup" --- ================================================ FILE: lessons/quicksort.md ================================================ --- path: "/quicksort" title: "Quick Sort" order: "8F" section: "Recursion" description: "learn Recursion from scratch" --- Quick sort is a highly efficient sorting algorithm and is based on partitioning of array of data into smaller arrays. A large array is partitioned into two arrays one of which holds values smaller than the specified value, say pivot, based on which the partition is made and another array holds values greater than the pivot value. Quicksort partitions an array and then calls itself recursively twice to sort the two resulting subarrays. This algorithm is quite efficient for large-sized data sets as its average and worst-case complexity are O(n^2), respectively. Quicksort picks an element as pivot, and then it partitions the given array around the picked pivot element. In quick sort, a large array is divided into two arrays in which one holds values that are smaller than the specified value (Pivot), and another array holds the values that are greater than the pivot. After that, left and right sub-arrays are also partitioned using the same approach. It will continue until the single element remains in the sub-array. ## Choosing the Pivot Picking a good pivot is necessary for the fast implementation of quicksort. However, it is typical to determine a good pivot. Some of the ways of choosing a pivot are as follows: - Pivot can be random, i.e. select the random pivot from the given array. - Pivot can either be the rightmost element of the leftmost element of the given array. - Select median as the pivot element. - Algorithm ## Quick Sort Algorithm ### Algorithm: ```Java QUICKSORT (array A, start, end) { if (start < end) { p = partition(A, start, end) QUICKSORT (A, start, p - 1) QUICKSORT (A, p + 1, end) } } ``` ## Example for better understanding Let the elements of array are - ``` 24 9 29 14 19 27 ``` So, in this case, a[left] = 24, a[right] = 27 and a[pivot] = 24. Since, pivot is at left, so algorithm starts from right and move towards left. So, a[pivot] < a[right], so algorithm moves forward one position towards left. Also after this, a[left] = 24, a[right] = 19, and a[pivot] = 24. Because, a[pivot] > a[right], so, algorithm will swap a[pivot] with a[right], and pivot moves to right. ``` 19 9 29 14 24 27 ``` Now, a[left] = 19, a[right] = 24, and a[pivot] = 24. Since, pivot is at right, so algorithm starts from left and moves to right. As a[pivot] > a[left], so algorithm moves one position to right .So, a[left] = 9, a[right] = 24, and a[pivot] = 24. As a[pivot] > a[left], so algorithm moves one position to right. ``` 19 9 24 14 29 27 ``` Since, pivot is at left, so algorithm starts from right, and move to left. Now, a[left] = 24, a[right] = 29, and a[pivot] = 24. As a[pivot] < a[right], so algorithm moves one position to left.So, a[pivot] = 24, a[left] = 24, and a[right] = 14. As a[pivot] > a[right]. so, swap a[pivot] and a[right], now pivot is at right. ``` 19 9 14 24 29 27 ``` Now, a[pivot] = 24, a[left] = 14, and a[right] = 24. Pivot is at right, so the algorithm starts from left and move to right. a[pivot] = 24, a[left] = 24, and a[right] = 24. So, pivot, left and right are pointing the same element. It represents the termination of procedure.Element 24, which is the pivot element is placed at its exact position. Elements that are right side of element 24 are greater than it, and the elements that are left side of element 24 are smaller than it. Also, in a similar manner, quick sort algorithm is separately applied to the left and right sub-arrays. After sorting gets done, the array will be: ``` 9 14 19 24 27 29 ``` ## Implementation of Quick Sort ```Java // Java implementation of QuickSort import java.io.*; class QuickSort{ // A utility function to swap two elements static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } static int partition(int[] arr, int low, int high) { // pivot int pivot = arr[high]; // Index of smaller element and // indicates the right position // of pivot found so far int i = (low - 1); for(int j = low; j <= high - 1; j++) { // If current element is smaller // than the pivot if (arr[j] < pivot) { // Increment index of // smaller element i++; swap(arr, i, j); } } swap(arr, i + 1, high); return (i + 1); } static void quickSort(int[] arr, int low, int high) { if (low < high) { // pi is partitioning index, arr[p] // is now at right place int pi = partition(arr, low, high); // Separately sort elements before // partition and after partition quickSort(arr, low, pi - 1); quickSort(arr, pi + 1, high); } } // Function to print an array static void printArray(int[] arr, int size) { for(int i = 0; i < size; i++) System.out.print(arr[i] + " "); System.out.println(); } // Driver Code public static void main(String[] args) { int[] arr = { 10, 7, 8, 9, 1, 5 }; int n = arr.length; quickSort(arr, 0, n - 1); System.out.println("Sorted array: "); printArray(arr, n); } } ``` ### Output ``` Sorted array: 1 5 7 8 9 10 ```` ## Time Complexity and Space Complexity ### Time Complexity - **Best Case Complexity:** In Quicksort, the best-case occurs when the pivot element is the middle element or near to the middle element. The best-case time complexity of quicksort is O(n*logn). - **Average Case Complexity:** It occurs when the array elements are in jumbled order that is not properly ascending and not properly descending. The average case time complexity of quicksort is O(n*logn). - **Worst Case Complexity:** In quick sort, worst case occurs when the pivot element is either greatest or smallest element. Suppose, if the pivot element is always the last element of the array, the worst case would occur when the given array is sorted already in ascending or descending order. The worst-case time complexity of quicksort is O(n2). ### Space Complexity - **Space Complexity:** The space complexity of quicksort is O(n*logn). ## The Uses and Real-time application of Quicksort - Commercial Computing is used in various government and private organizations for the purpose of sorting various data like sorting files by name/date/price, sorting of students by their roll no., sorting of account profile by given id, etc. - The sorting algorithm is used for information searching and as Quicksort is the fastest algorithm so it is widely used as a better way of searching. - It is used everywhere where a stable sort is not needed. - Quicksort is a cache-friendly algorithm as it has a good locality of reference when used for arrays. - It is tail -recursive and hence all the call optimization can be done. - It is an in-place sort that does not require any extra storage memory. - It is used in operational research and event-driven simulation. - Numerical computations and in scientific research, for accuracy in calculations most of the efficiently developed algorithm uses priority queue and quick sort is used for sorting. ## 3 way Quick Sort The idea of 3 way Quick Sort is to process all occurrences of the pivot and is based on Dutch National Flag algorithm. The three-way quicksort is similar, but there are three sections. array arr[1 to n] is divided into three parts. - arr[1 to i] - arr[i + 1, j] - arr[j + 1, n] ## Implementaion of 3 way Quick Sort ```Java public class QuickSort3 { public void sort(int[] A) { if (A == null || A.length <= 1) return; quicksort(A, 0, A.length - 1); } private void quicksort(int[] A, int start, int end) { if (start >= end) return; // choose the middle element as the pivot int mid = start + (end - start) / 2; int pivot = A[mid]; // move pivot to the front swap(A, start, mid); // lt: index to store next element < pivot // gt: index to store next element > pivot int lt = start, gt = end, i = start + 1; // 1: i <= gt not i <= end while (i <= gt) { // move elements < pivot to the front if (A[i] < pivot) swap(A, i++, lt++); // NOTE: don't move i, as we don't know whether value of the element // from the end that got swap to current i and we need to check it else if (A[i] > pivot) swap(A, i, gt--); // keep elements == pivot on the same positition else i++; } quicksort(A, start, lt - 1); quicksort(A, gt + 1, end); } private void swap(int[] A, int i, int j) { int temp = A[i]; A[i] = A[j]; A[j] = temp; } } ``` ================================================ FILE: lessons/radixsort.md ================================================ --- path: "/radixsort" title: "Radix Sort" order: "5G" section: "Searching & Sorting" description: "learn radix sort algorithms" --- Radix sort is a sorting algorithm that sorts the elements by first grouping the individual digits of the same place value. Then, sort the elements according to their increasing/decreasing order. Suppose, we have an array of 8 elements. First, we will sort elements based on the value of the unit place. Then, we will sort elements based on the value of the tenth place. This process goes on until the last significant place. ## Algorithm 1. Find the largest element in the array, i.e. max. Let X be the number of digits in max. X is calculated because we have to go through all the significant places of all elements. for example in the array [121, 432, 564, 23, 1, 45, 788], we have the largest number 788. It has 3 digits. Therefore, the loop should go up to hundreds place (3 times). 2. Now, go through each significant place one by one. Use any stable sorting technique to sort the digits at each significant place. We have used counting sort for this. Sort the elements based on the unit place digits (X=0). 3. Now, sort the elements based on digits at tens place. 4. Finally, sort the elements based on the digits at hundreds place. ## Code Implementation ```java // Radix Sort in Java Programming import java.util.Arrays; class RadixSort { // Using counting sort to sort the elements in the basis of significant places void countingSort(int array[], int size, int place) { int[] output = new int[size + 1]; int max = array[0]; for (int i = 1; i < size; i++) { if (array[i] > max) max = array[i]; } int[] count = new int[max + 1]; for (int i = 0; i < max; ++i) count[i] = 0; // Calculate count of elements for (int i = 0; i < size; i++) count[(array[i] / place) % 10]++; // Calculate cumulative count for (int i = 1; i < 10; i++) count[i] += count[i - 1]; // Place the elements in sorted order for (int i = size - 1; i >= 0; i--) { output[count[(array[i] / place) % 10] - 1] = array[i]; count[(array[i] / place) % 10]--; } for (int i = 0; i < size; i++) array[i] = output[i]; } // Function to get the largest element from an array int getMax(int array[], int n) { int max = array[0]; for (int i = 1; i < n; i++) if (array[i] > max) max = array[i]; return max; } // Main function to implement radix sort void radixSort(int array[], int size) { // Get maximum element int max = getMax(array, size); // Apply counting sort to sort elements based on place value. for (int place = 1; max / place > 0; place *= 10) countingSort(array, size, place); } // Driver code public static void main(String args[]) { int[] data = { 121, 432, 564, 23, 1, 45, 788 }; int size = data.length; RadixSort rs = new RadixSort(); rs.radixSort(data, size); System.out.println("Sorted Array in Ascending Order: "); System.out.println(Arrays.toString(data)); } } ``` ## Complexity analysis Time Complexity Best Case: **O(n+k)** Average Case: **O(n+k)** Worst Case: **O(n+k)** Space Complexity: **O(max)** Stability: **Yes** For the radix sort that uses counting sort as an intermediate stable sort, the time complexity is **O(d(n+k)).** Here, d is the number cycle and O(n+k) is the time complexity of counting sort. Thus, radix sort has linear time complexity which is better than O(nlog n) of comparative sorting algorithms. If we take very large digit numbers or the number of other bases like 32-bit and 64-bit numbers then it can perform in linear time however the intermediate sort takes large space. This makes radix sort space inefficient. This is the reason why this sort is not used in software libraries. ================================================ FILE: lessons/recurrence.md ================================================ --- path: "/recurrence" title: "Recurrence Relations" order: "7D" section: "Space & Time Complexity" description: "learn about time and space complexity for various algorithms" --- ================================================ FILE: lessons/recursion-arrays.md ================================================ --- path: "/recursion-arrays" title: "Recursion & Array" order: "8C" section: "Recursion" description: "learn Recursion from scratch" --- ================================================ FILE: lessons/recursion-practise.md ================================================ --- path: "/recursion-practise" title: "Standard Practise Questions" order: "8G" section: "Recursion" description: "learn Recursion from scratch" --- ## **Q1 : Recursive Solution of Pow(x, n)** Implement `pow(x, n)` which calculates `x` raised to the power `n` i.e. `x^n` ***Example 1:*** ``` Input: x = 2, n = 9 Output: 512 ``` ***Example 2:*** ``` Input: x = 5, n = 3 Output: 125 ``` ### **Solution & Approach :**
Rec-Relation
#### ***Rcursive Tree :*** For, **pow(2, 9) = 29**
Rec-Relation
### **Time Complexity :** O(log(n)) ### **Code :** ```java class PowerProgram { // power function public static int pow(int x, int n){ if (n==0) return 1; else if(n%2==0) { int temp = pow(x, n/2); return temp*temp; } else return x*pow(x, n-1); } // Driver Code public static void main(String args[]) { int n = 2, x = 9; int result = pow(n, x); System.out.print(result); } } ``` ### **Output :** ``` 512 ``` ## **Q2 : Recursive program to find all Indices of a Number from an Array** Given an array `arr` of size `N` and an integer `X`. The task is to find all the indices of the integer `X` in the array Examples: ``` Input: arr = {1, 2, 3, 2, 2, 5}, X = 2 Output: 1 3 4 As Element 2 is present at indices 1, 3, 4 (0 based indexing) ``` ### **Solution & Approach :** - If the start index reaches the length of the array, then return empty array - Else keep the first element of the array with yourself and pass the rest of the array to recursion. - If the element at start index is not equal to x then just simply return the answer which came from recursion. - Else if the element at start index is equal to x then shift the elements of the array (which is the answer of recursion) one step to the right and then put the start index in the front of the array (which came through recursion) ### **Code :** ```java public class FindAllIndices { public static int[] printAllIndex(int[] input, int x, int startIndex) { if (startIndex == input.length) { int[] output = new int[0]; return output; } int[] smallOutput = printAllIndex(input, x, startIndex + 1); if (input[startIndex] == x) { int[] output = new int[smallOutput.length + 1]; output[0] = startIndex; for (int i = 0; i < smallOutput.length; i++) { output[i + 1] = smallOutput[i]; } return output; } else { return smallOutput; } } public static int[] printAllIndex(int[] input) { return printAllIndex(input, 2, 0); } public static void main(String[] args) { int[] arr = { 1, 2, 3, 2, 2, 5 }; arr = printAllIndex(arr); for (int j : arr) { System.out.print(j + " "); } } } ``` ### **Output :** ``` 1 3 4 ``` ## **Q3 : Count Good Numbers** A digit string is good if the digits (0-indexed) at `even` indices are `even` and the digits at `odd` indices are `prime` (2, 3, 5, or 7). - For example, `2582` is good because the digits `(2 and 8)` at even positions are even and the digits `(5 and 2)` at odd positions are prime. However, `3245` is not good because `3` is at an even index but is not even. Given an integer `n`, return the total number of good digit strings of length n. Since the answer may be large, return it modulo` 10^9+7`. A digit string is a string consisting of digits 0 through 9 that may contain leading zeros. ***Example-1*** ``` Input: n = 1 Output: 5 Explanation: The good numbers of length 1 are "0", "2", "4", "6", "8". ``` ***Example-2*** ``` Input: n = 50 Output: 564908303 ``` ### **Solution & Approach :** ### **Code :** ```java class GoodNumber { static int mod=(int)1e9+7; public static int countGoodNumbers(long n) { if(n%2==0){ long a= power(4,n/2); long b=power(5,n/2); long z=a*b %mod; return (int)(z); }else{ long a= power(4,n/2); long b=power(5,(n/2)+1); long z=a*b%mod; return (int)(z); } } // power function public static long power(long x,long y){ long temp; if(y==0) return 1; temp=power(x,y/2); if(y%2==0) return (temp*temp)%mod; else return (x*temp*temp)%mod; } // Driver Code public static void main(String args[]) { int n = 1; int result = countGoodNumbers(n); System.out.print(result); } } ``` ### **Output :** ``` 5 ```

Happy Learning 👍 ================================================ FILE: lessons/recursion-string.md ================================================ --- path: "/recursion-string" title: "Recursion & Strings" order: "8D" section: "Recursion" description: "learn Recursion from scratch" --- The process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called as recursive function. Using recursive algorithm, certain problems can be solved quite easily. For example, we can define the operation "find your way home" as: - If you are at home, stop moving. - Take one step toward home. - "find your way home". Here the solution to finding your way home is two steps (three steps). First, we don't go home if we are already home. Secondly, we do a very simple action that makes our situation simpler to solve. Finally, we redo the entire algorithm. Here we are going to see some important examples based on strings using Recursion:- ### 1)String Reverse :- Examples:- 1) Input - nissan is a good company Output - ynapmoc doog a si nassin 2) Input - He is my brother Output - rehtorb ym si eh ### Approach/Algorithm:- Implement a recursive function that will reverse a string, Approach:- - If string length is null or less than equal to 1, then return the original string - Else call the function within itself and pass the substring of s from start index 0 to end index(length of string - 1). ```java string_rev(String s) { IF(s = Null or length of s <= 1){ RETURN } ELSE{ Call string_rev(substring of s from start index 0 to end index (length of s - 1)) } } ``` ### Code Implementation:- ```java class StringReverse { void string_rev(String s) { if ((s==null)||(s.length() <= 1)) System.out.println(s); else { System.out.print(s.charAt(s.length()-1)); string_rev(s.substring(0,s.length()-1)); } } public static void main(String[]args) { String s = "He is my Brother"; StringReverse obb = new StringReverse(); obb.string_rev(s); } } ``` ### OUTPUT:- "rehtorB ym si eH" ### 2) Remove consecutive character duplicates using recursion:- Examples:- Input:- aaabbccc Output:- abc Input:- aaaaaaabbbbb Output:- ab ### Approach/Algorithm:- The steps to solve this problem with recursion are as follows, 1) IF the String is null/empty, then simply return 2) ELSE compare the adjacent characters. IF the characters are identical, then shift the characters one by one to the left of the string. Call the function again(perform recursion) and pass the updated string S as the value. 3) ELSE if they are not similar, then call recursion on the string from the next portion of the string. ```java remove_dup(String S) { IF(length of S <= 1){ RETURN S } IF(S[0] = S[1]){ RETURN call remove_dup() and pass the substring of S from index 1 to end. } ELSE{ RETURN 1st character + call remove_dup() and pass the substring of S from index 1 to end. } } ``` ### Code Implementation:- ```java import java.io.*; class Program { public static String remove_dup(String s) { if(s.length()<=1) return s; if(s.charAt(0)==s.charAt(1)) return remove_dup(s.substring(1)); else return s.charAt(0) + remove_dup(s.substring(1)); } public static void main(String[] args) { String s = "aabcca"; System.out.println(remove_dup(s)); } } ``` ### Output:- abca 3) Tower of Hanoi(Using recursion):- Explanation:- Tower of Hanoi is a mathematical puzzle where we have three rods and N disks. The objective of the puzzle is to move the entire stack to another rod, obeying the following simple rules:- 1) Only one disk can be moved at a time. 2) Each move consists of taking the upper disk from one of the stacks and placing it on top of another stack i.e. a disk can only be moved if it is the uppermost disk on a stack. 3) No larger disk may be placed on top of a smaller disk. ### Code Implementation:- ```java class Program { /*A- Starting rod, B- Temporary rod, C- Destination rod */ public static void tower_of_hanoi(int n, char from_rod, char to_rod, char temp_rod) { if (n == 1) { System.out.println("Move disk 1 from rod " + from_rod + " to rod " + to_rod); return; } tower_of_hanoi(n-1, from_rod, temp_rod, to_rod); System.out.println("Disk " + n + " moved from rod " + from_rod + " to rod " + to_rod); tower_of_hanoi(n-1, temp_rod, to_rod, from_rod); } public static void main(String args[]) { int n = 4; // Number of disks System.out.println("A- Starting tower\nC- Destination tower\nB- Temporary tower"); tower_of_hanoi(n, \'A\', \'C\', \'B\'); } } ``` ### Output:- ```yml A- Starting tower C- Destination tower B- Temporary tower Disk 1 moved from rod 'A' to rod 'B' Disk 2 moved from rod 'A' to rod 'C' Disk 1 moved from rod 'B' to rod 'C' Disk 3 moved from rod 'A' to rod 'B' Disk 1 moved from rod 'C' to rod 'A' Disk 2 moved from rod 'C' to rod 'B' Disk 1 moved from rod 'A' to rod 'B' Disk 4 moved from rod 'A' to rod 'C' Disk 1 moved from rod 'B' to rod 'C' Disk 2 moved from rod 'B' to rod 'A' Disk 1 moved from rod 'C' to rod 'A' Disk 3 moved from rod 'B' to rod 'C' Disk 1 moved from rod 'A' to rod 'B' Disk 2 moved from rod 'A' to rod 'C' Disk 1 moved from rod 'B' to rod 'C' ``` ================================================ FILE: lessons/selectionsort.md ================================================ --- path: "/selectionsort" title: "Selection Sort" order: "5D" section: "Searching & Sorting" description: "learn Sorting algorithms" --- Selection sort is a simple sorting algorithm. This sorting algorithm is an in-place comparison-based algorithm in which the list is divided into two parts, the sorted part at the left end and the unsorted part at the right end. Initially, the sorted part is empty and the unsorted part is the entire list. The smallest element is selected from the unsorted array and swapped with the leftmost element, and that element becomes a part of the sorted array. This process continues moving unsorted array boundary by one element to the right. The average and worst-case complexity of selection sort is `O(n^2)`, where n is the number of items. Due to this, it is not suitable for large data sets. Selection sort is generally used when: - A small array is to be sorted - Swapping cost doesn't matter - It is compulsory to check all elements ## Selection Sort Algorithm ``` selectionSort(array, size) repeat (size - 1) times set the first unsorted element as the minimum for each of the unsorted elements if element < currentMinimum set element as new minimum swap minimum with first unsorted position end selectionSort ``` ## Example for better understanding Let the elements of array are - ``` 12 29 25 8 32 17 40 ``` Now, for the first position in the sorted array, the entire array is to be scanned sequentially.At present, 12 is stored at the first position, after searching the entire array, it is found that 8 is the smallest value. ``` 12 29 25 8 32 17 40 ``` So, swap 12 with 8. After the first iteration, 8 will appear at the first position in the sorted array. ``` 8 29 25 12 32 17 40 ``` For the second position, where 29 is stored presently, we again sequentially scan the rest of the items of unsorted array. After scanning, we find that 12 is the second lowest element in the array that should be appeared at second position. ``` 8 29 25 12 32 17 40 ``` Now, swap 29 with 12. After the second iteration, 12 will appear at the second position in the sorted array. So, after two iterations, the two smallest values are placed at the beginning in a sorted way. ``` 8 12 25 29 32 17 40 ``` The same process is applied to the rest of the array elements. So, the entire sorting process is shown below: ``` 8 12 25 29 32 12 40 ``` ``` 8 12 17 29 32 25 40 ``` ``` 8 12 17 25 32 29 40 ``` ``` 8 12 17 25 29 32 40 ``` Now, the array is completely sorted. ## Implementation of Selection Sort ```Java // Java program for implementation of Selection Sort class SelectionSort { void sort(int arr[]) { int n = arr.length; // One by one move boundary of unsorted subarray for (int i = 0; i < n-1; i++) { // Find the minimum element in unsorted array int min_idx = i; for (int j = i+1; j < n; j++) if (arr[j] < arr[min_idx]) min_idx = j; // Swap the found minimum element with the first // element int temp = arr[min_idx]; arr[min_idx] = arr[i]; arr[i] = temp; } } // Prints the array void printArray(int arr[]) { int n = arr.length; for (int i=0; i