diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..22dfbfc7 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,10 @@ +# This is a comment. +# Each line is a file pattern followed by one or more owners. + +# More details are here: https://help.github.com/articles/about-codeowners/ + +# The '*' pattern is global owners. + +# Order is important. The last matching pattern has the most precedence. + +* @vbrazo @Panquesito7 @appgurueu diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000..9878e1a4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,23 @@ +name: Bug report +description: Create a bug report to help us address errors in the repository +title: "[BUG] " +labels: [bug] +body: + - type: textarea + id: bugdescription + attributes: + label: Description of the bug + validations: + required: true + - type: textarea + id: screenshots + attributes: + label: Please add screenshots (if applicable) + validations: + required: false + - type: textarea + id: context + attributes: + label: Add any other context about the problem here + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..fcff12b9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Discord community + url: https://discord.gg/c7MnfGFGa6 + about: Have any questions or found any bugs? Please contact us via Discord diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000..46cc9a39 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,38 @@ +name: Feature request +description: Suggest features, propose improvements, discuss new ideas. +title: "[FEATURE]" +labels: [enhancement] +body: + - type: markdown + attributes: + value: Provide a general summary of the issue in the Title above + - type: textarea + id: description + attributes: + label: Detailed description + description: Provide a detailed description of the change or addition you are proposing + validations: + required: true + - type: textarea + id: context + attributes: + label: Context + description: | + Why is this change important to you? How would you use it? + How can it benefit other users? + validations: + required: true + - type: textarea + id: possibleimpl + attributes: + label: Possible implementation + description: Not obligatory, but suggest an idea for implementing addition or change + validations: + required: false + - type: textarea + id: extrainformation + attributes: + label: Additional information + description: Is there anything else we should know about this feature? + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/other.yml b/.github/ISSUE_TEMPLATE/other.yml new file mode 100644 index 00000000..f32dadef --- /dev/null +++ b/.github/ISSUE_TEMPLATE/other.yml @@ -0,0 +1,29 @@ +name: Other +description: Use this for any other issues. PLEASE do not create blank issues +title: "[OTHER]" +labels: ["awaiting triage"] +body: + - type: markdown + attributes: + value: "# Other issue" + - type: textarea + id: issuedescription + attributes: + label: What would you like to share? + 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 + - type: checkboxes + id: consent + attributes: + label: Would you like to work on this issue? + options: + - label: Yes, I want to work on this issue! + required: false diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..54904a21 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,31 @@ +### Description + + + + +Closes #{ISSUE_ID} + +### Checklist + +- [ ] A description of the changes in this PR is mentioned above. +- [ ] All the new and existing checks pass. +- [ ] No plagiarized, duplicated, or repetitive documentation that has been directly copied from another source. +- [ ] If it's a new explanation, it contains solid, understandable, and accessible information. +- [ ] I have read the whole [contributing guidelines](https://github.com/TheAlgorithms/Algorithms-Explanation/blob/master/CONTRIBUTING.md) and agree to the [Code of Conduct](https://github.com/TheAlgorithms/.github/blob/master/CODE_OF_CONDUCT.md). + +### Screenshots (if any) + + + +### Note to reviewers + + diff --git a/.github/workflows/approved-label.yml b/.github/workflows/approved-label.yml new file mode 100644 index 00000000..9fbc5ed0 --- /dev/null +++ b/.github/workflows/approved-label.yml @@ -0,0 +1,14 @@ +on: pull_request_review +name: Add "approved" label when approved +jobs: + add_label: + name: Add "approved" label when approved + runs-on: ubuntu-latest + steps: + - name: Add "approved" label when approved + uses: pullreminders/label-when-approved-action@master + env: + APPROVALS: "1" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ADD_LABEL: "approved" + REMOVE_LABEL: "" diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml new file mode 100644 index 00000000..ed4b6347 --- /dev/null +++ b/.github/workflows/codespell.yml @@ -0,0 +1,9 @@ +name: codespell +on: [pull_request, push] +jobs: + codespell: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - run: python3 -m pip install codespell + - run: codespell ./en/ # --ignore-words-list="" --skip="" diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000..bda5bfac --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,18 @@ +name: 'Close stale issues and PRs' +on: + schedule: + - cron: '0 0 * * *' +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v4 + with: + stale-issue-message: 'This issue has been automatically marked as abandoned because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.' + close-issue-message: 'Please ping one of the maintainers once you add more information and updates here. If this is not the case and you need some help, feel free to ask for help in our [Gitter](https://gitter.im/TheAlgorithms/community) channel. Thank you for your contributions!' + stale-pr-message: 'This pull request has been automatically marked as abandoned because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.' + close-pr-message: 'Please ping one of the maintainers once you commit the changes requested or make improvements on the code. If this is not the case and you need some help, feel free to ask for help in our [Gitter](https://gitter.im/TheAlgorithms/community) channel. Thank you for your contributions!' + exempt-issue-labels: 'dont-close,approved' + exempt-pr-labels: 'dont-close,approved' + days-before-stale: 30 + days-before-close: 7 diff --git a/.github/workflows/url_check.yml b/.github/workflows/url_check.yml new file mode 100644 index 00000000..6533f676 --- /dev/null +++ b/.github/workflows/url_check.yml @@ -0,0 +1,28 @@ +--- +name: url_check + +'on': + workflow_dispatch: + push: + branches: + - master + pull_request: + schedule: + - cron: '43 5 * * TUE' + +jobs: + run_lychee: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Check links + uses: lycheeverse/lychee-action@v1.9.3 + with: + args: > + --no-progress + * + fail: true +... diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..c48f48a8 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,64 @@ +# Contributing Guidelines + +## Legal + +Contributions must be all your own work; plagiarism is not allowed. +By submitting a pull request, you agree to license your contribution +under the [license of this repository](./LICENSE.txt). + +## Translations + +Translations go in the appropriate folder named by the locale code. + +Do not change the structure or formatting of the original (English) explanation when translating or updating translations. +You may change number formatting to fit the locale +(`42.33` may be formatted as `42,33` in a german translation for instance) +as long as it doesn't create ambiguities +(e.g. `[42,33, 13]` in an array would be disallowed and should either remain `[42.33, 13]` or use a different delimiter `[42,33; 13]`). + +## Writing Explanations + +See the [explanation of the Euclidean Algorithm](en/Basic%20Math/Euclidean%20algorithm.md) +for an example of how a good explanation may look like. + +### Structure + +You should structure your explanations using headings. +The top-level heading should be the name of the algorithm or data structure to be explained + +Subsequent sub-headings *may* be: + +1. Problem solved by the algorithm +2. Design/approach of the algorithm +3. Detailed (yet not too technical) description of the algorithm, usually including (pseudo)-code +4. Analysis (proof of correctness, best/worst/average cases, time & space complexity) +5. Walkthrough(s) of how the algorithm processes example input(s) +6. Application(s) of the algorithm +7. Further resources such as reference implementations, videos or other explanations. *If possible, link to The Algorithms' website as well (example: ).* + +### Capitalization + +- Use *Title Case* for headings. +- Start new sentences with a capital letter. + +### Typographical Conventions + +- Leave a space after punctuation such as `.`, `!`, `?`, `,`, `;` or `:`. +- Add a space before and after `-`. **Do not add a space before punctuation.** +- Add a space before an opening parenthesis `(`. Do not add a space before the closing parenthesis `)`. +- Add spaces around (but not inside) quotes. Use single quotes for quotes within quotes. + +### Markdown Conventions + +[GitHub-flavored Markdown is used](https://github.github.com/gfm/). Explanations should render well when viewed from GitHub. + +- **Do not add redundant formatting.** Formatting should always be meaningful. + If you apply a certain formatting to all elements of a certain kind (e.g. adding emphasis around all headings), you're doing something wrong. +- Use ATX-style "hashtag" headings: `#`, `##`, `###`, `####`, `#####`, `######` rather than Setext-style "underline" headings. + Leave blank lines around headings. The first heading should always be `# Title`. Subheadings must be exactly one level deeper than their parents. +- Indent lists by two blanks. Prefer `-` over `*` for bulleted lists. Enumerate numbered lists correctly, starting at `1`. +- Use fenced code blocks (and specify the correct language) rather than using indented code blocks. + Format code inside fenced code blocks properly (prefer pseudocode over code though). Leave blank lines around fenced code blocks. +- Use named links `[name](link)` rather than relying on automatic link detection or using `<>`-links. + There are rarely good reasons to not give a link a descriptive name. +- Use HTML only if necessary (rarely - if ever - the case). Do not use HTML for unnecessary formatting. diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..34466e2a --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2020-2024 The Algorithms and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 497c1b99..f9520d85 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,22 @@ -# Algorithm Name +# Algorithms explanation -Write a short description of algorithm like: -1. Time Complexity -2. Space Complexity -3. Applications -4. Founder's Name -5. etc... +[![Gitter chat](https://img.shields.io/badge/Chat-Gitter-ff69b4.svg?label=Chat&logo=gitter&style=flat-square)](https://gitter.im/TheAlgorithms/community)  +[![contributions welcome](https://img.shields.io/static/v1.svg?label=Contributions&message=Welcome&color=0059b3&style=flat-square)](https://github.com/TheAlgorithms/Ruby/blob/master/CONTRIBUTING.md)  +![Repository size](https://img.shields.io/github/repo-size/TheAlgorithms/Algorithms-Explanation.svg?label=Repo%20size&style=flat-square)  +[![Discord chat](https://img.shields.io/discord/808045925556682782.svg?logo=discord&colorB=5865F2&style=flat-square)](https://discord.gg/c7MnfGFGa6) -## Steps +Popular algorithms explained in simple language with examples and links to their implementation in various programming languages and other required resources. -Describe the algorithm in clear, simple and understandable steps. +## Languages -## Example +- [Uzbek](./uz) +- [Brazilian Portuguese](./pt-br) +- [English](./en) +- [French](./fr) +- [Hebrew](./he) +- [Indonesian](./id) +- [Korean](./ko) +- [Nepali](./ne) +- [Spanish](./es) -Trace the algorithm with a sample input data. - -## Implementation - -Links to their implementation in programming languages. -NOTE: The link should be within the other repos of this organization only. - -## Video URL - -Attach a URL of a video that explains the algorithm. - -## Others - -Any other information is always welcome and should be included in this section. +To add a new language, create a new folder using 2 character `ISO 639-1` code of that language. For example use `hi` for `Hindi` explanations. diff --git a/Sorting Algorithms/Heap Sort.md b/Sorting Algorithms/Heap Sort.md deleted file mode 100644 index 17e38bbf..00000000 --- a/Sorting Algorithms/Heap Sort.md +++ /dev/null @@ -1,72 +0,0 @@ -# Heap Sort - -#### Problem Statement - -Given an unsorted array of n elements, write a function to sort the array - -#### Approach - -- Build a max heap from the input data. -- At this point, the largest item is stored at the root of the heap. Replace it with the last item of the heap followed by reducing the size of heap by 1. Finally, heapify the root of tree. -- Repeat above steps while size of heap is greater than 1. - -#### Time Complexity - -O(n log n) Worst case performance - -O(n log n) (distinct keys) -or O(n) (equal keys) Best-case performance - -O(n log n) Average performance - -#### Space Complexity - -O(1) Worst case auxiliary - - -#### Example - ``` -Input data: 4, 10, 3, 5, 1 - 4(0) - / \ - 10(1) 3(2) - / \ - 5(3) 1(4) - -The numbers in bracket represent the indices in the array -representation of data. - -Applying heapify procedure to index 1: - 4(0) - / \ - 10(1) 3(2) - / \ -5(3) 1(4) - -Applying heapify procedure to index 0: - 10(0) - / \ - 5(1) 3(2) - / \ - 4(3) 1(4) -The heapify procedure calls itself recursively to build heap - in top down manner. - ``` - -![heap-image](https://upload.wikimedia.org/wikipedia/commons/1/1b/Sorting_heapsort_anim.gif "Heap Sort") - -#### Code Implementation Links - -- [Java](https://github.com/TheAlgorithms/Java/blob/master/Sorts/HeapSort.java) -- [C++](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/Sorting/Heap%20Sort%20.cpp) -- [Python](https://github.com/TheAlgorithms/Python/blob/master/sorts/heap_sort.py) -- [Go](https://github.com/TheAlgorithms/Go/blob/master/sorts/Heapsort.go) -- [Ruby](https://github.com/TheAlgorithms/Ruby/blob/master/Sorting/heap_sort.rb) -- [C-sharp](https://github.com/TheAlgorithms/C-Sharp/blob/master/sorts/heap_sort.cs) -- [C](https://github.com/TheAlgorithms/C/blob/master/sorting/HeapSort.c) -- [Javascript](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/heapSort.js) - - -#### Video Explanation - -[A video explaining the Selection Sort Algorithm](https://www.youtube.com/watch?v=MtQL_ll5KhQ) diff --git a/Sorting Algorithms/Merge Sort.md b/Sorting Algorithms/Merge Sort.md deleted file mode 100644 index c5c7edd6..00000000 --- a/Sorting Algorithms/Merge Sort.md +++ /dev/null @@ -1,44 +0,0 @@ -# Merge Sort (Divide and Conquer Algorithm) - -#### Problem Statement - -Given an array of n elements, write a function to sort the array - -#### Approach - -- Find a mid point and divide the array into to halves based on the mid point -- Recursively call the merge sort function for both the halves -- Merge the two sorted halves to get the sorted array - -#### Time Complexity - -O(nLogn) - -#### Space Complexity - -O(n) - -#### Example - -``` -arr = [1, 3, 9, 5, 0, 2] - -Divide the array in two halves [1, 3, 9] and [5, 0, 2] - -Recursively call merge sort function for both these halves which will provide sorted halves -=> [1, 3, 9] & [0, 2, 5] - -Now merge both these halves to get the sorted array [0, 1, 2, 3, 5, 9] - ``` - -#### Code Implementation Links - -- [Java](https://github.com/TheAlgorithms/Java/blob/master/Sorts/MergeSort.java) -- [C++](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/Sorting/Merge%20Sort.cpp) -- [Python](https://github.com/TheAlgorithms/Python/blob/master/sorts/merge_sort.py) -- [C-Sharp](https://github.com/TheAlgorithms/C-Sharp/blob/master/sorts/merge_sort.cs) -- [C](https://github.com/TheAlgorithms/C/blob/master/sorting/mergesort.c) - -#### Video Explanation - -[A CS50 video explaining the Merge Sort Algorithm](https://www.youtube.com/watch?v=EeQ8pwjQxTM) diff --git a/en/Basic Math/Aliquot_Sum.md b/en/Basic Math/Aliquot_Sum.md new file mode 100644 index 00000000..2f282440 --- /dev/null +++ b/en/Basic Math/Aliquot_Sum.md @@ -0,0 +1,41 @@ +# Aliquot Sum + +The aliquot sum $s(n)$ of a positive integer $n$ is the sum of all proper divisors of $n$, that is, all divisors of $n$ other than the number $n$ itself. That is: + +$$ s(n) = \sum_{d | n, d \neq n} {d} $$ + +So, for example, the aliquot sum of the number $15$ is $(1 + 3 + 5) = 9$ + +Aliquot sum is a very useful property in Number Theory, and can be used for defining: +- Prime Numbers +- Deficient Numbers +- Abundant Numbers +- Perfect Numbers +- Amicable Numbers +- Untouchable Numbers +- Aliquot Sequence of a number +- Quasiperfect & Almost Perfect Numbers +- Sociable Numbers + +## Facts about Aliquot Sum +- 1 is the only number whose aliquot sum is 0 +- The aliquot sums of perfect numbers is equal to the numbers itself +- For a [*semiprime*](https://en.wikipedia.org/wiki/Semiprime) number of the form $pq$, the aliquot sum is $p + q + 1$ +- The Aliquot sum function was one of favorite topics of investigation for the world famous Mathematician, [Paul Erdős](https://en.wikipedia.org/wiki/Paul_Erd%C5%91s) + +## Approach on finding the Aliquot sum + +### Step 1: *Obtain the proper divisors of the number* +We loop through all the numbers from $1$ to $[\frac{n} 2]$ and check if they divide $n$, which if they do we add them as a proper divisor. + +The reason we take the upper bound as $[\frac{n} 2]$ is that, the largest possible proper divisor of an even number is $\frac{n} 2 $, and if the number is odd, then its largest proper divisor is less than $[\frac{n} 2]$, hence making it a foolproof upper bound which is computationally less intensive than looping from $1$ to $n$. + +### Step 2: *Add the proper divisors of the number* +The sum which we obtain is the aliquot sum of the number + +## Implementations +- [TheAlgorithms](https://the-algorithms.com/algorithm/aliquot-sum) + +## Sources +- [Wikipedia](https://en.wikipedia.org/wiki/Aliquot_sum) +- [GeeksForGeeks](https://www.geeksforgeeks.org/aliquot-sum/) diff --git a/en/Basic Math/Arithmetic Progressions.md b/en/Basic Math/Arithmetic Progressions.md new file mode 100644 index 00000000..e8a6adf0 --- /dev/null +++ b/en/Basic Math/Arithmetic Progressions.md @@ -0,0 +1,42 @@ +# Arithmetic Progression + +A sequence of numbers is said to be in an `Arithmetic progression` if the difference between any two consecutive terms is always the same. In simple terms, it means that the next number in the series is calculated by adding a fixed number to the previous number in the series. +For example, 2, 4, 6, 8, 10 is an AP because the difference between any two consecutive terms in the series (common difference) is same (4 - 2 = 6 - 4 = 8 - 6 = 10 - 8 = 2). +

+ +

+ +**Facts about Arithmetic Progression:** + +1. Initial term: In an arithmetic progression, the first number in the series is called the initial term. +2. Common difference: The value by which consecutive terms increase or decrease is called the `common difference`. +3. The behavior of the arithmetic progression depends on the common difference `d`. If the common difference is positive, then the members (terms) will grow towards positive infinity. But if the common difference is negative, then the members (terms) will grow towards negative infinity. + +**Formula of the nth term of an A.P:** + +`a` is the initial term, and `d` is a common difference. Thus, the explicit formula is: +

+ +

+ +**Formula of the sum of first nth term of A.P:** + +

+ +

+ +**General Formulas to solve problems related to Arithmetic Progressions:** + + If `a` is the first term and `d` too, that would be a common difference: +- **nth term of an AP** = `a + (n-1)*d`. +- **Arithmetic Mean** = `Sum of all terms in the AP / Number of terms in the AP`. +- **Sum of ‘n’ terms** of an AP = 0.5 n (first term + last term) = `0.5 n [ 2a + (n-1) d ]`. + +# Source + +- [Arithmetic Progression](https://www.geeksforgeeks.org/arithmetic-progression) + +# YouTube + +- [Video URL for concept](https://youtu.be/gua96ju_FBk) +- [Video for understanding AP Dynamic Programming in C++](https://youtu.be/U_qtSRQYoPs) diff --git a/Basic Math/Average_Mean.md b/en/Basic Math/Average_Mean.md similarity index 84% rename from Basic Math/Average_Mean.md rename to en/Basic Math/Average_Mean.md index 501a383e..5eacce57 100644 --- a/Basic Math/Average_Mean.md +++ b/en/Basic Math/Average_Mean.md @@ -57,13 +57,9 @@ If we properly consider significant digits: `sum / count = 23` Return the value of 22.857142 or `23`. -## Implementation - -- [Python](https://github.com/TheAlgorithms/Python/blob/master/maths/average_mean.py) - ## Video URL -- [Mean on Khan Academy](https://www.khanacademy.org/math/ap-statistics/summarizing-quantitative-data-ap/measuring-center-quantitative/v/mean-median-and-mode) +- [Mean on Khan Academy](https://www.khanacademy.org/math/cc-sixth-grade-math/cc-6th-data-statistics/mean-and-median/v/mean-median-and-mode) ## Others diff --git a/en/Basic Math/Euclidean algorithm.md b/en/Basic Math/Euclidean algorithm.md new file mode 100644 index 00000000..d104998a --- /dev/null +++ b/en/Basic Math/Euclidean algorithm.md @@ -0,0 +1,92 @@ +# Euclidean algorithm + +## Problem + +Find the Greatest Common Divisor (GCD) of two positive integers $a$ and $b$, which is defined as the largest number $g = gcd(a, b)$ such that $g$ divides both $a$ and $b$ without remainder. + +## Idea + +The Euclidean algorithm is based on the simple observation that the GCD of two numbers doesn't change if the smaller number is subtracted from the larger number: + +Let $a > b$. Let $g$ be the GCD of $a$ and $b$. +Then $g$ divides $a$ and $b$. Thus $g$ also divides $a - b$. + +Let $g'$ be the GCD of $b$ and $a - b$. + +Proof by contradiction that $g' = g$: + +Assume $g' < g$ or $g' > g$. + +If $g' < g$, $g'$ would not be the *greatest* common divisor, +since $g$ is also a common divisor of $a - b$ and $b$. + +If $g' > g$, $g'$ divides $b$ and $a - b$ - +that is, there exist integers $n, m$ +such that $g'n = b$ and $g'm = a - b$. +Thus $g'm = a - g'n \iff g'm + g'n = a \iff g'(m + n) = a$. +This imples that $g' > g$ also divides $a$, +which contradicts the initial assumption that $g$ is the GCD of $a$ and $b$. + +## Implementation + +To speed matters up in practice, modulo division is used instead of repeated subtractions: +$b$ can be subtracted from $a$ as long as $a >= b$. +After these subtractions only the remainder of $a$ when divided by $b$ remains. + +A straightforward Lua implementation might look as follows: + +```lua +function gcd(a, b) + while b ~= 0 do + a, b = b, a % b + end + return a +end +``` + +note that `%` is the modulo/remainder operator; +`a` is assigned to the previous value of `b`, +and `b` is assigned to the previous value of `a` +modulo the previous value of `b` in each step. + +## Analysis + +### Space Complexity + +The space complexity can trivially be seen to be constant: +Only two numbers (of assumed constant size), $a$ and $b$, need to be stored. + +### Time Complexity + +Each iteration of the while loop runs in constant time and at least halves $b$. +Thus $O(log_2(n))$ is an upper bound for the runtime. + +## Walkthrough + +Finding the GCD of $a = 42$ and $b = 12$: + +1. $42 \mod 12 = 6$ +2. $12 \mod 6 = 0$ + +The result is $gcd(42, 12) = 6$. + +Finding the GCD of $a = 633$ and $b = 142$ using the Euclidean algorithm: + +1. $633 \mod 142 = 65$ +2. $142 \mod 65 = 12$ +3. $65 \mod 12 = 5$ +4. $12 \mod 5 = 2$ +5. $5 \mod 2 = 1$ +6. $2 \mod 1 = 0$ + +The result is $gcd(633, 142) = 1$: $a$ and $b$ are co-prime. + +## Applications + +* Shortening fractions +* Finding the Least Common Multiple (LCM) +* Efficiently checking whether two numbers are co-prime (needed e.g. for the RSA cryptosystem) + +## Resources + +* [Wikipedia Article](https://en.wikipedia.org/wiki/Euclidean_algorithm) diff --git a/en/Basic Math/Fibonacci_Numbers.md b/en/Basic Math/Fibonacci_Numbers.md new file mode 100644 index 00000000..eb8fac3f --- /dev/null +++ b/en/Basic Math/Fibonacci_Numbers.md @@ -0,0 +1,64 @@ +# Calculating Fibonacci numbers + +In mathematics, the Fibonacci numbers commonly denoted F(n), form a sequence, called the Fibonacci sequence, such that each number is the sum of the two preceding ones, starting from 0 and 1. The Sequence looks like this: + +`[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...]` + +## Applications + +Finding +```N-th``` member of this sequence would be useful in many Applications: + +- Recently Fibonacci sequence and the golden ratio are of great interest to researchers in many fields of +science including high energy physics, quantum mechanics, Cryptography and Coding. + +## Steps + +1. Prepare Base Matrice +2. Calculate the power of this Matrice +3. Take Corresponding value from Matrix + +## Example + +Find ```8-th``` member of Fibonacci + +### Step 0 + ``` +| F(n+1) F(n) | +| F(n) F(n-1)| +``` + +### Step 1 + ``` + Calculate matrix^1 +| 1 1 | +| 1 0 | +``` +### Step 2 +``` +Calculate matrix^2 +| 2 1 | +| 1 1 | +``` +### Step 3 +``` +Calculate matrix^4 +| 5 3 | +| 3 2 | +``` +### Step 4 +``` +Calculate matrix^8 +| 34 21 | +| 21 13 | +``` +### Step 5 +F(8)=21 + +## Video URL + +- [Youtube](https://www.youtube.com/watch?v=EEb6JP3NXBI) + +## Others + +- [Proof](https://brilliant.org/wiki/fast-fibonacci-transform/) diff --git a/en/Basic Math/Find the maximum number.md b/en/Basic Math/Find the maximum number.md new file mode 100644 index 00000000..6579ad98 --- /dev/null +++ b/en/Basic Math/Find the maximum number.md @@ -0,0 +1,107 @@ +# Find (Maximum) + +Find the maximum number from a list of given numbers. + +## Applications + +By finding the maximum number in a list, we can perform many operations based on this. + +Uses: + +- Sort our records based on the largest value. +- Makes our process of finding a particular item easy. +- If we are able to find out and sort our records based on + largest value then we can sort or find our records according + to particular index or element with ease. + +## Steps + +The maximum number from an array can be found by various ways. +Here, we will see three different ways of finding the largest +number. + +1. By comparing all the elements of an array. +2. By using predefined methods. +3. By sorting. + +## Example 1 + +By comparing all the elements of an array: + +Given the list `[6, 4, 50, 8, 70, 2, 20]`, let's find the maximum number. + +### Step 1 + +Provide `[6, 4, 50, 8, 70, 2, 20]` as input for a method or function. + +### Step 2 + +By using the comparison process, we are going to find the largest number. +Set the the index element of an array as maximum number. +max = array[0] +`max = 6` + +### Step 3 + +Looping the entire array of elements and compare each element with max. +If a given number is bigger than the max, then we make this particular number as max. +Consider one of the iterations, which happens between 6 and 50. +`max = 50` + +End of the entire loop. +`max = 70` + +### Step 4 + +Return the value 70. + +## Example 2 + +By predefined max method: + +Given the list `[6, 4, 50, 8, 70, 2, 20]`, let's find the maximum number. + +### Step 1 + +Provide `[6, 4, 50, 8, 70, 2, 20]` as input for a method/ function. + +### Step 2 + +The predefined max method, find the maximum element. +`70` + +### Step 3 + +Return the value 70. + +## Example 3 + +By sorting: + +Given the list `[6, 4, 50, 8, 70, 2, 20]`, let's find the maximum number. + +### Step 1 + +Provide `[6, 4, 50, 8, 70, 2, 20]` as input for a method/ function. + +### Step 2 + +The predefined sort method, sorts the entire array in ascending (small to big) order. +`[2, 4, 6, 8, 20, 50, 70]` + +### Step 3 + +Get the last value out of the list by using predefined last method. +`70` + +### Step 4 + +Return the value 70. + +# Source + +- [GeeksForGeeks](https://www.geeksforgeeks.org/c-program-find-largest-element-array/) + +# YouTube + +- [YouTube URL video](https://youtu.be/En68ipRaFOU) diff --git a/en/Basic Math/Finding the number of digits in a number.md b/en/Basic Math/Finding the number of digits in a number.md new file mode 100644 index 00000000..e2bcbb12 --- /dev/null +++ b/en/Basic Math/Finding the number of digits in a number.md @@ -0,0 +1,103 @@ +# Finding the number of digits in a number + +Let's say `N = 2019`. The number of digits in N here is 4 and the digits are: `2`, `0`, `1`, and `9`. + +Some more Examples: +``` +N = 00 [zero] +Number of digits = 0 + +N = -123 [negative] +Number of digits = 3 + +N = 10000 [positive] +Number of digits = 5 +``` + +
+

1st Solution

+
+ +### Simple Solution +The first solution that comes to mind is quite simple: + + 1. Check whether the number N is equal to zero. + 2. Increase the count of digits by 1 if N is not zero. + 3. Reduce the number by dividing it by 10. + 4. Repeat the above steps until the number is reduced to zero. + +**Analysis of the above algorithm:** You can clearly see that the number of operations performed in the above solution is equal to the count of digits present in the number. So, the time complexity of the solution is O(digitsCount). + +**Dry-run of the above algorithm:** +Consider an example, N = 58964. Initialize a variable digitsCount to zero which will store the count of digits. Keep incrementing digitsCount until N is not zero, and reduce it by dividing by 10 at each step. +``` +Iteration 1: N not equals to 0 +Increment digitsCount, digitsCount = digitsCount + 1. +digitsCount = 0 + 1 = 1. +N = N/10 = 58964/10 = 5896. + +Iteration 2: N not equals to 0 +Increment digitsCount, digitsCount = digitsCount + 1. +digitsCount = 1 + 1 = 2. +N = N/10 = 5896/10 = 589. + +Iteration 3: N not equals to 0 +Increment digitsCount, digitsCount = digitsCount + 1. +digitsCount = 2 + 1 = 3. +N = N/10 = 589/10 = 58. + +Iteration 4: N not equals to 0 +Increment digitsCount, digitsCount = digitsCount + 1. +digitsCount = 3 + 1 = 4. +N = N/10 = 58/10 = 5. + +Iteration 5: N not equals to 0 +Increment digitsCount, digitsCount = digitsCount + 1. +digitsCount = 4 + 1 = 5. +N = N/10 = 5/10 = 0. + +Iteration 6: N becomes equal to 0. +Terminate any further operation. +Return value of digitsCount. + +Therefore, number of digits = 5. +``` + +
+

2nd Solution

+
+ +### Better Solution +A better solution is to use mathematics to solve this problem. The number of digits in a number say N can be easily obtained by using the following formula: +``` +number of digits in N = log10(N) + 1. +``` + +**Derivation:** Suppose the number of digits in the number **N** is **K**. + +Therefore, we can say that: +``` +10^(K-1) <= N < 10K +``` +Applying base-10 logarithm to both sides in the above equation, we get: +``` +K-1 <= log10(N) < K. + +or, K - 1 + 1 <= log10(N) + 1 < K + 1 +or, K <= log10(N) + 1 < K + 1 +``` +Therefore, +``` +K = floor(log10(N) + 1) +``` + +**Analysis of the above algorithm:** The above algorithm uses two mathematical functions: the `logarithm of a number` and the `floor function`. Therefore, its time complexity depends on the complexity of those two functions. Practically, the `floor function` is always, or can at least easily be made, constant time - all it has to do is: drop the digits behind the decimal point. For practical purposes, one can `assume that the logarithm is constant time` as well, as one will usually be working with fixed-width floating-point values. If one uses `arbitrary-precision "big number" libraries` however, logarithm will not be constant anymore: performance will depend on the logarithm algorithms used. + + +# Source + +- [Proof in GeeksForGeeks](https://www.geeksforgeeks.org/program-count-digits-integer-3-different-methods/) + +# YouTube + +- [Video URL](https://www.youtube.com/watch?v=ngWnvWR8NkE) diff --git a/en/Basic Math/Geometric Pogression.md b/en/Basic Math/Geometric Pogression.md new file mode 100644 index 00000000..73c1f6ca --- /dev/null +++ b/en/Basic Math/Geometric Pogression.md @@ -0,0 +1,53 @@ +# Geometric Progression + +A sequence of numbers is said to be in a `Geometric progression` if the ratio of any two consecutive terms is always the same. In simple terms, it means that the next number in the series is calculated by multiplying a fixed number to the previous number in the series. + +For example, 2, 4, 8, 16 is a GP because ratio of any two consecutive terms in the series (common ratio) is the same (4 / 2 = 8 / 4 = 16 / 8 = 2). +

+ +

+ +**Facts about Geometric Progression:** + +1. **Initial term:** In a geometric progression, the first number is called the initial term. +2. **Common ratio:** The ratio of any two consecutive terms by taking the previous term in the denominator. +3. The behaviour of a geometric sequence depends on the value of the common ratio. If the common ratio is: + +- Positive, the terms will all be of the same sign as the initial term. +- Negative, the terms will alternate between positive and negative. +- Greater than 1, there will be exponential growth towards positive or negative infinity (depending on the sign of the initial term). +- 1, the progression is a constant sequence. +- Between -1 and 1 but not zero, there will be exponential decay towards zero. +- -1, the progression is an alternating sequence. +- Less than -1, for the absolute values there is exponential growth towards (unsigned) infinity, due to the alternating sign. + +**Formula of the nth term of a G.P:** + +`a` is the initial term, and `d` is a common difference. Thus, the explicit formula is: +

+ +

+ +**Formula of the sum of the first nth term of G.P:** + +

+ +

+ +**General Formulas to solve problems related to Geometric Progressions:** + +If `a` is the first term and `r` is the common ratio: +nth term of a GP = `a*rn-1`. + +- Geometric Mean = `nth root of the product of n terms in the GP`. +- Sum of `n` terms of a GP (r < 1) = `[a (1 – rn)] / [1 – r]`. +- Sum of `n` terms of a GP (r > 1) = `[a (rn – 1)] / [r – 1]`. +- Sum of infinite terms of a GP (r < 1) = `(a) / (1 – r)`. + +# Source + +- [Geometric Progression](https://www.geeksforgeeks.org/geometric-progression/) + +# YouTube + +- [Video URL for concept](https://youtu.be/gua96ju_FBk) diff --git a/en/Basic Math/magic_square.md b/en/Basic Math/magic_square.md new file mode 100644 index 00000000..4edce04a --- /dev/null +++ b/en/Basic Math/magic_square.md @@ -0,0 +1,72 @@ +# What is a Magic Square Puzzle? + +A magic square is defined as a square containing several distinct integers arranged so that the total or sum of the numbers is the same in every row, column, and main diagonal and usually in some or all of the other diagonals. + +# Magic Square Formula + +A magic square puzzle of the `n` order is an organization of `n²` numbers, usually unique integers, in a square. The `n` numbers in all rows, columns, and diagonals add up to the same constant. A magic square bears the integers from 1 to `n²`. The fixed sum in every row, column,and diagonal are known as the magic constant or the magic sum. It is represented by the M letter . The magic constant of a typical magic square depends entirely on the value of `n`. Thus, the value of the magic sum is calculated using the following formula: + +- M = `n(n² + 1)/2` + +- This is the formula for a magic square that is used to make magic squares of different orders. If we subtract each number from (`n²` + 1), we get another magic square, and this is called the complementary magic square. A square containing consecutive numbers beginning with 1 is often called the normal magic square. + +# How to Solve Magic square + +As mentioned above, the formula of the magic square sum is n(n² + 1)/2.\ +For a magic square of order 3, we need to substitute n = 3 to know the magic sum so that we can easily form the magic square 3×3. + +When `n = 3`, the sum = 3(3\*3 + 1)/2 = 3(9 + 1)/2 = (3 × 10)/2 = 15\ +Now, we have to place the numbers in the respective places so that the sum of numbers in each row, column and diagonal is equal to 15. + +## Magic Square Trick for order 3 + +Let `x` be the order of the magic square. + +In this case, `x = 3`. + +Consider another number, `y` such that the product of `x` and `y` is equal to the magic sum, i.e. 15. + +So, `y = 5 {xy = (3)(5) = 15}` + +The value of y should always be at the center of the square and x be on its left cell.\ +The cell above x is taken as y – 1 as given below: + +![magic-square-formula](https://user-images.githubusercontent.com/106215707/192823452-3eea7074-c8f0-4b30-9e83-ef7fb6641a01.png) +![magic-square-1](https://user-images.githubusercontent.com/106215707/192823521-c992c61b-055a-4af8-b697-71fb0ed22566.png) +![magic-square-2](https://user-images.githubusercontent.com/106215707/192823583-8a375043-21d7-4a74-b2d8-119a6ca727eb.png) + +Let us make the complementary magic square of the above square. + +`(n² + 1) = 32 + 1 = 9 + 1 = 10` + +Now, subtract each number from (n² + 1), i.e. from 10. + +- First row numbers: + + - 10 – 4 = 6 + - 10 – 3 = 7 + - 10 – 8 = 2 + +- Second row numbers: + + - 10 – 9 = 1 , + - 10 – 5 = 5 , + - 10 – 1 = 9 + +- Third row numbers: + - 10 – 2 = 8 , + - 10 – 7 = 3 , + - 10 – 6 = 4 + +![magic-square-3](https://user-images.githubusercontent.com/106215707/192823650-21655cfe-0b8f-4bcb-b7d0-76280770c615.png) + +# REFERENCE + +## website:- + +- [Byjus](https://byjus.com/maths/magic-square/) +- [geeksforgeeks](https://www.geeksforgeeks.org/magic-square/) + +## Youtube:- + +- [video](https://www.bing.com/videos/search?q=magic+square&&view=detail&mid=26BE595B719B8B532E5126BE595B719B8B532E51&&FORM=VRDGAR&ru=%2Fvideos%2Fsearch%3Fq%3Dmagic%2Bsquare%26FORM%3DHDRSC3) diff --git a/en/Ciphers/caesar_cipher.md b/en/Ciphers/caesar_cipher.md new file mode 100644 index 00000000..592b0374 --- /dev/null +++ b/en/Ciphers/caesar_cipher.md @@ -0,0 +1,37 @@ +# Caesar Cipher + +The Caesar cipher is a simple cipher and one of the best known encryption algorithms. It is very simple to encrypt, decrypt and intercept. The Caesar cipher is a substitution cipher where each letter in the plain-text (decoded text) is replaced by a letter a certain number of spaces to the right of the letter in the alphabet. (The amount of spaces is called the key or shift and is only known by the sender and intended receiver). + +**Disclaimer: Do not attempt to encrypt personal data or serious messages with this cipher!!! It takes only half a second to crack by a computer!** + +1. It takes a very small amount of time to encode and decode messages. (Less than a second, usually) +3. No real applications exist for the cipher as it is the most insecure out there. +4. This cipher was invented by Julius Caesar as a way to send messages of high military significance. + +## Steps + +### Encryption +1. Choose the alphabet you are going to use. +2. Choose a secret key (shift) that you are going to use in this case `n`. +3. For every letter in the plain-text, replace it by a letter of the alphabet that is `n` letters away from the letter. (Ex: for a key of `1`, `a` would become `b`, `z` would become `a`, etc.) +4. The message should now be encoded. + +### Decryption +1. Choose the alphabet that the message was encrypted with. +2. Let `n` be the secret key the message is encoded in. +3. For every letter in the cipher-text, replace it by a letter of the alphabet that is `n` letters behind in the alphabet from the letter. +`c` would be `b`, `a` would be `z` with a key of `1`. +4. The message should now be decoded + +## Example + +### An example of encryption +Let us say we are sending a secret message to a friend. + +* We first write out our message. In this case: `The Caesar cipher is a fun substitution cipher` +* Our alphabet will be: `abcdefghijklmnopqrstuvwxyz`. For the uses of this tutorial, case doesn't matter. (On a shift of `1`: `A` will become `B`, `a` will become `b`) +* Let our key be 6. +* Starting with the first letter: `T`. The letter 6 letters away is `Z`. We add `Z` to the message. +* The second letter is `h`. The letter 6 letters away is `n`. Our message is now `Zn` +* We continue like that until the end. Our final message is: `Znk Igkygx iovnkx oy g lat yahyzozazout iovnkx.` +* Decryption is the same way, except instead of going to the right in the alphabet, we go backwards. diff --git a/en/Ciphers/hill_cipher.md b/en/Ciphers/hill_cipher.md new file mode 100644 index 00000000..775e0ecb --- /dev/null +++ b/en/Ciphers/hill_cipher.md @@ -0,0 +1,59 @@ +# Hill Cipher + +The Hill cipher was invented by [Lester S. Hill](https://en.wikipedia.org/wiki/Lester_S._Hill). + +Hill cipher is a polygraphic substitution cipher based on linear algebra. Each letter is represented by a number modulo 26. Often the simple scheme `A = 0, B = 1, …, Z = 25` is used, but this is not an essential feature of the cipher. To encrypt a message, each block of `n` letters (considered as an n-component vector) is multiplied by an invertible `n × n` matrix, against modulus 26. To decrypt the message, each block is multiplied by the inverse of the matrix used for encryption. + +## Example + +Suppose we take an example as: +Plain Text (PT):ACT +key:`GYBNQKURP` + +## Steps + +### Encryption + +1. We have to write key as an `n × n` matrix as + + ``` + [6 24 1] + [13 16 10] + [20 17 15] +``` +2. Same way convert PT into a vector as + +``` + [0] + [2] + [19] +``` +3. Now, we need to encipher the vector by just multiplying these two matrices + +``` + [6 24 1] [0] [67] [15] + [13 16 10] * [2] = [222] ≈ [4] (mod 26) + [20 17 15] [19] [319] [7] +``` +So we will get the encrypted text as **POH**. + +### Decryption + +1. We need to first inverse our key matrix + ``` + -1 + [6 24 1] [8 5 10] + [13 16 10] ≈ [21 8 21] (mod 26) + [20 17 15] [21 12 8] + ``` +2. For the previous Cipher Text **POH** + +``` + [8 5 10] [15] [260] [0] + [21 8 21] * [14] ≈ [574] ≈ [2] (mod 26) ≈ ACT + [21 12 8] [7] [539] [19] +``` + +## Video Explanation + +[Video explanation of the Hill Cipher](https://www.youtube.com/watch?v=6T46sgty4Mk) diff --git a/en/Ciphers/playfair-cipher.md b/en/Ciphers/playfair-cipher.md new file mode 100644 index 00000000..158a4a92 --- /dev/null +++ b/en/Ciphers/playfair-cipher.md @@ -0,0 +1,122 @@ +# Playfair Cipher + +The Playfair cipher was invented in 1854 by [Charles Wheatstone](https://en.wikipedia.org/wiki/Charles_Wheatstone) but was named after Lord Playfair who promoted the use of the cipher. + +The Playfair cipher was the first practical digraph substitution cipher. In Playfair cipher unlike traditional cipher, we encrypt a pair of alphabets(digraphs) instead of a single alphabet. A `5 × 5` grid of alphabets was used as the key-square. Each of the 25 alphabets is unique and one letter of the alphabet (usually J) is omitted from the table. If the plaintext contains J, then it is replaced by I or vice-versa. The initial alphabets in the key square are the unique alphabets of the key in the order in which they appear followed by the remaining letters of the alphabet in order. + +## Example + +Suppose we take an example as: + +Plain Text (PT): instruments, key: `monarchy` + +## Rules + +1. If both the letters are in the same column, take the letter below each one (going back to the top if at the bottom). + +``` + Diagraph: "me" + Encrypted Text: cl + Encryption: + m -> c + e -> l +``` + +2. If both the letters are in the same row, take the letter to the right of each one (going back to the leftmost only if it's at the rightmost position). + +``` + Diagraph: "st" + Encrypted Text: tl + Encryption: + s -> t + t -> l +``` + +3. If neither of the above rules is true, form a rectangle with the two letters, and take the letters on the horizontal opposite corner of the rectangle. + +``` + Diagraph: "nt" + Encrypted Text: rq + Encryption: + n -> r + t -> q +``` + +The rules above are used for Encryption. Can be applied vice-versa for Decryption. + +## Steps + +### Encryption + +1. We have to generate a `5 × 5` matrix from the key as + + ``` + [m o n a r] + [c h y b d] + [e f g i k] + [l p q s t] + [u v w x z] +``` + +2. Split the plaintext in digraphs(pair of two). If there is an odd number of letters, an X is added to the last letter. Pairs cannot be made with same letter. If this occurs, split the pair by adding an X between the duplicate letters. + +``` + 'in' 'st' 'ru' 'me' 'nt' 'sx' +``` + +3. Now, we need to follow the rules for encrypting and do as follows: + +``` + Plain Text: instrumentsx + key: monarchy + Encryption: + i -> g + n -> a + s -> t + t -> l + r -> m + u -> z + m -> c + e -> l + n -> r + t -> q + s -> x + x -> a +``` +So we will get the encrypted text as **gatlmzclrqxa**. + +### Decryption + +1. We have to generate a `5 × 5` matrix from the key as + + ``` + [m o n a r] + [c h y b d] + [e f g i k] + [l p q s t] + [u v w x z] +``` + +2. We need to split the ciphertext as done for plaintext while encrypting + ``` + 'ga' 'tl' 'mz' 'cl' 'rq' 'xa' + ``` + +3. For the previous Cipher Text **gatlmzclrqxa**, by following the rules we get: + +``` + Plain Text: gatlmzclrqtx + key: monarchy + Decryption: + ga -> in + tl -> st + mz -> ru + cl -> me + rq -> nt + xa -> sx +``` +So we will get the encrypted text as **instrumentsx**. + +## Video Explanation + +- [**Video explanation of the Playfair Cipher algorithm**](https://www.youtube.com/watch?v=UURjVI5cw4g) diff --git a/en/Ciphers/rsa_cipher.md b/en/Ciphers/rsa_cipher.md new file mode 100644 index 00000000..3cae166d --- /dev/null +++ b/en/Ciphers/rsa_cipher.md @@ -0,0 +1,155 @@ +# RSA Cryptography Algorithm + +## About RSA Algorithm +RSA (Rivest–Shamir–Adleman) is one of the first public-key cryptosystems and is widely used for secure data transmission. In such a cryptosystem, the encryption key is public and distinct from the decryption key which is kept secret (private). + +## Algorithm + +1. Select 2 Prime Numbers - **p & q** +2. Calculate `n` as $$n = p * q$$ +3. In number theory, **Euler's Totient function** counts the positive integers up to a given integer n that are relatively prime to n. + + Calculate Euler's Totient Function of n. + $$φ(n) = (p-1) * (q-1)$$ + + Note, that Euler's Totient works only if $p$ and $q$ are Prime Numbers. +4. Select **Public Key** - $e$ , such that $e$ and $φ(n)$ are Co-primes, i.e, $$\gcd(e , φ(n))=1$$ +5. Calculate **Private Key**, $d$ such that $$(d * e) \mod φ(n) = 1$$ + +## Public and Private Keys + +1. The **Public key** is `( e , n )` which is known to all in the network. +2. The **Private key** is `( d , n )` which is known ONLY to the User to whom message is to be sent. + +## Encryption & Decryption + +#### Encryption Algorithm + +The Cipher Text, C is generated from the plaintext, M using the public key, e as: + +$$C = M^e \mod n$$ + +#### Decryption Algorithm + +The Plain Text, M is generated from the ciphertext, C using the private key, d as: + +$$M = C^d \mod n$$ + + + +## Encryption & Decryption Mechanism + +The Encryption and Decryption mechanism block diagram with sample message encryption. + +![RSA-Encryption-Decryption-block-diagram.png](https://github.com/TanmoySG/Cryptography-Algorithm/blob/master/RSA-Algorithm/diagrams/RSA-Encryption-Decryption-block-diagram.jpg) + +### Explanation + +The explanation for the above example, + +![RSA-Example-maths-only-diagram.png](https://github.com/TanmoySG/Cryptography-Algorithm/blob/master/RSA-Algorithm/diagrams/RSA-Example-maths-only-diagram.png) + +## Simple Implementation of RSA using Python + +```python +from sympy import * +import math + +#Generate p and q +p = randprime(1, 10) +q = randprime(11, 20) + +# Generate n and l(n) +n = p*q +l = (p-1)*(q-1) + +# Function to test Co-Primality for generation of list of Public Keys +def isCoPrime(x): + return math.gcd(l, x) == 1 + +# Function to find mod Inverese of e withl(n) to generate d +def modInverse(e, l): + e = e % l + for x in range(1, l): + if (e * x) % l == 1: + return x + return 1 + +# List for Co-Primes +listOfCP = [] +for i in range(1, l): + if isCoPrime(i) == True: + listOfCP.append(i) + +# Print values of P, Q, N, L +print("Value of P = ", p) +print("Value of Q = ", q) +print("Value of N = ", n) +print("Value of L = ", l) + +print(" ") + +# Print List of Co-Primes for e +print("List of Available Public Keys") +print(listOfCP) + +print(" ") + +# select a Public Key from list of Co-Primes +e = int(input("Select Public Key from the Above List ONLY: ")) + +# Value of d +d = modInverse(e, l) + +print(" ") + +# Print Public and Private Keys +print("PUBLIC KEY : { e , n } = {", e ,",", n , "}") +print("PRIVATE KEY : { d , n } = {", d ,",", n , "}") + +print(" ") + +# Encryption Algorithm +def encrypt(plainText): + return (plainText**e)%n + +# Decryption Algorithm +def decrypt(cipherText): + pvtKey = int(input("Enter your Private Key: ")) + return (cipherText**pvtKey)%n + +# Driver Code + +# Message Input +pt = int(input('Enter the Plain Text: ')) +print("CipherText: ", encrypt(pt)) + +print(" ") + +# CipherText Input +ct = int(input('Enter the Cipher Text: ')) +print("PlainText: ", decrypt(ct)) +``` + +``` +Value of P = 7 +Value of Q = 19 +Value of N = 133 +Value of L = 108 + +List of Available Public Keys +[1, 5, 7, 11, 13, 17, 19, 23, 25, 29, 31, 35, 37, 41, 43, 47, 49, 53, 55, 59, 61, 65, 67, 71, 73, 77, 79, 83, 85, 89, 91, 95, 97, 101, 103, 107] + +Select Public Key from the Above List ONLY: 47 + +PUBLIC KEY : { e , n } = { 47 , 133 } +PRIVATE KEY : { d , n } = { 23 , 133 } + +Enter the Plain Text: 51 +CipherText: 116 + +Enter the Cipher Text: 116 +Enter your Private Key: 23 +PlainText: 51 + +``` diff --git a/en/Ciphers/vigenere_cipher.md b/en/Ciphers/vigenere_cipher.md new file mode 100644 index 00000000..94bf5749 --- /dev/null +++ b/en/Ciphers/vigenere_cipher.md @@ -0,0 +1,63 @@ +# Vigenere Cipher + +The Vigenere cipher is a famous toy cipher. It was invented in 1553 by the Italian cryptographer Giovan Battista Bellaso but for centuries was attributed to the 16th-century French cryptographer Blaise de Vigenère, who devised a similar cipher in 1586. + +It is easy to encrypt and decrypt but at the same time, it is easy to intercept and crack this cipher. It is a polyalphabetic substitution cipher, meaning that the same letter of the alphabet can be replaced by different letters depending on the key. The key is a word or phrase that is repeated to match the length of the message. Then the letters of the key are used to shift the letters of the message. + +## Improvement over Caesar cipher + +The Vigenere cipher is an improvement over the Caesar cipher. The Caesar cipher uses a single character as the key to shift the message. In contrast, the Vigenere cipher uses a word or a phrase as the key. This means that the same character occurring at different positions in the message will be shifted by different amounts. This makes it harder to crack the cipher. + +## Setup + +1. Choose the message space you are going to use. In our case, we will use all lowercase letters of the English language. But we can use ASCII characters as well. Let us denote the size of the message space as $n$. In our case, $n = 26$. +2. Assign a numerical value to each letter of the message space. For example, $a=1, b=2, c=3$ and so on. +3. Choose a key. + +## Encryption + +1. Repeat the key to match the length of the message. For example, if the message is `checktheking` and the key is `chess`, the key is repeated to match the length of the message. The key is now `chesschessch`. +2. Now, the letters of the key are used to shift the letters of the message. Let $a$ be $1$, $b$ be $2$ and so on. Then, the message is encrypted using the following formula: $C_i = (V(M_i) + V(K_i)) \mod n$ where $C_i$ is the encrypted letter at position $i$, $V(M_i)$ is the numerical value of the letter at position $i$ and $V(K_i)$ is the numerical value of the letter at position $i$, and $n$ is the size of the message space. + +| Message | c | h | e | c | k | t | h | e | k | i | n | g | +|---------|---|---|---|---|---|---|---|---|---|---|---|---| +| Value | 3 | 8 | 5 | 3 | 11| 20| 8 | 5 | 11| 9 | 14| 7 | +| Key | c | h | e | s | s | c | h | e | s | s | c | h | +| Shift | 3 | 8 | 5 | 19| 19| 3 | 8 | 5 | 19| 19| 3 | 8 | +| Cipher | f | p | j | q | z | w | p | j | z | z | c | p | + +So the encrypted message is `fpjqzwjpzzcp`. + +## Decryption + +Decryption is the inverse of encryption. It is is done by subtracting the shift value from the cipher value. The formula is $M_i = L((C_i - V(K_i)) \mod n)$ where everything is defined as above and $L$ is additionally defined as a function which converts a numerical value back to a letter. + +| Cipher | f | p | j | q | z | w | p | j | z | z | c | p | +|---------|---|---|---|---|---|---|---|---|---|---|---|---| +| Key | c | h | e | s | s | c | h | e | s | s | c | h | +| Shift | 3 | 8 | 5 | 19| 19| 3 | 8 | 5 | 19| 19| 3 | 8 | +| Value | 3 | 8 | 5 | 3 | 11| 20| 8 | 5 | 11| 9 | 14| 7 | +| Message | c | h | e | c | k | t | h | e | k | i | n | g | + +So the decrypted message is `checktheking`, as expected. + +## Complexity Analysis + +### Encryption + +The encryption is done by adding the shift value to the message value. So the **time complexity is $O(n)$** where $n$ is the length of the message. +We use a linear data structure such as an array to store the message and the key. So the **space complexity is $O(n)$**. + +### Decryption + +Decryption is similar to encryption (except for the subtraction operation). +**So time and space complexity are the same as for encryption - $O(n)$**. + +## Cryptanalysis and caution + +1. **It is a toy cipher. It is easy to crack. It is not secure.** +2. There are several key (length) finding methods such as + - [Kasiski examination](https://en.wikipedia.org/wiki/Kasiski_examination) + - [Index of coincidence](https://en.wikipedia.org/wiki/Index_of_coincidence) +3. Once the key length is found, [frequency analysis](https://en.wikipedia.org/wiki/Frequency_analysis) can be used to find the key and hence crack the cipher. +4. Therefore, this cipher should not be used to encrypt any important data. diff --git a/en/Data Structures/Arrays/array.md b/en/Data Structures/Arrays/array.md new file mode 100644 index 00000000..5f085aa9 --- /dev/null +++ b/en/Data Structures/Arrays/array.md @@ -0,0 +1,14 @@ +# Arrays + +Arrays are the most basic data structures used in programming. There are two types of arrays - static arrays and dynamic arrays. Static arrays contain a group of a fixed number of elements that occupy the same space in memory. I.e., the memory occupied is known at compile time whereas in the case of dynamic arrays the size is not fixed. +The values of elements in an array can be retrieved very quickly in `O(1)` time. +All arrays consist of contiguous memory locations. We can access the elements with their index. The lowest address corresponds to the first element, and the highest address to the last element. + +# Source + +- [Introduction to arrays - GeeksForGeeks](https://www.geeksforgeeks.org/introduction-to-arrays/) + +# YouTube + +- [YouTube URL tutorial video](https://youtu.be/NptnmWvkbTw) +- [YouTube video for understanding Arrays in C++](https://youtu.be/ibeGtDEQGz0) diff --git a/Data Structures/Graph/Bellman-Ford.md b/en/Data Structures/Graph/Bellman-Ford.md similarity index 56% rename from Data Structures/Graph/Bellman-Ford.md rename to en/Data Structures/Graph/Bellman-Ford.md index e9bf06e1..49b1e59c 100644 --- a/Data Structures/Graph/Bellman-Ford.md +++ b/en/Data Structures/Graph/Bellman-Ford.md @@ -11,7 +11,7 @@ Given a weighted directed graph G(V,E) and a source vertex s ∈ V, determine fo - Create an array dist[] of size |V| with all values as infinite except dist[s]. - Repeat the following |V| - 1 times. Where |V| is number of vertices. - Create another loop to go through each edge (u, v) in E and do the following: - 1. dist[v] = minimum(dist[v], dist[u] + weight of edge). + 1. dist[v] = minimum(dist[v], dist[u] + weight of edge). - Lastly iterate through all edges on last time to make sure there are no negatively weighted cycles. #### Time Complexity @@ -30,7 +30,7 @@ O(V^2) ``` # of vertices in graph = 5 [A, B, C, D, E] - # of edges in graph = 8 + # of edges in graph = 8 edges [A->B, A->C, B->C, B->D, B->E, D->C, D->B, E->D] weight [ -1, 4, 3, 2, 2, 5, 1, -4 ] @@ -38,44 +38,44 @@ O(V^2) - // edge A->B - graph->edge[0].src = A - graph->edge[0].dest = B - graph->edge[0].weight = -1 - - // edge A->C - graph->edge[1].src = A - graph->edge[1].dest = C - graph->edge[1].weight = 4 - - // edge B->C - graph->edge[2].src = B - graph->edge[2].dest = C - graph->edge[2].weight = 3 - - // edge B->D - graph->edge[3].src = B - graph->edge[3].dest = D - graph->edge[3].weight = 2 - - // edge B->E - graph->edge[4].src = B - graph->edge[4].dest = E - graph->edge[4].weight = 2 - - // edge D->C + // edge A->B + graph->edge[0].src = A + graph->edge[0].dest = B + graph->edge[0].weight = -1 + + // edge A->C + graph->edge[1].src = A + graph->edge[1].dest = C + graph->edge[1].weight = 4 + + // edge B->C + graph->edge[2].src = B + graph->edge[2].dest = C + graph->edge[2].weight = 3 + + // edge B->D + graph->edge[3].src = B + graph->edge[3].dest = D + graph->edge[3].weight = 2 + + // edge B->E + graph->edge[4].src = B + graph->edge[4].dest = E + graph->edge[4].weight = 2 + + // edge D->C graph->edge[5].src = D - graph->edge[5].dest = C - graph->edge[5].weight = 5 - - // edge D->B + graph->edge[5].dest = C + graph->edge[5].weight = 5 + + // edge D->B graph->edge[6].src = D - graph->edge[6].dest = B - graph->edge[6].weight = 1 - - // edge E->D + graph->edge[6].dest = B + graph->edge[6].weight = 1 + + // edge E->D graph->edge[7].src = E - graph->edge[7].dest = D + graph->edge[7].dest = D graph->edge[7].weight = -3 for source = A @@ -86,15 +86,7 @@ O(V^2) C 2 A->B->C = -1 + 3 D -2 A->B->E->D = -1 + 2 + -3 E 1 A->B->E = -1 + 2 - ``` - - -#### Code Implementation Links - -- [Java](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Graphs/BellmanFord.java) -- [C++](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/Dynamic%20Programming/Bellman-Ford.cpp) -- [Python](https://github.com/TheAlgorithms/Python/blob/master/data_structures/graph/bellman_ford.py) -- [C](https://github.com/TheAlgorithms/C/blob/master/data_structures/graphs/Bellman-Ford.c) +``` #### Video Explanation @@ -103,5 +95,6 @@ O(V^2) #### Others Sources Used: + - https://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/ - https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm diff --git a/en/Data Structures/Linked Lists/Circular Linked List.md b/en/Data Structures/Linked Lists/Circular Linked List.md new file mode 100644 index 00000000..ab86a80e --- /dev/null +++ b/en/Data Structures/Linked Lists/Circular Linked List.md @@ -0,0 +1,69 @@ +# Circular Linked List + +Circular Linked List is an end-connected data structure made of Nodes. Similar to the linear and doubly linked list, each node is composed of a variable ```data``` where its content is stored and a pointer to the next Node on the list. +The Linked List has a ```pointer``` to the adjacent elements but the last node is connected towards the head node i.e the first node itself, thus forming a circular shape. + +### Advantages over Arrays & Linear Linked List & Doubly Linked List + +- Any node can be a starting point +- Useful for implementation of queue +- Circular lists are useful in applications to repeatedly go around the list +- Circular Doubly Linked Lists are used for the implementation of advanced data structures like Fibonacci Heap. +- The size of a linked list is not fixed (dynamic size) +- Deleting and adding an element is not expensive compared to an array + +### Drawbacks + +- Circular lists are complex as compared to singly linked lists. +- Reversing of circular list is a complex as compared to singly or doubly lists. +- If not traversed carefully, then we could end up in an infinite loop +- Elements can be accessed sequentially not randomly compared to an array +- Extra memory allocation needs to be done for pointers which connects elements in a linked list + +### Time Complexity + +| Operation | Average | Worst | +|-----------|---------|-------| +| Initialize| O(1) | - | +| Access | O(n) | O(n) | +| Search | O(n) | O(n) | +| Insertion | O(1) | O(n) | +| Deletion | O(1) | O(n) | + +### Real World Application + +- Allocating CPU to resources +- Multiplayer Board games + +### SLL v.s. CLL + +![image](https://tutorialhorizon.com/static/media/algorithms/2016/03/Circular-Linked-List.png) + +### Example + +Insertion +```java +public void insertHead(int data) +{ + Node temp = new Node(data); + Node cur = head; + while(cur.getNext() != head) + cur = cur.getNext(); + if(head == null) + { + head = temp; + head.setNext(head); + } + else + { + temp.setNext(head); + head = temp; + cur.setNext(temp); + } + size++; +} + ``` + +## Video Explanation + +[Video explanation on YouTube](https://youtu.be/HMkdlu5sP4A) diff --git a/Data Structures/Linked Lists/Doubly Linked List.md b/en/Data Structures/Linked Lists/Doubly Linked List.md similarity index 88% rename from Data Structures/Linked Lists/Doubly Linked List.md rename to en/Data Structures/Linked Lists/Doubly Linked List.md index 36b2f556..65fb7692 100644 --- a/Data Structures/Linked Lists/Doubly Linked List.md +++ b/en/Data Structures/Linked Lists/Doubly Linked List.md @@ -17,7 +17,7 @@ In singly linked list, to delete a node, pointer to the previous node is needed. ### Time Complexity | Operation | Average | Worst | -|:---------:|:-------:|:-----:| +|-----------|---------|-------| | Access | Θ(n) | O(n) | | Search | Θ(n) | O(n) | | Insertion | Θ(1) | O(1) | @@ -90,7 +90,7 @@ class LinkedList { new_node.next.prev = new_node; } } - ``` +``` ### Adding node at front @@ -100,13 +100,6 @@ class LinkedList { ![Tracing of algorithm](https://www.geeksforgeeks.org/wp-content/uploads/gq/2014/03/DLL_add_middle1.png) -## Code Implementation Links - -- [Java](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Lists/DoublyLinkedList.java) -- [C++](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/Data%20Structure/Doubly%20Linked%20List.cpp) -- [Python](https://github.com/TheAlgorithms/Python/blob/master/data_structures/linked_list/doubly_linked_list.py) -- [Go](https://github.com/TheAlgorithms/Go/blob/master/data-structures/linked-list/double-linkedlist.go) - ## Video Explanation [A CS50 video explaining the Doubly Linked List Data Structure](https://www.youtube.com/watch?v=FHMPswJDCvU) diff --git a/Data Structures/Linked Lists/Singly Linked List.md b/en/Data Structures/Linked Lists/Singly Linked List.md similarity index 79% rename from Data Structures/Linked Lists/Singly Linked List.md rename to en/Data Structures/Linked Lists/Singly Linked List.md index a5001efb..4b7e5823 100644 --- a/Data Structures/Linked Lists/Singly Linked List.md +++ b/en/Data Structures/Linked Lists/Singly Linked List.md @@ -15,7 +15,7 @@ Singly Linked List is a linear and connected data structure made of Nodes. Each ### Time Complexity | Operation | Average | Worst | -|:---------:|:-------:|:-----:| +|-----------|---------|-------| | Access | O(n) | O(n) | | Search | O(n) | O(n) | | Insertion | O(1) | O(1) | @@ -37,12 +37,6 @@ class LinkedList { } ``` -## Code Implementation Links - -- [Java](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Lists/SinglyLinkedList.java) -- [C++](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/Data%20Structure/Linked%20List.cpp) -- [Python](https://github.com/TheAlgorithms/Python/blob/master/data_structures/linked_list/singly_linked_list.py) - ## Video Explanation [A CS50 video explaining the Linked List Data Structure](https://www.youtube.com/watch?v=5nsKtQuT6E8) diff --git a/en/Data Structures/Probablistic/BloomFilter.md b/en/Data Structures/Probablistic/BloomFilter.md new file mode 100644 index 00000000..3fc5a19a --- /dev/null +++ b/en/Data Structures/Probablistic/BloomFilter.md @@ -0,0 +1,122 @@ +# Bloom Filter + +Bloom Filters are one of a class of probabilistic data structures. The Bloom Filter uses hashes and probability to determine whether a particular item is present in a set. It can do so in constant time: O(1) and sub-linear space, though technically still O(n). An important feature of a Bloom Filter is that it is guaranteed never to provide a false negative, saying an element isn't present when it is. However, it has a probability (based on the tuning of its parameters) of providing a false positive, saying an element is present when it is not. The Bloom Filter uses a multi-hash scheme. On insertion, the inserted object is run through each hash, which produces a slot number. That slot number is flipped to 1 in the bit array. During a presence check, the object is run through the same set of hashes, and if each corresponding slot is 1, the filter reports the object has been added. If any of them are 0, it reports that the object has not been added. The hashes must be deterministic and uniformly distributed over the slots for the Bloom filter to operate effectively. + +## Complexity + +| Operation | Average | +|-----------|---------| +| Initialize| O(1) | +| Insertion | O(1) | +| Query | O(1) | +| Space | O(n) | + +## Steps + +### Initialization + +1. Bloom Filter is Initialized, with a number of hash functions that will be run against it (henceforth known as `k`), and with an array of bits of size `M` with each bit set to 0. There are 3 distinct schemes to tune these parameters. + 1. `M` and `k` are explicitly set by the user + 2. `k` and `M` are calculated based off the expected number of elements to minimize false positives. + 3. `k` and `M` are calculated based off a desired error rate. + +### Insertion + +1. Object is run through `k` hashes +2. For each result of the hash `n` determine the slot within the filter `m` by calculating `n % M = m` +3. Set slot `m` within the filter to 1 + +### Query + +1. Object is run through `k` hashes +2. For each result of the hash `n` determine the slot within the filter `m` by calculating `n % M = m` +3. Check slot `m`, if `m` is set to 0 return false +4. Return true + +## Example + +### Initialize + +As an example, let us look at a Bloom Filter of Strings, we will initialize the Bloom Filter with 10 slots an we will use 3 hashes + +|slot |0|1|2|3|4|5|6|7|8|9| +|-----|-|-|-|-|-|-|-|-|-|-| +|state|0|0|0|0|0|0|0|0|0|0| + +### Insert + +Let's try to insert `foo`, we will run `foo` through our three hash functions + +```text +h1(foo) = 2 +h2(foo) = 5 +h3(foo) = 6 +``` + +With hashes run, we will flip the corresponding bits to 1 + +|slot |0|1|2|3|4|5|6|7|8|9| +|-----|-|-|-|-|-|-|-|-|-|-| +|state|0|0|1|0|0|1|1|0|0|0| + +### Query + +#### Query bar + +Let's first try querying `bar`, to query `bar` we run `bar` through our three hash functions: + +```text +h1(bar) = 3 +h2(bar) = 4 +h3(bar) = 6 +``` + +If we look at our bit array, bits 3 and 4 are both not set, if even just 1 bit is not set, we return false, so in this case we return false. `bar` has not been added + +#### Query foo + +Let's now try to query `foo`, when we run `foo` through our hashes we get: + +```text +h1(foo) = 2 +h2(foo) = 5 +h3(foo) = 6 +``` + +Of course, since we already inserted foo, our table has each of the three bits our hashes produced set to 1, so we return true, `foo` is present + +### False Positive + +Let's say we inserted `bar` and the current state of our table is: + +|slot |0|1|2|3|4|5|6|7|8|9| +|-----|-|-|-|-|-|-|-|-|-|-| +|state|0|0|1|1|1|1|1|0|0|0| + +Let's now query `baz`, when we run baz through our hash functions we get: + +```text +h1(baz) = 3 +h2(baz) = 5 +h3(baz) = 6 +``` + +Notice that this does not match either the result of `foo` or `bar`, however because slots 3, 5, and 6 are already set, we report true, that baz is in the set, and therefore produce a false positive. + +## Advantage Over HashSets + +* Significantly more space-efficient, Both are technically O(n) space complexity, but since bloom filters will only take up several bits per item, hash sets must hold the entire item. +* Presence checks are guaranteed to be O(1) for Bloom Filters, for HashSets, the average is O(1), but worst case is O(n) + +## Disadvantage v.s. Hash Sets + +* Bloom Filters can report false positives. Optimally there should be about a 1% false-positive rate. +* Bloom Filters do not store the objects inserted into it, so you cannot recover items inserted. + +## Optimizing + +The probability of false positives increases with the probability of hash collisions within the filter. However, you can optimize the number of collisions if you have some sense of the cardinality of your set ahead of time. You can do this by optimizing `k` and `M`, `M` should be ~ 8-10 bits per expected item, and `k` should be `(M/n) * ln2`. + +## Video Explainer + +[Video Explainer by Narendra L](https://www.youtube.com/watch?v=Bay3X9PAX5k) \ No newline at end of file diff --git a/en/Data Structures/Queues/queue.md b/en/Data Structures/Queues/queue.md new file mode 100644 index 00000000..93d83066 --- /dev/null +++ b/en/Data Structures/Queues/queue.md @@ -0,0 +1,35 @@ +# Queue + +## Description + +A queue is a linear data structure that follows the First-In-First-Out (FIFO) principle. It is often compared to a real-world queue of people waiting in line. The element that is added first is the one that gets removed first. Queues are commonly used for various applications, such as task scheduling, managing requests, and more. + +## Queue Operations + +1) Enqueue (Push): This operation is used to add an item to the back or end of the queue. It's equivalent to "pushing" an item onto the queue. When you enqueue an item, it becomes the last item in the queue. + +2) Dequeue (Pop): Dequeue is the operation used to remove and return the front item from the queue. The item that has been in the queue the longest (the front item) is the one removed. After dequeuing an item, the next item in the queue becomes the new front. + +3) Peek (Front): This operation is used to view the front item in the queue without removing it. It provides a way to examine the item at the front of the queue without actually dequeuing it. + +4) isEmpty: This operation checks whether the queue is empty. If the queue contains no items, it returns true; otherwise, it returns false. + +## Source + +- [Queue Data Structure](https://www.geeksforgeeks.org/queue-data-structure/) + +## Video URL + +- [Queue in Data Structure](https://www.youtube.com/watch?v=zp6pBNbUB2U) +- [Implementation of Queue using Arrays](https://www.youtube.com/watch?v=YqrFeU90Coo) +- [Queue Implementation using Linked List in C](https://www.youtube.com/watch?v=RN1wzY_tnYU) + +## Implementation + +1) Queue Implementation Using Lists (Arrays) + +In this approach, you can use a list (or array) to represent a queue. You will maintain two pointers, one pointing to the front of the queue and another pointing to the back. The front pointer keeps track of the element to be dequeued, and the back pointer keeps track of where new elements should be enqueued. + +2) Queue Implementation Using a Linked List + +In this approach, you can use a linked list to implement a queue. You maintain two pointers, one pointing to the front (head) of the queue and another pointing to the back (tail). Enqueueing involves adding a new node at the tail, and dequeueing involves removing the node at the head. diff --git a/en/Data Structures/Stacks/stack.md b/en/Data Structures/Stacks/stack.md new file mode 100644 index 00000000..b15b3527 --- /dev/null +++ b/en/Data Structures/Stacks/stack.md @@ -0,0 +1,29 @@ +# Stack + +A stack is a basic linear data structure that follows an order in which objects are accessed. The order is called LIFO(Last In First Out)or FILO(First in Last Out). +A perfect example of stacks would be plates in a canteen, a pile of books, or a box of Pringles,etc. +Stacks are used to implement parsers and evaluation expressions and backtracking algorithms. basic operations are pushing an element into the stack and popping the element out of the stack. +We can make use of linked lists or arrays of lists. The stack contains only one pointer +"top pointer" which points to the topmost elements of the stack. Insertion and deletion only occurs at one end of the stack. + +# Standard Stack Operations + +1) push(): inserts the element at the top of the stack. +2) pop(): When we delete the element at the top of the stack +3) isEmpty(): It determines whether the stack is empty. +4) isFull(): determines whether the stack is full or not +5) peek(): Gets the value of the top element without removing it + +# Working with Stacks + +A pointer called TOP is used to keep track of the top element in the stack. When initializing the stack, we set its value to -1 so that we can check if the stack is empty by comparing TOP == -1. On pushing an element, we increase the value of TOP and place the new element in the position pointed to by TOP. On popping an element, we return the element pointed to by TOP and reduce its value. Before pushing, we check if the stack is already full before popping, we check if the stack is already empty. + +# Source + +1) [Stack Data Structure - GeeksForGeeks](https://www.geeksforgeeks.org/stack-data-structure/) +2) [DS-Stack JavaPoint](https://www.javatpoint.com/data-structure-stack) +3) [Stack Data Structure](https://www.programiz.com/dsa/stack) + +# Video Playlist + +- [Stack Data Structure](https://youtu.be/F1F2imiOJfk) diff --git a/en/Data Structures/Tries/trie.md b/en/Data Structures/Tries/trie.md new file mode 100644 index 00000000..0be94fce --- /dev/null +++ b/en/Data Structures/Tries/trie.md @@ -0,0 +1,158 @@ +# Trie + +A trie (also called a prefix tree) is a tree data structure that shows order, linking parents to children. It is an efficient way of storing objects that have commonalities. A good example would be in storing phone numbers, or strings in general + +For the strings example, supposing we have a list of strings to store in our data store + +1. egg +2. eat +3. ear +4. end + +And one of the methods we are to support is a search operation for any of the words, we can approach it the basic way - select each word, and do a string comparison, matching letter to letter. The algorithm would be as follows: + + +``` +## searching for ear in data store + +data_store = ["egg", "eat", "ear", "end"] +to_find = "ear" + +## pick each word +## do a string match letter by letter +## when you find a mismatch, move to the next string +## continue this process +## if at the end of an iteration, index has been increased to +## the length of the word to find, we have found a match + +for word in data_store: + index = 0 + while index < len(word): + if to_find[index] != word[index]: + break + index += 1 + if index == len(to_find): + print("a match has been found") + +``` + +Without a doubt, this strategy will work, but the time complexity of doing this is *O(num of words x len of longest word)* which is quite expensive. +However, if we represent the storage of numbers in a tree such that each letter appears only once in a particular level in the tree, we can achieve a much better search time. Take, for example, the tree below + +``` + e + / | \ + a n g + / \ | | + r t d g + +``` + +You can see from the above representation, that all the words are in the tree, starting from the letter e, which is found at the beginning of all the words, then a, n, and g coming in the next level and so on... +The above representation is called a trie. + +# Standard Trie Operations + +1) insert(): inserts the string into the trie. +2) search(): searches for the string within the trie. + +# Building a Trie + +## Defining a node class for the elements of the trie + +To start building a trie, you first need to define a node with the revelant attributes needed for any trie. + +``` +class Node: + def __init__(self, is_word: bool=False): + self.is_word = is_word + self.children = {} +``` + +Here, you can see that the class `Node` has three instance attributes: +1. is_word: *bool* = to mark whether that node in the trie marks the completion of a word +2. children: *Dict* = to hold pointers to other children nodes + +Then the trie gets built by creating a node for each letter and adding it as a child to the node before it + +## Building the trie itself + +Start by initializing an empty node + +``` +class Trie: + def __init__(self): + self.node = Node() +``` + +For the insert operation, fetch the starting node, then for every letter in the word, add it to the children of the letter before it. The final node has its `is_word` attribute marked as **True** because we want to be aware of where the word ends + +``` +def insert(self, word: str) -> None: + node = self.node + for ltr in word: + if ltr not in node.children: + node.children[ltr] = Node() + node = node.children[ltr] + node.is_word=True +``` + +*In the code above, the `node` variable starts by holding a reference to the null node, while the `ltr` iterating variable starts by holding the first letter in `word`. This would ensure that `node` is one level ahead of `ltr`. As they are both moved forward in the iterations, `node` will always remain one level ahead of `ltr`* + +For the search operation, fetch the starting node, then for every letter in the word, check if it is present in the `children` attribute of the current node. As long as it is present, repeat for the next letter and next node. If during the search process, we find a letter that is not present, then the word does not exist in the trie. If we successfully get to the end of the iteration, then we have found what we are looking for. It is time to return a value + +Take a look at the code + +``` +def search(self, word: str) -> bool: + node = self.node + for ltr in word: + if ltr not in node.children: + return False + node = node.children[ltr] + return node.is_word +``` + +For the return value, there are two cases: +1. we are searching for a word -> return `node.is_word` because we want to be sure it is actually a word, and not a prefix +2. we are searching for a prefix -> return **True** because whether it is a word or not, it is prefix that exists in the trie + +Now here is the full code + +``` +class Node: + def __init__(self, is_word: bool=False): + self.is_word = is_word + self.children = {} + +class Trie: + + def __init__(self): + self.node = Node() + + + def insert(self, word: str) -> None: + node = self.node + for ltr in word: + if ltr not in node.children: + node.children[ltr] = Node() + node = node.children[ltr] + node.is_word=True + + + def search(self, word: str) -> bool: + node = self.node + for ltr in word: + if ltr not in node.children: + return False + node = node.children[ltr] + return node.is_word +``` + +# Helpful links + +1) [Trie Data Structure - GeeksForGeeks](https://www.geeksforgeeks.org/trie-insert-and-search/) + +# Video Playlist + +- [Trie Data Structure](https://www.youtube.com/watch?v=zIjfhVPRZCg) \ No newline at end of file diff --git a/Dynamic Programming/Coin Change.md b/en/Dynamic Programming/Coin Change.md similarity index 93% rename from Dynamic Programming/Coin Change.md rename to en/Dynamic Programming/Coin Change.md index 99a8a590..187f0dc0 100644 --- a/Dynamic Programming/Coin Change.md +++ b/en/Dynamic Programming/Coin Change.md @@ -42,14 +42,11 @@ Let's say we have 3 coin types `[1,2,3]` and we want to change for `7` cents. So ``` 4 ways to make 7 cents using value of 1 and 2. `{{1,1,1,1,1,1,1}, {1,1,1,1,1,2}, {1,1,1,2,2}, {1,2,2,2}}` -* For the final iteration (3rd iteration), we take a coin that has a value of 3. Like before, now all the columns that can be devided by 3 will store another new way. And the final result will be like: +* For the final iteration (3rd iteration), we take a coin that has a value of 3. Like before, now all the columns that can be divided by 3 will store another new way. And the final result will be like: ``` [1, 1, 2, 3, 4, 5, 7, 8] ``` So the final answer is **8**. 8 ways to make change of 7 cents using all coin types. `{{1,1,1,1,1,1,1}, {1,1,1,1,1,2}, {1,1,1,2,2}, {1,2,2,2}, {1,1,1,1,3}, {1,3,3}, {2,2,3}, {1,1,2,3}}` -#### Code Implementation Link -[Python](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/coin_change.py) - #### Video Explanation [Total Unique Ways To Make Change by Back To Back SWE](https://www.youtube.com/watch?v=DJ4a7cmjZY0) diff --git a/en/Dynamic Programming/Kadane's Algorithm.md b/en/Dynamic Programming/Kadane's Algorithm.md new file mode 100644 index 00000000..6d6c89f0 --- /dev/null +++ b/en/Dynamic Programming/Kadane's Algorithm.md @@ -0,0 +1,111 @@ +# Kadane's Algorithm + +## Problem Statement +Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. +Note: A subarray is a contiguous part of an array. + + +1st example + +```text + +Input: nums = [-2,1,-3,4,-1,2,1,-5,4] +Output: 6 +Explanation: [4,-1,2,1] has the largest sum = 6. +``` + +2nd example + +```text + +Input: nums = [5,4,-1,7,8] +Output: 23 +Explanation: [5,4,-1,7,8] has the largest sum = 23. +``` + + +## Time Complexity + +O(N) + +## Space Complexity + +O(1) + +## Algorithm +The idea is to keep track of the maximum sum of the subarray ending at the current index. +The maximum sum of the subarray ending at the current index can be calculated by adding the current element to the maximum sum of the subarray ending at the previous index. +If the maximum sum of the subarray ending at the previous index is negative, then the maximum sum of the subarray ending at the current index is the current element. +The maximum sum of the subarray ending at the current index is stored in a variable maxEndingHere. +The maximum sum of the subarray ending at the current index is compared with the maximum sum of the subarray ending at the previous index. +If the maximum sum of the subarray ending at the current index is greater than the maximum sum of the subarray ending at the previous index, then the maximum sum of the subarray ending at the current index is stored in a variable maxSoFar. +The maximum sum of the subarray ending at the current index is returned as the output. + + +## Walkthrough + +`array = [-2,1,-3,4,-1,2,1,-5,4]` + +We consider each element of the array and decide whether to include it in the current subarray or start a new subarray from it. + +### Calculation Formula for two variables + +``` +current Sum = 0 Calculated by max(number, currentSum + number) +largest Sum = float("-inf") Calculated by max(currentSum, largestSum) +``` + + +### Traversing through an array will look like + +``` +Consider -2 +current_sum = max(-2, current_sum + -2) = max(-2, 0 + -2) = -2 +largest_sum = max(-2, float("-inf")) = -2 +``` +``` +Consider 1 +current_sum = max(1, current_sum+1) = max(1, -2+1) = 1 +largest_sum = max(1, -2) = 1 +``` +``` +Consider -3 +current_sum = max(-3, current_sum + -3) = max(-3, 1 + -3) = -2 +largest_sum = max(-2, 1) = 1 +``` +``` +Consider 4 +current_sum = max(4, current_sum + 4) = max(4, -2 + 4) = 4 +largest_sum = max(4, 1) = 4 +``` +``` +Consider -1 +current_sum = max(-1, current_sum + -1) = max(-1, 4 + -1) = 3 +largest_sum = max(3, 4) = 4 +``` +``` +Consider 2 +current_sum = max(2, current_sum + 2) = max(2, 3 + 2) = 5 +largest_sum = max(5, 4) = 5 +``` +``` +Consider 1 +current_sum = max(1, current_sum + 1) = max(1, 5 + 1) = 6 +largest_sum = max(6, 5) = 6 +``` +``` +Consider -5 +current_sum = max(-5, current_sum + -5) = max(-5, 6 + -5) = 1 +largest_sum = max(1, 6) = 6 +``` +``` +Consider 4 +current_sum = max(4, current_sum + 4) = max(4, 1 + 4) = 5 +largest_sum = max(5, 6) = 6 +``` + +```Hence the output will be 6``` + +### Video Explanation Link + +- [Kadane's Algorithm to Maximum Sum Subarray Problem](https://www.youtube.com/watch?v=86CQq3pKSUw) diff --git a/Dynamic Programming/Longest Common Subseqence.md b/en/Dynamic Programming/Longest Common Subsequence.md similarity index 78% rename from Dynamic Programming/Longest Common Subseqence.md rename to en/Dynamic Programming/Longest Common Subsequence.md index 7dbc0627..d613f807 100644 --- a/Dynamic Programming/Longest Common Subseqence.md +++ b/en/Dynamic Programming/Longest Common Subsequence.md @@ -2,7 +2,7 @@ #### Problem Statement -Given two strings `S` and `T`, find the length of the longest common subsequence (LCS). +Given two strings `S` and `T`, find the length of the longest common subsequence (LCS). #### Approach @@ -19,14 +19,14 @@ We could see that we can fill our `dp` table row by row, column by column. So ou - Let's say that we have strings `S` of the length N and `T` of the length M (numbered from 1). Let's create the table `dp` of size `(N + 1) x (M + 1)` numbered from 0. - Let's fill the 0th row and the 0th column of `dp` with 0. - Then, we follow the algorithm: - ``` - for i in range(1..N): - for j in range(1..M): - if(S[i] == T[j]) - dp[i][j] = dp[i - 1][j - 1] + 1 - else - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) - ``` +``` +for i in range(1..N): + for j in range(1..M): + if(S[i] == T[j]) + dp[i][j] = dp[i - 1][j - 1] + 1 + else + dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) +``` #### Time Complexity @@ -35,8 +35,8 @@ We could see that we can fill our `dp` table row by row, column by column. So ou #### Space Complexity -`O(N * M)` - simple implementation -`O(min {N, M})` - two-layers implementation (as `dp[i][j]` depends on only i-th and i-th layers, we coudld store only two layers). +`O(N * M)` - simple implementation +`O(min {N, M})` - two-layers implementation (as `dp[i][j]` depends on only i-th and i-th layers, we coudld store only two layers). #### Example @@ -49,7 +49,7 @@ B 0 ? ? ? ? C 0 ? ? ? ? B 0 ? ? ? ? ``` -Now we will start to fill our table from 1st row. Since `S[1] = A` and `T[1] = B`, the `dp[1][1]` will be tha maximal value of `dp[0][1] = 0` and `dp[1][0] = 0`. So `dp[1][1] = 0`. But now `S[2] = B = T[1]`, so `dp[1][2] = dp[0][1] + 1 = 1`. `dp[1][3]` is `1` since `A != C` and we pick `max{dp[1][2], dp[0][3]}`. And `dp[1][4] = dp[0][3] + 1 = 1`. +Now we will start to fill our table from 1st row. Since `S[1] = A` and `T[1] = B`, the `dp[1][1]` will be the maximal value of `dp[0][1] = 0` and `dp[1][0] = 0`. So `dp[1][1] = 0`. But now `S[2] = B = T[1]`, so `dp[1][2] = dp[0][1] + 1 = 1`. `dp[1][3]` is `1` since `A != C` and we pick `max{dp[1][2], dp[0][3]}`. And `dp[1][4] = dp[0][3] + 1 = 1`. ``` # # A B C B # 0 0 0 0 0 @@ -69,12 +69,6 @@ B 0 0 1 2 3 ``` So the length of LCS is `dp[4][4] = 3`. -#### Code Implementation Links - -- [Java](https://github.com/TheAlgorithms/Java/blob/master/Dynamic%20Programming/LongestCommonSubsequence.java) -- [Python](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/longest_common_subsequence.py) -- [C++](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/Dynamic%20Programming/Longest%20Common%20Subsequence.cpp) - #### Video Explanation [Video explanation by Tushar Roy](https://youtu.be/NnD96abizww) diff --git a/en/Dynamic Programming/Longest Increasing Subsequence.md b/en/Dynamic Programming/Longest Increasing Subsequence.md new file mode 100644 index 00000000..fa9f5039 --- /dev/null +++ b/en/Dynamic Programming/Longest Increasing Subsequence.md @@ -0,0 +1,112 @@ +# Longest Increasing Subsequence in O(NlogN) + +## Problem Statement + +Given an Array of Integers `A`, find the length of the longest increasing subsequence (**LIS**) such that all elements of the subsequence are sorted in increasing order. An increasing subsequence contains elements `A[i]` and `A[j]` only if `i < j` and `A[i] < A[j]`. + +## Approach + +The basic idea behind the solution is to keep track of all active subsequences at a given point in time. Based on the current number being considered, update these active lists. To understand this process, let’s work out an example. + +``` +A = {2,8,7} +Monotonically increasing subsequences are {2,8} and {2,7} +``` +What if we add another element, 11 in this? + +``` +A = {2,8,7,11} +Monotonically increasing subsequences are {2,8,11} and {2,7,11} +``` +What if a new element 9 is added to the array? What happens now? If we add t0 subsequences, the length of the longest subsequence remains 3. + +``` +A = {2,8,7,11,9} +Monotonically increasing subsequences are {2,8,9} and {2,7,9} +``` +The decision to take for each element being considered is whether we create new active subsequences with length 3 with element 9 in them or continue with 11. If the next element is 10 we know that adding 9 to subsequence leads us to longer subsequences rather than keeping 11. + +How do we decide when to replace and when to continue with the old element in the list of subsequences? + +We add a new number `A[i]` to the sequence if `A[i]` > `E`, `E` is the last element in subsequence +and replace an number with `A[i]`, if there exists a number `A[j]` such that if `E` > `A[i]` < `A[j]`, it means, the new number falls somewhere between `A[j]` and `E`. + +What if `A[i]` is smaller than all elements in the present list of subsequences? In this case, we have to create a new list and add `A[i]` into it. The invariant is to maintain lists of increasing sequences and update them based on the next number. +Each time a new element is to be added, scan all the lists of subsequences in decreasing order of their length. The following algorithm shows how to add/replace the new elements in the existing lists or to create a new list with them. + +``` +1. If A[i] is the smallest among all end candidates of active lists, start a new active list with A[i] of length 1. +2. If A[i] is largest among all end candidates of active lists, clone the largest active list, and append A[i] to it. +3. If A[i] is in between, find the list with the largest end number that is smaller than A[i]. Clone and append A[i] to this list. +4. Discard all other lists of the same length as that of this modified list. +``` + +## Time Complexity + +`O(N * LogN)` In any case +`O(logn)` time to find the ceiling of it and put it at the correct position + +## Space Complexity + +`O(N)` for each element in the array + +## Example + +Let’s take an example and see how it works with an array `A = [ 0, 8, 4, 12, 2, 10, 6, 14]`.
+For `A[0]`, there are no active lists of subsequences. We will create a new one. + +``` +[0,8,4,12,2,10,6,14] +[0] +``` +Next, we go to `A[1]` which is 8. `A[i]` is greater than the ends of all the current lists, we will take the longest one and append `A[1]` to it. + +``` +[0,8,4,12,2,10,6,14] +[[0],[0,8]] +``` +For `A[2]` with value 4, `A[i]` is less than the end of one of the lists and greater than the end of the other. We will find the list which has an end less than `A[i]`. In this case, it is the first list containing [0]. Clone it and append `A[2]` to it and discard all other lists of the same length. + +``` +[0,8,4,12,2,10,6,14] +[[0],[0,4]] +[0,8] is discarded as it is of the same length 2. +``` +For `A[3]` with value 12, it is the same case as `A[1]` since it is greater than all the ends of the current lists, we will clone the longest available list and append it to that. + +``` +[0,8,4,12,2,10,6,14] +[[0],[0,4],[0,4,12]] +``` +`A[4]` with value 2, it has the same case as `A[2]`, clone the one with the largest end which is less than `A[4]`, append `A[4]` to it, and discard all same length lists. + +``` +[0,8,4,12,2,10,6,14] +[[0],[0,2],[0,4,12]] +``` +`A[5]` with value 10. Same as `A[4]`. Clone, extend and discard all the same length subsequences. +Lists = [ [0], [0, 2], [0,2,10] ] and [0, 4, 12] is discarded. + +`A[6]` is 6. Same as `A[5]` We will clone the list which has an end smaller than `A[6]`, extend it, and discard all other lists which have the same length. +Lists = [ [0], [0, 2], [0,2,6] ] and [0, 2, 10] is discarded. + +Following the same approach, we will go through all the numbers in the given array. The longest increasing subsequence in the given array is [ 0,2,6,14] with a length of 4. + +``` +[0,8,4,12,2,10,6,14] +[[0],[0,2],[0,2,6],[0,2,6,14]] +``` +It seems like a lot of things need to be done just for maintaining the lists and there is significant space complexity required to store all of these lists. We can optimize on this, observe that we use only ends of the list and their sizes. We do not care what was before them on the list. So, can we store the ends of all the lists of an auxiliary array and do operations on them? The size of this array in the worst case will be n. + +To append to the list, add another element in the auxiliary array. To replace just overwrite the smallest number which is greater than the current number. To find the smallest number which is greater than the current number, we can use binary search algorithm. + +To find the length of the longest subsequence, keep track of the length of the auxiliary array because this will be the length of LIS. + + +## Code Implementation Links + +[Code Implementation](https://www.geeksforgeeks.org/longest-monotonically-increasing-subsequence-size-n-log-n/) + +## Video Explanation + +[Video explanation by Tushar Roy](https://www.youtube.com/watch?v=S9oUiVYEq7E&ab_channel=TusharRoy-CodingMadeSimple) diff --git a/en/Greedy Algorithms/Fractional Knapsack.md b/en/Greedy Algorithms/Fractional Knapsack.md new file mode 100644 index 00000000..fb49dab1 --- /dev/null +++ b/en/Greedy Algorithms/Fractional Knapsack.md @@ -0,0 +1,40 @@ +# Knapsack Problem (Greedy algorithm) + +#### Problem Statement + +Given a set of items, each with weight and a value, determine the number of each item included in a collection so that the total weight is less than or equal to the given limit and the total value is as large as possible. + +##### Greedy method will always provide an optimal solution with fractional knapsack problem. + +#### Time Complexity + +O(nlog n) Worst Case + +#### Example + +``` +Lets assume the capacity of knapsack, W = 60 +value = [280, 100, 120, 120] +weight = [40, 10, 20, 24] + +Ratio(V/W) = 7,10,6,5 +Say those items as A,B,C,D +next, the items should be sorted in descending order based on the ratio of value by weight to get maximum profit +First and foremost, B was picked since its weight is smaller than the knapsack's capacity. The next item, A, is chosen since the knapsack's available capacity is more than A's weight. C is now the next item on the list. However, the entire item cannot be chosen because the knapsack's remaining capacity is less than C's weight. +As a result, the C proportion (60–50)/20) +The knapsack's capacity is now equal to the specified items. +As a result, no more items can be chosen. + +10 + 40 + 20*(10/20) = 60 is the total weight of the chosen goods. + +100+280+120*(10/20)=380+60=440 is the total profit. + +This is the most suitable option. + +We won't be able to make more money by combining diverse things. + +``` + +#### Video Explanation + +[A CS50 video explaining the Greedy Algorithm](https://www.youtube.com/watch?v=Ou9OA0yQCYA) diff --git a/Image Processing/Harris Detector.md b/en/Image Processing/Harris Detector.md similarity index 71% rename from Image Processing/Harris Detector.md rename to en/Image Processing/Harris Detector.md index 54fe9953..16b5f3ed 100644 --- a/Image Processing/Harris Detector.md +++ b/en/Image Processing/Harris Detector.md @@ -13,11 +13,6 @@ Given image $I$, $n\times n$ size Gaussian Kernel $G_{n\times n}$, 3. Compute the response function $R$, where $R=AB-C^2-k(A+B)$ 4. Classify all points in $R​$. -## Code Implementation Links - -- [Python](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/feature_detectors/harris.py) - ## Reference -C. Harris and M. Stephens, “A Combined Corner and Edge Detector,” in *Procedings of the Alvey Vision Conference 1988*, Manchester, 1988, pp. 23.1-23.6. - +C. Harris and M. Stephens, “A Combined Corner and Edge Detector,” in *Proceedings of the Alvey Vision Conference 1988*, Manchester, 1988, pp. 23.1-23.6. diff --git a/en/README.md b/en/README.md new file mode 100644 index 00000000..fe4e8a23 --- /dev/null +++ b/en/README.md @@ -0,0 +1,30 @@ +# Algorithm Name + +Write a short description of algorithm like: + +1. Time Complexity +2. Space Complexity +3. Applications +4. Founder's Name +5. etc... + +## Steps + +Describe the algorithm in clear, simple and understandable steps. + +## Example + +Trace the algorithm with a sample input data. + +## Implementation + +Links to their implementation in programming languages. +NOTE: The link should be within the other repos of this organization only. + +## Video URL + +Attach a URL of a video that explains the algorithm. + +## Others + +Any other information is always welcome and should be included in this section. diff --git a/Search Algorithms/Binary Search.md b/en/Search Algorithms/Binary Search.md similarity index 57% rename from Search Algorithms/Binary Search.md rename to en/Search Algorithms/Binary Search.md index 5267c1ea..ff704de5 100644 --- a/Search Algorithms/Binary Search.md +++ b/en/Search Algorithms/Binary Search.md @@ -6,45 +6,37 @@ Given a sorted array of n elements, write a function to search for the index of #### Approach -- Search for the array by dividing the array in half repeatedly. -- Initialy consider the actual array and pick the element at the middle index +- Search for the array by dividing the array in half repeatedly. +- Initially consider the actual array and pick the element at the middle index - Keep a lower index i.e. 0 and higher index i.e. length of array - If it is equal to the target element then return the index - Else if it is greater than the target element then consider only the left half of array. (lower index = 0, higher = middle - 1) - Else if it is less than the target element then consider only the right half of array. (lower index = middle + 1, higher = length of array) -- Return -1 if target element is not found in the array (Base Case: If lower index is greater than or equal to higher index) +- Return -(insertion index + 1) if the target element is not found in the array (If the lower index is greater than or equal to higher index). Some simpler implementations just return -1 if the element is not found. The offset of 1 must be added as the insertion index might be 0 (the searched value might be smaller than all elements in the array). As indexing starts at 0, this must be distinguishable from the case where the target element has the index 0. #### Time Complexity -O(Logn) Worse Case +O(log n) Worst Case O(1) Best Case (If middle element of initial array is the target element) #### Space Complexity O(1) For iterative approach -O(Logn) For recursive approach due to recursion call stack +O(1) For recursive approach *if tail call optimization is used*, O(log n) due to recursion call stack, otherwise #### Example ``` arr = [1,2,3,4,5,6,7] -target = 2 +target = 2 Initially the element at middle index is 4 which is greater than 2. Therefore we search the left half of the -array i.e. [1,2,3]. +array i.e. [1,2,3]. Here we find the middle element equal to target element so we return its index i.e. 1 target = 9 -Binary Search should return -1 as 9 is not present in the array - ``` - -#### Code Implementation Links - -- [Java](https://github.com/TheAlgorithms/Java/blob/master/Searches/BinarySearch.java) -- [C++](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/Search/Binary%20Search.cpp) -- [Python](https://github.com/TheAlgorithms/Python/blob/master/searches/binary_search.py) -- [C-Sharp](https://github.com/TheAlgorithms/C-Sharp/blob/master/searches/binary_search.cs) -- [C](https://github.com/TheAlgorithms/C/blob/master/searching/Binary_Search.c) +A simple Binary Search implementation may return -1 as 9 is not present in the array. A more complex one would return the index at which 9 would have to be inserted, which would be `-8` (last position in the array (7) plus one (7+1), negated)`. +``` #### Video Explanation diff --git a/en/Search Algorithms/Exponential Search.md b/en/Search Algorithms/Exponential Search.md new file mode 100644 index 00000000..3530b2c5 --- /dev/null +++ b/en/Search Algorithms/Exponential Search.md @@ -0,0 +1,55 @@ +# Exponential Search + +#### Prerequisites + +- [Binary Search algorithm](Binary%20Search.md) + +#### Problem Statement + +Given a sorted array of *n* elements, write a function to search for the index of a given element (target) + +#### Approach + +- Search for the **range** within which the target is included increasing *index* by powers of 2 +- If this range exists in array apply the Binary Search algorithm over it +- Else return -1 + +#### Example + +```markdown +arr = [1, 2, 3, 4, 5, 6, 7, ... 998, 999, 1_000] + +target = 998 +index = 0 +1. SEARCHING FOR THE RANGE +index = 1, 2, 4, 8, 16, 32, 64, ..., 512, ..., 1_024 +after 10 iteration we have the index at 1_024 and outside of the array +2. BINARY SEARCH +Now we can apply the binary search on the subarray from 512 and 1_000. +``` + +***Note***: we apply the Binary Search from 512 to 1_000 because at `i = 2^10 = 1_024` the array is finisced and the target number is less than the latest index of the array ( 1_000 ). + +#### Time Complexity + +**worst case:** `O(log *i*)` where `*i* = index` (position) of the target + +**best case:** `O(*1*)` + +#### Complexity Explanation + +- The complexity of the first part of the algorithm is **O( log *i* )** because if *i* is the position of the target in the array, after doubling the search *index* `⌈log(i)⌉` times, the algorithm will be at a search index that is greater than or equal to *i*. We can write `2^⌈log(i)⌉ >= i` +- The complexity of the second part of the algorithm also is **O ( log *i* )** because that is a simple Binary Search. The Binary Search complexity ( as explained [here](Binary%20Search.md) ) is O( *n* ) where *n* is the length of the array. In the Exponential Search, the length of the array on which the algorithm is applied is `2^i - 2^(i-1)`, put into words it means '( the length of the array from start to *i* ) - ( the part of array skipped until the previous iteration )'. Is simple verify that `2^i - 2^(i-1) = 2^(i-1) ` + +After this detailed explanation we can say that the the complexity of the Exponential Search is: + +```mathematica +O(log i) + O(log i) = 2O(log i) = O(log i) +``` + +#### Binary Search vs Exponential Search + +Let's take a look at this comparison with a less theoretical example. Imagine we have an array with`1_000_000` elements and we want to search an element that is in the `4th` position. It's easy to see that: + +- The Binary Search start from the middle of the array and arrive to the 4th position after many iterations +- The Exponential Search arrive at the 4th index after only 2 iterations diff --git a/en/Search Algorithms/Floyd Cycle Detection Algorithm to Find Duplicate Number.md b/en/Search Algorithms/Floyd Cycle Detection Algorithm to Find Duplicate Number.md new file mode 100644 index 00000000..a431d58d --- /dev/null +++ b/en/Search Algorithms/Floyd Cycle Detection Algorithm to Find Duplicate Number.md @@ -0,0 +1,73 @@ +# Floyd Cycle Detection Algorithm to find duplicate numbers in an array + +## Problem Statement + +Given an array of integers containing `n + 1` integers, where each integer is in the range `[1, n]` inclusive. If there is only one duplicate number in the input array, this algorithm returns the duplicate number without modifying the original array, otherwise, it returns -1. + +## Approach +- We can imagine the array `arr` as a directed graph where each element is a node. `arr[i]` is the index of the node to which the i-th node points. +- For example, given the `arr = [1, 3, 4, 2, 3]`, we can represent `arr` as the following

+![image](images/graph_1.png) + +- Since there are duplicates in `arr`, a cycle exists in the directed graph as there is a path from node 3 to itself, `3 -> 2 -> 4 -> 3`. +- The problem now becomes finding the entrance node to the cycle (3 in this case). +- We can use the Floyd Cycle Detection Algorithm (also known as the "Hare and Tortoise algorithm") to detect the entrance of the cycle. +- The idea of the algorithm is to maintain two pointers, `hare` and `tortoise` that iterate the array at different "speeds" (just like the fable). The details are as follows: + +### The procedure +- Using two pointers `hare` and `tortoise`. +- Initiate `hare = tortoise = arr[0]`. +- For every next step until `hare == tortoise` again, assign `hare = arr[arr[hare]]` and `tortoise = arr[tortoise]` (`hare` "jumps" 2 steps while `tortoise` "jumps" one step). +- At this point, `hare == tortoise`, reset `tortoise = arr[0]` while keeping the value of `hare` in the above procedure. +- For every next step until `hare == tortoise` again, assign `hare = arr[hare]` and `tortoise = arr[tortoise]` (this time `hare` only "jumps" one step). +- When `tortoise == hare`, the entrance of the cycle is found, hence `hare` and `tortoise` represent the value of the duplicated element. +- Return `tortoise` (also possible to return `hare`) + +## Time Complexity + +`O(n)` + +## Space Complexity + +`O(1)`, since we only use two extra variables as pointers. + +## Example with step-by-step explanation +![image](images/graph_2.png) + +``` +arr = [3, 4, 8, 5, 9, 1, 2, 6, 7, 4] + +hare = tortoise = arr[0] = 3 + +1st step: + - hare = arr[arr[3]] = arr[5] = 1 + - tortoise = arr[3] = 5 +2nd step: + - hare = arr[arr[1]] = arr[4] = 9 + - tortoise = arr[5] = 1 +3rd step: + - hare = arr[arr[9]] = arr[4] = 9 + - tortoise = arr[1] = 4 +4th step: + - hare = arr[arr[9]] = 9 + - tortoise = arr[4] = 9 + +tortoise = arr[0] = 3 + +1st step: + - hare = arr[9] = 4 + - tortoise = arr[3] = 5 +2nd step: + - hare = arr[4] = 9 + - tortoise = arr[5] = 1 +3rd step: + - hare = arr[9] = 4 + - tortoise = arr[1] = 4 + +return tortoise = 4 +``` + +#### Video Explanation + +- [YouTube video explaining the Floyd Cycle Detection algorithm](https://www.youtube.com/watch?v=B6smdk7pZ14) +- [Another Youtube video](https://www.youtube.com/watch?v=PvrxZaH_eZ4&t=1s) diff --git a/Search Algorithms/Linear Search.md b/en/Search Algorithms/Linear Search.md similarity index 66% rename from Search Algorithms/Linear Search.md rename to en/Search Algorithms/Linear Search.md index 3fc1bf3d..4da70e54 100644 --- a/Search Algorithms/Linear Search.md +++ b/en/Search Algorithms/Linear Search.md @@ -7,7 +7,7 @@ Given an array of n elements, write a function to search for the index of a give #### Approach - Start iterating with the first element in the array. -- Compare it with the target element +- Compare it with the target element - If it is equal to the target element then return the index - Else continue iterating - Return -1 if target element is not found in the array @@ -26,23 +26,17 @@ O(1) ``` arr = [1, 3, 9, 5, 0, 2] -target = 5 +target = 5 Linear Search should return index 3 as 5 is on index 3 target = 6 -Linear Search should return -1 as 6 is not present in the array - ``` - -#### Code Implementation Links - -- [Java](https://github.com/TheAlgorithms/Java/blob/master/Searches/LinearSearch.java) -- [C++](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/Search/Linear%20Search.cpp) -- [Python](https://github.com/TheAlgorithms/Python/blob/master/searches/linear_search.py) +Linear Search should return -1 as 6 is not present in the array +``` #### Video Explanation [A CS50 video explaining the Linear Search Algorithm](https://www.youtube.com/watch?v=CX2CYIJLwfg) - #### Animation Explanation + - [Tute Board](https://boardhub.github.io/tute/?wd=linearSearchAlgo) diff --git a/en/Search Algorithms/images/graph_1.png b/en/Search Algorithms/images/graph_1.png new file mode 100644 index 00000000..2a45b595 Binary files /dev/null and b/en/Search Algorithms/images/graph_1.png differ diff --git a/en/Search Algorithms/images/graph_2.png b/en/Search Algorithms/images/graph_2.png new file mode 100644 index 00000000..d51e9516 Binary files /dev/null and b/en/Search Algorithms/images/graph_2.png differ diff --git a/en/Selection Algorithms/Find Second Largest Element.md b/en/Selection Algorithms/Find Second Largest Element.md new file mode 100644 index 00000000..14971faa --- /dev/null +++ b/en/Selection Algorithms/Find Second Largest Element.md @@ -0,0 +1,70 @@ +# Find Second Largest Element + +#### Problem statement + +Given an unsorted array, write a function to find the second largest element in the array. + +#### Approach + +- Find the largest element in the array by traversing through the array using a loop and store the value in a variable (for ex: a ) +- Assign a variable to store the negative infinite value, which stores the least value (for ex: b ) +- Run a loop from zero to the size of the array. +- Now check whether the current element is greater than variable "b" and also not equal to variable "a", which is the largest number in the array. +- if the above condition is true, then the variable b stores the current element. + +#### Time Complexity + +- Best case: `O(n)` +- Average case: `O(n)` +- Worst case: `O(n)` + +#### Space Complexity + +Worst case: `O(1)` + +#### Example + +```txt +arr = [2, 5, 3, 9, 12, 34, 25] +Indexes: 0 1 2 3 4 5 6 +a = max(arr) +(a = 34) +b = float("-inf") + +Traverse elements from i = 0 to i = 6 +i = 0 +Check if b < arr[i] (arr[0]) and arr[0] != a +True : b = arr[0] (b = 2) + +i = 1 +Check if b < arr[i] (arr[1]) and arr[1] != a +True : b = arr[0] (b = 5) + +i = 2 +Check if b < arr[i] (arr[2]) and arr[2] != a +False : As b = 5 is greater than the current element arr[2] = 3 +continues with the loop + +i = 3 +Check if b < arr[i] (arr[3]) and arr[3] != a +True : b = arr[3] (b = 9) + +i = 4 +Check if b < arr[i] (arr[4]) and arr[4] != a +True : b = arr[4] (b = 12) + +i = 5 +Check if b < arr[i] (arr[5]) and arr[5] != a +False: As current element is equal to the variable "a" which stores the highest value in the array +continues with the loop + +i = 6 +Check if b < arr[i] (arr[6]) and arr[6] != a +True : b = arr[6] (b = 25) + +Now we get the value 25 in the variable "b", which is the second highest value in the array. +``` + +#### Video Explanation + +[Video explaining 2 approaches](https://www.youtube.com/watch?v=Mv8jhYQEbkA) diff --git a/en/Selection Algorithms/Quick Select.md b/en/Selection Algorithms/Quick Select.md new file mode 100644 index 00000000..cc915e4e --- /dev/null +++ b/en/Selection Algorithms/Quick Select.md @@ -0,0 +1,46 @@ +# Quick Select + +### Problem Statement + +Given an array, find the kth largest / smallest element in linear time complexity. + +### Approach + +- Select a pivot element at random +- Apply partitioning as used in quick sort +- After partitioning, the pivot will be placed in its sorted location ie. All elements smaller than the pivot will be on its left and greater on its right +- If index of sorted pivot is k, then the pivot is our kth element and we return the number +- Else, check if 'k' is greater or smaller and choose a new pivot in that range. +- Repeat till we get the kth element at kth position + +### Time Complexity + +- `O(n^2)` Worst-Case Performance + +- `O(n)` Best-case Performance + +- `O(n)` Average Performance + + +### Founder's Name + +- This algorithm was developed by Tony Hoare and is also called `Hoare's Selection Algorithm`. + +### Example + +``` +arr[] = {8,2,11,7,9,1,3} +Indexes: 0 1 2 3 4 5 6 + +Let's say k = 4. ie. We have to find 4th smallest element. + +1. Choosing random pivot as 7 +2. Swap 7 with the last element and apply the partitioning algorithm +3. After applying partition, all elements smaller than 7 will be placed to the left and greater in its right. + Thus we can say that 7 is in its sorted position arr[] = {2,3,1,7,8,9,11} +4. As position of '7' is 4th (ie. k). Thus we will simply return 7 +``` + +### Helpful Video Links + +[Video explaining how to find the Kth smallest/largest element in varying complexities](https://youtu.be/hGK_5n81drs) diff --git a/Sorting Algorithms/Bubble Sort.md b/en/Sorting Algorithms/Bubble Sort.md similarity index 59% rename from Sorting Algorithms/Bubble Sort.md rename to en/Sorting Algorithms/Bubble Sort.md index be8e6351..3ce99615 100644 --- a/Sorting Algorithms/Bubble Sort.md +++ b/en/Sorting Algorithms/Bubble Sort.md @@ -15,19 +15,19 @@ Given an unsorted array of n elements, write a function to sort the array #### Time Complexity -O(n^2) Worst case performance +`O(n^2)` Worst case performance -O(n) Best-case performance +`O(n)` Best-case performance -O(n^2) Average performance +`O(n^2)` Average performance #### Space Complexity -O(1) Worst case +`O(1)` Worst case #### Founder's Name -- +- The term “Bubble Sort” was first used by Iverson, K in 1962. #### Example @@ -46,7 +46,7 @@ Indexes: 0 1 2 3 7. 80 > 30, swap 80 and 30 8. The array now is {10, 40, 30, 80} - Repeat the Above Steps again +Repeat the Above Steps again arr[] = {10, 40, 30, 80} Indexes: 0 1 2 3 @@ -62,7 +62,7 @@ Indexes: 0 1 2 3 7. 40 < 80, do nothing 8. The array now is {10, 30, 40, 80} - Repeat the Above Steps again +Repeat the Above Steps again arr[] = {10, 30, 40, 80} Indexes: 0 1 2 3 @@ -76,24 +76,8 @@ Indexes: 0 1 2 3 5. Index = 2, Number = 40 6. 40 < 80, do nothing - Since there are no swaps in above steps, it means the array is sorted and we can stop here. - - - ``` - - -#### Code Implementation Links - -- [Java](https://github.com/TheAlgorithms/Java/blob/master/Sorts/BubbleSort.java) -- [C++](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/Sorting/Bubble%20Sort.cpp) -- [Python](https://github.com/TheAlgorithms/Python/blob/master/sorts/bubble_sort.py) -- [C-Sharp](https://github.com/TheAlgorithms/C-Sharp/blob/master/sorts/bubble_sort.cs) -- [Go](https://github.com/TheAlgorithms/Go/blob/master/sorts/bubble_sort.go) -- [Ruby](https://github.com/TheAlgorithms/Ruby/blob/master/Sorting/bubble_sort.rb) -- [C](https://github.com/TheAlgorithms/C/blob/master/sorting/BubbleSort.c) -- [Scala](https://github.com/TheAlgorithms/Scala/blob/master/src/main/scala/Sort/BubbleSort.scala) -- [Javascript](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/bubblesort.js) - +Since there are no swaps in above steps, it means the array is sorted and we can stop here. +``` #### Video Explanation @@ -106,4 +90,3 @@ Bubble sort is also known as Sinking sort. #### Animation Explanation - [Tute Board](https://boardhub.github.io/tute/?wd=bubbleSortAlgo2) - diff --git a/en/Sorting Algorithms/Counting Sort.md b/en/Sorting Algorithms/Counting Sort.md new file mode 100644 index 00000000..984d28bc --- /dev/null +++ b/en/Sorting Algorithms/Counting Sort.md @@ -0,0 +1,50 @@ +# Counting Sort + +#### Problem Statement + +Given an unsorted array of `n` elements, write a function to sort the array. + +#### Approach + +- Find out the maximum element (let's call it `max`) from the given array. +- Initialize an array of length `max+1` with all elements set to 0 to store the array's count. +- Store the count of each element at their respective index in the array's count. +- Store cumulative sum of the elements of the count array. It helps in placing the elements into the correct index of the sorted array. +- Find the index of each element of the original array in the array's count. This gives the cumulative count. +- Place the element at the index calculated and decrease its count by one. + +#### Time Complexity + +`O(n+k)`: where `k` is the range of the non-negative key values. + +#### Space Complexity + +`O(n+k)`: where `k` is the range of the non-negative key values. + +#### Founder's Name + +- Harold H. Seward. + +#### Example + +``` +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 +``` + +#### Video Explanation + +[A video explaining the Counting Sort Algorithm](https://www.youtube.com/watch?v=7zuGmKfUt7s) + +#### Animation Explanation + +[Counting Sort visualization](https://www.cs.usfca.edu/~galles/visualization/CountingSort.html) diff --git a/en/Sorting Algorithms/Cycle Sort.md b/en/Sorting Algorithms/Cycle Sort.md new file mode 100644 index 00000000..840aab13 --- /dev/null +++ b/en/Sorting Algorithms/Cycle Sort.md @@ -0,0 +1,69 @@ +# Cycle Sort + +#### Problem Statement + +Given an unsorted array of n elements, write a function to sort the array + +#### Approach + +- If the element is already at its correct position do nothing +- Otherwise, find the correct position of a by counting the total number of elements that are less than current element +- Insert current element into its correct position +- Set replaced element as new current element and find its correct position +- Continue process until array is sorted + +#### Time Complexity + +`O(n^2)` Worst case performance + +`O(n^2)` Best-case performance + +`O(n^2)` Average performance + +#### Space Complexity + +`O(n)` Worst case + +#### Application of algorithm + +- Cycle sort algorithm is useful for situations where memory write or element swap operations are costly. + +#### Example + +A single cycle of sorting array | b | d | e | a | c | + +``` +1. Select element for which the cycle is run, i.e. "b". + +|b|d|e|a|c| + +b - current element + +2. Find correct location for current element and update current element. + +|b|b|e|a|c| + +d - current element + +3. One more time, find correct location for current element and update current element. + +|b|b|e|d|c| + +a - current element + +4. Current element is inserted into position of initial element "b" which ends the cycle. + +|a|b|e|d|c| + +a - current element + +5. New cycle should be started for next element. +``` + +#### Video Explanation + +[A video explaining the Cycle Sort Algorithm](https://www.youtube.com/watch?v=gZNOM_yMdSQ) + +#### The Algorithms Page + +[Cycle Sort](https://the-algorithms.com/algorithm/cycle-sort) diff --git a/en/Sorting Algorithms/Heap Sort.md b/en/Sorting Algorithms/Heap Sort.md new file mode 100644 index 00000000..7b545351 --- /dev/null +++ b/en/Sorting Algorithms/Heap Sort.md @@ -0,0 +1,60 @@ +# Heap Sort + +#### Problem Statement + +Given an unsorted array of n elements, write a function to sort the array + +#### Approach + +- Build a max heap from the input data. +- At this point, the largest item is stored at the root of the heap. Replace it with the last item of the heap followed by reducing the size of heap by 1. Finally, heapify the root of tree. +- Repeat above steps while size of heap is greater than 1. + +#### Time Complexity + +`O(n log n)` Worst case performance + +`O(n log n)` (distinct keys) +or O(n) (equal keys) Best-case performance + +`O(n log n)` Average performance + +#### Space Complexity + +`O(1)` Worst case auxiliary + +#### Example + +``` +Input data: 4, 10, 3, 5, 1 + 4(0) + / \ + 10(1) 3(2) + / \ +5(3) 1(4) + +The numbers in bracket represent the indices in the array +representation of data. + +Applying heapify procedure to index 1: + 4(0) + / \ + 10(1) 3(2) + / \ +5(3) 1(4) + +Applying heapify procedure to index 0: + 10(0) + / \ + 5(1) 3(2) + / \ +4(3) 1(4) +The heapify procedure calls itself recursively to build heap +in top down manner. +``` + +![heap-image](https://upload.wikimedia.org/wikipedia/commons/1/1b/Sorting_heapsort_anim.gif "Heap Sort") + +#### Video Explanation + +[A video explaining the Heap Sort Algorithm](https://www.youtube.com/watch?v=MtQL_ll5KhQ) diff --git a/Sorting Algorithms/Insertion Sort.md b/en/Sorting Algorithms/Insertion Sort.md similarity index 65% rename from Sorting Algorithms/Insertion Sort.md rename to en/Sorting Algorithms/Insertion Sort.md index fa4cc35b..d1253151 100644 --- a/Sorting Algorithms/Insertion Sort.md +++ b/en/Sorting Algorithms/Insertion Sort.md @@ -8,19 +8,18 @@ Given an array of n elements, write a function to sort the array in increasing o - Define a "key" index, the subarray to the left of which is sorted. - Initiate "key" as 1, ie. the second element of array(as there is only one element to left of the second element, which can be considered as sorted array with one element). - -- If value of element at (key - 1) position is less than value of element at (key) position; increament "key". +- If value of element at (key - 1) position is less than value of element at (key) position; increment "key". - Else move elements of sorted subarray that are greater than value of element at "key" to one position ahead of their current position. Put the value of element at "key" in the newly created void. #### Time Complexity -О(n^2) comparisons, О(n^2) swaps -- Worst Case +- `О(n^2)` comparisons, `О(n^2)` swaps -- Worst Case -O(n) comparisons, O(1) swaps -- Best Case +- `O(n)` comparisons, `O(1)` swaps -- Best Case #### Space Complexity -O(1) -- (No extra space needed, sorting done in place) +`O(1)` -- (No extra space needed, sorting done in place) #### Example @@ -47,16 +46,7 @@ i = 4. 6 will move to position after 5, and elements from 11 to 13 will move one position ahead of their current position. 5, 6, 11, 12, 13 -- sorted array - ``` - -#### Code Implementation Links - -- [Java](https://github.com/TheAlgorithms/Java/blob/master/Sorts/InsertionSort.java) -- [C](https://github.com/TheAlgorithms/C/blob/master/sorting/InsertionSort.c) -- [C++](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/Sorting/Insertion%20Sort.cpp) -- [C#](https://github.com/TheAlgorithms/C-Sharp/blob/master/sorts/insertion_sort.cs) -- [Scala](https://github.com/TheAlgorithms/Scala/blob/master/src/main/scala/Sort/InsertionSort.scala) -- [Python](https://github.com/TheAlgorithms/Python/blob/master/sorts/insertion_sort.py) +``` #### Video Explanation diff --git a/en/Sorting Algorithms/Merge Sort.md b/en/Sorting Algorithms/Merge Sort.md new file mode 100644 index 00000000..d26b6275 --- /dev/null +++ b/en/Sorting Algorithms/Merge Sort.md @@ -0,0 +1,64 @@ +# Merge Sort (Divide and Conquer Algorithm) + +#### Problem Statement + +Given an array of n elements, write a function to sort the array + +#### Approach + +- Find a mid point and divide the array into to halves based on the mid point +- Recursively call the merge sort function for both the halves +- Merge the two sorted halves to get the sorted array + +#### Time Complexity + +``` +Best case - O(n log n) +Average - O(n log n) +Worst case - O(n log n) +``` + +#### Space Complexity + +`O(n)` + +#### Example 1 + +``` +arr = [1, 3, 9, 5, 0, 2] + +Divide the array in two halves [1, 3, 9] and [5, 0, 2] + +Recursively call merge sort function for both these halves which will provide sorted halves +=> [1, 3, 9] & [0, 2, 5] + +Now merge both these halves to get the sorted array [0, 1, 2, 3, 5, 9] +``` + +#### Example 2 + +``` +arr = [1, 9, 2, 5, 7, 3, 6, 4] + +Divide the array into two halves [1, 9, 2, 5] and [7, 3, 6, 4] + +As you can see that the above two halves are not yet sorted, so divide both of them into two halves again. + +This time we get four arrays as [1, 9], [2, 5], [7, 3] and [6, 4]. + +We see that the last two arrays are again not sorted, so we divide them again into two halves and we will get [7], [3], [6], and [4]. + +Since an array of a single element is sorted, we now have all the arrays sorted, now we only need to merge them appropriately. + +First, the arrays of one element will be merged as they were divided in last, and are at top of the recursion stack, so we get [3,7] and [4,6]. + +Now the merge will occur accordingly to the recursion stack, [1, 9] and [2, 5] will be merged and will make [1, 2, 5, 9]. + +Similarly [3, 7] and [4, 6] will be merged and made [3, 4, 6, 7]. + +At the next stack level [1, 2, 5, 9] and [3, 4, 6, 7] will be merged and we will get the final sorted array as [1, 2, 3, 4, 5, 6, 7, 9]. +``` + +#### Video Explanation + +[A CS50 video explaining the Merge Sort Algorithm](https://www.youtube.com/watch?v=EeQ8pwjQxTM) diff --git a/Sorting Algorithms/Quick Sort.md b/en/Sorting Algorithms/Quick Sort.md similarity index 65% rename from Sorting Algorithms/Quick Sort.md rename to en/Sorting Algorithms/Quick Sort.md index 564d743e..666e0c46 100644 --- a/Sorting Algorithms/Quick Sort.md +++ b/en/Sorting Algorithms/Quick Sort.md @@ -9,16 +9,16 @@ Given an unsorted array of n elements, write a function to sort the array - partition the array using pivot value - quicksort left partition recursively - quicksort right partition recursively -#### Time Complexity -O(n^2) Worst case performance +#### Time Complexity -O(n log n) Best-case performance +- `O(n^2)` Worst case performance +- `O(n log n)` Best-case performance +- `O(n log n)` Average performance -O(n log n) Average performance #### Space Complexity -O(log(n)) Worst case +`O(log n)` Worst case #### Founder's Name @@ -28,15 +28,15 @@ Tony Hoare in 1959 ``` arr[] = {10, 80, 30, 90, 40, 50, 70} -Indexes: 0 1 2 3 4 5 6 +Indexes: 0 1 2 3 4 5 6 low = 0, high = 6, pivot = arr[h] = 70 Initialize index of smaller element, i = -1 Traverse elements from j = low to high-1 j = 0 : Since arr[j] <= pivot, do i++ and swap(arr[i], arr[j]) -i = 0 -arr[] = {10, 80, 30, 90, 40, 50, 70} // No change as i and j +i = 0 +arr[] = {10, 80, 30, 90, 40, 50, 70} // No change as i and j // are same j = 1 : Since arr[j] > pivot, do nothing @@ -44,7 +44,7 @@ j = 1 : Since arr[j] > pivot, do nothing j = 2 : Since arr[j] <= pivot, do i++ and swap(arr[i], arr[j]) i = 1 -arr[] = {10, 30, 80, 90, 40, 50, 70} // We swap 80 and 30 +arr[] = {10, 30, 80, 90, 40, 50, 70} // We swap 80 and 30 j = 3 : Since arr[j] > pivot, do nothing // No change in i and arr[] @@ -52,25 +52,19 @@ j = 3 : Since arr[j] > pivot, do nothing j = 4 : Since arr[j] <= pivot, do i++ and swap(arr[i], arr[j]) i = 2 arr[] = {10, 30, 40, 90, 80, 50, 70} // 80 and 40 Swapped -j = 5 : Since arr[j] <= pivot, do i++ and swap arr[i] with arr[j] -i = 3 -arr[] = {10, 30, 40, 50, 80, 90, 70} // 90 and 50 Swapped +j = 5 : Since arr[j] <= pivot, do i++ and swap arr[i] with arr[j] +i = 3 +arr[] = {10, 30, 40, 50, 80, 90, 70} // 90 and 50 Swapped We come out of loop because j is now equal to high-1. Finally we place pivot at correct position by swapping -arr[i+1] and arr[high] (or pivot) -arr[] = {10, 30, 40, 50, 70, 90, 80} // 80 and 70 Swapped +arr[i+1] and arr[high] (or pivot) +arr[] = {10, 30, 40, 50, 70, 90, 80} // 80 and 70 Swapped Now 70 is at its correct place. All elements smaller than 70 are before it and all elements greater than 70 are after -it. - ``` - -#### Code Implementation Links - -- [Java](https://github.com/TheAlgorithms/Java/blob/master/Sorts/QuickSort.java) -- [C++](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/Sorting/Quick%20Sort.cpp) -- [Python](https://github.com/TheAlgorithms/Python/blob/master/sorts/quick_sort.py) +it. +``` #### Video Explanation diff --git a/en/Sorting Algorithms/Radix Sort.md b/en/Sorting Algorithms/Radix Sort.md new file mode 100644 index 00000000..0e474d06 --- /dev/null +++ b/en/Sorting Algorithms/Radix Sort.md @@ -0,0 +1,51 @@ +# Radix Sort + +The lower bound for Comparison based sorting algorithm (Merge Sort, Heap Sort, Quick-Sort .. etc) is `Ω(nlogn)`, i.e., they cannot do better than `nlogn`. + +Counting sort is a linear time sorting algorithm that sort in `O(n+k)` time when elements are in the range from 1 to k. + +What if the elements are in the range from 1 to n2? We can’t use counting sort because counting sort will take `O(n2)` which is worse than comparison-based sorting algorithms. Can we sort such an array in linear time? + +Radix Sort is the answer. The idea of Radix Sort is to do digit by digit sort starting from least significant digit to most significant digit. Radix sort uses counting sort as a subroutine to sort. + +## The Radix Sort Algorithm + +Do following for each digit i where i varies from least significant digit to the most significant digit. +Sort input array using counting sort (or any stable sort) according to the i’th digit. + +Example: + +Original, unsorted list: +`170, 45, 75, 90, 802, 24, 2, 66` + +Sorting by least significant digit (1s place) gives: + +[*Notice that we keep 802 before 2, because 802 occurred +before 2 in the original list, and similarly for pairs +170 & 90 and 45 & 75.] + +Sorting by next digit (10s place) gives: + +[*Notice that 802 again comes before 2 as 802 comes before 2 in the previous list.] + +`802, 2, 24, 45, 66, 170, 75, 90` + +Sorting by the most significant digit (100s place) gives: +`2, 24, 45, 66, 75, 90, 170, 802` + +## What is the running time of Radix Sort? + +Let there be d digits in input integers. Radix Sort takes `O(d*(n+b))` time where b is the base for representing numbers, for example, for the decimal system, b is 10. +What is the value of d? If `k` is the maximum possible value, then d would be `O(logb(k))`. So overall time complexity is `O((n+b) * logb(k))`. Which looks more than the +time complexity of comparison-based sorting algorithms for a large k. Let us first limit k. Let k <= nc where c is a constant. In that case, the complexity becomes +`O(n logb(n))`. But it still doesn’t beat comparison-based sorting algorithms. + +## Is Radix Sort preferable to Comparison based sorting algorithms like Quick-Sort? + +If we have `log2n` bits for every digit, the running time of Radix appears to be better than Quick Sort for a wide range of input numbers. The constant factors hidden in +asymptotic notation are higher for Radix Sort and Quick-Sort uses hardware caches more effectively. Also, Radix sort uses counting sort as a subroutine and counting sort +takes extra space to sort numbers. + +#### Video Explanation + +Video reference: https://youtu.be/nu4gDuFabIM diff --git a/en/Sorting Algorithms/Recursive Versions/Recursive Bubble Sort.md b/en/Sorting Algorithms/Recursive Versions/Recursive Bubble Sort.md new file mode 100644 index 00000000..0c66b6b6 --- /dev/null +++ b/en/Sorting Algorithms/Recursive Versions/Recursive Bubble Sort.md @@ -0,0 +1,68 @@ +# Recursive Bubble Sort + +Bubble Sort is one of the simplest sorting algorithms that compares two elements at a time and swaps them if they are in the wrong order. This process is repeated until the entire sequence is in order. + +- Time Complexity: `O(n ^ 2)` for average case; `O(n)` for best case. +- Space Complexity: `O(n)`; note that iterative bubble sort has space complexity as `O(1)`. + +## Steps + +Base case: If the size of the array is 1, return. + +- We need to fix the last element of the current sub-array. For this, iterate over the entire array using normal Bubble Sort, and perform swapping. +- Next, call the function on the entire array excluding the last element(which was fixed by the iteration in the above step) +- Repeat until Base Case is reached. + +## Example + +Let the given array be: `{5, 3, 2, 1, 4}` + +**First Iteration:** + +- {`5`, `3`, 2, 1, 4} -> {`3`, `5`, 2, 1, 4} Swap since `5 > 3` +- {3, `5`, `2`, 1, 4} -> {3, `2`, `5`, 1, 4} Swap since `5 > 2` +- {3, 2, `5`, `1`, 4} -> {3, 2, `1`, `5`, 4} Swap since `5 > 1` +- {3, 2, 1, `5`, `4`} -> {3, 2, 1, `4`, `5`} Swap since `5 > 4` + +This iteration has fixed the position of 5. Now, we will consider the array up to index 3. + +**Second Iteration:** + +- {`3`, `2`, 1, 4, 5} -> {`2`, `3`, 1, 4, 5} Swap since `3 > 2` +- {2, `3`, `1`, 4, 5} -> {2, `1`, `3`, 4, 5} Swap since `3 > 1` +- {2, 1, `3`, `4`, 5}; As `3 < 4`, do not swap + +Note: As we check one less element with every iteration, we do not need elements at index 3 and 4 i.e., `4` and `5`, as 5 is already in order. Formally, for an array with `n` integers, we consider elements only up to index `n - i`, where `i` is the iteration number. + +**Third Iteration:** + +- {`2`, `1`, 3, 4, 5} -> {`1`, `2`, 3, 4, 5} Swap since `1 > 2` +- {1, `2`, `3`, 4, 5}; As `2 < 3`, do not swap + +**Fourth Iteration:** + +- {`1`, `2`, 3, 4, 5}; As `1 < 2`, do not swap + +**Fifth Iteration:** + +- {`1`, 2, 3, 4, 5}; As the size of the array is 1, return. + +Note: This is the base case. + +## Pseudo Code + +``` +void bubbleSort(arr[], n) + if(n==1) + return; + + for(i = 0; i arr[i+1]) + swap(arr[i], arr[i+1]) + + bubbleSort(arr, n-1) +``` + +## Video Explanation + +[A video explaining iterative as well as recursive bubble sort](https://www.youtube.com/watch?v=gDMDVLBfCI0) diff --git a/Sorting Algorithms/Selection Sort.md b/en/Sorting Algorithms/Selection Sort.md similarity index 57% rename from Sorting Algorithms/Selection Sort.md rename to en/Sorting Algorithms/Selection Sort.md index f1a22a0a..713b2d41 100644 --- a/Sorting Algorithms/Selection Sort.md +++ b/en/Sorting Algorithms/Selection Sort.md @@ -15,16 +15,15 @@ Given an unsorted array of n elements, write a function to sort the array #### Time Complexity -O(n^2) Worst case performance +`O(n^2)` Worst case performance -O(n^2) Best-case performance +`O(n^2)` Best-case performance -O(n^2) Average performance +`O(n^2)` Average performance #### Space Complexity -O(1) Worst case - +`O(1)` Worst case #### Example @@ -32,7 +31,7 @@ O(1) Worst case arr[] = {80, 10, 40, 30} Indexes: 0 1 2 3 -1. Index = 0 +1. Index = 0 Select the minimum number from the array (between index 0-3), ie, 10 2. Swap 10 and 80 (arr[0]) 3. The array now is {10, 80, 40, 30} @@ -47,27 +46,13 @@ Indexes: 0 1 2 3 8. Swap 40 and 40 (arr[2]) 9. The array now is {10, 30, 40, 80} - The array is now sorted. - ``` - - -#### Code Implementation Links - -- [Java](https://github.com/TheAlgorithms/Java/blob/master/Sorts/SelectionSort.java) -- [C++](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/Sorting/Selection%20Sort.cpp) -- [Python](https://github.com/TheAlgorithms/Python/blob/master/sorts/selection_sort.py) -- [Go](https://github.com/TheAlgorithms/Go/blob/master/sorts/selection_sort.go) -- [Ruby](https://github.com/TheAlgorithms/Ruby/blob/master/Sorting/selection_sort.rb) -- [C](https://github.com/TheAlgorithms/C/blob/master/sorting/SelectionSort.c) -- [Scala](https://github.com/TheAlgorithms/Scala/blob/master/src/main/scala/Sort/SelectionSort.scala) -- [Javascript](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/selectionSort.js) - +The array is now sorted. +``` #### Video Explanation [A video explaining the Selection Sort Algorithm](https://www.youtube.com/watch?v=f8hXR_Hvybo) - #### Animation Explanation - [Tute Board](https://boardhub.github.io/tute/?wd=selectSortAlgo2) diff --git a/Sorting Algorithms/Shell Sort.md b/en/Sorting Algorithms/Shell Sort.md similarity index 60% rename from Sorting Algorithms/Shell Sort.md rename to en/Sorting Algorithms/Shell Sort.md index 11bfe227..94b94060 100644 --- a/Sorting Algorithms/Shell Sort.md +++ b/en/Sorting Algorithms/Shell Sort.md @@ -13,18 +13,18 @@ Given an unsorted array of n elements, write a function to sort the array - decrease the gap and repeat until gap = 1 #### Time Complexity -Time complexity is dependent on the gap sequences. +Time complexity is dependent on the gap sequences. Below time complexities are based on the gap sequences of n/2^k. -O(n^2) Worst case performance +`O(n^2)` Worst case performance -O(n) Best-case performance +`O(n)` Best-case performance -O(n^2) Average performance +`O(n^2)` Average performance #### Space Complexity -O(1) Worst case +`O(1)` Worst case #### Founder's Name @@ -52,21 +52,7 @@ Initial Gap: 4 11. 111 < 119, do nothing and continue 12. Divide the gap by 2 and repeat until gap = 1 - - ``` - - -#### Code Implementation Links - -- [Java](https://github.com/TheAlgorithms/Java/blob/master/Sorts/ShellSort.java) -- [C++](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/Sorting/Shell%20Sort.cpp) -- [Python](https://github.com/TheAlgorithms/Python/blob/master/sorts/shell_sort.py) -- [C-Sharp](https://github.com/TheAlgorithms/C-Sharp/blob/master/sorts/shell_sort.cs) -- [Go](https://github.com/TheAlgorithms/Go/blob/master/sorts/shell_sort.go) -- [Ruby](https://github.com/TheAlgorithms/Ruby/blob/master/Sorting/shell_sort.rb) -- [C](https://github.com/TheAlgorithms/C/blob/master/sorting/shellSort.c) -- [Javascript](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/shellSort.js) - +``` #### Video Explanation diff --git a/es/Algoritmos de Ordenamiento/Ordenamiento Burbuja.md b/es/Algoritmos de Ordenamiento/Ordenamiento Burbuja.md new file mode 100644 index 00000000..2e1b0be4 --- /dev/null +++ b/es/Algoritmos de Ordenamiento/Ordenamiento Burbuja.md @@ -0,0 +1,92 @@ +# Bubble Sort + +#### Planteamiento del problema + +Dado un arreglo desordenado de n elementos, escribir una función que ordene el arreglo. + +#### Procedimiento + +- Seleccionar el primer elemento del arreglo. +- Comparar con el elemento siguiente. +- Si es más grande que el elemento siguiente se intercambian. +- Sino no se hace nada. +- Realizar las operaciones anteriores para cada elemento del arreglo. +- Repetir el procedimiento descrito n veces. + +#### Complejidad temporal + +`O(n^2)` Rendimiento en el peor de los casos + +`O(n)` Rendimiento en el mejor de los casos + +`O(n^2)` Rendimiento promedio + +#### Complejidad espacial + +`O(1)` Peor caso + +#### Nombre del creador del algoritmo + +- + +#### Ejemplo + +``` +arreglo[] = {10, 80, 40, 30} +Indices: 0 1 2 3 + +1. Indice = 0, Numero = 10 +2. 10 < 80, No se hace nada. Continuar + +3. Indice = 1, Numero = 80 +4. 80 > 40, intercambiar 80 y 40 +5. El arreglo ahora es {10, 40, 80, 30} + +6. Indice = 2, Numero = 80 +7. 80 > 30, intercambiar 80 y 30 +8. El arreglo ahora es {10, 40, 30, 80} + +Repetir los pasos de arriba. + +arreglo[] = {10, 40, 30, 80} +Indices: 0 1 2 3 + +1. Indice = 0, Numero = 10 +2. 10 < 40, No se hace nada. Continuar + +3. Indice = 1, Numero = 40 +4. 40 > 30, intercambiar 40 y 30 +5. El arreglo ahora es {10, 30, 40, 80} + +6. Indice = 2, Numero = 40 +7. 40 < 80, No se hace nada. Continuar +8. El arreglo ahora es {10, 30, 40, 80} + +Repetir los pasos de arriba. + +arreglo[] = {10, 30, 40, 80} +Indices: 0 1 2 3 + +1. Indice = 0, Numero = 10 +2. 10 < 30, No se hace nada. Continuar + +3. Indice = 1, Numero = 30 +4. 30 < 40, No se hace nada. Continuar + +5. Indice = 2, Numero = 40 +6. 40 < 80, No se hace nada + +Como no hay intercambios en los pasos de arriba, el arreglo ya se ha ordenado y nos podemos detener. +``` + +#### Explicación en video + +[Un video explicando el Algoritmo de Ordenamiento Burbuja](https://www.youtube.com/watch?v=EQMGabLO_M0) + +#### Otros + +El Ordenamiento Burbuja también es conocido como Sinking sort. + +#### Explicación animada + +- [Tablero Tute](https://boardhub.github.io/tute/?wd=bubbleSortAlgo2) diff --git a/es/Algoritmos de Ordenamiento/Ordenamiento Radix.md b/es/Algoritmos de Ordenamiento/Ordenamiento Radix.md new file mode 100644 index 00000000..5e9cce2d --- /dev/null +++ b/es/Algoritmos de Ordenamiento/Ordenamiento Radix.md @@ -0,0 +1,48 @@ +# Ordenamiento Radix + +El límite inferior para el algoritmo de ordenación basado en comparación (Orden de fusión, Ordenación de montón, Ordenación rápida, etc.) es `Ω(nlogn)`, es decir, no pueden hacerlo mejor que `nlogn`. + +La ordenación del recuento es un algoritmo de ordenación de tiempo lineal que ordena en el tiempo `O(n+k)` cuando los elementos están en el rango de 1 a k. + +¿Qué sucede si los elementos están en el rango de 1 a n2? No podemos usar la ordenación de recuento, porque la ordenación de recuento tomará `O(n2)`, que es peor que los algoritmos de clasificación basados en comparación. ¿Podemos ordenar una matriz de este tipo en tiempo lineal? + +Radix Sort es la respuesta. La idea de Radix Sort es hacer orden dígito por dígito a partir de un dígito menos significativo a un dígito más significativo. La ordenación de radios utiliza la ordenación de recuento como subrutina para ordenar. + +## El algoritmo de ordenación de radios + +Haga lo siguiente para cada dígito i donde varía de un dígito menos significativo al dígito más significativo. +Ordene la matriz de entrada mediante la ordenación de recuento (o cualquier ordenación estable) según el dígito i'th. + +Ejemplo: + +Lista original y no ordenada: +`170, 45, 75, 90, 802, 24, 2, 66` + +Ordenar por el dígito menos significativo (lugar 1s) da: + +[*Observe que mantenemos el 802 antes de las 2, porque ocurrió el 802 +antes de 2 en la lista original, y de manera similar para los pares +170 &90 y 45 &75.] + +Ordenar por el siguiente dígito (lugar de los años 10) da: + +[*Observe que 802 de nuevo viene antes de 2 como 802 viene antes de 2 en la lista anterior.] + +`802, 2, 24, 45, 66, 170, 75, 90` + +La clasificación por el dígito más significativo (lugar de los años 100) da: +`2, 24, 45, 66, 75, 90, 170, 802` + +## ¿Cuál es el tiempo de ejecución de Radix Sort? + +Deje que haya dígitos `d` en los enteros de entrada. Radix Sort toma `O(d*(n+b))` tiempo donde `b` es la base para representar números, por ejemplo, para el sistema decimal, `b` es 10. +¿Cuál es el valor de `d`? Si `k` es el valor máximo posible, entonces sería `O(logb(k))`. Así que la complejidad general temporal es `O((n+b) * logb(k))`. Lo que parece más que el +complejidad temporal de algoritmos de ordenación basados en comparación para una `k` grande. Limitemos primero `k`. Deje `k <= nc` donde `c` es una constante. En ese caso, la complejidad se convierte en +`O(n logb(n))`. Pero todavía no supera los algoritmos de clasificación basados en comparación. + +## ¿Radix Sort es preferible a algoritmos de ordenación basados en comparación como Quick-Sort? + +Si, tenemos bits `log2n` para cada dígito, el tiempo de ejecución de Radix parece ser mejor que la ordenación rápida para una amplia gama de números de entrada. Los factores constantes ocultos en la notación asintótica, son mayores para Radix Sort y Quick-Sort que utiliza cachés de hardware de forma más eficaz. Además, Radix sort utiliza la ordenación de recuento como una subrutina y la ordenación de recuento +necesita espacio adicional para ordenar los números. + +**Vídeo de referencia:** https://youtu.be/nu4gDuFabIM diff --git a/es/Algoritmos de Ordenamiento/Ordenamiento Shell.md b/es/Algoritmos de Ordenamiento/Ordenamiento Shell.md new file mode 100644 index 00000000..3c4aa1e7 --- /dev/null +++ b/es/Algoritmos de Ordenamiento/Ordenamiento Shell.md @@ -0,0 +1,64 @@ +# Ordenamiento Shell + +#### Declaración de problema + +Dada una matriz no ordenada de `n` elementos, escriba una función para ordenar la matriz. + +#### Enfoque + +- Empezar con la brecha inicial, `g` +- Ir a través de los primeros `(n - g)` elementos en la matriz +- Comparar el elemento con el siguiente elemento que está a una distancia `g` +- Intercambiar los dos elementos si el primer elemento es más grande +- Disminuir la brecha y repetir hasta la brecha = 1 + +#### Complejidad temporal + +La complejidad temporal depende de las secuencias de separación. +Las complejidades de tiempo inferior se basan en las secuencias de separación de `n/2^k`. + +`O(n^2)` Peor rendimiento en el caso + +`O(n)` Mejor actuación en el caso + +`O(n^2)` Rendimiento medio + +#### Complejidad espacial + +`O(1)` El peor caso + +#### Nombre del Fundador + +Donald Shell + +#### Ejemplo + +```markdown +arr[] = {61, 109, 149, 111, 34, 2, 24, 119} +Brecha inicial: 4 + +1. Índice = 0, Siguiente índice de elementos = 4 +2. 61 > 34, swap 61 y 34 +3. La matriz es ahora {34, 109, 149, 111, 61, 2, 24, 119} + +4. Índice = 1, Siguiente índice de elementos = 5 +5. 109 > 2, swap 109 y 2 +6. La matriz es ahora {34, 2, 149, 111, 61, 109, 24, 119} + +7. Índice = 2, Siguiente índice de elementos = 6 +8. 149 > 24, swap 149 y 24 +9. La matriz es ahora {34, 2, 24, 111, 61, 109, 149, 119} + +10. Índice = 3, Siguiente índice de elementos = 7 +11. 111 < 119, no hagan nada y continúen + +12. Divida la brecha por 2 y repita hasta la brecha = 1 +``` + +#### Explicación de vídeo + +[Un vídeo explicando el algoritmo del ordenamiento de Shell](https://www.youtube.com/watch?v=H8NiFkGu2PY) + +#### Otros + +La ordenación del shell también se conoce como clasificación de incremento de disminución. diff --git "a/es/Algoritmos de Ordenamiento/Ordenamiento de fusi\303\263n.md" "b/es/Algoritmos de Ordenamiento/Ordenamiento de fusi\303\263n.md" new file mode 100644 index 00000000..02df6850 --- /dev/null +++ "b/es/Algoritmos de Ordenamiento/Ordenamiento de fusi\303\263n.md" @@ -0,0 +1,36 @@ +# Ordenamiento de fusión (dividir y conquistar algoritmo) + +#### Declaración de problema + +Dada una matriz de n elementos, escriba una función para ordenar la matriz + +#### Enfoque + +- Encontrar un punto medio y dividir la matriz en mitades basadas en el punto medio +- Llamar recursivamente a la función de ordenación de fusión para las dos mitades +- Combinar las dos mitades ordenadas para obtener la matriz ordenada + +#### Complejidad temporal + +`O(n log n)` + +#### Complejidad espacial + +`O(n)` + +#### Ejemplo + +```markdown +arr = [1, 3, 9, 5, 0, 2] + +Divida la matriz en dos mitades [1, 3, 9] y [5, 0, 2] + +Vuelva a llamar a la función de ordenación de combinación de llamadas para estas dos mitades, lo que proporcionará mitades ordenadas +=> [1, 3, 9] & [0, 2, 5] + +Ahora combine ambas mitades para obtener la matriz ordenada [0, 1, 2, 3, 5, 9] +``` + +#### Explicación de vídeo + +[Un vídeo CS50 que explica el algoritmo de ordemaniento de fusión](https://www.youtube.com/watch?v=EeQ8pwjQxTM) diff --git "a/es/Algoritmos de Ordenamiento/Ordenamiento de inserci\303\263n.md" "b/es/Algoritmos de Ordenamiento/Ordenamiento de inserci\303\263n.md" new file mode 100644 index 00000000..20a9d11d --- /dev/null +++ "b/es/Algoritmos de Ordenamiento/Ordenamiento de inserci\303\263n.md" @@ -0,0 +1,52 @@ +# Ordenación de inserción + +#### Declaración de problema + +Dada una matriz de `N` elementos, escriba una función para ordenar la matriz en orden creciente. + +#### Enfoque + +- Definir un índice "clave", el subarray a la izquierda de los cuales se ordena. +- Iniciar "clave" como 1, es decir. el segundo elemento de array(ya que solo queda un elemento del segundo elemento, que se puede considerar como matriz ordenada con un elemento). +- Si el valor del elemento en la posición (clave - 1) es menor que el valor del elemento en la posición (clave); incremento "clave". +- De lo contrario, mueva elementos de subarray ordenados que sean mayores que el valor del elemento en "clave" a una posición por delante de su posición actual. Coloque el valor del elemento en "clave" en el vacío recién creado. + +#### Complejidad temporal + +- Comparaciones `О(n^2)`, intercambia `О(n^2)` -- Peor caso +- Comparaciones `O(n)`, intercambia `O(1)` -- Mejor caso + +#### Complejidad espacial + +`O(1)` -- (No se necesita espacio adicional, clasificación hecha en su lugar) + +#### Ejemplo + +```markdown + +12, 11, 13, 5, 6 + +Vamos a bucle para i = 1 (segundo elemento de la matriz) a 4 (Tamaño de la matriz de entrada) + +i = 1. +Dado que 11 es menor que 12, mueva 12 e inserte 11 antes de 12 +11, 12, 13, 5, 6 + +i = 2. +13 permanecerán en su posición, ya que todos los elementos en subarray ordenado son menores de 13 +11, 12, 13, 5, 6 + +i = 3. +5 se moverá al principio, +y todos los demás elementos de 11 a 13 se moverán una posición por delante de su posición actual. +5, 11, 12, 13, 6 + +i = 4. +6 se moverá a la posición después de 5, +y los elementos del 11 al 13 se moverán una posición por delante de su posición actual. +5, 6, 11, 12, 13 -- matriz ordenada +``` + +#### Explicación de vídeo + +[Un vídeo CS50 que explica el algoritmo de Ordenamiento de inserción](https://www.youtube.com/watch?v=DFG-XuyPYUQ) diff --git "a/es/Algoritmos de Ordenamiento/Ordenamiento de mont\303\263n (heap sort).md" "b/es/Algoritmos de Ordenamiento/Ordenamiento de mont\303\263n (heap sort).md" new file mode 100644 index 00000000..2732ff73 --- /dev/null +++ "b/es/Algoritmos de Ordenamiento/Ordenamiento de mont\303\263n (heap sort).md" @@ -0,0 +1,60 @@ +# Heap sort + +### Declaración de problema + +Dada una matriz no ordenada de `N` elementos, escriba una función para ordenar la matriz. + +#### Enfoque + +- Construir un montón máximo a partir de los datos de entrada. +- En este punto, el elemento más grande se almacena en la raíz del montón. Reemplácelo por el último elemento del montón seguido de reducir el tamaño del montón en 1. Finalmente, amontonar la raíz del árbol. +- Repita los pasos anteriores mientras que el tamaño del montón es mayor que 1. + +#### Complejidad temporal + +`O(n log n)` Peor rendimiento del caso + +`O(n log n)` (claves distintas) +o `O(n)` (teclas iguales) Rendimiento en el mejor de los casos + +`O(n log n)` Rendimiento medio + +#### Complejidad espacial + +`O(1)` Peor caso auxiliar + +#### Ejemplo + +``` +Datos de entrada: 4, 10, 3, 5, 1 + 4(0) + / + 10(1) 3(2) + / + 5(3) 1(4) + +Los números del corchete representan los índices de la matriz +representación de datos. + +Aplicación del procedimiento de amontonación al índice 1: + 4(0) + / + 10(1) 3(2) + / +5(3) 1(4) + +Aplicación del procedimiento de amontonación al índice 0: + 10(0) + / + 5(1) 3(2) + / + 4(3) 1(4) +El procedimiento de amontonar se llama a sí mismo recursivamente para construir el montón + de la manera de arriba hacia abajo. +``` + +![imagen del montón](https://upload.wikimedia.org/wikipedia/commons/1/1b/Sorting_heapsort_anim.gif "Heap sort") + +#### Explicación de vídeo + +[Un vídeo explicando el algoritmo de ordenamiento de montón (heap sort)](https://www.youtube.com/watch?v=MtQL_ll5KhQ) diff --git "a/es/Algoritmos de Ordenamiento/Ordenamiento de selecci\303\263n.md" "b/es/Algoritmos de Ordenamiento/Ordenamiento de selecci\303\263n.md" new file mode 100644 index 00000000..8aaa49cb --- /dev/null +++ "b/es/Algoritmos de Ordenamiento/Ordenamiento de selecci\303\263n.md" @@ -0,0 +1,58 @@ +# Ordenamiento de selección + +#### Declaración de problema + +Dada una matriz no ordenada de `N` elementos, escriba una función para ordenar la matriz. + +#### Enfoque + +- Seleccione el elemento más pequeño de la matriz +- Ponerlo al principio de la matriz +- A continuación, seleccione la matriz más pequeña de la lista no ordenada restante +- Anexarlo a la matriz ordenada al principio +- Seguir haciendo esto para cada elemento de la matriz +- Repetir el proceso anterior n veces + +#### Complejidad temporal + +`O(n^2)` Peor rendimiento en el caso + +`O(n^2)` Mejor rendimiento en el caso + +`O(n^2)` Rendimiento medio + +#### Complejidad espacial + +`O(1)` El peor caso + +#### Ejemplo + +```markdown +arr[] = {80, 10, 40, 30} +Índices: 0 1 2 3 + +1. Índice = 0 + Seleccione el número mínimo de la matriz (entre el índice 0-3), es decir, 10 +2. Intercambio 10 y 80 (arr[0]) +3. La matriz ahora es {10, 80, 40, 30} + +4. Índice = 1 + Seleccione el número mínimo de la matriz (entre el índice 1-3), es decir, 30 +5. Intercambio 30 y 80 (arr[1]) +6. La matriz ahora es {10, 30, 40, 80} + +7. Índice = 2 + Seleccione el número mínimo de la matriz (entre el índice 2-3), es decir, 40 +8. Intercambio 40 y 40 (arr[2]) +9. La matriz ahora es {10, 30, 40, 80} + +La matriz ahora está ordenada. +``` + +#### Explicación de vídeo + +[Un vídeo explicando el algoritmo de Ordenamiento de selección](https://www.youtube.com/watch?v=f8hXR_Hvybo) + +#### Explicación de animación + +- [Tabla de tute](https://boardhub.github.io/tute/?wd=selectSortAlgo2) diff --git "a/es/Algoritmos de Ordenamiento/Ordenamiento r\303\241pido.md" "b/es/Algoritmos de Ordenamiento/Ordenamiento r\303\241pido.md" new file mode 100644 index 00000000..62c9dfd9 --- /dev/null +++ "b/es/Algoritmos de Ordenamiento/Ordenamiento r\303\241pido.md" @@ -0,0 +1,72 @@ +# Ordenación rápida + +#### Declaración de problema + +Dada una matriz no ordenada de n elementos, escriba una función para ordenar la matriz + +#### Enfoque + +- Hacer el pivote de valor de índice más correcto +- particionar la matriz utilizando el valor de pivote +- quicksort partición izquierda recursivamente +- quicksort partición derecha recursivamente + +#### Complejidad temporal + +- `O(n^2)` Peor rendimiento en el caso +- `O(n log n)` Mejor rendimiento en el caso +- `O(n log n)` Rendimiento medio + +#### Complejidad espacial + +`O(log n)` El peor caso + +#### Nombre del Fundador + +Tony Hoare, en 1959 + +#### Ejemplo + +```markdown +arr[] = {10, 80, 30, 90, 40, 50, 70} +Índices: 0 1 2 3 4 5 6 + +bajo = 0, alto = 6, pivote = arr[h] = 70 +Inicializar el índice de elemento más pequeño, i = -1 + +Atravesar elementos de j = bajo a alto-1 +j = 0 : Desde arr[j] <= pivote, hacer i++ e swap(arr[i], arr[j]) +i = 0 +arr[] = {10, 80, 30, 90, 40, 50, 70} // Ningún cambio como i y j + son los mismos + +j = 1 : Desde arr[j] > pivote, no hagas nada +Sin cambios en i y arr[] + +j = 2 : Desde arr[j] <= pivote, hacer i++ e swap(arr[i], arr[j]) +i = 1 +arr[] = {10, 30, 80, 90, 40, 50, 70} // Intercambiamos 80 y 30 + +j = 3 : Desde arr[j] > pivote, no hagas nada +Sin cambios en i y arr[] + +j = 4 : Desde arr[j] <= pivote, hacer i++ e swap(arr[i], arr[j]) +i = 2 +arr[] = {10, 30, 40, 90, 80, 50, 70} // 80 y 40 Intercambiados +j = 5 : Desde arr[j] <= pivote, haga i++ e intercambie arr[i] con arr[j] +i = 3 +arr[] = {10, 30, 40, 50, 80, 90, 70} // 90 y 50 Intercambiados + +Salimos del bucle porque j es ahora igual a high-1. +Finalmente colocamos pivote en la posición correcta intercambiando +arr[i+1] y arr[high] (o pivote) +arr[] = {10, 30, 40, 50, 70, 90, 80} // 80 y 70 Intercambiados + +Ahora 70 está en su lugar correcto. Todos los elementos más pequeños que +70 están antes y todos los elementos mayores de 70 años están después +eso. +``` + +#### Explicación de vídeo + +[Un vídeo explicando el algoritmo de ordenamiento rápido](https://www.youtube.com/watch?v=COk73cpQbFQ) diff --git "a/es/Algoritmos de b\303\272squeda/B\303\272squeda binaria.md" "b/es/Algoritmos de b\303\272squeda/B\303\272squeda binaria.md" new file mode 100644 index 00000000..089c1566 --- /dev/null +++ "b/es/Algoritmos de b\303\272squeda/B\303\272squeda binaria.md" @@ -0,0 +1,47 @@ +# Búsqueda binaria (un algoritmo de divide y vencerás) + +#### Declaración de problema + +Dada una matriz ordenada de `n` elementos, escriba una función para buscar el índice de un elemento determinado (destino). + +#### Enfoque + +- Se busca la matriz dividiendo la matriz por la mitad repetidamente. +- Inicialmente, se considera la matriz real y se selecciona el elemento en el índice medio. +- Se mantiene el índice más bajo, el número 0, y el más alto, la longitud de la matriz. +- Si es igual al elemento de destino, se devuelve el índice. +- De lo contrario, si es mayor que el elemento de destino, se condiera únicamente la mitad izquierda de la matriz (índice inferior = 0, superior = medio - 1). +- De lo contrario, si es menor que el elemento de destino, se considera únicamente la mitad derecha de la matriz (índice inferior = medio + 1, más alto = longitud de la matriz). +- Se devuelve -1 si el elemento de destino no se encuentra en la matriz (caso base: si el índice inferior es mayor o igual que el índice superior). + +#### Complejidad temporal + +`O(log n)`- En el peor de los casos +`O(1)`- En el mejor de los casos (Si el elemento central de la matriz inicial es el elemento de destino) + +#### Complejidad espacial + +`O(1)`- Para un enfoque iterativo +`O(log n)`- Para un enfoque recursivo debido a la pila de llamadas de recursividad + +#### Ejemplo + +``` +arr = [1,2,3,4,5,6,7] + +target = 2 +Inicialmente, el elemento en el índice medio es 4, que es mayor que 2. Por lo tanto, buscamos la mitad izquierda de la +matriz, es decir: [1,2,3]. +Aquí encontramos el elemento central igual al elemento objetivo, por lo que devolvemos su índice: 1 + +target = 9 +Búsqueda binaria debe devolver -1 dado que 9 no está presente en la matriz +``` + +#### Explicación en vídeo de YouTube + +[Un vídeo CS50 explicando el algoritmo de búsqueda binaria](https://www.youtube.com/watch?v=5xlIPT1FRcA) + +#### Explicación de animación + +- [Tute Board](https://boardhub.github.io/tute/?wd=binarySearchAlgo2) diff --git "a/es/Algoritmos de b\303\272squeda/B\303\272squeda exponencial.md" "b/es/Algoritmos de b\303\272squeda/B\303\272squeda exponencial.md" new file mode 100644 index 00000000..dbddf8c1 --- /dev/null +++ "b/es/Algoritmos de b\303\272squeda/B\303\272squeda exponencial.md" @@ -0,0 +1,55 @@ +# Búsqueda exponencial + +#### Requisitos previos + +- [Algoritmo de búsqueda binaria](Búsqueda%20binaria.md) + +#### Declaración de problema + +Dada una matriz ordenada de *`n`* elementos, escriba una función para buscar el índice de un elemento determinado (destino) + +#### Enfoque + +- Búsqueda del **rango** dentro del cual se incluye el objetivo aumentando *index* por poderes de 2 +- Si este rango existe en la matriz aplicar el algoritmo de búsqueda binaria sobre él +- Más retorno -1 + +#### Ejemplo + +```markdown +arr = [1, 2, 3, 4, 5, 6, 7, ... 998, 999, 1_000] + +objetivo = 998 +índice = 0 +1. BÚSQUEDA DEL RANGO +índice = 1, 2, 4, 8, 16, 32, 64, ..., 512, ..., 1_024 +después de 10 iteración tenemos el índice en 1_024 y fuera de la matriz +2. BÚSQUEDA BINARIA +Ahora podemos aplicar la búsqueda binaria en el subarray de 512 y 1_000. +``` + +**Nota**: aplicamos la búsqueda binaria de 512 a 1_000 porque en `i = 2^10 = 1_024` la matriz está finisced y el número de destino es menor que el índice más reciente de la matriz ( 1_000 ). + +#### Complejidad temporal + +**Peor caso:** `O(log *i*)` donde `*i* = índice` (posición) del objetivo + +**Mejor caso:** `O(*1*)` + +#### Explicación de complejidad + +- La complejidad de la primera parte del algoritmo es **`O( log *i* )`** porque si *i* es la posición del destino en la matriz, después de duplicar la búsqueda *index* `⌈log(i)⌉` veces, el algoritmo estará en un índice de búsqueda que es mayor o igual que *i*. Podemos escribir `2^⌈log(i)⌉ >= i` +- La complejidad de la segunda parte del algoritmo también es **`O ( log *i* )`** porque se trata de una simple búsqueda binaria. La complejidad de búsqueda binaria ( como se explica [aquí](Búsqueda%20binaria.md) ) es `O(*n*)` donde *n* es la longitud de la matriz. En la búsqueda exponencial, la longitud de la matriz en la que se aplica el algoritmo es `2^i - 2^(i-1)`, en palabras significa `(la longitud de la matriz de principio a *i* ) - (la parte de matriz omitida hasta la iteración anterior)`. Es simple verificar que `2^i - 2^(i-1) = 2^(i-1)`. + +Después de esta explicación detallada, podemos decir que la complejidad de la búsqueda exponencial es: + +```mathematica +O(log i) + O(log i) = 2O(log i) = O(log i) +``` + +#### Búsqueda binaria vs Búsqueda exponencial + +Echemos un vistazo a esta comparación con un ejemplo menos teórico. Imagine que tenemos una matriz con elementos `1_000_000` y queremos buscar un elemento que esté en la posición `4th`. Es fácil ver que: + +- La búsqueda binaria comienza desde el centro de la matriz y llega a la 4ª posición después de muchas iteraciones +- La búsqueda exponencial llega al 4º índice después de sólo 2 iteraciones diff --git "a/es/Algoritmos de b\303\272squeda/B\303\272squeda lineal.md" "b/es/Algoritmos de b\303\272squeda/B\303\272squeda lineal.md" new file mode 100644 index 00000000..1e86ff63 --- /dev/null +++ "b/es/Algoritmos de b\303\272squeda/B\303\272squeda lineal.md" @@ -0,0 +1,42 @@ +# Búsqueda lineal + +#### Declaración de problema + +Dada una matriz de `n` elementos, escriba una función para buscar el índice de un elemento determinado (destino) + +#### Enfoque + +- Comience a iterar con el primer elemento de la matriz. +- Compararlo con el elemento objetivo. +- Si es igual al elemento de destino, devuelva el índice. +- De lo contrario, continúe iterando. +- Devolver -1 si el elemento de destino no se encuentra en la matriz. + +#### Complejidad temporal + +`O(n)` Peor caso +`O(1)` Mejor caso (Si el primer elemento de matriz es el elemento de destino) + +#### Complejidad espacial + +`O(1)` + +#### Ejemplo + +``` +arr = [1, 3, 9, 5, 0, 2] + +target = 5 +La búsqueda lineal debe devolver el índice 3, ya que 5 está en el índice 3. + +target = 6 +La búsqueda lineal debe devolver -1 ya que 6 no está presente en la matriz +``` + +#### Explicación en YouTube + +[Un vídeo CS50 que explica el algoritmo de búsqueda lineal](https://www.youtube.com/watch?v=CX2CYIJLwfg) + +#### Explicación de animación + +- [Tute Board](https://boardhub.github.io/tute/?wd=linearSearchAlgo) diff --git "a/es/Algoritmos de selecci\303\263n/Selecci\303\263n R\303\241pida.md" "b/es/Algoritmos de selecci\303\263n/Selecci\303\263n R\303\241pida.md" new file mode 100644 index 00000000..d15428ee --- /dev/null +++ "b/es/Algoritmos de selecci\303\263n/Selecci\303\263n R\303\241pida.md" @@ -0,0 +1,44 @@ +# Selección rápida o Quick Select + +## Definición del problema + +Dada una matriz, encontrar el k-ésimo elemento mayor y menor con un una complejidad lineal de Tiempo + +## Enfoque + +- Selecciona un elemento que sirva de pivote aleatoriamente. +- Aplica particiones como las utilizadas en el algoritmo de ordenamiento rápido o quick sort. +- Después de realizar las particiones, el pivote se deberá colocar en su posición ordenada. Todos los elementos menores que el pivote quedarán a su izquierda y los mayores a su derecha. +- Si el índice del pivote ordenado es k, entonces el pivote está en su k-ésimo elemento y devolveremos el número. +- De otro modo, verifica si 'k' es mayor o menor y selecciona un nuevo pivote en el rango. +- Repite los pasos hasta conseguir el k-ésimo elemento en la k-ésima posición. + +## Complejidad temporal + +- `O(n^2)` En el peor de los casos + +- `O(n)` En el mejor de los casos + +- `O(n)` Rendimiento promedio + +## Nombre de su fundador + +- Este algoritmo fue desarrollado por Tony Hoare. También es conocido como el 'Algoritmo de Selección de Hoare'. + +## Ejemplo + +``` +Matriz[] = {8,2,11,7,9,1,3} +Índices: 0 1 2 3 4 5 6 + +Digamos que k = 4 y tenemos que encontrar el cuarto elemento menor: + +1. Escogiendo un pivote de forma aleatoria, obtenemos 7. +2. Intercambiamos 7 con el último elemento y aplicamos el algoritmo de particionado. +3. Después de aplicar la partición, todos los elementos menores que 7 se colocan a la izquierda y los mayores, a la derecha. +4. Como la posición de '7' es la cuarta, simplemente devolveremos el valor 7. +``` + +## Enlaces de explicación en vídeo + +[Programación en C++, Ordenamiento por Selección](https://www.youtube.com/watch?v=HVa2_UtXkCI) diff --git a/es/Cifrado/Cifrado Cesar.md b/es/Cifrado/Cifrado Cesar.md new file mode 100644 index 00000000..daf35af8 --- /dev/null +++ b/es/Cifrado/Cifrado Cesar.md @@ -0,0 +1,40 @@ +# Cifrado César + +El cifrado César es un cifrado simple y uno de los algoritmos de cifrado más conocidos. Es muy simple de cifrar, descifrar e interceptar. El cifrado César es un cifrado de sustitución donde cada letra del texto sin formato (texto decodificado) se sustituye por una letra un cierto número de espacios a la derecha de la letra en el alfabeto (La cantidad de espacios se denomina clave o cambio y solo es conocida por el remitente y el receptor previsto). + +**Descargo de responsabilidad: ¡No intente cifrar datos personales o mensajes serios con este cifrado! ¡Sólo se tarda medio segundo en ser crackeado por un ordenador!** + +1. Se necesita una cantidad muy pequeña de tiempo para codificar y decodificar mensajes (Menos de un segundo, por lo general). +2. No existen aplicaciones reales para el cifrado, ya que es el más inseguro por ahí. +3. Este cifrado fue inventado por Julio César como una forma de enviar mensajes de gran importancia militar. + +## Pasos + +### Cifrado + +1. Elija el alfabeto que va a utilizar. +2. Elija una clave secreta (turno) que va a utilizar en este caso `n`. +3. Por cada letra del texto sin formato, sustitúyala por una letra del alfabeto que esté `n` letras alejadas de la letra. (Por ejemplo: para una clave de «1», «a» se convertiría en «b», «z» se convertiría en «a», etc.) +4. El mensaje ahora debe codificarse. + +### Descifrado + +1. Elija el alfabeto con el que se cifró el mensaje. +2. Deje que `n` sea la clave secreta en la que se codifica el mensaje. +3. Por cada letra del texto cifrado, sustitúyala por una letra del alfabeto que esté `n` letras detrás en el alfabeto de la letra. +`c` sería `b`, `a` sería `z` con una llave de `1`. +4. El mensaje ahora debe ser decodificado + +## Ejemplo + +### Un ejemplo de cifrado + +Digamos que estamos enviando un mensaje secreto a un amigo. + +* Primero escribimos nuestro mensaje. En este caso: `El cifrado César es un divertido cifrado de sustitución` +* Nuestro alfabeto será: `abcdefghijklmnopqrstuvwxyz`. Para los usos de este tutorial, el caso no importa. (En un cambio de «1»: «A» se convertirá en «B», `a` se convertirá en «b») +* Deje que nuestra llave sea 6. +* Comenzando con la primera letra: `T`. La letra a 6 letras de distancia es `Z`. Añadimos `Z` al mensaje. +* La segunda letra es `h`. La letra a 6 letras de distancia es `n`. Nuestro mensaje ahora es `Zn` +* Seguimos así hasta el final. Nuestro mensaje final es: `Znk Igkygx iovnkx oy g lat yahyzozazout iovnkx.` +* El descifrado es de la misma manera, excepto que en lugar de ir a la derecha en el alfabeto, vamos hacia atrás. diff --git "a/es/Estructuras de datos/Gr\303\241fico/Bellman Ford.md" "b/es/Estructuras de datos/Gr\303\241fico/Bellman Ford.md" new file mode 100644 index 00000000..d3908206 --- /dev/null +++ "b/es/Estructuras de datos/Gr\303\241fico/Bellman Ford.md" @@ -0,0 +1,98 @@ +# Bellman Ford + +#### Declaración de problema + +Dado un gráfico dirigido ponderado `G(V,E)` y un vértice de origen s ∈ V, determine para cada `v v v ∈ V` el trayecto más corto entre `s` y `v`. + +#### Enfoque + +- Inicializar la distancia de la fuente a todos los vértices como infinito. +- Inicializar la distancia a sí mismo como 0. +- Crear una matriz dist[] de tamaño | V| con todos los valores como infinitos excepto dist[s]. +- Repita los siguientes |V| - 1 vez, dónde |V| es el número de vértices. +- Crear otro bucle para ir a través de cada borde `(u, v)` en E y hacer lo siguiente: + 1. `dist[v] = minimum(dist[v], dist[u] + peso de borde`. +- Por último, iterar a través de todos los bordes en la última vez, para asegurarse de que no hay ciclos ponderados negativamente. + +#### Complejidad temporal + +`O(VE)` + +#### Complejidad espacial + +`O(V^2)` + +#### Nombre del Fundador + +- Richard Bellman & Lester Ford, Jr. + +#### Ejemplo + +```markdown +# de vértices en el gráfico = 5 [A, B, C, D, E] +# de bordes en gráfico = 8 + +bordes [A->B, A->C, B->C, B->D, B->E, D->C, D->B, E->D] +peso [ -1, 4, 3, 2, 2, 5, 1, -4 ] +fuente [ A, A, B, B, B, D, D, E ] + +borde A->B +graph->edge[0].src = A +graph->edge[0].dest = B +graph->edge[0].weight = -1 + +borde A->C +graph->edge[1] .src = A +graph->edge[1].dest = C +gráfico->edge[1] .weight = 4 + +borde B->C +graph->edge[2].src = B +graph->edge[2].dest = C +gráfico->edge[2].peso = 3 + +borde B->D +gráfico->edge[3] .src = B +graph->edge[3] .dest = D +gráfico->edge[3] .peso = 2 + +borde B->E +graph->edge[4].src = B +graph->edge[4].dest = E +gráfico->edge[4].peso = 2 + +borde D->C +graph->edge[5].src = D +graph->edge[5].dest = C +gráfico->edge[5].peso = 5 + +borde D->B +graph->edge[6] .src = D +graph->edge[6].dest = B +gráfico->edge[6].weight = 1 + +borde E->D +graph->edge[7] .src = E +graph->edge[7].dest = D +gráfico->edge[7].weight = -3 + +para la fuente = A + +Distancia de vértice desde la fuente +A 0 A->A +B -1 A->B +C 2 A->B->C = -1 + 3 +D -2 A->B->E->D = -1 + 2 + -3 +E 1 A->B->E = -1 + 2 +``` + +#### Explicación de vídeo + +[Un video explicando el algoritmo Bellman Ford](https://www.youtube.com/watch?v=hxMWBBCpR6A) + +#### Otros + +Fuentes utilizadas: + +- +- diff --git a/es/Estructuras de datos/Listas vinculadas/Doble lista vinculada.md b/es/Estructuras de datos/Listas vinculadas/Doble lista vinculada.md new file mode 100644 index 00000000..6cd9548a --- /dev/null +++ b/es/Estructuras de datos/Listas vinculadas/Doble lista vinculada.md @@ -0,0 +1,107 @@ +# Lista doblemente vinculada + +Singly Linked List es una estructura de datos lineal y conectada formada por nodos. Cada nodo se compone de una variable 'data' donde se almacena su contenido y un puntero al siguiente nodo de la lista. La lista vinculada tiene un puntero al primer elemento de esta secuencia de nodos y también puede tener otro puntero al último nodo para realizar operaciones en el extremo lejano menos lento. También puede almacenar una variable 'length' para almacenar la longitud total. + +Una lista vinculada doblemente (DLL)** contiene un puntero adicional, normalmente denominado puntero anterior, junto con el puntero siguiente y los datos que están allí en la lista vinculada individualmente. + +### Ventajas sobre la lista vinculada individualmente + +- Un archivo DLL se puede atravesar tanto en dirección hacia delante como hacia atrás. +- La operación de eliminación en DLL es más eficaz si se da puntero al nodo que se va a eliminar. +- Podemos insertar rápidamente un nuevo nodo antes de un nodo determinado. +En la lista vinculada individualmente, para eliminar un nodo, se necesita puntero al nodo anterior. Para obtener este nodo anterior, a veces se atraviesa la lista. En DLL, podemos obtener el nodo anterior mediante el puntero anterior. + +### Desventajas sobre la lista de vinculados individualmente + +- Cada nodo de DLL requiere espacio adicional para un puntero anterior. Sin embargo, es posible implementar DLL con un solo puntero (Consulte esto y esto). +- Todas las operaciones requieren un puntero adicional anterior para ser mantenido. Por ejemplo, en la inserción, necesitamos modificar punteros anteriores junto con punteros siguientes. Por ejemplo, en las siguientes funciones para las inserciones en diferentes posiciones, necesitamos 1 o 2 pasos adicionales para establecer el puntero anterior. + +### Complejidad temporal + +| Operación | Promedio | Peor | +|-----------|---------|-------| +| Acceso | Ḥ(n) | O(n) | +| Buscar | Ḥ(n) | O(n) | +| | de inserción Θ(1) | O(1) | +| | de eliminación Θ(1) | O(1) | + +## Ejemplo + +```java +class LinkedList { + + Node head; // Pointer to the first element + Node tail; // Optional. Points to the last element + + int length; // Optional + + class Node { + int data; // Node data. Can be int, string, float, templates, etc + Node next; // Pointer to the next node on the list + Node prev; + + Node(int data) { + this.data = data; + } + } + + + // Asignar el nodo al frente de la lista + public void push(int new_data) { + + /* 1. Asignar nodo. + * 2. Ponga los datos. */ + Node new_Node = new Node(new_data); + + /* 3. Haga el siguiente de nuevo nodo como cabeza y anterior como NULL. */ + new_Node.next = head; + new_Node.prev = null; + + /* 4. Cambie el nodo principal anterior a nuevo nodo. */ + if (head != null) + head.prev = new_Node; + + /* 5. Mueva la cabeza para apuntar al nuevo nodo. */ + head = new_Node; + } + + /* Dado un nodo como prev_node, inserte un nuevo nodo después del nodo dado. */ + public void InsertAfter(Node prev_Node, int new_data) { + + /* 1. Comprobar si el prev_node dado es NULL. */ + if (prev_Node == null) { + System.out.println("The given previous node cannot be NULL "); + return; + } + + /* 1. Asignar nodo. + * 2. Ponga los datos. */ + Node new_node = new Node(new_data); + + /* 4. Haga el siguiente de nuevo nodo como el siguiente de prev_node. */ + new_node.next = prev_Node.next; + + /* 5. Haz el siguiente de prev_node como new_node. */ + prev_Node.next = new_node; + + /* 6. Haga prev_node como antes de new_node. */ + new_node.prev = prev_Node; + + /* 7. Cambie el anterior del siguiente nodo de new_node. */ + if (new_node.next != null) + new_node.next.prev = new_node; + } +} +``` + +### Adición de nodos en frente + +![Seguimiento del algoritmo](https://www.geeksforgeeks.org/wp-content/uploads/gq/2014/03/DLL_add_front1.png) + +### Agregue un nodo después de un nodo determinado + +![Seguimiento del algoritmo](https://www.geeksforgeeks.org/wp-content/uploads/gq/2014/03/DLL_add_middle1.png) + +## Explicación de vídeo + +[Un vídeo CS50 explicando la Estructura de Datos de la Lista Doblemente Vinculada](https://www.youtube.com/watch?v=FHMPswJDCvU) diff --git a/es/Estructuras de datos/Listas vinculadas/Lista singular vinculada.md b/es/Estructuras de datos/Listas vinculadas/Lista singular vinculada.md new file mode 100644 index 00000000..8be7ca58 --- /dev/null +++ b/es/Estructuras de datos/Listas vinculadas/Lista singular vinculada.md @@ -0,0 +1,43 @@ +# Lista singular vinculada + +Singly Linked List es una estructura de datos lineal y conectada formada por nodos. Cada nodo se compone de una variable '''data''' donde se almacena su contenido y un puntero al siguiente nodo de la lista. La lista vinculada tiene un puntero al primer elemento de esta secuencia de nodos y también puede tener otro puntero al último nodo para realizar operaciones en el extremo lejano menos lento. También puede almacenar una variable '''length''' para almacenar la longitud total. + +### Ventajas sobre matrices + +- El tamaño de una lista vinculada no es fijo (tamaño dinámico). +- Eliminar y agregar un elemento no es caro en comparación con una matriz. + +### Inconvenientes + +- Se puede acceder a los elementos secuencialmente no al azar en comparación con una matriz. +- Es necesario realizar una asignación de memoria adicional para los punteros que conecta los elementos de una lista vinculada. + +### Complejidad temporal + +| Operación | Promedio | Peor | +|-----------|---------|-------| +| Acceso | `O(n)` | `O(n)` | +| Buscar | `O(n)` | `O(n)` | +| de inserción | `O(1)` | `O(1)` | +| de eliminación | `O(1)` | `O(1)` | + +## Ejemplo en Java + +```java +class LinkedList { + Node head; // Puntero al primer elemento. + Node tail; // Opcional. Apunta al último elemento. + + int length; // Opcional. + + class Node { + int data; // Datos del nodo. Puede ser `int`, `string`, `float`, `templates`, etc.. + Node next; // Puntero al siguiente nodo de la lista. + } +} +``` + + +## Explicación de vídeo + +[Un vídeo CS50 explicando la Estructura de Datos de la Lista Singular Vinculada](https://www.youtube.com/watch?v=5nsKtQuT6E8) diff --git "a/es/Matematicas B\303\241sico/Numeros_Fibonacci.md" "b/es/Matematicas B\303\241sico/Numeros_Fibonacci.md" new file mode 100644 index 00000000..23778eed --- /dev/null +++ "b/es/Matematicas B\303\241sico/Numeros_Fibonacci.md" @@ -0,0 +1,74 @@ +# Cálculo de números de Fibonacci + +En matemáticas, los números de Fibonacci comúnmente denotados F(n), forman una secuencia, llamada secuencia Fibonacci, de tal manera que cada número es la suma de los dos anteriores, a partir de 0 y 1. La secuencia tiene este aspecto: + +`[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...]` + +## Aplicaciones + +Encontrar +El miembro enésimo (```N-th```) de esta secuencia sería útil en muchas aplicaciones: + +- Recientemente, la secuencia de Fibonacci y la relación de oro, son de gran interés para los investigadores en muchos campos de +ciencia, incluyendo física de alta energía, mecánica cuántica, criptografía, y codificación. + +## Pasos + +1. Preparar la base matriz +2. Calcular el poder de esta Matriz +3. Tome el valor correspondiente de Matrix + +## Ejemplo + +Encuentra el octavo miembro de Fibonacci + +### Paso 0 + +``` +| F(n+1) F(n) | +| F(n) F(n-1)| +``` + +### Paso 1 + +``` + Calcular matriz^1 +| 1 1 | +| 1 0 | +``` + +### Paso 2 + +``` +Calcular matriz^2 +| 2 1 | +| 1 1 | +``` + +### Paso 3 + +``` +Calcular matriz^4 +| 5 3 | +| 3 2 | +``` + +### Paso 4 + +``` +Calcular matriz^8 +| 34 21 | +| 21 13 | +``` + +### Paso 5 + +F(8)=21 + +## Video en YouTube + +- [YouTube](https://www.youtube.com/watch?v=EEb6JP3NXBI) + +## Otros + +- [Prueba](https://brilliant.org/wiki/fast-fibonacci-transform/) diff --git "a/es/Matematicas B\303\241sico/Promedio.md" "b/es/Matematicas B\303\241sico/Promedio.md" new file mode 100644 index 00000000..02d3801f --- /dev/null +++ "b/es/Matematicas B\303\241sico/Promedio.md" @@ -0,0 +1,67 @@ +# Promedio + +Calcule el promedio de una lista de números utilizando la media. + +## Aplicaciones + +Calcular la media de una lista de números es una de las maneras más comunes de +determinar el promedio de esos números. + +Calcular una media sería útil en estas situaciones: + +- Determinar la puntuación media de todos los jugadores de un nivel de videojuego. +- Encontrar la nota promedio para las pruebas que un estudiante tomó este semestre. +- Determinar el tamaño medio de todos los archivos de un directorio/carpeta. + +## Pasos + +1. Introduzca una lista de números. +2. Calcule la suma de todos los números de la lista. +3. Cuente los números de la lista. +4. Divida la suma por el recuento total de números de la lista. +5. Rentabilidad media. + +## Ejemplo + +Dada la lista `[2, 4, 6, 8, 20, 50, 70]`, vamos a calcular el promedio. + +### Paso 1 + +Enviar `[2, 4, 6, 8, 20, 50, 70]` como entrada para un método/función. + +### Paso 2 + +Agregue todos los números juntos. + +`2 + 4 + 6 + 8 + 20 + 50 + 70 = 160`, por lo que `suma = 160`. + +### Paso 3 + +Cuente los números de la lista. + +La lista tiene siete números, por lo que `count = 7`. + +### Paso 4 + +Divida la suma de todos los números por el recuento de los números. + +``` +suma = 160 +conteo = 7 +``` + +Si ignoramos dígitos significativos: `suma / recuento = `22. 857142 + +Si consideramos correctamente dígitos significativos: `suma / recuento = 23` + +### Paso 5 + +Devuelva el valor de 22. 857142 o `23`. + +## Video en YouTube + +- [Media en Khan Academy](https://www.khanacademy.org/math/cc-sixth-grade-math/cc-6th-data-statistics/mean-and-median/v/mean-median-and-mode) + +## Otros + +- [Media en Wikipedia](https://en.wikipedia.org/wiki/Mean) diff --git a/es/Procesamiento de imagenes/Detector de Harris.md b/es/Procesamiento de imagenes/Detector de Harris.md new file mode 100644 index 00000000..b171a86f --- /dev/null +++ b/es/Procesamiento de imagenes/Detector de Harris.md @@ -0,0 +1,18 @@ +# Detector de Harris + +## Declaración del problema + +Detecte esquinas y bordes en una imagen determinada. + +## Enfoque + +Dada la imagen `$I$`, $ntimes n$ tamaño Gaussian Kernel `$G_{ntimes n}$`, + +1. Calcule los degradados de la imagen, tanto horizontales como verticales. `$X=(-1, 0, 1)otimes I$`, `$Y=(-1, 0, 1)^T otimes I$` +2. Calcule la matriz `$M$`, donde `$A = G_{ntimes n} otimes X^2$`, `$B=G_{ntimes n}otimes Y^2$`, `$C=G_{ntimes n}otimes XY$` +3. Calcule la función de respuesta `$R$`, donde `$R=AB-C^2-k(A+B)$` +4. Clasifique todos los puntos en `$R$`. + +## Referencia + +C. Harris y M. Stephens, "A Combined Corner and Edge Detector", en *Procedings of the Alvey Vision Conference 1988*, Manchester, 1988, págs. 23.1-23.6. diff --git "a/es/Programaci\303\263n dinamica/Cambio de monedas.md" "b/es/Programaci\303\263n dinamica/Cambio de monedas.md" new file mode 100644 index 00000000..7e1228a4 --- /dev/null +++ "b/es/Programaci\303\263n dinamica/Cambio de monedas.md" @@ -0,0 +1,63 @@ +# Cambio de monedas + +#### Declaración de problema +Dado un valor `N`, si queremos hacer un cambio para los centavos `N`, y tenemos una oferta infinita de cada una de las monedas valoradas `S = {S1, S2, .. , Sm}`, ¿cuántas maneras podemos hacer el cambio? El orden de las monedas no importa. + +#### Enfoque + +Deje que el `dp[i]` sea la longitud del cambio de moneda del prefijo `N[1..i]`. Nuestra respuesta es `dp[N]`. +Llenamos `dp[0]` como 1 porque sólo hay una manera de conseguir 0 monedas (No recogemos monedas). + +Ahora vamos a tratar de calcular `dp[i]` para cualquier `i`. `dp[0..i]` almacenará cada sub-problema de `0` a `N`. Es por eso que la respuesta será `dp[N]`. En primer lugar, necesitamos iterar cada tipo de moneda para elegirlos uno por uno. Luego iteramos los sub problemas de la moneda actual que recogemos antes a los centavos `N`. Es por eso que debemos hacer la tabla dp con columnas `N`. + +Estos son los códigos para el algoritmo coin change: +``` + para coin_val en S: + para i en rango (coin_val, n + 1): + dp[i] += dp[i - coin_val] +``` + +En la segunda iteración, por cada centavo que se puede intercambiar, lo tomamos restando la columna enésima por el valor de la moneda que tomamos y añadiéndolo a la columna actual. Así que `dp[i]` almacenará el sub problema actual. + +#### Complejidad temporal + +`O(N * S)` - en cualquier caso + +#### Complejidad espacial + +`O(N)` - implementación simple. Sólo necesitamos arreglos de discos 1D para almacenar la respuesta. + +#### Ejemplo + +Digamos que tenemos 3 tipos de monedas `[1,2,3]`, y queremos cambiarlas por 7 centavos. Así que definiremos nuestra mesa así: + +``` +[1, 0, 0, 0, 0, 0, 0, 0] +``` + +0ª columna almacenará 1, ya que sólo hay una manera de obtener 0 centavos. + +* Para la primera iteración, tomamos una moneda que tiene un valor de 1. Entonces para todos los sub problemas, sólo hay una manera de hacer el cambio. Por 7 céntimos, la única vía es `{1,1,1,1,1,1,1}`. En la iteración final, nuestra mesa es como esta: + +``` +[1, 1, 1, 1, 1, 1, 1, 1] +``` + +* Para la segunda iteración, tomamos una moneda que tiene un valor de 2. A partir de aquí, todos los sub problemas que se pueden dividir por 2 almacenarán otra nueva forma de hacer un cambio. Por lo tanto, cuando la iteración se detuvo en la 2ª columna será como `dp[2] += dp[0]`. Sabemos que `dp[0]` almacenaba un valor de 1. Por lo tanto, dp[2] almacenará el valor de `1 + 1 = 2`. Desde aquí sabemos que por 2 centavos, hay 2 maneras `{1,1}` y `{2}`. Y esta operación continuará. Ahora nuestra mesa es como esta: + +``` +[1, 1, 2, 2, 3, 3, 4, 4] +``` +4 maneras de ganar 7 centavos usando el valor de 1 y 2. `{{1,1,1,1,1,1,1}, {1,1,1,1,1,2}, {1,1,1,2,2}, {1,2,2,2}}` + +* Para la iteración final (3ª iteración), tomamos una moneda que tiene un valor de 3. Como antes, ahora todas las columnas que se pueden vided por 3 almacenarán otra nueva manera. Y el resultado final, será así: + +``` +[1, 1, 2, 3, 4, 5, 7, 8] +``` + +Así que la respuesta final es **8**. 8 maneras de hacer un cambio de 7 centavos usando todos los tipos de monedas. `{{1,1,1,1,1,1,1}, {1,1,1,1,1,2}, {1,1,1,2,2}, {1,2,2,2}, {1,1,1,1,3}, {1,3,3}, {2,2,3}, {1,1,2,3}}` + +#### Vídeo de explicación + +[Formas únicas totales de hacer el cambio de espaldas a espaldas SWE](https://www.youtube.com/watch?v=DJ4a7cmjZY0) diff --git "a/es/Programaci\303\263n dinamica/Subsecuencia com\303\272n m\303\241s larga.md" "b/es/Programaci\303\263n dinamica/Subsecuencia com\303\272n m\303\241s larga.md" new file mode 100644 index 00000000..d51e4f55 --- /dev/null +++ "b/es/Programaci\303\263n dinamica/Subsecuencia com\303\272n m\303\241s larga.md" @@ -0,0 +1,80 @@ +# Subsecuencia común más larga + +#### Declaración de problema + +Dadas dos cadenas `S` y `T`, busque la longitud de la subsecuencia común más larga (LCS). + +#### Enfoque + +Que el `dp[i][j]` sea la longitud de la subsecuencia común más larga de los prefijos `S[1..i]` y `T[1..j]`. Nuestra respuesta (la longitud de LCS) es `dp[| S|] [| T|]`, ya que el prefijo de la longitud de la cadena es la propia cadena. + +Tanto `dp[0][i]` como `dp[i][0]` son `0` para cualquier `i`, desde el LCS de prefijo vacío y cualquier otra cosa es una cadena vacía. + +Ahora, vamos a tratar de calcular `dp[i][j]` para cualquier `i`, `j`. Digamos `S[1..i] = *A` y `T[1..j] = *B` donde `*` significa cualquier secuencia de letras (podría ser diferente para `S` y `T`), `A` significa cualquier letra y `B` significa cualquier letra diferente de `A`. Dado que `A != B`, nuestro LCS no incluye `A` o `B` como último carácter. Así que podríamos tratar de tirar a la distancia el personaje `A` o `B`. Si lanzamos `A`, nuestra longitud LCS será `dp[i - 1][j]` (ya que tenemos prefijos `S[1..i - 1]` y `T[1..j]`). Si intentamos lanzar el carácter `B`, tendremos prefijos `S[1..i]` y `T[1..j - 1]`, por lo que la longitud de LCS será `dp[i][j - 1]`. Mientras buscamos la subsecuencia común más larga, elegiremos el valor máximo de `dp[i][j - 1]` y `dp[i - 1] [j]`. + +¿Pero qué pasa si `S[1..i] = *A` y `T[1..j] = *A`? Podríamos decir que el LCS de nuestros prefijos es LCS de prefijos `S[1..i - 1]` y `T[1..j - 1]` más la letra `A`. Así que `dp[i][j] = dp[i - 1][j - 1] + 1` es igual a `S[i] = T[j]`. + +Pudimos ver que podemos llenar nuestra tabla `dp` fila por fila, columna por columna. Así que nuestro algoritmo será como: + +- Digamos que tenemos cuerdas `S` de la longitud N y `T` de la longitud M (numeradas a partir de 1). Vamos a crear la tabla `dp` de tamaño `(N + 1) x (M + 1)` numerada a partir de 0. +- Vamos a llenar la 0ª fila y la 0ª columna de `dp` con 0. +- A continuación, seguimos el algoritmo: + +```python +for i in range(1..N): + for j in range(1..M): + if(S[i] == T[j]) + dp[i][j] = dp[i - 1][j - 1] + 1 + else + dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) +``` + +#### Complejidad temporal + +`O(N * M)` - En cualquier caso + +#### Complejidad espacial + +`O(N * M)` - implementación simple +`O(min {N, M})` - implementación de dos capas (como `dp[i][j]` depende sólo de las capas i-th e i-th, coudld almacenamos sólo dos capas). + +#### Ejemplo + +Digamos que tenemos cuerdas `ABCB` y `BBCB`. Construiremos una mesa de este tipo: + +``` +# # Una B C B +# 0 0 0 0 0 +B 0 ? ? ? ? +B 0 ? ? ? ? +C 0 ? ? ? +B 0 ? ? ? ? +``` + +Ahora empezaremos a llenar nuestra mesa desde la 1ª fila. Puesto que `S[1] = A` y `T[1] = B`, `dp[1] [1]` será el valor máximo de `dp[0] [1] = 0` y `dp[1] [0] = 0`. Así que `dp[1] [1] = 0`. Pero ahora `S[2] = B = T[1]`, así que `dp[1] [2] = dp[0] [1] + 1 = 1`. `dp[1] [3]` es `1` desde `A != C` y elegimos `max{dp[1] [2], dp[0] [3]}`. Y `dp[1] [4] = dp[0] [3] + 1 = 1`. + +``` +# # A B C B +# 0 0 0 0 0 +B 0 0 1 1 1 +B 0 ? ? ? ? +C 0 ? ? ? ? +B 0 ? ? ? ? +``` + +Ahora vamos a llenar la otra parte de la tabla: + +``` +# # A B C B +# 0 0 0 0 0 +B 0 0 1 1 1 +B 0 0 1 1 2 +C 0 0 1 2 2 +B 0 0 1 2 3 +``` + +Así que la longitud de LCS es `dp[4] [4] = 3`. + +#### Explicación en YouTube + +[Explicación en YouTube de Tushar Roy](https://youtu.be/NnD96abizww) diff --git a/es/README.md b/es/README.md new file mode 100644 index 00000000..3df647bc --- /dev/null +++ b/es/README.md @@ -0,0 +1,30 @@ +# Nombre del algoritmo + +Escribe una breve descripción del algoritmo como: + +1. Complejidad temporal +2. Complejidad espacial +3. Aplicaciones +4. Nombre del fundador +5. etc ... + +## Pasos + +Describe el algoritmo en pasos claros, simples y comprensibles. + +## Ejemplo + +Rastree el algoritmo con datos de entrada de muestra. + +## Implementación + +Enlaces a su implementación en lenguajes de programación. +NOTA: El enlace debe estar dentro de los otros repositorios de esta organización únicamente. + +## URL del vídeo + +Adjunte una URL de un video que explique el algoritmo. + +## Otros + +Cualquier otra información es siempre bienvenida y debe incluirse en esta sección. diff --git a/fr/Exemples/math/Determinant.mp4 b/fr/Exemples/math/Determinant.mp4 new file mode 100644 index 00000000..398527b5 Binary files /dev/null and b/fr/Exemples/math/Determinant.mp4 differ diff --git a/fr/Exemples/math/FibonacciNormal.mp4 b/fr/Exemples/math/FibonacciNormal.mp4 new file mode 100644 index 00000000..216b2a73 Binary files /dev/null and b/fr/Exemples/math/FibonacciNormal.mp4 differ diff --git a/fr/Exemples/math/FibonacciRecursif.mp4 b/fr/Exemples/math/FibonacciRecursif.mp4 new file mode 100644 index 00000000..8d523822 Binary files /dev/null and b/fr/Exemples/math/FibonacciRecursif.mp4 differ diff --git a/fr/Exemples/math/FindMax.mp4 b/fr/Exemples/math/FindMax.mp4 new file mode 100644 index 00000000..b93bfd3c Binary files /dev/null and b/fr/Exemples/math/FindMax.mp4 differ diff --git a/fr/Exemples/math/FindMin.mp4 b/fr/Exemples/math/FindMin.mp4 new file mode 100644 index 00000000..96f40e75 Binary files /dev/null and b/fr/Exemples/math/FindMin.mp4 differ diff --git a/fr/Exemples/tri/TriInsertionGeneral.mp4 b/fr/Exemples/tri/TriInsertionGeneral.mp4 new file mode 100644 index 00000000..1643fbaf Binary files /dev/null and b/fr/Exemples/tri/TriInsertionGeneral.mp4 differ diff --git a/fr/Exemples/tri/TriInsertionMeilleur.mp4 b/fr/Exemples/tri/TriInsertionMeilleur.mp4 new file mode 100644 index 00000000..9bc79862 Binary files /dev/null and b/fr/Exemples/tri/TriInsertionMeilleur.mp4 differ diff --git a/fr/Exemples/tri/TriInsertionPire.mp4 b/fr/Exemples/tri/TriInsertionPire.mp4 new file mode 100644 index 00000000..603cfb9b Binary files /dev/null and b/fr/Exemples/tri/TriInsertionPire.mp4 differ diff --git a/fr/README.md b/fr/README.md new file mode 100644 index 00000000..c30872c2 --- /dev/null +++ b/fr/README.md @@ -0,0 +1,33 @@ +# Nom de l'algorithme + +## Description + +Écrivez une courte description de l'algorithme : + +1. Complexité temporelle +2. Complexité spatiale +3. Applications possibles +4. Nom de l'auteur +5. ... + +## Étapes + +Décrire l'algorithme en étapes concises et compréhensibles. + +## Exemple + +Écrivez le fonctionnement de l'algorithme avec un exemple. + +## Implémentation + +Liens vers des implémentations de ce programme dans des langages. +NOTE : Merci de ne mettre des liens que vers les dossiers de cette organisation. +Si le programme n'existe pas dans un langage, n'hésitez pas à le rajouter ! + +## Vidéo + +Lien vers une vidéo qui explique le fonctionnement de l'algorithme. + +## Autres + +D'autres informations sont toujours les bienvenues and doivent être incluses dans cette section. diff --git a/fr/ToDo.md b/fr/ToDo.md new file mode 100644 index 00000000..5dea9eb0 --- /dev/null +++ b/fr/ToDo.md @@ -0,0 +1,12 @@ +# Algo à faire + +* Terminer de remplir les infos pour fibo et max + +* Filtres audio + * filtre iir + * montrer reponse +* math + * Basiquement tout +* tri + * basiquement tout +* Tout le reste diff --git a/fr/filtres_audio/filtre_butterworth.md b/fr/filtres_audio/filtre_butterworth.md new file mode 100644 index 00000000..b02fc4ba --- /dev/null +++ b/fr/filtres_audio/filtre_butterworth.md @@ -0,0 +1,29 @@ +# Le filtre Butterworth + +## Description + +### Principe + +* Le filtre de Butterworth est originellement un filtre passe-bas, et c'est le filtre le plus utilisé du fait de son gain extrêmement plat dans la zone passe-bande. +* L'avantage d'un tel filtre est d'amplifier toutes les fréquences voulues de façon uniforme, au lieu d'amplifier certaines fréquences plus que d'autre comme le faisaient les filtres en usage avant sa découverte (les filtres [elliptiques](https://fr.wikipedia.org/wiki/Filtre_elliptique) et [de Tchebychev](https://fr.wikipedia.org/wiki/Filtre_de_Tchebychev)). +* De plus, Butterworth a prouvé que le filtre passe-bas pouvait être modifié facilement afin de donner des filtres passe-haut, passe-bande ou coupe-bande. +* La fonction de transfert d'un filtre de Butterworth passe-bas d'ordre $n$ dans le domaine fréquentielle est : +$$\tag{avec $p_k=\omega_ce^{\frac{j(2k+n-1)\pi}{2n}}$}H(p) = \frac{G_0}{\prod^n_{k=1}(p-p_k)/\omega_c}$$ + +### Complexités + +* Considérant qu'il s'agit simplement d'une formule à appliquer, les complexités temporelle et spatiale de l'algorithme est très faible. + +### Applications + +* Les filtres sont utilisés dans tous les domaines faisant du traitement de signal, que ce soit dans le domaine de la radio-communication où celui du traitement d'images. +* En associant par exemple dans un circuit éléctronique un filtre passe-bande et un amplificateur opérationnel, il est possible de créer un générateur d'onde sinusoïdale. + +### L'auteur + +* Stephen Butterworth est un ingénieur britannique et il décrit ce type de filtre en 1930 dans son livre 'Traité sur la théorie des filtres'. + +## Étapes + +* On commence par calculer les différents coefficients pour le filtre. +* On applique ces coefficients à un filtre IIR. diff --git a/fr/math/Determinant.md b/fr/math/Determinant.md new file mode 100644 index 00000000..717bdb0c --- /dev/null +++ b/fr/math/Determinant.md @@ -0,0 +1,36 @@ +# Déterminant + +## Description + +### Principe + +* Calculer le déterminant d'une matrice permet de savoir si elle est inversible ou non. +* Avoir cette information en elle-même ne sert pas à grand-chose, mais si cette matrice représente (par exemple) un système d'équation, cela permet de savoir si ce système possède une solution. + +### Complexités + +* L'algorithme possède une complexité temporelle de l'ordre de $n!$ (À vérifier). +* On utilise une fonction récursive, ce qui est gourmand en termes de mémoire. + +### Applications + +* Trouver le déterminant d'une matrice permet de savoir si on peut utiliser la méthode du pivot de Gauss ou pas. + +## Étapes + +* Puisque le déterminant n'est défini que pour les matrices carrées, il faut d'abord vérifier que la matrice est carré. +* Ensuite, nous développons la matrice par rapport à la première ligne. +* On répète ces étapes à la matrice ainsi développer jusqu'à tomber sur une matrice 2×2, où on applique la formule connue $\bigg(\begin{vmatrix}a&b\\c&d\end{vmatrix}=ad-cb\bigg)$. +* De là, on remonte la cascade d'appel en effectuant les calculs. + +## Exemple + +Calculons le déterminant de la matrice $\begin{bmatrix}1&2&3\\4&5&6\\7&8&9\end{bmatrix}$. + +### Exemple en vidéo + +* [Déterminant](../Exemples/math/Determinant.mp4) + +### Conclusion + +Le déterminant de $\begin{bmatrix}1&2&3\\4&5&6\\7&8&9\end{bmatrix}$ est $0$. diff --git a/fr/math/Suite_de_Fibonacci.md b/fr/math/Suite_de_Fibonacci.md new file mode 100644 index 00000000..b6ce3d60 --- /dev/null +++ b/fr/math/Suite_de_Fibonacci.md @@ -0,0 +1,42 @@ +# La suite de Fibonacci + +## Description + +### Principe + +* La suite de Fibonacci est définie mathématiquement de la sorte : +$$ +\begin{cases} +F(0) = 0\\ +F(1) = 1\\ +\forall n \in \natnums / n \ge 2, F(n) = F(n-2) + F(n-1) +\end{cases} +$$ +* Cela signifie que chaque terme est la somme des deux termes précédents, en ayant pour termes de départ 0 et 1. +La suite ressemble à ceci : +$$0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, \ldots$$ +\ +De nombreux algorithmes existent pour calculer les nombres de la suite, mais nous allons ici nous intéresser à l'implémentation la plus directe. + +### Complexités + +* L'algorithme possède une complexité temporelle de l'ordre de $n$. +* La complexité spatiale est extrêmement faible car nous ne stockons que les 2 derniers termes. + +## Étapes + +* La première étape consiste à calculer $F(2)$ à partir de $F(1)$ et F(0)$. +* La deuxième, à calculer $F(3)$ à partir de $F(2)$ et F(1)$. +* Et ainsi de suite jusqu'à $F(n)$. + +## Exemple + +Dans notre exemple nous cherchons à calculer F(6), le 7ème terme de la suite. + +### Exemple en vidéo + +* [Fibonacci normal](../Exemples/math/FibonacciNormal.mp4) + +### Conclusion + +On a donc $F(6) = 8$ diff --git "a/fr/math/Suite_de_Fibonacci_r\303\251cursive.md" "b/fr/math/Suite_de_Fibonacci_r\303\251cursive.md" new file mode 100644 index 00000000..12506035 --- /dev/null +++ "b/fr/math/Suite_de_Fibonacci_r\303\251cursive.md" @@ -0,0 +1,43 @@ +# La suite de Fibonacci récursive + +## Description + +### Principe + +* La suite de Fibonacci est définie mathématiquement de la sorte : +$$ +\begin{cases} +F(0) = 0\\ +F(1) = 1\\ +\forall n \in \natnums / n \ge 2, F(n) = F(n-2) + F(n-1) +\end{cases} +$$ +* Cela signifie que chaque terme est la somme des deux termes précédents, en ayant pour termes de départ 0 et 1. +La suite ressemble à ceci : +$$0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, \ldots$$ +\ +De nombreux algorithmes existent pour calculer les nombres de la suite, mais nous allons ici nous intéresser à l'implémentation la plus immédiate/directe, celle qui est récursive. + +### Complexités + +* Cet algorithme n'est pas optimal et prends beaucoup de place et de temps à se terminer. +Plus précisement, la complexité temporelle de ce programme est $\phi^n$ ($\phi$ étant le nombre d'or), et sa complexité spatiale est $2^n$. + +## Étapes + +* La première étape consiste à appeler $F(n-2)$ et $F(n-1)$. +* La deuxième consite à appeler $F(n-4)$ et $F(n-3)$ (venant de $F(n-2)$) ainsi que $F(n-3)$ et $F(n-2)$ (venant de $F(n-1)$). +* Ainsi de suite, jusqu'à appeler $F(1)$ ou $F(0)$, où on peut commencer à remonter la cascade d'appel et à additionner les termes. +* On obtient à la fin $F(n)$. + +## Exemple + +Dans notre exemple nous cherchons à calculer $F(4)$, le 5ème terme de la suite. + +### Exemple en vidéo + +* [Fibonacci récursif](../Exemples/math/FibonacciRecursif.mp4) + +### Conclusion + +On a donc $F(4) = 3$ diff --git a/fr/math/Trouver_Maximum.md b/fr/math/Trouver_Maximum.md new file mode 100644 index 00000000..e44f3204 --- /dev/null +++ b/fr/math/Trouver_Maximum.md @@ -0,0 +1,35 @@ +# Trouver le Maximum + +## Description + +### Principe + +* L'algorithme est direct : on parcourt toute la liste de nombre et on retient le plus grand nombre rencontré jusqu'à ce point. + +### Complexités + +* La complexité temporelle est de $n$ (la longueur de la liste). +* Pour la complexité spatiale, nous avons seulement à retenir le plus grand nombre + +### Applications + +* Un algorithme permettant de trouver le plus grand nombre d'une liste est utile dans presque tous les domaines. + +### Auteurs + +* À la vue de la très grande utilité et de la simplicité de cet algorithme, de nombreuses personnes l'ont très certainement mis au point en même temps. + +## Étapes + +* En premier lieu, il faut initialiser le maximum. Pour cela, on dit que le maximum est égale au 1er terme de la liste. + * Attention ! Il ne faut pas prendre pour 1er maximum 0, car si notre liste est composée uniquement de nombres $< 0$, on ne va pas avoir un maximum correct. + * Pour la même raison, il ne faut pas comparer les valeurs absolues des nombres. +* Ensuite on compare les nombres. Si le 2ème est plus grand que le maximum, il devient le maximum et ainsi de suite, jusqu'à arriver à la fin de la liste. + +## Exemple + +Dans notre exemple, on va prendre la liste $-48,0,8,22,0,31,-38,-15,43,14,22,21,44,15,-36,-4,-17, -47,45\\,-5,35,-26,-48,-17,-14,47,-39,41$ + +### Exemple en vidéo + +* [Maximum](../Exemples/math/FindMax.mp4) diff --git a/fr/math/Trouver_Minimum.md b/fr/math/Trouver_Minimum.md new file mode 100644 index 00000000..47560f56 --- /dev/null +++ b/fr/math/Trouver_Minimum.md @@ -0,0 +1,35 @@ +# Trouver le Maximum + +## Description + +### Principe + +* L'algorithme est direct : on parcourt toute la liste de nombre et on retient le plus petit nombre rencontré jusqu'à ce point. + +### Complexités + +* La complexité temporelle est de $n$ (la longueur de la liste). +* Pour la complexité spatiale, nous avons seulement à retenir le plus grand nombre + +### Applications + +* Un algorithme permettant de trouver le plus petit nombre d'une liste est utile dans presque tous les domaines. + +### Auteurs + +* À là vue de la très grande utilité et de la simplicité de cet algorithme, de nombreuses personnes l'ont très certainement mis au point en même temps. + +## Étapes + +* La première étape est d'initialiser le minimum. Pour cela, on dit qu'il est égale au 1er terme de la liste. + * Attention ! Il ne faut pas prendre pour 1er minimum 0, car si notre liste est composée uniquement de nombres $> 0$, on ne va pas avoir un minimum correct. + * Pour la même raison, il ne faut pas comparer les valeurs absolues des nombres. +* Ensuite on compare les nombres. Si le 2ème est plus grand que le minimum, il devient le minimum et ainsi de suite, jusqu'à arriver à la fin de la liste. + +## Exemple + +Dans notre exemple, on va prendre la liste $16,6,2,-14,43,-28,-35,20,-23,25,9,38,17,43,-44,-16,-16,39,\\-4,4,2,-42,11,-13,30,-47,7,-10$ + +### Exemple en vidéo + +* [Minimum](../Exemples/math/FindMin.mp4) diff --git a/fr/tri/Tri_fusion.md b/fr/tri/Tri_fusion.md new file mode 100644 index 00000000..b2b12e4c --- /dev/null +++ b/fr/tri/Tri_fusion.md @@ -0,0 +1,48 @@ +# Tri Fusion + +## Description + +### Principe +Le tri fusion, aussi appelé "tri dichotomique" est un Algorithme de tri Stable, qui est basé sur la technique "diviser pour régner". + +### Complexités + +#### Complexités spatiale + +La complexité spatiale de l'algorithme est de `O(n)` + +#### Complexités temporelle + +- meilleur cas : `O(n log n)` +- cas moyens : `O(n log n)` +- pire cas : `O(n log n)` + +## Étapes + +- Trouvez le milieu du tableau et divisez le en deux moitiés en fonction du milieu. +- Appeler récursivement la fonction de tri fusion pour les deux moitiés +- Fusionnez les deux moitiés triées pour obtenir le tableau trié. + +## Exemple + +```txt +tab = [1, 9, 2, 5, 7, 3, 6, 4] + +Divisez le tableau en deux moitiés [1, 9, 2, 5] et [7, 3, 6, 4] + +Les deux moitiés ci-dessus ne sont pas encore triées, donc nous devons les diviser à nouveau en deux moitiés. + +Cette fois, nous obtenons quatre tableaux : [1, 9], [2, 5], [7, 3] et [6, 4]. + +les deux derniers tableaux ne sont toujours pas triés, donc nous les divisons à nouveau en deux moitiés et nous obtenons [7], [3], [6], and [4]. + +Puisqu'un tableau d'un seul élément est trié, nous avons maintenant tous les tableaux triés, il ne nous reste plus qu'à les fusionner de manière appropriée. + +D'abord, les tableaux d'un seul élément seront fusionnés vu qu'ils ont été divisés en dernier, et sont au sommet de la pile de récursion, donc nous obtenons [3,7] et [4,6]. + +Puis la fusion va se produire conformément à la pile de récurrence, [1, 9] et [2, 5] seront fusionnés et donneront [1, 2, 5, 9]. + +De même, [3, 7] et [4, 6] seront fusionnés et donneront [3, 4, 6, 7]. + +Au niveau suivant de la pile, [1, 2, 5, 9] et [3, 4, 6, 7] seront fusionnés et nous obtiendrons le tableau trié final comme [1, 2, 3, 4, 5, 6, 7, 9]. +``` diff --git a/fr/tri/Tri_par_insertion.md b/fr/tri/Tri_par_insertion.md new file mode 100644 index 00000000..b03c5b02 --- /dev/null +++ b/fr/tri/Tri_par_insertion.md @@ -0,0 +1,51 @@ +# Tri par insertion + +## Description + +### Principe + +Le principe du tri par insertion est de parcourir la liste de valeurs, en les classant par rapport aux valeurs déjà parcourues. +On trie la 2ème valeur par rapport à la 1ère, la 3ème par rapport à la 2ème et la 1ème, etc. +Ainsi, lorsque l'on compare la n-ième valeur, toutes les valeurs précédentes sont triées. + +### Complexités + +Lors de l'évaluation des complexités d'un algorithme de tri, il est nécessaire de prendre en compte non seulement le cas général, mais également le meilleur et le pire cas. +Dans un algorithme de tri, le meilleur cas est celui où la liste est déjà triée, le pire est généralement le cas où la liste est triée "à l'envers" (décroissant si on cherche l'ordre croissant et inversement), le cas général correspond à une liste d'éléments dans le désordre. + +* La complexité spatiale d'un tri par insertion est simple et est constante à travers les cas. Il s'agit de la liste des valeurs, car le tri est effectué directement dans la liste, plus une variable qui servira à retenir la valeur que l'on est en train de trier. +* La complexité temporelle varie beaucoup selon les cas : + * Dans le pire des cas, la complexité est en $n^2/2$. + * Dans le meilleur cas, la complexité est seulement de $n$. + * Finalement, dans le cas général, la complexité est de $n^2/4$. +* Cet algorithme de tri a pour seuls avantages la très grande facilité d'implémentation, le peu de place mémoire prise et sa rapidité sur les très petites listes ou les listes "presque triées". +* On préféra utiliser d'autres algorithmes de tri comme le tri par fusion ou le tri rapide dans la grande majorité des cas (cf. leurs explications respectives). + +## Étapes + +* On commence par comparer la 2ème valeur à la 1ère, et on la place accordement. +* On compare la 3ème valeur avec la 2ème. + * Soit la 3ème valeur est plus grande, auquel cas on passe à la 4eme. + * Où alors, elle est plus petite, auquel cas on copie la 2ème valeur à la place de la 3ème, et on compare avec la 1ère. + * De là, soit la 1ère est plus petite, et on passe à la 4ème valeur. + * Soit, la 1ère est plus grande, et on copie la 1ère à la place de la 2ème, puis on place la valeur que l'on trie à la place de la 1ère. +* On continue comme cela jusqu'à atteindre la fin de la liste. +(Je vous conseille de regarder la vidéo pour que le principe soit plus clair.) + +## Exemple + +Dans notre exemple, on va trier la liste $84, 33, 82, 53, 50, 66, 10, 92, 96, 77, 29$ + +### Exemple en vidéo + +Tri par insertion dans le : + +* [cas général](../Exemples/tri/TriInsertionGeneral.mp4) +* [meilleur cas](../Exemples/tri/TriInsertionMeilleur.mp4) +* [pire cas](../Exemples/tri/TriInsertionPire.mp4) + +## Pour aller plus loin + +* Dans le meilleur cas, nous n'effectuons qu'une unique comparaison. En effet, le terme comparé et plus grand que le terme juste avant, donc aucune modification n'est à effectuer. (ce qui correspond bien à $n$ opérations) +* Dans le pire des cas, on doit au contraire "redescendre" tous les termes un par un. On effectue une opération pour remonter le 2ème terme, deux pour le 3ème, etc. On effectue au total un nombre d'opérations de l'ordre de $\Theta(n^2)$. + * Bien que le cas moyen soit également un $\Theta(n^2)$, le pire cas effectue plus précisément $\Theta(n^2/2)$ opérations, tandis que le cas moyen en effectue $\Theta(n^2/4)$ diff --git a/fr/tri/Tri_par_selection.md b/fr/tri/Tri_par_selection.md new file mode 100644 index 00000000..e7f04bb6 --- /dev/null +++ b/fr/tri/Tri_par_selection.md @@ -0,0 +1,50 @@ +# Tri par Selection + +## Description + +### Principe + +Le tri par sélection est un algorithme de tri par comparaison, qui malgres sa simplicité est en generale considerer comme ineficasse de fait de sa complexité. + +### Complexités + +#### Complexités spatiale + +- `O(1)` + +#### Complexité temporelle + +- Pire, moyens et meilleur cas : `O(n^2)` + +## Étapes + +- Sélectionner le plus petit élément du tableau +- Le permuter avec le premier élément du tableau +- Puis sélectionner le plus petit élément du tableau dans la liste non triée restante +- Le permuter avec le premier élément du tableau dans la liste non triée restante +- Continuez à faire cela pour chaque élément du tableau + +## Exemple + +```txt + +tab[] = {80, 10, 40, 30} +Indexes : 0 1 2 3 + +1. Index = 0 + Sélectionnez le nombre minimum dans le tableau et son index (index entre 0-3), (la plus petite valeur est 10, et l'index est 1) +2. Permuter les indexe 1 et 0 (valeurs 10 et 80) +3. La nouvelle valeur du tableau est : {10, 80, 40, 30} + +4. Index = 1 + Sélectionnez le nombre minimum dans le tableau et son index (index entre 1-3), (la plus petite valeur est 30, et l'index est 3) +5. Permuter les indexe 3 et 1 (valeurs 30 et 80) +6. La nouvelle valeur du tableau est : {10, 30, 40, 80} + +7. Index = 2 + Sélectionnez le nombre minimum dans le tableau et son index (index entre 2-3), (la plus petite valeur est 40, et l'index est 2) +8. Permuter les indexe 2 et 2 (valeurs 40 et 40) +9. La nouvelle valeur du tableau est : {10, 30, 40, 80} + +Le Tableau est maintenant trié. +``` diff --git "a/fr/tri/Tri_\303\240_bulles.md" "b/fr/tri/Tri_\303\240_bulles.md" new file mode 100644 index 00000000..1d460c17 --- /dev/null +++ "b/fr/tri/Tri_\303\240_bulles.md" @@ -0,0 +1,75 @@ +# Tri à bulles + +## Description + +### Principe + +Le principe du tri à bulles est de comparer répétitivement les éléments consécutifs d'un tableau deux à deux, et de les permuter lorsque ces derniers sont mal trié. + +### Complexités + +#### Complexités temporelle + +- Dans le pire des cas, lorsque le plus petit élément est à la fin du tableau, la complexité est de `O(n^2)` +- Dans le meilleur cas, lorsque le tableau est déjà trié, la complexité est de `O(n)` (on n'effectue qu’une seule itération de l'algorithme) +- En moyenne, la complexité est de `O(n^2)` + + +## Étapes + +- Sélectionner le premier élément du tableau +- Le comparer avec l'élément suivant + - Si la valeur du premier élément est plus grande que celle du deuxième, permuter ces derniers. + - Sinon, ne rien faire +- Continuez à faire cela pour chaque index du tableau. +- Répétez les étapes précédentes n fois. + +## Exemple + +```txt +tab[] = {10, 80, 40, 30} +Indexes: 0 1 2 3 + +1. Index = 0, Valeur = 10 +2. 10 < 80, ne rien faire et continuer + +3. Index = 1, Valeur = 80 +4. 80 > 40, permuter 80 et 40 +5. Les nouvelles valeurs du tableau sont : {10, 40, 80, 30} + +6. Index = 2, Valeur = 80 +7. 80 > 30, permuter 80 et 30 +8. Les nouvelles valeurs du tableau sont : {10, 40, 30, 80} + +Répétez les étapes précédentes + +tab[] = {10, 40, 30, 80} +Indexes: 0 1 2 3 + +1. Index = 0, Valeur = 10 +2. 10 < 40, ne rien faire et continuer + +3. Index = 1, Valeur = 40 +4. 40 > 30, permuter 40 et 30 +5. Les nouvelles valeurs du tableau sont : {10, 30, 40, 80} + +6. Index = 2, Valeur = 40 +7. 40 < 80, ne rien faire +8. Les nouvelles valeurs du tableau sont : {10, 30, 40, 80} + +Répétez les étapes précédentes + +tab[] = {10, 30, 40, 80} +Indexes: 0 1 2 3 + +1. Index = 0, Valeur = 10 +2. 10 < 30, ne rien faire et continuer + +3. Index = 1, Valeur = 30 +4. 30 < 40, ne rien faire et continuer + +5. Index = 2, Valeur = 40 +6. 40 < 80, ne rien faire + +Puisqu'il n'y a pas de permutations dans les étapes précédentes, cela signifie que le tableau est trié et que nous pouvons nous arrêter ici. +``` diff --git "a/he/\327\236\327\252\327\236\327\230\327\231\327\247\327\224 \327\221\327\241\327\231\327\241\327\231\327\252/\327\236\327\241\327\244\327\250\327\231 \327\244\327\231\327\221\327\225\327\240\327\220\327\246'\327\231.md" "b/he/\327\236\327\252\327\236\327\230\327\231\327\247\327\224 \327\221\327\241\327\231\327\241\327\231\327\252/\327\236\327\241\327\244\327\250\327\231 \327\244\327\231\327\221\327\225\327\240\327\220\327\246'\327\231.md" new file mode 100644 index 00000000..52411f28 --- /dev/null +++ "b/he/\327\236\327\252\327\236\327\230\327\231\327\247\327\224 \327\221\327\241\327\231\327\241\327\231\327\252/\327\236\327\241\327\244\327\250\327\231 \327\244\327\231\327\221\327\225\327\240\327\220\327\246'\327\231.md" @@ -0,0 +1,88 @@ +

חישוב סדרת פיבונאצ'י

+ +
+ + במתמטיקה, מספרי פיבונאצ'י המצוינים בדרך כלל כ: + F(n), יוצרים רצף המכונה רצף פיבונאצ'י,
+ כך שכל מספר הוא הסכום של שני הקודמים, החל מ- 0 ו- 1. הרצף נראה כך: + +
+ +
+ +

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...]

+ +

יישום

+ +

+מציאת החישוב ה: N-th ברצף זה שימושי ביישומים רבים.
+לאחרונה רצף פיבונאצ'י ויחס הזהב מעניינים מאוד חוקרים בתחומי מדע רבים כולל פיזיקה של אנרגיה גבוהה, מכניקת קוונטים, קריפטוגרפיה וקידוד. +

+ +

צעדים למימוש

+ +

+1. הכן מטריצה בסיסית
+2. חשב את כוחה של מטריצה זו
+3. קח ערך מקביל ממטריקס +

+ +
+ +

דוגמא

+
מציאת האיבר ה-8 בסדרת פיבונאצ'י
+ +
+ +

חישוב 0

+ +``` +| F(n+1) F(n) | +| F(n) F(n-1)| +``` + +

חישוב 1

+ +``` +חישוב matrix^1 +| 1 1 | +| 1 0 | +``` + +

חישוב 2

+ +``` +חישוב matrix^2 +| 2 1 | +| 1 1 | +``` + +

חישוב 3

+ +``` +חישוב matrix^4 +| 5 3 | +| 3 2 | +``` + +

חישוב 4

+ +``` +חישוב matrix^8 +| 34 21 | +| 21 13 | +``` + +

חישוב 5

+ +``` +F(8)=21 +``` + +

קישור לסרטון הסבר

+ +- [Youtube](https://www.youtube.com/watch?v=EEb6JP3NXBI) + +

שונות

+ +- [הוכחה לסדרת פיבונאצ'י](https://brilliant.org/wiki/fast-fibonacci-transform/) diff --git a/id/README.md b/id/README.md new file mode 100644 index 00000000..93c4864e --- /dev/null +++ b/id/README.md @@ -0,0 +1,30 @@ +# Nama Algoritma + +Tulis deskripsi singkat algoritmanya dengan: +1. Kompleksitas waktu (_time complexity_) +2. Kompleksitas ruang (_space complexity_) +3. Aplikasinya +4. Pembuat atau penemunya +5. dll... + +## Langkah-Langkah + +Deskripsikan algoritmanya dengan jelas, sederhana, dan dengan langkah-langkah +yang mudah dimengerti. + +## Contoh + +Lacak (_trace_) algoritma dengan sampel data masukan. + +## Implementasi + +Tambahkan tautan implementasinya dalam suatu bahasa pemrograman. +CATATAN: Tautan sumbernya hanya boleh berasal dari repositori atau organisasi ini. + +## URL Video + +Lampirkan URL dari video yang menjelaskan algoritmanya. + +## Lainnya + +Segala bentuk informasi lainnya juga boleh dan memang sebaiknya ditambahkan di bagian ini. diff --git a/ko/README.md b/ko/README.md new file mode 100644 index 00000000..0f503ee5 --- /dev/null +++ b/ko/README.md @@ -0,0 +1,30 @@ +# 알고리즘 이름 + +알고리즘에 대한 간략한 설명을 다음과 같이 적어주세요: + +1. 시간 복잡도 +2. 공간 복잡도 +3. 활용 +4. 만든 사람 +5. 등... + +## 절차 + +알고리즘을 명확하고 단순하며 이해하기 쉬운 단계로 구분하여 설명해주세요. + +## 예시 + +간단한 예시를 들어 알고리즘의 동작 과정을 보여주세요. + +## 구현 + +다양한 프로그래밍 언어로 구현된 알고리즘을 링크로 연결해주세요. +NOTE: `TheAlgorithms`의 다른 저장소 안에 있는 링크만 연결해주세요. + +## 영상 URL + +알고리즘을 설명하는 영상의 URL을 첨부해주세요. + +## 기타 + +다른 모든 정보는 이 섹션에 포함해주세요. diff --git "a/ko/\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\266\204\355\225\240 \352\260\200\353\212\245\355\225\234 \353\260\260\353\202\255 \353\254\270\354\240\234.md" "b/ko/\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\266\204\355\225\240 \352\260\200\353\212\245\355\225\234 \353\260\260\353\202\255 \353\254\270\354\240\234.md" new file mode 100644 index 00000000..02885f8c --- /dev/null +++ "b/ko/\352\267\270\353\246\254\353\224\224 \354\225\214\352\263\240\353\246\254\354\246\230/\353\266\204\355\225\240 \352\260\200\353\212\245\355\225\234 \353\260\260\353\202\255 \353\254\270\354\240\234.md" @@ -0,0 +1,38 @@ +# 배낭 문제 (그리디 알고리즘) + +#### 문제 + +무게와 가치가 정해진 항목들의 집합이 주어졌을 때, 주어진 최대 무게 내에서 가치가 최대가 되도록 하는 항목의 수를 찾아라. + +##### 그리디 알고리즘은 분할 가능한 배낭 문제에서 항상 최적해를 제공한다. + +#### 시간 복잡도 + +최악: $O(nlog n)$ + +#### 예시 + +``` +배낭의 최대 무게 W = 60 +value = [280, 100, 120, 120] +weight = [40, 10, 20, 24] + +Ratio(V/W) = 7,10,6,5 +각 항목을 A,B,C,D라 하자. + +먼저 항목들을 가치와 무게의 비율을 기준으로 내림차순으로 정렬한다. +B는 배낭의 용량보다 작기 때문에 첫 번째로 선택된다. 다음으로, 남은 용량이 A의 무게보다 크기 때문에 A가 선택된다. +배낭의 남은 용량이 C의 무게보다 작기 때문에 C는 전체 항목을 선택할 수 없다. +따라서 C는 (60-50)/20의 비율만큼 일부만 선택된다. +이제 배낭의 용량은 지정된 항목들의 무게와 동일해서 더 이상 항목을 선택할 수 없다. + +선택된 물건들의 총 무게는 10+40+20*(10/20) = 60이다. + +총 이익은 100+280+120*(10/20) = 380+60 = 440이다. + +이것이 가장 적합한 선택이다. 다른 항목을 조합하여 더 많은 돈을 버는 것은 불가능하다. +``` + +#### 영상 URL + +[A CS50 video explaining the Greedy Algorithm](https://www.youtube.com/watch?v=Ou9OA0yQCYA) diff --git "a/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\353\223\261\353\271\204\354\210\230\354\227\264.md" "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\353\223\261\353\271\204\354\210\230\354\227\264.md" new file mode 100644 index 00000000..2d1a571f --- /dev/null +++ "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\353\223\261\353\271\204\354\210\230\354\227\264.md" @@ -0,0 +1,52 @@ +# 등비수열 + +연속된 두 항의 비율이 항상 같을 때 그 수열을 `등비수열`이라고 한다. 간단히 말해, 이전 항에 상수를 곱하여 다음 항을 계산하여 등비수열을 만들 수 있다. + +예를 들어, `2, 4, 8, 16`은 연속된 두 항의 비율(공비)가 모두 같으므로 등비수열이다 (4 / 2 = 8 / 4 = 16 / 8 = 2). + +

+ +

+ +**등비수열에 관한 사실들:** + +1. **초항:** 등비수열에서, 첫 항은 초항이라고 불린다. +2. **공비:** 다음 항을 이전 항으로 나누어 나타낸 연속된 두 항의 비율 +3. 등비수열은 공비에 따라 여러 경향을 보인다. 만약 공비가: + - 양수이면, 모든 항은 첫 항과 같은 부호를 가진다. + - 음수이면, 부호가 번갈아 가며 나타난다. + - 1보다 크면, (초항의 부호에 따라) 양의 무한대 또는 음의 무한대를 향해 지수적으로 증가한다. + - 1이면, 모든 항의 값이 같은 상수수열이다. + - −1과 1사이에 있지만 0이 아니면, 0을 향해 지수적으로 감소한다. + - −1이면, 모든 항의 절댓값은 같지만, 부호가 번갈아 가며 나타난다. + - -1보다 작으면, 부호가 번갈아 가며 나타나고, 절대값은 양의 무한대를 향해 지수적으로 증가한다. + +**등비수열의 n번째 항 공식:** + +$a$가 초항, $r$이 공비일 때, $n$번째 항은: + +

+ +

+ +**등비급수(등비수열의 첫 n항의 합) 공식:** + +

+ +

+ +**등비수열에 관련된 문제를 풀기 위한 일반적인 공식:** + +$a$가 초항, $r$이 공비일 때: + +- 등비급수 $(r < 1) = \frac{a(1-r^n)}{1-r}$ +- 등비급수 $(r > 1) = \frac{a(r^n-1)}{r-1}$ +- 무한등비급수 $(r < 1) = \frac{a}{1-r}$ + +## 영상 URL + +- [Don't Memorise](https://youtu.be/gua96ju_FBk) + +## 출처 + +- [GeeksforGeeks](https://www.geeksforgeeks.org/geometric-progression/) diff --git "a/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\353\223\261\354\260\250\354\210\230\354\227\264.md" "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\353\223\261\354\260\250\354\210\230\354\227\264.md" new file mode 100644 index 00000000..23ac8ad7 --- /dev/null +++ "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\353\223\261\354\260\250\354\210\230\354\227\264.md" @@ -0,0 +1,45 @@ +# 등차수열 + +연속된 두 항의 차이가 항상 같을 때 그 수열을 `등차수열`이라고 한다. 간단히 말해, 이전 항에 상수를 더하여 다음 항을 계산하여 등차수열을 만들 수 있다. + +예를 들어, `2, 4, 6, 8, 10`은 연속된 두 항의 차이(공차)가 모두 같으므로 등차수열이다 (4 - 2 = 6 - 4 = 8 - 6 = 10 - 8 = 2). + +

+ +

+ +**등차수열에 관한 사실들:** + +1. 초항: 등차수열에서, 수열의 첫 항은 초항이라고 불린다. +2. 공차: 연속된 두 항의 차이를 공차라고 한다. +3. 등차수열의 경향성은 공차 `d`에 따라 결정된다. 만약 공차가 양수라면, 모든 항은 양의 무한대를 향해 증가한다. 하지만 만약 공차가 음수라면, 모든 항은 음의 무한대를 향해 감소한다. + +**등차수열의 n번째 항 공식:** + +$a$가 초항, $d$가 공차일 때, $n$번째 항은: + +

+ +

+ +**등차급수(등차수열의 첫 n항의 합) 공식:** + +

+ +

+ +**등차수열에 관련된 물제를 풀기 위한 일반적인 공식:** + +$a$가 초항, $d$가 공차일 때: + +- 산술평균 = `전체 항의 합 / 항의 개수` +- 등차급수 = `n * (초항 + 말항) / 2` = $\frac{n \cdot (2a + (n-1)d)}{2}$ + +## 영상 URL + +- [Don't Memorise](https://youtu.be/gua96ju_FBk) +- [iBytes Academy (C++)](https://youtu.be/U_qtSRQYoPs) + +## 출처 + +- [GeeksforGeeks](https://www.geeksforgeeks.org/arithmetic-progression) diff --git "a/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\353\247\210\353\260\251\354\247\204.md" "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\353\247\210\353\260\251\354\247\204.md" new file mode 100644 index 00000000..5639c404 --- /dev/null +++ "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\353\247\210\353\260\251\354\247\204.md" @@ -0,0 +1,72 @@ +# 마방진이란? + +마방진이란 모든 행, 열, 주대각선과 일반적으로 다른 대각선의 일부 혹은 모든 대각선 방향으로 수를 모두 더하면 그 합이 같도록 배열된 고유한 정수를 포함하는 정사각형으로 정의한다. + +# 마방진 공식 + +`n`차 마방진은 일반적으로 `n²`개의 고유한 정수 숫자들을 정사각형 안에 정리한 것이다. 모든 행, 열, 대각선의 `n` 개의 숫자를 합하면 같은 상수가 된다. 마방진은 1부터 `n²`까지의 정수를 가진다. 모든 행, 열 및 대각선의 고정 합을 마법 상수 또는 마법합이라고 한다. 이를 M이라는 문자로 표시한다. 전형적인 마방진의 마법 상수는 전적으로 `n`의 값에 따라 결정된다. 따라서 마법합의 값은 다음 공식을 사용하여 계산한다: + +- M = `n(n² + 1)/2` + +- 이는 다른 차수의 마방진을 만드는 데 사용되는 마방진 공식이다. (`n²` + 1)에서 각 위치의 숫자를 빼면, 또 다른 마방진을 만들 수 있는데, 이를 서로 보완적인 마방진(complementary magic square)이라고 부른다. 그리고 1부터 시작하여 연속된 자연수들로 이루어진 마방진을 정규(normal) 마방진이라고 알려져 있다. + +# 마방진을 푸는 방법 + +위에서 언급한 바와 같이, 마법합의 공식은 n(n² + 1)/2이다.\ +3차 마방진에 경우, n = 3 을 대입하여 마법합의 값을 구한다면 3×3 마방진을 쉽게 형성할 수 있다. + +`n = 3`일 경우, 마법합 = 3(3\*3 + 1)/2 = 3(9 + 1)/2 = (3 × 10)/2 = 15이다.\ +이제, 우리는 각 행, 열, 대각선 방향으로 더한 숫자들의 합이 15와 동일하도록 각각의 위치에 숫자를 배치해야 한다. + +## 3차 마방진 만들기 요령 + +`x`를 마방진의 차수라고 하자. + +이 경우, `x = 3`이다. + +`x`와 `y`의 곱이 마법합의 값인 15가 되는 또 다른 숫자 `y`를 생각해 보자. + +그렇다면, `y = 5 {xy = (3)(5) = 15}` + +y의 값은 항상 정사각형 정중앙에 있어야 하고, x의 값은 y의 값 왼쪽 셀에 있어야 한다.\ +x 위의 셀은 아래의 이미지처럼 y – 1를 가진다: + +![magic-square-formula](https://user-images.githubusercontent.com/106215707/192823452-3eea7074-c8f0-4b30-9e83-ef7fb6641a01.png) +![magic-square-1](https://user-images.githubusercontent.com/106215707/192823521-c992c61b-055a-4af8-b697-71fb0ed22566.png) +![magic-square-2](https://user-images.githubusercontent.com/106215707/192823583-8a375043-21d7-4a74-b2d8-119a6ca727eb.png) + +위 마방진의 서로 보완적인 마방진(complementary magic square)을 만들자. + +`(n² + 1) = 32 + 1 = 9 + 1 = 10` + +이제, (n² + 1)의 값인 10에서 각 숫자를 빼라. + +- 첫 번째 행의 숫자들: + + - 10 – 4 = 6 + - 10 – 3 = 7 + - 10 – 8 = 2 + +- 두 번째 행의 숫자들: + + - 10 – 9 = 1 , + - 10 – 5 = 5 , + - 10 – 1 = 9 + +- 세 번째 행의 숫자들: + - 10 – 2 = 8 , + - 10 – 7 = 3 , + - 10 – 6 = 4 + +![magic-square-3](https://user-images.githubusercontent.com/106215707/192823650-21655cfe-0b8f-4bcb-b7d0-76280770c615.png) + +# 참조 + +## 웹사이트 + +- [Byjus](https://byjus.com/maths/magic-square/) +- [geeksforgeeks](https://www.geeksforgeeks.org/magic-square/) + +## The Algorithms 페이지 + +- [마방진](https://the-algorithms.com/ko/algorithm/magic-square) diff --git "a/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\354\234\240\355\201\264\353\246\254\353\223\234 \354\225\214\352\263\240\353\246\254\354\246\230.md" "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\354\234\240\355\201\264\353\246\254\353\223\234 \354\225\214\352\263\240\353\246\254\354\246\230.md" new file mode 100644 index 00000000..d0c7fb0d --- /dev/null +++ "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\354\234\240\355\201\264\353\246\254\353\223\234 \354\225\214\352\263\240\353\246\254\354\246\230.md" @@ -0,0 +1,92 @@ +# 유클리드 알고리즘 + +## 문제 + +양의 정수 $a$와 $b$의 최대공약수 $g = gcd(a, b)$를 구하시오. 여기서 $g$는 나머지 없이 $a$와 $b$ 모두 나누는 가장 큰 수로 정의한다. + +## 발상 + +유클리드 알고리즘은 큰 수에서 작은 수를 빼면 두 수의 최대공약수가 변하지 않는다는 단순한 관찰을 기반한다: + +$a > b$인 상황에서 $g$는 $a$와 $b$의 최대공약수라고 하자. +그렇다면 $g$는 $a$와 $b$를 나눌 수 있다. 따라서 $g$는 $a - b$도 나눌 수 있다. (분배법칙) + +$g'$를 $b$와 $a - b$의 최대공약수라 하자. + +$g' = g$ 귀류법: + +$g' < g$ 또는 $g' > g$이라고 가정하자. + +$g' < g$일 때, $g'$는 _최대_ 공약수가 될 수 없다. +$g$도 $a - b$와 $b$의 공약수이기 때문이다. + +$g' > g$일 때, $g'$는 $b$와 $a - b$의 약수이다 - +즉, $g'n = b$와 $g'm = a - b$로 표현할 수 있는 정수 $n, m$이 존재한다. +따라서 $g'm = a - g'n \iff g'm + g'n = a \iff g'(m + n) = a$이다. +이는 $g'$도 $a$의 약수이며, $g$가 $a$와 $b$의 최대공약수라는 초기 가정과 $g' > g$는 모순이다. + +## 구현 + +실제 실행에서 속도를 높이기 위해 반복해서 뺄셈하는 대신 나머지 연산이 사용된다: +$b$는 $a >= b$만큼 $a$에서 여러 번 반복해서 뺄 수 있다. +이러한 뺄셈 후에는 $b$로 나눌 때 $a$의 나머지만 남게 된다. + +간단한 Lua 구현은 다음과 같다: + +```lua +function gcd(a, b) + while b ~= 0 do + a, b = b, a % b + end + return a +end +``` + +`%`가 나머지 연산자임을 유의하자; +각 단계에서 새로운 `a`에 `b`를 할당하고, +새로운 `b`에는 `a`를 `b`로 나눈 나머지 연산한 값을 할당한다. + +## 분석 + +### 공간 복잡도 + +공간 복잡도는 약간 일정하다: +(일정한 크기로 가정된) $a$와 $b$라는 두 개의 숫자만 저장한다. + +### 시간 복잡도 + +while문의 각 반복은 일정한 시간에 실행되며 최소한 $b$를 절반으로 줄인다. 따라서 $O(log_2(n))$는 런타임의 상한값이다. + +## 연습 + +$a = 42$와 $b = 12$의 최대공약수를 구하라: + +1. $42 \mod 12 = 6$ +2. $12 \mod 6 = 0$ + +결과는 $gcd(42, 12) = 6$. + +유클리드 알고리즘을 사용하여 $a = 633$와 $b = 142$의 최대공약수를 구하라: + +1. $633 \mod 142 = 65$ +2. $142 \mod 65 = 12$ +3. $65 \mod 12 = 5$ +4. $12 \mod 5 = 2$ +5. $5 \mod 2 = 1$ +6. $2 \mod 1 = 0$ + +결과는 $gcd(633, 142) = 1$: $a$와 $b$는 서로소이다. + +## 활용 + +- 분수 단축하기 +- 최소공배수 구하기 +- 두 수가 서로소인지 효율적으로 확인하기 (예: RSA 암호화 시스템에 필요) + +## 참고자료 + +- [위키피디아 "유클리드 호제법" 항목](https://ko.wikipedia.org/wiki/%EC%9C%A0%ED%81%B4%EB%A6%AC%EB%93%9C_%ED%98%B8%EC%A0%9C%EB%B2%95) + +## The Algorithms 페이지 + +- [유클리드 알고리즘](https://the-algorithms.com/ko/algorithm/euclidean-gcd) diff --git "a/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\354\236\220\353\246\277\354\210\230.md" "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\354\236\220\353\246\277\354\210\230.md" new file mode 100644 index 00000000..114be2d0 --- /dev/null +++ "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\354\236\220\353\246\277\354\210\230.md" @@ -0,0 +1,103 @@ +# 자릿수 + +`N = 2019`이라고 할 때, `N`의 자릿수는 4이고, 각 자리의 숫자는 `2`, `0`, `1`, `9`이다. + +몇 가지 예시를 보면: + +``` +N = 00 [영(零)] +자릿수 = 0 + +N = -123 [음수] +자릿수 = 3 + +N = 10000 [양수] +자릿수 = 5 +``` + +## 간단한 방법 + +가장 먼저 떠오르는 방법은 간단하다: + + 1. 숫자 N이 0인지 확인한다. + 2. N이 0이 아닌 경우, 자릿수를 1 늘린다. + 3. N을 10으로 나눈다. + 4. N이 0이 될 때까지 위의 과정을 반복한다. + +**알고리즘 분석:** 위 방법에서 수행되는 작업의 수는 숫자 N의 자릿수와 같다는 사실을 쉽게 알 수 있다. 따라서 이 방법의 시간 복잡도는 $O(d)$이다. ($d$는 숫자 N의 자릿수) + +**모의 실행:** `N = 58964`라고 할 때, + +자릿수를 저장할 변수 `digitsCount`를 0으로 초기화하고, `N`이 0이 아닌 동안 반복적으로 `digitsCount`를 늘리고 `N`을 10으로 나눈다. + +``` +Iteration 1: N not equals to 0 +Increment digitsCount, digitsCount = digitsCount + 1. +digitsCount = 0 + 1 = 1. +N = N/10 = 58964/10 = 5896. + +Iteration 2: N not equals to 0 +Increment digitsCount, digitsCount = digitsCount + 1. +digitsCount = 1 + 1 = 2. +N = N/10 = 5896/10 = 589. + +Iteration 3: N not equals to 0 +Increment digitsCount, digitsCount = digitsCount + 1. +digitsCount = 2 + 1 = 3. +N = N/10 = 589/10 = 58. + +Iteration 4: N not equals to 0 +Increment digitsCount, digitsCount = digitsCount + 1. +digitsCount = 3 + 1 = 4. +N = N/10 = 58/10 = 5. + +Iteration 5: N not equals to 0 +Increment digitsCount, digitsCount = digitsCount + 1. +digitsCount = 4 + 1 = 5. +N = N/10 = 5/10 = 0. + +Iteration 6: N becomes equal to 0. +Terminate any further operation. +Return value of digitsCount. +``` + +그러므로 `N`의 자릿수는 5이다. + +## 더 나은 방법 + +수학을 활용하면 더 나은 방법을 찾을 수 있다. N의 자릿수는 다음의 공식으로 쉽게 구할 수 있다: + +``` +N의 자릿수 = log10(N) + 1. +``` + +**유도:** `N`의 자릿수를 `K`라고 하면: + +``` +10^(K-1) <= N < 10^K +``` + +위 부등식의 양변에 상용로그(밑이 10인 로그)를 취하면: + +``` +K - 1 <= log10(N) < K. + +또는, K - 1 + 1 <= log10(N) + 1 < K + 1 +또는, K <= log10(N) + 1 < K + 1 +``` + +그러므로, + +``` +K = floor(log10(N) + 1) +``` + +**알고리즘 분석:** 위 방법은 `로그`와 `버림`이라는 수학적인 함수를 사용한다. 그러므로 이 방법의 시간 복잡도는 두 함수의 복잡도에 따라 달라진다. 버림함수는 소수점 이하의 숫자들을 버리기만 하면 되기 때문에 사실상 항상 일정한 시간이 걸린다 (적어도 그렇게 만들기 쉽다). 일반적으로 고정폭 부동 소수점 값을 사용하기 때문에 실용적으로는 `로그함수도 일정한 시간이 걸린다고 가정`할 수 있다. 하지만 임의 정밀도 "큰 수" 라이브러리를 사용하면, 사용되는 로그 알고리즘에 따라 로그함수의 성능이 달라질 수 있다. + +## 영상 URL + +- [Programming Tutorials (C, C++)](https://www.youtube.com/watch?v=ngWnvWR8NkE) + +## 출처 + +- [GeeksforGeeks](https://www.geeksforgeeks.org/program-count-digits-integer-3-different-methods/) diff --git "a/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\354\247\204\354\225\275\354\210\230\354\235\230 \355\225\251.md" "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\354\247\204\354\225\275\354\210\230\354\235\230 \355\225\251.md" new file mode 100644 index 00000000..8014d44b --- /dev/null +++ "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\354\247\204\354\225\275\354\210\230\354\235\230 \355\225\251.md" @@ -0,0 +1,48 @@ +# 진약수의 합 + +$s(n)$은 양의 정수 $n$에 대한 모든 진약수의 합을 구하는 표현식이다. 여기서, 진약수는 자기 자신인 $n$을 제외한 $n$의 모든 약수를 의미한다. + +$$ s(n) = \sum\_{d | n, d \neq n} {d} $$ + +예를 들면, $15$ 에 대한 진약수의 합은 $(1 + 3 + 5) = 9$ 이다. + +진약수의 합은 정수론에서 매우 유용한 성질이며, 다음을 정의하는 데 사용할 수 있다: + +- 소수(Prime Numbers) +- 부족수(Deficient Numbers) +- 과잉수(Abundant Numbers) +- 완전수(Perfect Numbers) +- 친화수(Amicable Numbers) +- 불가촉수(Untouchable Numbers) +- 진약수의 합 수열(Aliquot Sequence of a number) +- 준완전수&근완전수(Quasiperfect & Almost Perfect Numbers) +- 사교수(Sociable Numbers) + +## 진약수의 합에 관한 사실들 + +- 1은 진약수의 합이 0인 유일한 수 +- 완전수는 진약수들의 합이 자기 자신이 되는 수 +- $pq$처럼 곱셈 형태인 [_준소수_](https://en.wikipedia.org/wiki/Semiprime)에 대한 진약수의 합은 $p + q + 1$ 이다 (p와 q는 1이 아닌 서로 다른 숫자인 상황을 가정) +- 진약수의 합은 세계적으로 유명한 수학자 [Paul Erdős](https://en.wikipedia.org/wiki/Paul_Erd%C5%91s)가 가장 좋아하는 조사 주제 중 하나 + +## 진약수의 합을 찾는 접근방식 + +### 1단계: _진약수 구하기_ + +$1$부터 $[\frac{n} 2]$까지의 모든 수를 반복하여, $n$을 나눌 수 있는지 확인하고, 분할할 수 있다면 진약수에 추가한다. + +$[\frac{n} 2]$와 같은 상계를 가지는 이유는 $n$이 짝수인 경우, 가능한 진약수 중 가장 큰 진약수는 $\frac{n} 2 $이며, $n$이 홀수인 경우, 가능한 진약수 중 가장 큰 진약수가 $[\frac{n} 2]$보다 작다. 따라서, 상계를 만들어 계산하는 방법이 $1$부터 $n$까지 모든 수를 반복하는 방법보다 불필요한 계산을 줄일 수 있다. + +### 2단계: _진약수 더하기_ + +이렇게 구한 합은 진약수의 합이다 + +## 출처 + +- [위키피디아 "진약수의 합" 항목](https://ko.wikipedia.org/wiki/%EC%A7%84%EC%95%BD%EC%88%98%EC%9D%98_%ED%95%A9) +- [Wikipedia "Aliquot sum" 항목](https://en.wikipedia.org/wiki/Aliquot_sum) +- [GeeksForGeeks](https://www.geeksforgeeks.org/aliquot-sum/) + +## The Algorithms 페이지 + +- [진약수의 합](https://the-algorithms.com/ko/algorithm/aliquot-sum) diff --git "a/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\354\265\234\353\214\223\352\260\222.md" "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\354\265\234\353\214\223\352\260\222.md" new file mode 100644 index 00000000..2eb04336 --- /dev/null +++ "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\354\265\234\353\214\223\352\260\222.md" @@ -0,0 +1,94 @@ +# 최댓값 + +숫자로 구성된 리스트의 최댓값을 찾는다. + +## 활용 + +리스트의 최댓값을 찾으면, 다음과 같은 작업들을 수행할 수 있다. + +- 가장 큰 값을 기준으로 레코드 정렬하기 +- 특정 항목을 탐색하는 시간 줄이기 + +## 방법 + +최댓값은 다양한 방식으로 찾을 수 있다. 여기서는 세 가지 방법을 제시한다. + +1. 리스트의 모든 원소를 비교한다. +2. 이미 정의된 함수를 사용한다. +3. 정렬한다. + +## 예시 1 + +리스트의 모든 원소를 비교한다: + +`[6, 4, 50, 8, 70, 2, 20]`라는 리스트가 주어졌을 때, 이 리스트의 최댓값을 구하라. + +### 1단계 + +`[6, 4, 50, 8, 70, 2, 20]`를 함수에 입력한다. + +### 2단계 + +비교 과정을 통해 가장 큰 숫자를 찾을 것이다. 리스트의 첫 원소를 최댓값으로 설정한다. + +`max = array[0]`이므로, `max = 6`이다. + +### 3단계 + +리스트의 모든 원소와 최댓값을 비교한다. 만약 원소가 최댓값보다 크면, 그 수를 최댓값으로 지정한다. + +`max`와 `array[2]`를 비교하면 `6 < 50`이므로, `max = 50`이 된다. + +모든 원소와 비교가 끝나면, `max = 70`이다. + +### 4단계 + +`70`을 반환한다. + +## 예시 2 + +이미 정의된 함수를 사용한다: + +`[6, 4, 50, 8, 70, 2, 20]`라는 리스트가 주어졌을 때, 이 리스트의 최댓값을 구하라. + +### 1단계 + +`[6, 4, 50, 8, 70, 2, 20]`를 함수에 입력한다. + +### 2단계 + +이미 정의된 `max` 함수가 `70`을 반환한다. + +### 3단계 + +`70`을 반환한다. + +## 예시 3 + +정렬한다: + +`[6, 4, 50, 8, 70, 2, 20]`라는 리스트가 주어졌을 때, 이 리스트의 최댓값을 구하라. + +### 1단계 + +`[6, 4, 50, 8, 70, 2, 20]`를 함수에 입력한다. + +### 2단계 + +이미 정의된 `sort` 함수가 전체 리스트를 오름차순으로 정렬하여 `[2, 4, 6, 8, 20, 50, 70]`을 반환한다. + +### 3단계 + +이미 정의된 `last` 함수가 리스트의 마지막 원소로 `70`을 반환한다. + +### 4단계 + +`70`을 반환한다. + +## 영상 URL + +- [GeeksforGeeks](https://youtu.be/En68ipRaFOU) + +## 출처 + +- [GeeksforGeeks](https://www.geeksforgeeks.org/c-program-find-largest-element-array/) diff --git "a/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\355\217\211\352\267\240\352\260\222.md" "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\355\217\211\352\267\240\352\260\222.md" new file mode 100644 index 00000000..553fcacf --- /dev/null +++ "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\355\217\211\352\267\240\352\260\222.md" @@ -0,0 +1,65 @@ +# 평균값 + +숫자로 구성된 리스트의 평균값을 계산한다. + +## 활용 + +평균값을 계산하는 것은 다음과 같은 상황에서 유용하다: + +- 비디오 게임에서 같은 레벨의 플레이어의 평균 점수 결정 +- 이번 학기 수강생의 평균 시험 성적 산출 +- 폴더 내 모든 파일의 평균 크기 결정 + +## 절차 + +1. 숫자로 구성된 리스트를 입력한다. +2. 리스트에 속한 수를 모두 합한다. +3. 리스트에 속한 수의 개수를 센다. +4. 합을 리스트에 속한 수의 개수로 나눈다. +5. 평균값을 반환한다. + +## 예시 + +`[2, 4, 6, 8, 20, 50, 70]`라는 리스트가 주어졌을 때, 이 리스트의 평균값을 구하라. + +### 1단계 + +`[2, 4, 6, 8, 20, 50, 70]`를 함수에 입력한다. + +### 2단계 + +리스트에 속한 수를 모두 합한다. + +`2 + 4 + 6 + 8 + 20 + 50 + 70 = 160`이므로, `sum = 160`. + +### 3단계 + +리스트에 속한 수의 개수를 센다. + +위 리스트는 7개의 숫자를 가지고 있으므로, `count = 7`. + +### 4단계 + +모든 수의 합을 수의 개수로 나눈다. + +``` +sum = 160 +count = 7 +``` + +유효숫자를 무시하면 22.857142 + +유효숫자를 고려하면 23 + +### 5단계 + +22.857142나 23을 반환한다. + +## 영상 URL + +- [Khan Academy](https://www.khanacademy.org/math/cc-sixth-grade-math/cc-6th-data-statistics/mean-and-median/v/mean-median-and-mode) + +## 기타 + +- [위키피디아 "평균" 항목](https://ko.wikipedia.org/wiki/%ED%8F%89%EA%B7%A0) +- [Wikipedia "Mean" 항목](https://en.wikipedia.org/wiki/Mean) diff --git "a/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\355\224\274\353\263\264\353\202\230\354\271\230 \354\210\230.md" "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\355\224\274\353\263\264\353\202\230\354\271\230 \354\210\230.md" new file mode 100644 index 00000000..b1731808 --- /dev/null +++ "b/ko/\352\270\260\354\264\210 \354\210\230\355\225\231/\355\224\274\353\263\264\353\202\230\354\271\230 \354\210\230.md" @@ -0,0 +1,74 @@ +# 피보나치 수 + +수학에서, 일반적으로 $F(n)$으로 표기하는 피보나치 수는 첫째 및 둘째 항이 1이며 그 뒤의 모든 항은 바로 앞 두 항의 합인 피보나치 수열을 구성한다. + +`[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...]` + +## 활용 + +`N번째 피보나치 수`를 구하는 것은 다양하게 활용될 수 있다: + +- 최근 피보나치 수열과 황금비는 고에너지 물리학, 양자역학, 암호학, 코딩 등 다양한 과학 분야의 연구자들에게 큰 관심을 받고 있다. + +## 절차 + +1. 기본 행렬을 준비한다. +2. 기본 행렬의 거듭제곱을 계산한다. +3. 행렬의 원소 중 필요한 값을 찾는다. + +## 예시 + +`8번째` 피보나치 수를 구하라. + +### 0단계 + +``` +| F(n+1) F(n) | +| F(n) F(n-1)| +``` + +### 1단계 + +``` +기본 행렬 +| 1 1 | +| 1 0 | +``` + +### 2단계 + +``` +기본 행렬의 제곱 +| 2 1 | +| 1 1 | +``` + +### 3단계 + +``` +기본 행렬의 네제곱 +| 5 3 | +| 3 2 | +``` + +### 4단계 + +``` +기본 행렬의 여덟제곱 +| 34 21 | +| 21 13 | +``` + +### 5단계 + +``` +F(8) = 21 +``` + +## 영상 URL + +- [Gaurav Sen](https://www.youtube.com/watch?v=EEb6JP3NXBI) + +## 기타 + +- [증명](https://brilliant.org/wiki/fast-fibonacci-transform/) diff --git "a/ko/\354\204\240\355\203\235 \354\225\214\352\263\240\353\246\254\354\246\230/\355\200\265 \354\205\200\353\240\211\355\212\270.md" "b/ko/\354\204\240\355\203\235 \354\225\214\352\263\240\353\246\254\354\246\230/\355\200\265 \354\205\200\353\240\211\355\212\270.md" new file mode 100644 index 00000000..94779760 --- /dev/null +++ "b/ko/\354\204\240\355\203\235 \354\225\214\352\263\240\353\246\254\354\246\230/\355\200\265 \354\205\200\353\240\211\355\212\270.md" @@ -0,0 +1,45 @@ +# 퀵 셀렉트 + +### 문제 + +주어진 배열에 대해, k번째로 큰/작은 원소를 선형 시간복잡도 안에 찾아라. + +### 접근 + +- 배열에서 무작위로 '피벗'으로 쓰일 원소를 정한다. +- 퀵 소트에서와 같이, 파티션을 적용한다. +- 파티션을 나누면, 피벗보다 작은 원소들은 피벗의 왼쪽 부분에 위치하고, 피벗보다 큰 원소들은 피벗의 오른쪽 부분에 위치하게 된다. 즉, 피벗은 배열 내에서 정렬된 위치에 존재한다. +- 피벗의 인덱스가 k라면, 원하는 원소를 찾았으므로 피벗을 반환한다. +- 아니라면, 현재 피벗의 위치가 k보다 큰지 작은지 확인하고, 이에 따라 k번째 원소가 위치할 수 있는 범위 안에서 새로운 피벗을 고른다. +- 이를 반복한다. + +### 시간 복잡도 + +- 최악의 경우 `O(n^2)` + +- 최선의 경우 `O(n)` + +- 평균 `O(n)` + + +### 알고리즘을 고안한 사람 + +- 이 알고리즘은 토니 호어(Tony Hoare)에 의해 발명되어, `호어의 선택 알고리즘`이라고도 불린다. + +### 예시 + +``` +배열 = {8,2,11,7,9,1,3} +인덱스: 0 1 2 3 4 5 6 + +k = 4, 즉 4번째로 작은 원소를 찾고 싶다고 하자. + +1. 무작위로 피벗을 고른다. 여기서는 7을 골랐다고 하자. +2. 7과 마지막 원소(3)의 위치를 바꾸고, 파티션을 적용한다. +3. 그러면 7보다 작은 모든 원소들은 7의 왼쪽에 있고, 7보다 큰 모든 원소들은 7의 오른쪽에 있게 된다. 즉, 7은 정렬된 위치에 있다. (배열 = {2,3,1,7,8,9,11}) +4. 7의 위치가 4번째이므로, 우리가 찾는 원소이다. 7을 반환한다. +``` + +### 관련 영상 + +[여러가지 시간 복잡도에 따라 K번째로 작은/큰 원소를 찾는 방법을 설명하는 영상](https://youtu.be/hGK_5n81drs) diff --git "a/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\352\267\270\353\236\230\355\224\204/\353\262\250\353\250\274-\355\217\254\353\223\234 \354\225\214\352\263\240\353\246\254\354\246\230.md" "b/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\352\267\270\353\236\230\355\224\204/\353\262\250\353\250\274-\355\217\254\353\223\234 \354\225\214\352\263\240\353\246\254\354\246\230.md" new file mode 100644 index 00000000..a5f41609 --- /dev/null +++ "b/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\352\267\270\353\236\230\355\224\204/\353\262\250\353\250\274-\355\217\254\353\223\234 \354\225\214\352\263\240\353\246\254\354\246\230.md" @@ -0,0 +1,104 @@ +# 벨먼-포드 알고리즘 + +## 문제 + +방향 가중치 그래프 $G(V, E)$와 시작점 $s \in V$가 주어졌을 때, 각 점 $v \in V$에 대하여 $s$와 $v$를 잇는 가장 짧은 경로를 구하라. ($V$는 꼭짓점의 집합, $E$는 간선의 집합) + +## 절차 + +1. 시작점에서 모든 꼭짓점까지의 거리를 무한대로 초기화한다. +2. 시작점으로의 거리를 0으로 초기화한다. +3. `dist[s]`를 제외한 모든 값을 무한대로 하는 크기가 $|V|$인 `dist`라는 배열을 만든다. +4. 다음을 $|V|-1$회 반복한다. +5. $E$에 속한 모든 간선 `(u,v)`에 대해 다음을 반복한다: + + ``` + dist[v] = minimum(dist[v], dist[u] + weight of edge) + ``` + +6. 마지막으로 모든 간선에 대해 음의 사이클(negative cycle)이 없는지 확인한다. + +## 시간 복잡도 + +$O(VE)$ + +## 공간 복잡도 + +$O(V^2)$ + +## 만든 사람 + +- [리처드 벨먼](https://ko.wikipedia.org/wiki/%EB%A6%AC%EC%B2%98%EB%93%9C_%EB%B2%A8%EB%A8%BC) +- [래스터 포드 주니어](https://en.wikipedia.org/wiki/L._R._Ford_Jr.) + +## 예시 + +``` + 꼭짓점: [A, B, C, D, E] + + 간선: [A->B, A->C, B->C, B->D, B->E, D->C, D->B, E->D] + 가중치: [ -1, 4, 3, 2, 2, 5, 1, -4 ] + 시작점: [ A, A, B, B, B, D, D, E ] + + + 꼭짓점 개수 = 5 + 간선 개수 = 8 + + // A->B + graph->edge[0].src = A + graph->edge[0].dest = B + graph->edge[0].weight = -1 + + // A->C + graph->edge[1].src = A + graph->edge[1].dest = C + graph->edge[1].weight = 4 + + // B->C + graph->edge[2].src = B + graph->edge[2].dest = C + graph->edge[2].weight = 3 + + // B->D + graph->edge[3].src = B + graph->edge[3].dest = D + graph->edge[3].weight = 2 + + // B->E + graph->edge[4].src = B + graph->edge[4].dest = E + graph->edge[4].weight = 2 + + // D->C + graph->edge[5].src = D + graph->edge[5].dest = C + graph->edge[5].weight = 5 + + // D->B + graph->edge[6].src = D + graph->edge[6].dest = B + graph->edge[6].weight = 1 + + // E->D + graph->edge[7].src = E + graph->edge[7].dest = D + graph->edge[7].weight = -3 + + for source = A + + 꼭짓점 시작점으로부터의 거리 + A 0 (A->A) + B -1 (A->B) + C 2 (A->B->C = -1 + 3) + D -2 (A->B->E->D = -1 + 2 + -3) + E 1 (A->B->E = -1 + 2) +``` + +## 영상 URL + +- [Yusuf Shakeel (C)](https://www.youtube.com/watch?v=hxMWBBCpR6A) + +## 출처 + +- [GeeksforGeeks](https://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/) +- [위키피디아 "벨먼-포드 알고리즘" 항목](https://ko.wikipedia.org/wiki/%EB%B2%A8%EB%A8%BC-%ED%8F%AC%EB%93%9C_%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98) diff --git "a/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\353\260\260\354\227\264/\353\260\260\354\227\264.md" "b/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\353\260\260\354\227\264/\353\260\260\354\227\264.md" new file mode 100644 index 00000000..78536127 --- /dev/null +++ "b/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\353\260\260\354\227\264/\353\260\260\354\227\264.md" @@ -0,0 +1,14 @@ +# 배열 + +배열은 프로그래밍에서 가장 기본적인 데이터 구조이다. 배열은 정적 배열과 동적 배열로 나눠진다. 정적 배열은 요소의 수가 고정되어 있고, 각각은 메모리의 동일한 공간을 차지한다. 즉, 정적 배열이 차지하는 메모리는 컴파일 시간에 결정되지만, 동적 배열의 경우 크기가 고정되지 않는다. + +배열 요소의 값은 $O(1)$ 시간 안에 검색할 수 있다. + +모든 배열은 연속된 메모리 주소를 가진다. 우리는 인덱스로 각 요소에 접근할 수 있다. +가장 낮은 인덱스는 첫 요소에 해당하고 가장 높은 인덱스는 마지막 요소에 해당한다. + +## 영상 URL + +- [GeeksforGeeks](https://www.geeksforgeeks.org/introduction-to-arrays/) +- [The Coding Train](https://youtu.be/NptnmWvkbTw) +- [Simple Snippets (C++)](https://youtu.be/ibeGtDEQGz0) diff --git "a/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\354\212\244\355\203\235/\354\212\244\355\203\235.md" "b/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\354\212\244\355\203\235/\354\212\244\355\203\235.md" new file mode 100644 index 00000000..50106851 --- /dev/null +++ "b/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\354\212\244\355\203\235/\354\212\244\355\203\235.md" @@ -0,0 +1,27 @@ +# 스택 + +스택은 객체에 접근하는 순서가 정해진 기본적인 선형 데이터 구조이다. 이 순서는 LIFO (Last In First Out) 또는 FILO (First in Last Out)라고 불린다. 대표적인 스택 예시로는 식당의 접시, 쌓인 책 더미, 프링글스 상자 등이 있다. +스택은 파서 및 식 평가, 백트래킹 알고리즘 등을 구현하는 데 사용된다. 기본 작업은 스택에 요소를 넣는 것(push)과 스택에서 요소를 빼는 것(pop)이다. +연결 리스트 또는 리스트 배열을 사용하여 구현할 수 있다. 스택은 가장 위에 있는 요소를 가리키는 "top 포인터" 하나만 가진다. 삽입과 삭제는 스택의 한쪽 끝에서만 발생한다. + +# 표준 스택 연산자 + +1) push(): 스택의 맨 위에 요소 삽입 +2) pop(): 스택의 맨 위에 있는 요소 삭제 +3) isEmpty(): 스택이 비어 있는지 여부 확인 +4) isFull(): 스택이 가득 찼는지 여부 확인 +5) peek(): 맨 위에 있는 요소의 값을 가져옴(제거X) + +# 스택으로 작업하기 + +스택에서는 TOP이라는 포인터를 사용하여 스택의 맨 위에 있는 요소를 추적한다. 스택을 초기화할 때, TOP의 값을 -1로 설정하여 TOP == -1인 경우 스택이 비어 있는지 확인할 수 있다. 요소를 push할 때마다, TOP의 값을 증가시키고, TOP이 가리키는 위치에 새로운 요소를 넣는다. 요소를 pop할 때, TOP이 가리키는 값을 반환하고, TOP의 값을 감소시킨다. push하기 전에 스택이 가득 차 있는지 확인하고, pop하기 전에 스택이 이미 비어 있는지 확인한다. + +# 소스 + +1) [Stack Data Structure - GeeksForGeeks](https://www.geeksforgeeks.org/stack-data-structure/) +2) [DS-Stack JavaPoint](https://www.javatpoint.com/data-structure-stack) +3) [Stack Data Structure](https://www.programiz.com/dsa/stack) + +# 영상 URL + +- [Stack Data Structure](https://youtu.be/F1F2imiOJfk) diff --git "a/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270/\353\213\250\354\235\274 \354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270.md" "b/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270/\353\213\250\354\235\274 \354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270.md" new file mode 100644 index 00000000..d07fe863 --- /dev/null +++ "b/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270/\353\213\250\354\235\274 \354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270.md" @@ -0,0 +1,43 @@ +# 단일 연결 리스트 + +단일 연결 리스트는 선형으로 연결된 데이터 구조로, 노드로 구성되어 있다. 각 노드는 내용이 저장된 `data` 변수와 다음 노드를 가리키는 `pointer`로 구성되어 있다. 연결 리스트는 이런 노드들의 첫 원소를 가리키는 포인터를 가지며, 연산에 걸리는 시간을 훨씬 절약하기 위해 마지막 노드를 가리키는 포인터를 가질 수도 있다. 전체 노드 수를 저장하는 `length` 변수를 추가할 수도 있다. + +### 배열보다 우수한 점 + +- 연결 리스트의 크기는 고정되어 있지 않다. (가변 크기) +- 배열에 비해 원소의 제거와 추가가 쉽다. + +### 단점 + +- 원소에 순차적으로 접근해야 한다. (임의 접근 불가) +- 포인터를 저장하기 위해 추가적인 메모리가 필요하다. + +### 시간 복잡도 + +| 작업 | 평균 | 최악 | +| --- | ------ | ------ | +| 접근 | $O(n)$ | $O(n)$ | +| 탐색 | $O(n)$ | $O(n)$ | +| 삽입 | $O(1)$ | $O(1)$ | +| 제거 | $O(1)$ | $O(1)$ | + +## 예시 + +```java +class LinkedList { +<<<<<<< HEAD + Node head; // 첫 원소를 가리키는 포인터 + Node tail; // (Optional) 마지막 원소를 가리키는 포인터 + + int length; // (Optional) 전체 노드 수 + + class Node { + int data; // 노드의 데이터 + Node next; // 다음 노드를 가리키는 포인터 + } +} +``` + +## 영상 URL + +- [CS50](https://www.youtube.com/watch?v=5nsKtQuT6E8) diff --git "a/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270/\354\233\220\355\230\225 \354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270.md" "b/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270/\354\233\220\355\230\225 \354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270.md" new file mode 100644 index 00000000..5e956227 --- /dev/null +++ "b/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270/\354\233\220\355\230\225 \354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270.md" @@ -0,0 +1,69 @@ +# 원형 연결 리스트 + +원형 연결 리스트는 노드로 이루어진 최종 연결 데이터 구조이다. 단일 및 이중 연결 리스트와 마찬가지로, 각 노드는 그 내용이 저장되는 변수 `data`와 목록의 다음 노드에 대한 `pointer`로 구성된다. +연결 리스트는 인접한 요소에 대해 `pointer`를 가지고 있지만 마지막 노드는 헤드 노드, 즉 첫 번째 노드 자체를 향해 연결되어 원형 모양을 형성한다. + +### 배열 & 단일 연결 리스트 & 이중 연결 리스트보다 우수한 점 + +- 모든 노드가 시작점이 될 수 있다. +- 큐 구현에 유용하다. +- 원형 연결 리스트는 응용프로그램에서 목록을 반복적으로 순환하는 데 유용하다. +- 원형 이중 연결 리스트는 `Fibonacci Heap`과 같은 고급 자료구조의 구현을 위해 사용된다. +- 연결 리스트의 크기가 고정되어 있지 않다(가변 크기). +- 배열에 비해 `element`삭제, 추가비용이 적다. + +### 단점 + +- 원형 연결 리스트는 단일 연결 리스트에 비해 복잡하다. +- 원형 연결 리스트의 `reversing`이 단일 연결 리스트나 이중 연결 리스트에 비해 복잡하다. +- 주의하지 않으면 무한 루프에 빠질 수 있다. +- `element`는 배열과 비교하여 직접 접근할 수 없고 순차적으로 접근해야 한다. +- 연결된 리스트의 `element`를 연결하는 `pointer`에 대한 추가 메모리 할당을 필요하다. + +### 시간 복잡도 + +| Operation | Average | Worst | +|-----------|---------|-------| +| Initialize| O(1) | - | +| Access | O(n) | O(n) | +| Search | O(n) | O(n) | +| Insertion | O(1) | O(n) | +| Deletion | O(1) | O(n) | + +### 실제 적용 사례 + +- CPU 자원 할당 +- 멀티플레이어 보드 게임 + +### SLL v.s. CLL + +![영상](https://tutorialhorizon.com/static/media/algorithms/2016/03/Circular-Linked-List.png) + +### 예시 + +Insertion +```java +public void insertHead(int data) +{ + Node temp = new Node(data); + Node cur = head; + while(cur.getNext() != head) + cur = cur.getNext(); + if(head == null) + { + head = temp; + head.setNext(head); + } + else + { + temp.setNext(head); + head = temp; + cur.setNext(temp); + } + size++; +} + ``` + +## 영상 URL + +[유투브 영상](https://youtu.be/HMkdlu5sP4A) diff --git "a/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270/\354\235\264\354\244\221 \354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270.md" "b/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270/\354\235\264\354\244\221 \354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270.md" new file mode 100644 index 00000000..df89bcec --- /dev/null +++ "b/ko/\354\236\220\353\243\214\352\265\254\354\241\260/\354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270/\354\235\264\354\244\221 \354\227\260\352\262\260 \353\246\254\354\212\244\355\212\270.md" @@ -0,0 +1,105 @@ +# 이중 연결 리스트 + +단일 연결 리스트는 선형으로 연결된 데이터 구조로, 노드로 구성되어 있다. 각 노드는 내용이 저장된 `data` 변수와 다음 노드를 가리키는 `pointer`로 구성되어 있다. 연결 리스트는 이런 노드들의 첫 원소를 가리키는 포인터를 가지며, 연산에 걸리는 시간을 훨씬 절약하기 위해 마지막 노드를 가리키는 포인터를 가질 수도 있다. 전체 노드 수를 저장하는 `length` 변수를 추가할 수도 있다. + +**이중 연결 리스트 (DLL)** 는 여기에 더해 이전 노드를 가리키는 `previous pointer`라는 추가적인 포인터도 가진다. + +### 단일 연결 리스트보다 우수한 점 + +- 정방향과 역방향 순회가 가능하다. +- 제거될 노드를 가리키는 포인터가 알려져 있다면, 원소의 제거가 더 효율적이다. +- 특정 노드 앞에 새로운 노드를 빠르게 삽입할 수 있다. +- 단일 연결 리스트에서 노드를 제거하려면 이전 노드의 `pointer`를 알아야 한다. 어쩌면 이 노드를 찾기 위해 리스트를 전부 순회해야 할 수도 있다. 그러나 DLL에서는 `previous pointer`를 이용하여 이전 노드를 찾을 수 있다. + +### 단점 + +- 포인터를 저장하기 위한 메모리가 단일 연결 리스트보다 더 많이 필요하다. 그러나 포인터 하나로 DLL을 구현할 수도 있다. +- 모든 작업에 추가적인 연산이 필요하다. 예를 들어, 삽입 시 `pointer`와 `previous pointer`를 모두 수정해야 한다. + +### 시간 복잡도 + +| 작업 | 평균 | 최악 | +| --- | ----------- | ------ | +| 접근 | $\Theta(n)$ | $O(n)$ | +| 탐색 | $\Theta(n)$ | $O(n)$ | +| 삽입 | $\Theta(1)$ | $O(1)$ | +| 제거 | $\Theta(1)$ | $O(1)$ | + +## 예시 + +```java +class LinkedList { + Node head; // 첫 원소를 가리키는 포인터 + Node tail; // (Optional) 마지막 원소를 가리키는 포인터 + + int length; // (Optional) 전체 노드 수 + + class Node { + int data; // 노드의 데이터 + Node next; // 다음 노드를 가리키는 포인터 + Node prev; + + Node(int data) { + this.data = data; + } + } +``` + +- 맨 앞에 노드 추가하기 + ![Tracing of algorithm](https://www.geeksforgeeks.org/wp-content/uploads/gq/2014/03/DLL_add_front1.png) + + ```java + public void push(int new_data) { + + /* 1. 노드를 만든다 + 2. 데이터를 입력한다다 */ + Node new_Node = new Node(new_data); + + /* 3. 새로운 노드의 next 변수를 head로, prev 변수를 NULL로 설정한다 */ + new_Node.next = head; + new_Node.prev = null; + + /* 4. head의 prev 변수를 새로운 노드로 변경한다 */ + if (head != null) + head.prev = new_Node; + + /* 5. head를 새로운 노드로 변경한다 */ + head = new_Node; + } + ``` + +- 주어진 노드 뒤에 노드 추가하기 + ![Tracing of algorithm](https://www.geeksforgeeks.org/wp-content/uploads/gq/2014/03/DLL_add_middle1.png) + + ```java + public void InsertAfter(Node prev_Node, int new_data) { + + /*1. 주어진 prev_Node가 NULL인지 확인한다 */ + if (prev_Node == null) { + System.out.println("The given previous node cannot be NULL "); + return; + } + + /* 2. 노드를 만든다 + 3. 데이터를 입력한다 */ + Node new_Node = new Node(new_data); + + /* 4. 새로운 노드의 next 변수를 prev_Node의 next 변수값으로 설정한다 */ + new_Node.next = prev_Node.next; + + /* 5. prev_Node의 next 변수를 새로운 노드로 변경한다 */ + prev_Node.next = new_Node; + + /* 6. 새로운 노드의 prev 변수를 prev_Node로 설정한다 */ + new_Node.prev = prev_Node; + + /* 7. 새로운 노드의 다음 노드의 prev 변수를 새로운 노드로 변경한다 */ + if (new_Node.next != null) + new_Node.next.prev = new_Node; + } + } + ``` + +## 영상 URL + +- [CS50](https://www.youtube.com/watch?v=FHMPswJDCvU) diff --git "a/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\352\263\204\354\210\230 \354\240\225\353\240\254.md" "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\352\263\204\354\210\230 \354\240\225\353\240\254.md" new file mode 100644 index 00000000..4f53712e --- /dev/null +++ "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\352\263\204\354\210\230 \354\240\225\353\240\254.md" @@ -0,0 +1,50 @@ +# 계수 정렬 + +## 문제 + +n개 원소로 구성된 배열이 주어졌을 때, 이 배열을 정렬하는 함수를 구하라. + +## 절차 + +- Find out the maximum element (let's call it `max`) from the given array. +- Initialize an array of length `max+1` with all elements set to 0 to store the array's count. +- Store the count of each element at their respective index in the array's count. +- Store cumulative sum of the elements of the count array. It helps in placing the elements into the correct index of the sorted array. +- Find the index of each element of the original array in the array's count. This gives the cumulative count. +- Place the element at the index calculated and decrease its count by one. + +## 시간 복잡도 + +- $O(n+k)$ ($k$는 음수가 아닌 key 값의 범위) + +## 공간 복잡도 + +- $O(n+k)$ ($k$는 음수가 아닌 key 값의 범위) + +## 만든 사람 + +- [해롤드 H. 수어드](https://en.wikipedia.org/wiki/Harold_H._Seward) + +## 예시 + +``` +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 +``` + +## 영상 URL + +- [GeeksforGeeks](https://www.youtube.com/watch?v=7zuGmKfUt7s) + +## 기타 + +- [David Galles (University of San Francisco)](https://www.cs.usfca.edu/~galles/visualization/CountingSort.html) diff --git "a/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\352\270\260\354\210\230 \354\240\225\353\240\254.md" "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\352\270\260\354\210\230 \354\240\225\353\240\254.md" new file mode 100644 index 00000000..1048889e --- /dev/null +++ "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\352\270\260\354\210\230 \354\240\225\353\240\254.md" @@ -0,0 +1,51 @@ +# 기수 정렬 + +The lower bound for Comparison based sorting algorithm (Merge Sort, Heap Sort, Quick-Sort .. etc) is `Ω(nlogn)`, i.e., they cannot do better than `nlogn`. + +Counting sort is a linear time sorting algorithm that sort in `O(n+k)` time when elements are in the range from 1 to k. + +What if the elements are in the range from 1 to n2? We can’t use counting sort because counting sort will take `O(n2)` which is worse than comparison-based sorting algorithms. Can we sort such an array in linear time? + +Radix Sort is the answer. The idea of Radix Sort is to do digit by digit sort starting from least significant digit to most significant digit. Radix sort uses counting sort as a subroutine to sort. + +## 절차 + +Do following for each digit i where i varies from least significant digit to the most significant digit. +Sort input array using counting sort (or any stable sort) according to the i’th digit. + +## 예시 + +Original, unsorted list: +`170, 45, 75, 90, 802, 24, 2, 66` + +Sorting by least significant digit (1s place) gives: + +[*Notice that we keep 802 before 2, because 802 occurred +before 2 in the original list, and similarly for pairs +170 & 90 and 45 & 75.] + +Sorting by next digit (10s place) gives: + +[*Notice that 802 again comes before 2 as 802 comes before 2 in the previous list.] + +`802, 2, 24, 45, 66, 170, 75, 90` + +Sorting by the most significant digit (100s place) gives: +`2, 24, 45, 66, 75, 90, 170, 802` + +## 시간 복잡도 + +Let there be d digits in input integers. Radix Sort takes `O(d*(n+b))` time where b is the base for representing numbers, for example, for the decimal system, b is 10. +What is the value of d? If `k` is the maximum possible value, then d would be `O(logb(k))`. So overall time complexity is `O((n+b) * logb(k))`. Which looks more than the +time complexity of comparison-based sorting algorithms for a large k. Let us first limit k. Let k <= nc where c is a constant. In that case, the complexity becomes +`O(n logb(n))`. But it still doesn’t beat comparison-based sorting algorithms. + +## Is Radix Sort preferable to Comparison based sorting algorithms like Quick-Sort? + +If we have `log2n` bits for every digit, the running time of Radix appears to be better than Quick Sort for a wide range of input numbers. The constant factors hidden in +asymptotic notation are higher for Radix Sort and Quick-Sort uses hardware caches more effectively. Also, Radix sort uses counting sort as a subroutine and counting sort +takes extra space to sort numbers. + +## 영상 URL + +- [](https://youtu.be/nu4gDuFabIM) diff --git "a/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\353\262\204\353\270\224 \354\240\225\353\240\254 (\354\236\254\352\267\200 \353\262\204\354\240\204).md" "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\353\262\204\353\270\224 \354\240\225\353\240\254 (\354\236\254\352\267\200 \353\262\204\354\240\204).md" new file mode 100644 index 00000000..2c65b559 --- /dev/null +++ "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\353\262\204\353\270\224 \354\240\225\353\240\254 (\354\236\254\352\267\200 \353\262\204\354\240\204).md" @@ -0,0 +1,74 @@ +# 버블 정렬 (재귀 버전) + +Bubble Sort is one of the simplest sorting algorithms that compares two elements at a time and swaps them if they are in the wrong order. This process is repeated until the entire sequence is in order. + +## 절차 + +Base case: If the size of the array is 1, return. + +- We need to fix the last element of the current sub-array. For this, iterate over the entire array using normal Bubble Sort, and perform swapping. +- Next, call the function on the entire array excluding the last element(which was fixed by the iteration in the above step) +- Repeat until Base Case is reached. + +## 시간 복잡도 + +- 최선: $O(n)$ +- 평균: $O(n^2)$ + +## 공간 복잡도 + +- 최악: $O(n)$ (참고: 기존 버블 정렬의 공간 복잡도는 $O(1)$) + +## 예시 + +Let the given array be: `{5, 3, 2, 1, 4}` + +**First Iteration:** + +- {`5`, `3`, 2, 1, 4} -> {`3`, `5`, 2, 1, 4} Swap since `5 > 3` +- {3, `5`, `2`, 1, 4} -> {3, `2`, `5`, 1, 4} Swap since `5 > 2` +- {3, 2, `5`, `1`, 4} -> {3, 2, `1`, `5`, 4} Swap since `5 > 1` +- {3, 2, 1, `5`, `4`} -> {3, 2, 1, `4`, `5`} Swap since `5 > 4` + +This iteration has fixed the position of 5. Now, we will consider the array up to index 3. + +**Second Iteration:** + +- {`3`, `2`, 1, 4, 5} -> {`2`, `3`, 1, 4, 5} Swap since `3 > 2` +- {2, `3`, `1`, 4, 5} -> {2, `1`, `3`, 4, 5} Swap since `3 > 1` +- {2, 1, `3`, `4`, 5}; As `3 < 4`, do not swap + +Note: As we check one less element with every iteration, we do not need elements at index 3 and 4 i.e., `4` and `5`, as 5 is already in order. Formally, for an array with `n` integers, we consider elements only up to index `n - i`, where `i` is the iteration number. + +**Third Iteration:** + +- {`2`, `1`, 3, 4, 5} -> {`1`, `2`, 3, 4, 5} Swap since `1 > 2` +- {1, `2`, `3`, 4, 5}; As `2 < 3`, do not swap + +**Fourth Iteration:** + +- {`1`, `2`, 3, 4, 5}; As `1 < 2`, do not swap + +**Fifth Iteration:** + +- {`1`, 2, 3, 4, 5}; As the size of the array is 1, return. + +Note: This is the base case. + +## Pseudo Code + +``` +void bubbleSort(arr[], n) + if(n==1) + return; + + for(i = 0; i arr[i+1]) + swap(arr[i], arr[i+1]) + + bubbleSort(arr, n-1) +``` + +## 영상 URL + +- [Programming Tutorials](https://www.youtube.com/watch?v=gDMDVLBfCI0) diff --git "a/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\353\262\204\353\270\224 \354\240\225\353\240\254.md" "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\353\262\204\353\270\224 \354\240\225\353\240\254.md" new file mode 100644 index 00000000..577e27a3 --- /dev/null +++ "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\353\262\204\353\270\224 \354\240\225\353\240\254.md" @@ -0,0 +1,89 @@ +# 버블 정렬 + +## 문제 + +원소 n개로 이루어진 정렬되지 않은 배열이 주어졌을 때, 배열을 정렬하는 함수를 작성하라. + +## 접근방식 + +- 배열의 첫 번째 원소를 선택한다. +- 다음 원소와 비교한다. +- 다음 원소보다 크다면 교환한다. +- 아니라면 아무것도 하지 않는다. +- 배열의 모든 인덱스에 이 작업을 진행한다. +- 위의 과정을 n번 반복한다. + +## 시간 복잡도 + +$O(n^2)$ 최악의 경우 + +$O(n)$ 최선의 경우 + +$O(n^2)$ 평균 복잡도 + +## 공간 복잡도 + +$O(1)$ 최악의 경우 + +## 만든 사람 + +- “Bubble Sort”라는 용어는 1962년 Iverson, K에 의해 처음 사용되었다. + +## 예시 + +``` +배열 = {10, 80, 40, 30} +인덱스들: 0 1 2 3 + +1. 인덱스 = 0, 숫자 = 10 +2. 10 < 80, 아무것도 하지 않고 다음 단계로 넘어간다. + +3. 인덱스 = 1, 숫자 = 80 +4. 80 > 40, 80과 40을 교환한다. +5. 현재 배열은 {10, 40, 80, 30} + +6. 인덱스 = 2, 숫자 = 80 +7. 80 > 30, 80과 30을 교환한다. +8. 현재 배열은 {10, 40, 30, 80} + +위 단계를 다시 반복한다. + +배열 = {10, 40, 30, 80} +인덱스들: 0 1 2 3 + +1. 인덱스 = 0, 숫자 = 10 +2. 10 < 40, 아무것도 하지 않고 다음 단계로 넘어간다. + +3. 인덱스 = 1, 숫자 = 40 +4. 40 > 30, 40과 30을 교환한다. +5. 현재 배열은 {10, 30, 40, 80} + +6. 인덱스 = 2, 숫자 = 40 +7. 40 < 80, 아무것도 하지 않는다. +8. 현재 배열은 {10, 30, 40, 80} + +위 단계를 다시 반복한다. + +배열 = {10, 30, 40, 80} +인덱스들: 0 1 2 3 + +1. 인덱스 = 0, 숫자 = 10 +2. 10 < 30, 아무것도 하지 않고 다음 단계로 넘어간다. + +3. 인덱스 = 1, 숫자 = 30 +4. 30 < 40, 아무것도 하지 않고 다음 단계로 넘어간다. + +5. 인덱스 = 2, 숫자 = 40 +6. 40 < 80, 아무것도 하지 않는다. + +위 단계에서 교환이 없기 때문에 배열이 정렬되었음을 의미하고, 여기서 멈출 수 있다. +``` + +## 영상 URL + +- [버블정렬 알고리즘에 대한 영상 설명](https://www.youtube.com/watch?v=Jdtq5uKz-w4) + +## 기타 + +- 버블 정렬은 싱킹 정렬이라고도 한다. +- 시각화: [튜트 보드](https://boardhub.github.io/tute/?wd=bubbleSortAlgo2) diff --git "a/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\353\263\221\355\225\251 \354\240\225\353\240\254.md" "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\353\263\221\355\225\251 \354\240\225\353\240\254.md" new file mode 100644 index 00000000..905846b3 --- /dev/null +++ "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\353\263\221\355\225\251 \354\240\225\353\240\254.md" @@ -0,0 +1,36 @@ +# 병합 정렬 (분할 정복 알고리즘) + +## 문제 + +n개 원소로 구성된 배열이 주어졌을 때, 이 배열을 정렬하는 함수를 구하라. + +## 절차 + +- Find a mid point and divide the array into to halves based on the mid point +- Recursively call the merge sort function for both the halves +- Merge the two sorted halves to get the sorted array + +## 시간 복잡도 + +- $O(n \log n)$ + +## 공간 복잡도 + +- $O(n)$ + +## 예시 + +``` +arr = [1, 3, 9, 5, 0, 2] + +Divide the array in two halves [1, 3, 9] and [5, 0, 2] + +Recursively call merge sort function for both these halves which will provide sorted halves +=> [1, 3, 9] & [0, 2, 5] + +Now merge both these halves to get the sorted array [0, 1, 2, 3, 5, 9] +``` + +## 영상 URL + +- [CS50](https://www.youtube.com/watch?v=EeQ8pwjQxTM) diff --git "a/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\354\202\275\354\236\205 \354\240\225\353\240\254.md" "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\354\202\275\354\236\205 \354\240\225\353\240\254.md" new file mode 100644 index 00000000..7b9b3310 --- /dev/null +++ "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\354\202\275\354\236\205 \354\240\225\353\240\254.md" @@ -0,0 +1,56 @@ +# 삽입 정렬 + +## 문제 + +n개 원소로 구성된 배열이 주어졌을 때, 이 배열을 정렬하는 함수를 구하라. + +## 절차 + +- Define a "key" index, the subarray to the left of which is sorted. +- Initiate "key" as 1, ie. the second element of array(as there is only one element to left of the second element, which can be considered as sorted array with one element). +- If value of element at (key - 1) position is less than value of element at (key) position; increment "key". +- Else move elements of sorted subarray that are greater than value of element at "key" to one position ahead of their current position. Put the value of element at "key" in the newly created void. + +## 시간 복잡도 + +- 최악 + - 비교: $O(n^2)$ + - 교환: $O(n^2)$ +- 최선 + - 비교: $O(n)$ + - 교환: $O(1)$ + +## 공간 복잡도 + +- 최악: $O(1)$ ([In-place 알고리즘](https://en.wikipedia.org/wiki/In-place_algorithm)으로, 추가적인 메모리 할당이 필요하지 않다) + +## 예시 + +``` + +12, 11, 13, 5, 6 + +Let us loop for i = 1 (second element of the array) to 4 (Size of input array) + +i = 1. +Since 11 is smaller than 12, move 12 and insert 11 before 12 +11, 12, 13, 5, 6 + +i = 2. +13 will remain at its position as all elements in sorted subarray are smaller than 13 +11, 12, 13, 5, 6 + +i = 3. +5 will move to the beginning, +and all other elements from 11 to 13 will move one position ahead of their current position. +5, 11, 12, 13, 6 + +i = 4. +6 will move to position after 5, +and elements from 11 to 13 will move one position ahead of their current position. +5, 6, 11, 12, 13 -- sorted array +``` + +## 영상 URL + +- [CS50](https://www.youtube.com/watch?v=DFG-XuyPYUQ) diff --git "a/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\354\204\240\355\203\235 \354\240\225\353\240\254.md" "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\354\204\240\355\203\235 \354\240\225\353\240\254.md" new file mode 100644 index 00000000..1f81c92a --- /dev/null +++ "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\354\204\240\355\203\235 \354\240\225\353\240\254.md" @@ -0,0 +1,56 @@ +# 선택 정렬 + +## 문제 + +n개 원소로 구성된 배열이 주어졌을 때, 이 배열을 정렬하는 함수를 구하라. + +## 절차 + +- select the smallest element from the array +- put it at the beginning of the array +- then select the smallest array from the remaining unsorted list +- append it to the sorted array at the beginning +- keep doing this for every element of the array +- repeat the above process n times + +## 시간 복잡도 + +- 최악: $O(n^2)$ +- 최선: $O(n^2)$ +- 평균: $O(n^2)$ + +## 공간 복잡도 + +- 최악: $O(1)$ + +## 예시 + +``` +arr[] = {80, 10, 40, 30} +Indexes: 0 1 2 3 + +1. Index = 0 + Select the minimum number from the array (between index 0-3), ie, 10 +2. Swap 10 and 80 (arr[0]) +3. The array now is {10, 80, 40, 30} + +4. Index = 1 + Select the minimum number from the array (between index 1-3), ie, 30 +5. Swap 30 and 80 (arr[1]) +6. The array now is {10, 30, 40, 80} + +7. Index = 2 + Select the minimum number from the array (between index 2-3), ie, 40 +8. Swap 40 and 40 (arr[2]) +9. The array now is {10, 30, 40, 80} + +The array is now sorted. +``` + +## 영상 URL + +- [CS50](https://www.youtube.com/watch?v=f8hXR_Hvybo) + +## 기타 + +- [Tute Board](https://boardhub.github.io/tute/?wd=selectSortAlgo2) diff --git "a/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\354\205\270 \354\240\225\353\240\254.md" "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\354\205\270 \354\240\225\353\240\254.md" new file mode 100644 index 00000000..81efb901 --- /dev/null +++ "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\354\205\270 \354\240\225\353\240\254.md" @@ -0,0 +1,57 @@ +# 셸 정렬 + +## 문제 + +n개 원소로 구성된 배열이 주어졌을 때, 이 배열을 정렬하는 함수를 구하라. + +## 절차 + +- start with the initial gap, g +- go through the first (n - g) elements in the array +- compare the element with the next element that is g distance away +- swap the two elements if the first element is bigger +- decrease the gap and repeat until gap = 1 + +## 시간 복잡도 + +셸 정렬의 시간 복잡도는 gap sequences에 따라 다르다. 아래 시간 복잡도는 $(\frac{n}{2})^k$의 gap sequences를 가정한다. + +- 최악: $O(n^2)$ +- 최선: $O(n)$ +- 평균: $O(n^2)$ + +## 공간 복잡도 + +- 최악: $O(1)$ + +## 만든 사람 + +- [도널드 셸](https://en.wikipedia.org/wiki/Donald_Shell) + +## 예시 + +``` +arr[] = {61, 109, 149, 111, 34, 2, 24, 119} +Initial Gap: 4 + +1. Index = 0, Next element index = 4 +2. 61 > 34, swap 61 and 34 +3. The array is now {34, 109, 149, 111, 61, 2, 24, 119} + +4. Index = 1, Next element index = 5 +5. 109 > 2, swap 109 and 2 +6. The array is now {34, 2, 149, 111, 61, 109, 24, 119} + +7. Index = 2, Next element index = 6 +8. 149 > 24, swap 149 and 24 +9. The array is now {34, 2, 24, 111, 61, 109, 149, 119} + +10. Index = 3, Next element index = 7 +11. 111 < 119, do nothing and continue + +12. Divide the gap by 2 and repeat until gap = 1 +``` + +## 영상 URL + +- [Computer Education for All](https://www.youtube.com/watch?v=H8NiFkGu2PY) diff --git "a/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\355\200\265 \354\240\225\353\240\254.md" "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\355\200\265 \354\240\225\353\240\254.md" new file mode 100644 index 00000000..07a8c779 --- /dev/null +++ "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\355\200\265 \354\240\225\353\240\254.md" @@ -0,0 +1,72 @@ +# 퀵 정렬 + +## 문제 + +n개 원소로 구성된 배열이 주어졌을 때, 이 배열을 정렬하는 함수를 구하라. + +## 절차 + +- Make the right-most index value pivot +- partition the array using pivot value +- quicksort left partition recursively +- quicksort right partition recursively + +## 시간 복잡도 + +- 최악: $O(n^2)$ +- 최선: $O(n \log n)$ +- 평균: $O(n \log n)$ + +## 공간 복잡도 + +- 최악: $O(\log n)$ + +## 만든 사람 + +- [토니 호어](https://ko.wikipedia.org/wiki/%ED%86%A0%EB%8B%88_%ED%98%B8%EC%96%B4) + +## 예시 + +``` +arr[] = {10, 80, 30, 90, 40, 50, 70} +Indexes: 0 1 2 3 4 5 6 + +low = 0, high = 6, pivot = arr[h] = 70 +Initialize index of smaller element, i = -1 + +Traverse elements from j = low to high-1 +j = 0 : Since arr[j] <= pivot, do i++ and swap(arr[i], arr[j]) +i = 0 +arr[] = {10, 80, 30, 90, 40, 50, 70} // No change as i and j + // are same + +j = 1 : Since arr[j] > pivot, do nothing +// No change in i and arr[] + +j = 2 : Since arr[j] <= pivot, do i++ and swap(arr[i], arr[j]) +i = 1 +arr[] = {10, 30, 80, 90, 40, 50, 70} // We swap 80 and 30 + +j = 3 : Since arr[j] > pivot, do nothing +// No change in i and arr[] + +j = 4 : Since arr[j] <= pivot, do i++ and swap(arr[i], arr[j]) +i = 2 +arr[] = {10, 30, 40, 90, 80, 50, 70} // 80 and 40 Swapped +j = 5 : Since arr[j] <= pivot, do i++ and swap arr[i] with arr[j] +i = 3 +arr[] = {10, 30, 40, 50, 80, 90, 70} // 90 and 50 Swapped + +We come out of loop because j is now equal to high-1. +Finally we place pivot at correct position by swapping +arr[i+1] and arr[high] (or pivot) +arr[] = {10, 30, 40, 50, 70, 90, 80} // 80 and 70 Swapped + +Now 70 is at its correct place. All elements smaller than +70 are before it and all elements greater than 70 are after +it. +``` + +## 영상 URL + +- [mycodeschool](https://www.youtube.com/watch?v=COk73cpQbFQ) diff --git "a/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\355\236\231 \354\240\225\353\240\254.md" "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\355\236\231 \354\240\225\353\240\254.md" new file mode 100644 index 00000000..68bc3fc3 --- /dev/null +++ "b/ko/\354\240\225\353\240\254 \354\225\214\352\263\240\353\246\254\354\246\230/\355\236\231 \354\240\225\353\240\254.md" @@ -0,0 +1,58 @@ +# 힙 정렬 + +## 문제 + +정렬되지 않은 n개의 원소로 이루어진 배열이 주어졌을 때, 배열을 정렬하는 함수를 작성하라 + +## 접근방식 + +- 입력 데이터에서 최대 힙을 빌드한다. +- 이때, 가장 큰 원소가 힙의 루트에 저장된다. 해당 원소를 힙의 마지막 원소로 교체한 뒤, 힙의 사이즈를 1 줄인다. +- 힙의 사이즈가 1보다 크다면 위 과정을 반복한다. + +## 시간 복잡도 + +$O(n log n)$ 최악의 경우 + +$O(n log n)$ (고유 키) +or O(n) (동일 키) 최선의 경우 + +$O(n log n)$ 평균 복잡도 + +## 공간 복잡도 + +$O(1)$ 최악의 경우 + +## 예시 + +``` +입력 원소 : 4, 10, 3, 5, 1 + 4(0) + / \ + 10(1) 3(2) + / \ +5(3) 1(4) + +괄호 안의 숫자는 데이터의 배열 인덱스를 나타낸다. + +1번 인덱스에 힙 절차 적용 : + 4(0) + / \ + 10(1) 3(2) + / \ +5(3) 1(4) + +0번 인덱스의 힙 절차 적용: + 10(0) + / \ + 5(1) 3(2) + / \ +4(3) 1(4) +힙 절차는 재귀적으로 호출하여 하향식 방식으로 힙을 빌드한다. +``` + +![힙 이미지](https://upload.wikimedia.org/wikipedia/commons/1/1b/Sorting_heapsort_anim.gif) + +## 영상 URL + +[힙 정렬 알고리즘에 대한 영상 설명](https://www.youtube.com/watch?v=MtQL_ll5KhQ) diff --git "a/ko/\355\203\220\354\203\211 \354\225\214\352\263\240\353\246\254\354\246\230/\354\204\240\355\230\225 \355\203\220\354\203\211.md" "b/ko/\355\203\220\354\203\211 \354\225\214\352\263\240\353\246\254\354\246\230/\354\204\240\355\230\225 \355\203\220\354\203\211.md" new file mode 100644 index 00000000..d024fdeb --- /dev/null +++ "b/ko/\355\203\220\354\203\211 \354\225\214\352\263\240\353\246\254\354\246\230/\354\204\240\355\230\225 \355\203\220\354\203\211.md" @@ -0,0 +1,53 @@ +# 선형 탐색 + +## 문제 + +n개 원소로 구성된 배열이 주어졌을 때, 특정 원소의 인덱스를 찾는 함수를 구하라. + +## 절차 + +1. 배열의 첫 원소와 찾고자 하는 원소를 비교한다. +2. 만약 같다면 그 인덱스를 반환한다. + - 만약 다르다면, 다음 원소와 찾고자 하는 원소를 비교한다. +3. 만약 찾고자 하는 원소가 없다면 -1을 반환한다. + +## 시간 복잡도 + +- 최악의 경우: $O(n)$ +- 최선의 경우: $O(1)$ (배열의 첫번째 원소가 찾는 원소인 경우) + +## 공간 복잡도 + +- $O(1)$ + +## 예시 + +``` +arr = [1, 3, 9, 5, 0, 2] +target = 5 + +1과 5가 같지 않으므로 다음 원소와 목표를 비교한다. +3과 5가 같지 않으므로 다음 원소와 목표를 비교한다. +9과 5가 같지 않으므로 다음 원소와 목표를 비교한다. +5가 4번째 위치에 있으므로 3을 반환한다. +``` + +``` +arr = [1, 3, 9, 5, 0, 2] +target = 6 + +1과 6이 같지 않으므로 다음 원소와 목표를 비교한다. +3과 6이 같지 않으므로 다음 원소와 목표를 비교한다. +9과 6이 같지 않으므로 다음 원소와 목표를 비교한다. +5와 6이 같지 않으므로 다음 원소와 목표를 비교한다. +0과 6이 같지 않으므로 다음 원소와 목표를 비교한다. +마지막 원소가 목표와 같지 않으므로 6이 배열에 들어있지 않다고 판단하여 -1을 반환한다. +``` + +## 영상 URL + +- [CS50](https://www.youtube.com/watch?v=CX2CYIJLwfg) + +## 기타 + +- [Tute Board](https://boardhub.github.io/tute/?wd=linearSearchAlgo) diff --git "a/ko/\355\203\220\354\203\211 \354\225\214\352\263\240\353\246\254\354\246\230/\354\235\264\354\247\204 \355\203\220\354\203\211.md" "b/ko/\355\203\220\354\203\211 \354\225\214\352\263\240\353\246\254\354\246\230/\354\235\264\354\247\204 \355\203\220\354\203\211.md" new file mode 100644 index 00000000..9e378db2 --- /dev/null +++ "b/ko/\355\203\220\354\203\211 \354\225\214\352\263\240\353\246\254\354\246\230/\354\235\264\354\247\204 \355\203\220\354\203\211.md" @@ -0,0 +1,62 @@ +# 이진 탐색 (분할 정복 알고리즘) + +## 문제 + +원소 $n$개로 이루어진 정렬된 배열이 주어졌을 때, 입력받은 원소의 인덱스를 반환하는 함수를 작성하라. + +## 접근 방식 + +- 배열을 반으로 계속 나누어 가며 탐색할 것이다(분할 정복). +- 먼저, 주어진 배열에서 가운데에 있는 원소를 선택한다. +- 만약 선택한 원소와 찾는 원소가 같다면, 그 인덱스를 반환하고 종료한다. +- 만약 선택한 원소가 찾는 원소보다 작다면, 배열의 오른쪽 절반만 고려하면 된다. 오른쪽 절반 배열에 대해 처음부터 반복한다. +- 만약 선택한 원소가 찾는 원소보다 크다면, 배열의 왼쪽 절반만 고려하면 된다. 왼쪽 절반 배열에 대해 처음부터 반복한다. +- 만약 찾는 원소가 초기 배열에 없다면, -1을 반환하면 된다.(분할 정복을 반복하다 보면 배열의 크기가 1이하가 되고, 이때 찾는 원소가 없다면 없는 것이다.) + +## 시간 복잡도 + +최악의 경우: $O(\log n)$ +최선의 경우: $O(1)$ +(찾는 원소가 초기 배열의 가운데에 있는 경우) + +## 공간 복잡도 + +단순 반복으로 구현한 경우, $O(1)$ +재귀를 사용하는 경우, $O(\log n)$ +(재귀함수를 부를 때마다 스택에 쌓이므로) + +## 예시 + +``` +arr = [1, 2, 3, 4, 5, 6, 7] +target = 2 + +중간 원소는 4로, 목표인 2보다 크다. 그러므로 배열의 왼쪽 절반을 탐색한다. + +arr = [1, 2, 3] + +중간 원소가 목표와 같으므로 이 원소의 인덱스를 반환한다. +``` + +``` +arr = [1, 2, 3, 4, 5, 6, 7] +target = 9 + +중간 원소는 4로, 목표인 9보다 작다. 그러므로 배열의 오른쪽 절반을 탐색한다. + +arr = [5, 6, 7] + +중간 원소는 6으로, 목표보다 작다. 그러므로 오른쪽 절반을 탐색한다. + +arr = [7] + +유일한 원소가 목표와 같지 않으므로 9가 배열에 들어있지 않다고 판단하여 -1을 반환한다. +``` + +## 영상 URL + +- [CS50: 이진 탐색](https://www.youtube.com/watch?v=5xlIPT1FRcA) + +## 시각화된 설명 + +- [Tute 보드](https://boardhub.github.io/tute/?wd=binarySearchAlgo2) diff --git "a/ko/\355\203\220\354\203\211 \354\225\214\352\263\240\353\246\254\354\246\230/\354\247\200\354\210\230 \355\203\220\354\203\211.md" "b/ko/\355\203\220\354\203\211 \354\225\214\352\263\240\353\246\254\354\246\230/\354\247\200\354\210\230 \355\203\220\354\203\211.md" new file mode 100644 index 00000000..ff42267a --- /dev/null +++ "b/ko/\355\203\220\354\203\211 \354\225\214\352\263\240\353\246\254\354\246\230/\354\247\200\354\210\230 \355\203\220\354\203\211.md" @@ -0,0 +1,57 @@ +# 지수 탐색 + +## 알아야 하는 내용 + +- [이진 탐색](./이진%20탐색.md) + +## 문제 + +n개 원소로 구성된 **정렬된** 배열이 주어졌을 때, 특정 원소의 인덱스를 찾는 함수를 구하라. + +## 절차 + +1. 인덱스를 2배씩 늘려가며 찾고자 하는 원소가 속하는 범위를 찾는다. +2. 만약 찾고자 하는 원소가 속하는 범위를 찾는다면, 해당 범위에서 이진 탐색을 수행한다. +3. 만약 찾고자 하는 원소가 속하는 범위가 없다면 -1을 반환한다. + +## 시간 복잡도 + +- 최악: $O(\log i)$ ($i$는 찾고자 하는 원소의 인덱스) +- 최선: $O(1)$ + +$i$가 찾고자 하는 원소의 인덱스라고 할 때, 탐색을 $\lceil \log i \rceil$번 수행하기 때문에 찾고자 하는 원소가 속하는 범위를 찾는 과정의 복잡도는 $O(\log i)$이다. + +이진 탐색을 수행하는 과정의 복잡도는 이진 탐색의 복잡도와 동일하게 $O(\log i)$이다. (참고: [이진 탐색](./이진%20탐색.md)) + +그러므로, 지수 탐색의 복잡도는 다음과 같이 쓸 수 있다. + +$O(\log i) + O(\log i) = 2O(\log i) = O(\log i)$ + +## 예시 + +``` +arr = [1, 2, 3, 4, 5, 6, 7, ... 998, 999, 1000] +target = 998 + +1. 찾고자 하는 원소가 속하는 범위 탐색 + arr[1]이 998보다 작으므로 인덱스를 2배 늘린다. + arr[2]이 998보다 작으므로 인덱스를 2배 늘린다. + arr[4]이 998보다 작으므로 인덱스를 2배 늘린다. + arr[8]이 998보다 작으므로 인덱스를 2배 늘린다. + arr[16]이 998보다 작으므로 인덱스를 2배 늘린다. + arr[32]이 998보다 작으므로 인덱스를 2배 늘린다. + arr[64]이 998보다 작으므로 인덱스를 2배 늘린다. + arr[128]이 998보다 작으므로 인덱스를 2배 늘린다. + arr[256]이 998보다 작으므로 인덱스를 2배 늘린다. + arr[512]이 998보다 작으므로 인덱스를 2배 늘린다. + arr[1024]가 존재하지 않으므로 512 이상의 범위에 대해 이진 탐색을 수행한다. + +2. 이진 탐색 +``` + +## 이진 탐색과의 비교 + +논의의 편의를 위해 덜 이론적인 예시를 살펴보자. 1,000,000개 원소로 이루어진 배열에서 4번째에 위치한 원소를 찾는다고 할 때, + +- 이진 탐색은 배열의 중간부터 시작하여 많은 반복문을 지나야 4번째 원소에 도착한다. +- 지수 탐색은 2번 만에 4번째 원소에 도착한다. diff --git "a/ko/\355\203\220\354\203\211 \354\225\214\352\263\240\353\246\254\354\246\230/\355\224\214\353\241\234\354\235\264\353\223\234 \354\210\234\355\231\230 \355\203\220\354\203\211 \354\225\214\352\263\240\353\246\254\354\246\230.md" "b/ko/\355\203\220\354\203\211 \354\225\214\352\263\240\353\246\254\354\246\230/\355\224\214\353\241\234\354\235\264\353\223\234 \354\210\234\355\231\230 \355\203\220\354\203\211 \354\225\214\352\263\240\353\246\254\354\246\230.md" new file mode 100644 index 00000000..70162f38 --- /dev/null +++ "b/ko/\355\203\220\354\203\211 \354\225\214\352\263\240\353\246\254\354\246\230/\355\224\214\353\241\234\354\235\264\353\223\234 \354\210\234\355\231\230 \355\203\220\354\203\211 \354\225\214\352\263\240\353\246\254\354\246\230.md" @@ -0,0 +1,34 @@ +# 배열에서 중복 번호를 찾는 플로이드 순환 탐색 알고리즘 + +## 문제 + +`n + 1` 정수를 포함하는 정수 배열이 주어지면 각 정수는 `[1, n]`을 포함한 범위에 있다. 입력 배열에 중복 숫자가 하나만 있으면 이 알고리즘은 원래 배열을 수정하지 않고 중복 숫자를 반환하고, 그렇지 않으면 `-1`을 반환한다. + +## 절차 + + +- 함수 `f(x) = arr[x]`를 사용하여 시퀀스를 구성한다. +<예시> `arr[0]`, `arr[arr[0]]`, `arr[arr[arr[0]]]`, `arr[arr[arr[arr[0]]]]` +- 시퀀스의 각각의 새로운 원소는 이전 요소의 인덱스에 있는 `arr[]`의 원소입니다. +- `x = arr[0]`부터 시작하여 원형 연결 리스트를 생성한다. +- `arr[]`에 중복 원소(최소 하나)가 포함되어 있기 때문에 `cycle`이 나타난다. 중복 값은 순환의 시작점이다. + +## 시간 복잡도 + +$O(n)$ + +## 공간 복잡도 + +$O(1)$ + +## 예시 + +``` +arr = [3, 4, 8, 5, 9, 1, 2, 6, 7, 4] + +return value = 4 +``` + +## 영상 URL + +- [플로이드 순환 탐색 알고리즘 유튜브 영상](https://www.youtube.com/watch?v=B6smdk7pZ14) diff --git a/ne/README.md b/ne/README.md new file mode 100644 index 00000000..8c26e146 --- /dev/null +++ b/ne/README.md @@ -0,0 +1,29 @@ +# एल्गोरिथ्म नाम + +एल्गोरिथ्मको छोटो वर्णन लेख्नुहोस् जस्तै: +1. समय जटिलता +2. ठाउँ जटिलता +3. अनुप्रयोगहरू +4. संस्थापकको नाम +5. आदि ... + +## चरणहरू + +स्पष्ट, सरल र बुझ्ने चरणहरूमा एल्गोरिथ्म वर्णन गर्नुहोस्। + +## उदाहरण + +नमूना इनपुट डाटाको साथ एल्गोरिथ्म ट्रेस गर्नुहोस्। + +## कार्यान्वयन + +प्रोग्रामिंग भाषाहरूमा उनीहरूको कार्यान्वयनको लागि लिंकहरू। +नोट: लिंक यो संगठनको अन्य repos भित्र मात्र हुनुपर्दछ। + +## भिडियो यूआरएल + +एल्गोरिथ्मको वर्णन गर्ने भिडियोको URL संलग्न गर्नुहोस्। + +## अन्य + +कुनै पनि अन्य जानकारी सँधै स्वागत गरिन्छ र यस सेक्सनमा समावेश गर्नुपर्दछ। diff --git a/pt-br/Algoritmos de Busca/Busca Binaria.md b/pt-br/Algoritmos de Busca/Busca Binaria.md new file mode 100644 index 00000000..cd350166 --- /dev/null +++ b/pt-br/Algoritmos de Busca/Busca Binaria.md @@ -0,0 +1,49 @@ +# Busca Binária (algoritmo de divisão e conquista) + +#### Declaração do problema + +Dada uma matriz classificada de n elementos, escreva uma função para pesquisar o índice de um determinado elemento (destino) + +#### Abordagem + +- Pesquise a matriz dividindo-a ao meio repetidamente. +- Considere inicialmente a matriz real e escolha o elemento no índice do meio +- Mantenha um índice mais baixo, ou seja, 0, e um índice mais alto, ou seja, tamanho da matriz +- Se for igual ao elemento de destino, retorne o índice +- Caso contrário, se for maior do que o elemento de destino, considere apenas a metade esquerda da matriz. (índice inferior = 0, superior = médio - 1) +- Caso contrário, se for menor que o elemento de destino, considere apenas a metade direita da matriz. (índice inferior = meio + 1, superior = comprimento da matriz) +- Retorne -1 se o elemento de destino não for encontrado na matriz (Caso Base: Se o índice inferior for maior ou igual ao índice superior) + +#### Complexidade de tempo + +`O(log n)` Pior Caso +`O(1)` Melhor Caso (se o elemento do meio da matriz inicial for o elemento de destino) + +#### Complexidade de espaço + +`O(1)` Para abordagem iterativa +`O(log n)` Para abordagem recursiva devido à pilha de chamadas de recursão + +#### Exemplo + +```python +arr = [1, 2, 3, 4, 5, 6, 7] + +# alvo = 2 +# Inicialmente, o elemento no índice do meio é 4, que é maior do que 2. +# Portanto, procuramos a metade esquerda do +# matriz, ou seja, [1,2,3]. +# Aqui encontramos o elemento do meio igual ao elemento de destino, +# portanto, retornamos seu índice, ou seja, 1. + +alvo = 9 +# A pesquisa binária deve retornar -1, pois 9 não está presente na matriz +``` + +#### Explicação em vídeo + +[Um vídeo CS50 explicando o algoritmo de pesquisa binária](https://www.youtube.com/watch?v=5xlIPT1FRcA) + +#### Explicação em formato de animação + +- [Tute Board](https://boardhub.github.io/tute/?wd=binarySearchAlgo2) diff --git a/pt-br/Algoritmos de Busca/Busca Linear.md b/pt-br/Algoritmos de Busca/Busca Linear.md new file mode 100644 index 00000000..5d6690e0 --- /dev/null +++ b/pt-br/Algoritmos de Busca/Busca Linear.md @@ -0,0 +1,42 @@ +# Busca Linear + +#### Declaração do problema + +Dada uma matriz de `n` elementos, escreva uma função para pesquisar o índice de um determinado elemento (destino). + +#### Abordagem + +- Comece a iterar com o primeiro elemento da matriz. +- Compare-o com o elemento de destino. +- Se for igual ao elemento de destino, retorne o índice. +- Caso contrário, continue iterando. +- Retorne -1 se o elemento de destino não for encontrado na matriz. + +#### Complexidade de tempo + +- `O(n)` pior caso +- `O(1)` Melhor Caso (Se o primeiro elemento da matriz for o elemento de destino) + +#### Complexidade de espaço + +`O(1)` + +#### Exemplo + +```python +arr = [1, 3, 9, 5, 0, 2] + +alvo = 5 +# A pesquisa linear deve retornar o índice 3, pois 5 está no índice 3 + +alvo = 6 +# A pesquisa linear deve retornar -1, pois 6 não está presente na matriz +``` + +#### Explicação em vídeo + +[Um vídeo CS50 explicando o algoritmo de pesquisa linear](https://www.youtube.com/watch?v=CX2CYIJLwfg) + +#### Explicação em formato de animação + +- [Tute Board](https://boardhub.github.io/tute/?wd=linearSearchAlgo) diff --git "a/pt-br/Algoritmos de Ordena\303\247\303\243o/Bubble Sort.md" "b/pt-br/Algoritmos de Ordena\303\247\303\243o/Bubble Sort.md" new file mode 100644 index 00000000..d4599dd9 --- /dev/null +++ "b/pt-br/Algoritmos de Ordena\303\247\303\243o/Bubble Sort.md" @@ -0,0 +1,92 @@ +# Bubble Sort + +#### Declaração do problema + +Dada uma matriz não classificada de n elementos, escreva uma função para classificar a matriz + +#### Abordagem + +- selecione o primeiro elemento da matriz +- compare-o com seu próximo elemento +- se for maior do que o próximo elemento, troque-os +- mais não faça nada +- continue fazendo isso para cada índice da matriz +- repita o processo acima n vezes. + +#### Complexidade de tempo + +`O(n^2)` Desempenho de pior caso + +`O(n)` Melhor caso de desempenho + +`O(n^2)` Desempenho médio + +#### Complexidade do Espaço + +`O(1)` Pior caso + +#### Nome do fundador + +- O termo “Bubble Sort” foi a primeira vez usado por Iverson, K em 1962. + +#### Exemplo + +``` +arr[] = {10, 80, 40, 30} +Índices: 0 1 2 3 + +1. Índice = 0, Número = 10 +2. 10 <80, não faça nada e continue + +3. Índice = 1, Número = 80 +4. 80> 40, troque 80 e 40 +5. A matriz agora é {10, 40, 80, 30} + +6. Índice = 2, Número = 80 +7. 80> 30, troque 80 e 30 +8. A matriz agora é {10, 40, 30, 80} + +Repita as etapas acima novamente + +arr[] = {10, 40, 30, 80} +Índices: 0 1 2 3 + +1. Índice = 0, Número = 10 +2. 10 <40, não faça nada e continue + +3. Índice = 1, Número = 40 +4. 40> 30, troque 40 e 30 +5. A matriz agora é {10, 30, 40, 80} + +6. Índice = 2, Número = 40 +7. 40 <80, não faça nada +8. A matriz agora é {10, 30, 40, 80} + +Repita as etapas acima novamente + +arr[] = {10, 30, 40, 80} +Índices: 0 1 2 3 + +1. Índice = 0, Número = 10 +2. 10 <30, não faça nada e continue + +3. Índice = 1, Número = 30 +4. 30 <40, não faça nada e continue + +5. Índice = 2, Número = 40 +6. 40 <80, não faça nada + +Como não há trocas nas etapas acima, isso significa que a matriz está classificada e podemos parar por aqui. +``` + +#### Explicação em vídeo + +[Um vídeo explicando o algoritmo de classificação por bolha](https://www.youtube.com/watch?v=Jdtq5uKz-w4) + +#### Outras + +A classificação por bolha também é conhecida como classificação por afundamento. + +#### Explicação em formato de animação + +- [Tute Board](https://boardhub.github.io/tute/?wd=bubbleSortAlgo2) diff --git "a/pt-br/Algoritmos de Ordena\303\247\303\243o/Heap Sort.md" "b/pt-br/Algoritmos de Ordena\303\247\303\243o/Heap Sort.md" new file mode 100644 index 00000000..461cb947 --- /dev/null +++ "b/pt-br/Algoritmos de Ordena\303\247\303\243o/Heap Sort.md" @@ -0,0 +1,60 @@ +# Heap Sort + +#### Declaração do problema + +Dada uma matriz não classificada de n elementos, escreva uma função para classificar a matriz + +#### Abordagem + +- Construa um heap máximo a partir dos dados de entrada. +- Neste ponto, o maior item é armazenado na raiz do heap. Substitua-o pelo último item do heap seguido pela redução do tamanho do heap em 1. Finalmente, monte a raiz da árvore. +- Repita as etapas acima enquanto o tamanho do heap for maior que 1. + +#### Complexidade de tempo + +- `O(n log n)` Pior caso de desempenho +- `O(n log n)` (chaves distintas) ou `O(n)` (teclas iguais) Melhor caso de desempenho +- `O(n log n)` Desempenho médio + +#### Complexidade de Espaço + +`O(1)` Pior caso auxiliar + +#### Exemplo + +``` +Dados de entrada: 4, 10, 3, 5, 1 + + 4 (0) + / \ + 10 (1) 3 (2) + / \ + 5 (3) 1 (4) + +Os números entre colchetes representam os índices na matriz +representação de dados. + +Aplicando procedimento de heapify ao índice 1: + + 4 (0) + / \ + 10 (1) 3 (2) + / \ +5 (3) 1 (4) + +Aplicando procedimento heapify ao índice 0: + + 10 (0) + / \ + 5 (1) 3 (2) + / \ + 4 (3) 1 (4) + +O procedimento heapify chama a si mesmo recursivamente para construir heap de cima para baixo. +``` + +![heap-image](https://upload.wikimedia.org/wikipedia/commons/1/1b/Sorting_heapsort_anim.gif "Heap Sort") + +#### Explicação em vídeo + +[Um vídeo explicando o algoritmo de classificação por seleção](https://www.youtube.com/watch?v=MtQL_ll5KhQ) diff --git "a/pt-br/Algoritmos de Ordena\303\247\303\243o/Insertion Sort.md" "b/pt-br/Algoritmos de Ordena\303\247\303\243o/Insertion Sort.md" new file mode 100644 index 00000000..4d85bda3 --- /dev/null +++ "b/pt-br/Algoritmos de Ordena\303\247\303\243o/Insertion Sort.md" @@ -0,0 +1,51 @@ +# Insertion Sort + +#### Declaração do problema + +Dado um array de n elementos, escreva uma função para classificar o array em ordem crescente. + +#### Abordagem + +- Defina um índice de "chave", o subarray à esquerda do qual é classificado. +- Inicie a "chave" como 1, ou seja. o segundo elemento da matriz (como há apenas um elemento à esquerda do segundo elemento, que pode ser considerado como uma matriz classificada com um elemento). +- Se o valor do elemento na posição (chave - 1) for menor que o valor do elemento na posição (chave); incremento "chave". +- Caso contrário, mova os elementos do subarray classificado que são maiores que o valor do elemento na "chave" para uma posição à frente de sua posição atual. Coloque o valor do elemento em "chave" no vazio recém-criado. + +#### Complexidade de tempo + +- `О(n^2)` comparações, `О(n^2)` swaps - Pior caso +- Comparações `O(n)`, swaps `O(1)` - Melhor Caso + +#### Complexidade de espaço + +`O(1)` - (sem espaço extra necessário, classificação feita no local) + +#### Exemplo + +``` +12, 11, 13, 5, 6 + +Vamos fazer um loop de i = 1 (segundo elemento da matriz) para 4 (Tamanho da matriz de entrada) + +i = 1. +Como 11 é menor que 12, mova 12 e insira 11 antes de 12 +11, 12, 13, 5, 6 + +i = 2. +13 permanecerá em sua posição, pois todos os elementos no subarray classificado são menores do que 13 +11, 12, 13, 5, 6 + +i = 3. +5 moverá para o início, +e todos os outros elementos de 11 a 13 se moverão uma posição à frente de sua posição atual. +5, 11, 12, 13, 6 + +i = 4. +6 se moverá para a posição após 5, +e os elementos de 11 a 13 se moverão uma posição à frente de sua posição atual. +5, 6, 11, 12, 13 - matriz classificada +``` + +#### Explicação em vídeo + +[Um vídeo CS50 explicando o algoritmo de pesquisa de inserção](https://www.youtube.com/watch?v=DFG-XuyPYUQ) diff --git "a/pt-br/Algoritmos de Ordena\303\247\303\243o/Merge Sort.md" "b/pt-br/Algoritmos de Ordena\303\247\303\243o/Merge Sort.md" new file mode 100644 index 00000000..a29a4285 --- /dev/null +++ "b/pt-br/Algoritmos de Ordena\303\247\303\243o/Merge Sort.md" @@ -0,0 +1,36 @@ +# Merge Sort (Algoritmo de divisão e conquista) + +#### Declaração do problema + +Dado um array de n elementos, escreva uma função para classificar o array + +#### Abordagem + +- Encontre um ponto médio e divida a matriz em metades com base no ponto médio +- Chame recursivamente a função de classificação de mesclagem para ambas as metades +- Junte as duas metades classificadas para obter a matriz classificada + +#### Complexidade de tempo + +`O(n log n)` + +#### Complexidade do Espaço + +`O(n)` + +#### Exemplo + +``` +arr = [1, 3, 9, 5, 0, 2] + +Divida a matriz em duas metades [1, 3, 9] e [5, 0, 2] + +Chame recursivamente a função merge sort para ambas as metades, o que fornecerá metades ordenadas +=> [1, 3, 9] e [0, 2, 5] + +Agora mescle as duas metades para obter a matriz classificada [0, 1, 2, 3, 5, 9] +``` + +#### Explicação em vídeo + +[Um vídeo CS50 explicando o algoritmo de classificação de mesclagem](https://www.youtube.com/watch?v=EeQ8pwjQxTM) diff --git "a/pt-br/Algoritmos de Ordena\303\247\303\243o/Quick Sort.md" "b/pt-br/Algoritmos de Ordena\303\247\303\243o/Quick Sort.md" new file mode 100644 index 00000000..765d5a27 --- /dev/null +++ "b/pt-br/Algoritmos de Ordena\303\247\303\243o/Quick Sort.md" @@ -0,0 +1,72 @@ +# Quick Sort (Ordenação rápida) + +#### Declaração do problema + +Dada uma matriz não classificada de n elementos, escreva uma função para classificar a matriz. + +#### Aproximação + +- Faça o pivô de valor de índice mais à direita +- particionar a matriz usando o valor dinâmico +- partição esquerda quicksort recursivamente +- partição direita quicksort recursivamente + +#### Complexidade de tempo + +- `O(n^2)` Desempenho de pior caso +- `O(n log n)` Desempenho de melhor caso +- `O(n log n)` Desempenho médio + +#### Complexidade do Espaço + +`O(log (n))` Pior caso + +#### Nome do fundador + +Tony Hoare em 1959. + +#### Exemplo + +``` +arr[] = {10, 80, 30, 90, 40, 50, 70} +Índices: 0 1 2 3 4 5 6 + +baixo = 0, alto = 6, pivô = arr[h] = 70 +Inicialize o índice do elemento menor, i = -1 + +Atravesse elementos de j = baixo para alto-1 +j = 0: como arr [j] <= pivô, faça i ++ e troque (arr[i], arr[j]) +i = 0 +arr [] = {10, 80, 30, 90, 40, 50, 70} // Sem alteração como i e j + // são iguais + +j = 1: como arr[j] > pivô, não faça nada +// Sem alteração em i e arr[] + +j = 2: Como arr [j] <= pivô, faça i ++ e troque (arr [i], arr [j]) +i = 1 +arr [] = {10, 30, 80, 90, 40, 50, 70} // Trocamos 80 e 30 + +j = 3: Como arr[j] > pivô, não faça nada +// Sem alteração em i e arr[] + +j = 4: Como arr [j] <= pivô, faça i ++ e troque (arr[i], arr[j]) +i = 2 +arr[] = {10, 30, 40, 90, 80, 50, 70} // 80 e 40 trocados +j = 5: Como arr[j] <= pivô, faça i ++ e troque arr[i] por arr[j] +i = 3 +arr[] = {10, 30, 40, 50, 80, 90, 70} // 90 e 50 trocados + +Saímos do loop porque j agora é igual a high-1. +Finalmente, colocamos o pivô na posição correta, trocando +arr[i + 1] e arr[alto] (ou pivô) +arr[] = {10, 30, 40, 50, 70, 90, 80} // 80 e 70 trocados + +Agora, 70 está em seu lugar correto. Todos os elementos menores que +70 estão antes dele e todos os elementos maiores que 70 estão depois +isto. +``` + +#### Explicação em vídeo + +[Um vídeo explicando o algoritmo de classificação rápida](https://www.youtube.com/watch?v=COk73cpQbFQ) diff --git "a/pt-br/Algoritmos de Ordena\303\247\303\243o/Selection Sort.md" "b/pt-br/Algoritmos de Ordena\303\247\303\243o/Selection Sort.md" new file mode 100644 index 00000000..575bbc7d --- /dev/null +++ "b/pt-br/Algoritmos de Ordena\303\247\303\243o/Selection Sort.md" @@ -0,0 +1,56 @@ +# Classificação de Seleção + +#### Declaração do problema + +Dada uma matriz não classificada de n elementos, escreva uma função para classificar a matriz + +#### Abordagem + +- selecione o menor elemento da matriz +- coloque-o no início da matriz +- em seguida, selecione a menor matriz da lista não classificada restante +- acrescente-o à matriz classificada no início +- continue fazendo isso para cada elemento da matriz +- repita o processo acima n vezes + +#### Complexidade de tempo + +- `O(n^2)` Desempenho de pior caso +- `O(n^2)` Desempenho de melhor caso +- `O(n^2)` Desempenho médio + +#### Complexidade do Espaço + +`O(1)` Pior caso + +#### Exemplo + +``` +arr[] = {80, 10, 40, 30} +Índices: 0 1 2 3 + +1. Índice = 0 +Selecione o número mínimo da matriz (entre o índice 0-3), ou seja, 10 +2. Troque 10 e 80 (arr[0]) +3. A matriz agora é {10, 80, 40, 30} + +4. Índice = 1 +Selecione o número mínimo da matriz (entre os índices 1-3), ou seja, 30 +5. Troque 30 e 80 (arr[1]) +6. A matriz agora é {10, 30, 40, 80} + +7. Índice = 2 +Selecione o número mínimo da matriz (entre o índice 2-3), ou seja, 40 +8. Troque 40 e 40 (arr[2]) +9. A matriz agora é {10, 30, 40, 80} + +A matriz agora está classificada. +``` + +#### Explicação em vídeo + +[Um vídeo explicando o algoritmo de classificação por seleção](https://www.youtube.com/watch?v=f8hXR_Hvybo) + +#### Explicação em formato de animação + +- [Tute Board](https://boardhub.github.io/tute/?wd=selectSortAlgo2) diff --git "a/pt-br/Algoritmos de Ordena\303\247\303\243o/Shell Sort.md" "b/pt-br/Algoritmos de Ordena\303\247\303\243o/Shell Sort.md" new file mode 100644 index 00000000..535e7ecf --- /dev/null +++ "b/pt-br/Algoritmos de Ordena\303\247\303\243o/Shell Sort.md" @@ -0,0 +1,61 @@ +# Shell Sort + +#### Declaração do problema + +Dada uma matriz não classificada de n elementos, escreva uma função para classificar a matriz + +#### Abordagem + +- comece com a lacuna inicial, g +- percorrer os primeiros (n - g) elementos na matriz +- compare o elemento com o próximo elemento que está a g distância +- troque os dois elementos se o primeiro elemento for maior +- diminua o intervalo e repita até o intervalo = 1 + +#### Complexidade de tempo +A complexidade do tempo depende das sequências de lacunas. +As complexidades de tempo abaixo são baseadas nas sequências de lacunas de n / 2 ^ k. + +- `O(n^2)` Desempenho de pior caso +- `O(n)` Melhor caso de desempenho +- `O(n^2)` Desempenho médio + +#### Complexidade do Espaço + +`O(1)` Pior caso + +#### Nome do fundador + +Donald Shell + +#### Exemplo + +``` +arr[] = {61, 109, 149, 111, 34, 2, 24, 119} +Lacuna inicial: 4 + +1. Índice = 0, Índice do próximo elemento = 4 +2. 61> 34, troque 61 e 34 +3. A matriz agora é {34, 109, 149, 111, 61, 2, 24, 119} + +4. Índice = 1, índice do próximo elemento = 5 +5. 109> 2, troque 109 e 2 +6. A matriz agora é {34, 2, 149, 111, 61, 109, 24, 119} + +7. Índice = 2, Índice do próximo elemento = 6 +8. 149> 24, troca 149 e 24 +9. A matriz agora é {34, 2, 24, 111, 61, 109, 149, 119} + +10. Índice = 3, Índice do próximo elemento = 7 +11. 111 <119, não faça nada e continue + +12. Divida a lacuna por 2 e repita até lacuna = 1 +``` + +#### Explicação em vídeo + +[Um vídeo explicando o algoritmo de classificação Shell](https://www.youtube.com/watch?v=H8NiFkGu2PY) + +#### Outras + +A classificação de shell também é conhecida como classificação de incremento decrescente. diff --git a/pt-br/Estruturas de Dados/Graph/Bellman-Ford.md b/pt-br/Estruturas de Dados/Graph/Bellman-Ford.md new file mode 100644 index 00000000..14beb730 --- /dev/null +++ b/pt-br/Estruturas de Dados/Graph/Bellman-Ford.md @@ -0,0 +1,97 @@ +# Bellman-Ford + +#### Declaração do problema + +Dado um grafo direcionado ponderado G (V, E) e um vértice fonte s ∈ V, determine para cada vértice v ∈ V o caminho mais curto entre s e v. + +#### Abordagem + +- Inicialize a distância da fonte a todos os vértices como infinita. +- Inicialize a distância para si mesmo como 0. +- Crie um array dist[] de tamanho | V | com todos os valores infinitos, exceto dist[s]. +- Repita o seguinte | V | - 1 vezes. Onde | V | é o número de vértices. +- Crie outro loop para passar por cada aresta (u, v) em E e faça o seguinte: +1. dist[v] = mínimo (dist[v], dist[u] + peso da aresta). +- Por último, itere por todas as arestas da última vez para garantir que não haja ciclos com peso negativo. + +#### Complexidade de tempo + +`O(VE)` + +#### Complexidade do Espaço + +`O(V^2)` + +#### Nome do fundador + +- Richard Bellman e Lester Ford, Jr. + +#### Exemplo + +``` +Nº de vértices no gráfico = 5 [A, B, C, D, E] +# de arestas no gráfico = 8 + +arestas [A-> B, A-> C, B-> C, B-> D, B-> E, D-> C, D-> B, E-> D] +peso [-1, 4, 3, 2, 2, 5, 1, -4] +fonte [A, A, B, B, B, D, D, E] + +// borda A-> B +gráfico-> borda [0] .src = A +gráfico-> borda [0] .dest = B +gráfico-> borda [0] .weight = -1 + +// borda A-> C +gráfico-> borda [1] .src = A +gráfico-> borda [1] .dest = C +gráfico-> borda [1] .weight = 4 + +// borda B-> C +gráfico-> borda [2] .src = B +gráfico-> borda [2] .dest = C +gráfico-> borda [2] .peso = 3 + +// borda B-> D +gráfico-> aresta [3] .src = B +gráfico-> borda [3] .dest = D +gráfico-> borda [3] .peso = 2 + +// borda B-> E +gráfico-> borda [4] .src = B +gráfico-> borda [4] .dest = E +gráfico-> borda [4] .weight = 2 + +// borda D-> C +gráfico-> borda [5] .src = D +gráfico-> borda [5] .dest = C +gráfico-> borda [5] .weight = 5 + +// borda D-> B +gráfico-> borda [6] .src = D +gráfico-> borda [6] .dest = B +gráfico-> borda [6] .weight = 1 + +// borda E-> D +gráfico-> borda [7] .src = E +gráfico-> borda [7] .dest = D +gráfico-> borda [7] .weight = -3 + +// para fonte = A + +// Distância do vértice da fonte +A 0 A-> A +B -1 A-> B +C2A-> B-> C = -1 + 3 +D -2 A-> B-> E-> D = -1 + 2 + -3 +E 1 A-> B-> E = -1 + 2 +``` + +#### Explicação em vídeo + +[Um vídeo explicando o Algoritmo Bellman-Ford](https://www.youtube.com/watch?v=hxMWBBCpR6A) + +#### Outras + +Fontes usadas: +- https://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/ +- https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm diff --git a/pt-br/Estruturas de Dados/Linked Lists/Lista Duplamente Vinculada.md b/pt-br/Estruturas de Dados/Linked Lists/Lista Duplamente Vinculada.md new file mode 100644 index 00000000..dc09750d --- /dev/null +++ b/pt-br/Estruturas de Dados/Linked Lists/Lista Duplamente Vinculada.md @@ -0,0 +1,107 @@ +# Lista duplamente vinculada (Doubly Linked List) + +Singly Linked List é uma estrutura de dados linear e conectada feita de nós. Cada nó é composto de uma variável `data` onde seu conteúdo é armazenado e um ponteiro para o próximo nó na lista. A Lista Vinculada tem um ponteiro para o primeiro elemento desta sequência de Nó e também pode ter outro ponteiro para o último Nó para tornar as operações na extremidade mais demoradas. Você também pode armazenar uma variável `length` para armazenar o comprimento total. + +Uma ** Lista duplamente vinculada (DLL) ** contém um ponteiro extra, normalmente chamado de ponteiro anterior, junto com o próximo ponteiro e os dados que estão lá na lista vinculada individualmente. + +### Vantagens em relação à lista vinculada isoladamente + +- Uma DLL pode ser percorrida tanto para frente quanto para trás. +- A operação de exclusão na DLL é mais eficiente se o ponteiro para o nó a ser excluído for fornecido. +- Podemos inserir rapidamente um novo nó antes de um determinado nó. +Na lista vinculada individualmente, para excluir um nó, é necessário um ponteiro para o nó anterior. Para obter esse nó anterior, às vezes a lista é percorrida. Na DLL, podemos obter o nó anterior usando o ponteiro anterior. + +### Desvantagens em relação à lista vinculada isoladamente + +- Cada nó de DLL requer espaço extra para um ponteiro anterior. É possível implementar DLL com um único ponteiro embora (veja isto e isto). +- Todas as operações requerem um ponteiro extra anterior para ser mantido. Por exemplo, na inserção, precisamos modificar os ponteiros anteriores junto com os próximos ponteiros. Por exemplo, nas seguintes funções para inserções em posições diferentes, precisamos de 1 ou 2 etapas extras para definir o ponteiro anterior. + +### Complexidade de tempo + +| Operação | Média | Pior | +| --------- | ------- | ----- | +| Acesso Θ (n) | O (n) | +| Pesquisa | Θ (n) | O (n) | +| Inserção | Θ (1) | O (1) | +| Exclusão | Θ (1) | O (1) | + +## Exemplo + +```java +class LinkedList { + +Cabeça do nó; // Ponteiro para o primeiro elemento +Cauda do nó; // Opcional. Aponta para o último elemento + +comprimento interno; // opcional + + class Node { + dados internos; // Dados do nó. Pode ser int, string, float, templates, etc. + Nó próximo; // Ponteiro para o próximo nó da lista + Node prev; + + Nó (dados internos) { + this.data = data; + } + } + + + // Adicionando um nó na frente da lista + public void push (int new_data) { + + // 1. alocar nó + // 2. inserir os dados + Nó new_Node = novo Nó (new_data); + + // 3. Faça o próximo do novo nó como principal e o anterior como NULL * / + new_Node.next = head; + new_Node.prev = null; + + // 4. alterar anterior do nó principal para o novo nó * / + if (head! = null) + head.prev = new_Node; + + // 5. mova a cabeça para apontar para o novo nó * / + head = new_Node; + } + + // Dado um nó como prev_node, insira um novo nó após o nó fornecido * / + public void InsertAfter (Node prev_Node, int new_data) { + + // 1. verifique se o prev_node fornecido é NULL * / + if (prev_Node == null) { + System.out.println ("O nó anterior fornecido não pode ser NULL"); + Retorna; + } + + // 2. alocar nó + // 3. coloque os dados * / + Nó new_node = new Node (new_data); + + // 4. Faça o próximo do novo nó como próximo do prev_node + new_node.next = prev_Node.next; + + // 5. Faça o próximo de prev_node como new_node + prev_Node.next = new_node; + + // 6. Faça prev_node como anterior de new_node + new_node.prev = prev_Node; + + // 7. Alterar anterior do próximo nó de new_node + if (new_node.next! = null) + new_node.next.prev = new_node; + } +} +``` + +### Adicionando nó na frente + +! [Rastreamento de algoritmo](https://www.geeksforgeeks.org/wp-content/uploads/gq/2014/03/DLL_add_front1.png) + +### Adicionar um nó após um determinado nó + +! [Rastreamento de algoritmo](https://www.geeksforgeeks.org/wp-content/uploads/gq/2014/03/DLL_add_middle1.png) + +## Explicação em vídeo + +[Um vídeo CS50 explicando a estrutura de dados da lista duplamente vinculada](https://www.youtube.com/watch?v=FHMPswJDCvU) diff --git a/pt-br/Estruturas de Dados/Linked Lists/Lista individual.md b/pt-br/Estruturas de Dados/Linked Lists/Lista individual.md new file mode 100644 index 00000000..d66044aa --- /dev/null +++ b/pt-br/Estruturas de Dados/Linked Lists/Lista individual.md @@ -0,0 +1,42 @@ +# Lista vinculada individualmente (Singly Linked List) + +Singly Linked List é uma estrutura de dados linear e conectada feita de nós. Cada nó é composto de uma variável `dados` onde seu conteúdo é armazenado e um ponteiro para o próximo nó da lista. A Lista Vinculada tem um ponteiro para o primeiro elemento desta sequência de Nó e também pode ter outro ponteiro para o último Nó para tornar as operações na extremidade mais demoradas. Você também pode armazenar uma variável `length` para armazenar o comprimento total. + +### Vantagens sobre Arrays + +- O tamanho de uma lista vinculada não é fixo (tamanho dinâmico). +- Excluir e adicionar um elemento não é uma operação computacional caro em comparação com uma matriz. + +### Desvantagens + +- Os elementos podem ser acessados ​​sequencialmente, não aleatoriamente em comparação com uma matriz. +- Alocação de memória extra precisa ser feita para ponteiros que conectam elementos em uma lista vinculada. + +### Complexidade de tempo + +| Operação | Média | Pior | +| ------------ | ----- | ----- | +| Acesso O (n) | O (n) | | +| Pesquisa | O (n) | O (n) | +| Inserção | O (1) | O (1) | +| Exclusão | O (1) | O (1) | + +## Exemplo + +```.java +class LinkedList { + Cabeça do nó; // Ponteiro para o primeiro elemento + Cauda do nó; // Opcional. Aponta para o último elemento + + comprimento interno; // opcional + + class Node { + dados internos; // Dados do nó. Pode ser int, string, float, templates, etc. + Nó próximo; // Ponteiro para o próximo nó da lista + } +} +``` + +## Explicação em vídeo + +[Um vídeo CS50 explicando a estrutura de dados da lista vinculada](https://www.youtube.com/watch?v=5nsKtQuT6E8) diff --git "a/pt-br/Matem\303\241tica B\303\241sica/M\303\251dia.md" "b/pt-br/Matem\303\241tica B\303\241sica/M\303\251dia.md" new file mode 100644 index 00000000..40193b9f --- /dev/null +++ "b/pt-br/Matem\303\241tica B\303\241sica/M\303\251dia.md" @@ -0,0 +1,67 @@ +# Média + +Calcule a média de uma lista de números usando a média. + +## Aplicações + +Calcular a média de uma lista de números é uma das maneiras mais comuns de +determinar a média desses números. + +Calcular uma média seria útil nestas situações: + +- Determinar a pontuação média de todos os jogadores de um nível de videogame. +- Encontrar a nota média das provas que um aluno fez neste semestre. +- Determinar o tamanho médio de todos os arquivos em um diretório / pasta. + +## Passos + +1. Insira uma lista de números. +2. Calcule a soma de todos os números da lista. +3. Conte os números da lista. +4. Divida a soma pela contagem total de números na lista. +5. Média de retorno. + +## Exemplo + +Dada a lista `[2, 4, 6, 8, 20, 50, 70]`, vamos calcular a média. + +### Passo 1 + +Envie `[2, 4, 6, 8, 20, 50, 70]` como entrada para um método / função. + +### Passo 2 + +Some todos os números. + +`2 + 4 + 6 + 8 + 20 + 50 + 70 = 160`, então `soma = 160`. + +### Etapa 3 + +Conte os números da lista. + +A lista tem sete números, então `contagem = 7`. + +### Passo 4 + +Divida a soma de todos os números pela contagem dos números. + +``` +soma = 160 +contagem = 7 +``` + +Se ignorarmos os dígitos significativos: `soma / contagem = 22`. + +Se considerarmos corretamente os dígitos significativos: `soma / contagem = 23`. + +### Etapa 5 + +Retorne o valor de 22 ou `23`. + +## URL do vídeo + +- [Média na Khan Academy](https://www.khanacademy.org/math/cc-sixth-grade-math/cc-6th-data-statistics/mean-and-median/v/mean-median-and-mode) + +## Outros + +- [Média na Wikipedia](https://en.wikipedia.org/wiki/Mean) diff --git "a/pt-br/Programa\303\247\303\243o Din\303\242mica/Subsequencia Maxima - Maior Subsequencia Comum (LCS).md" "b/pt-br/Programa\303\247\303\243o Din\303\242mica/Subsequencia Maxima - Maior Subsequencia Comum (LCS).md" new file mode 100644 index 00000000..8535f49b --- /dev/null +++ "b/pt-br/Programa\303\247\303\243o Din\303\242mica/Subsequencia Maxima - Maior Subsequencia Comum (LCS).md" @@ -0,0 +1,84 @@ +# Subsequência Maxima / Maior Subsequência Comum + +#### Declaração do problema + +Dadas duas strings/palavras, `S` e `T`, encontre o comprimento da maior subsequência comum. + +#### Abordagem + +Considere uma array/matriz `dp[i][j]` que representa o comprimento da maior subsequência comum com os prefixos `S[1..i]` e `T[1..j]`. Nossa resposta pode ser representada por `dp[|S|][|T|]`, visto que o prefixo de comprimento da string/palavra, é a própria string. + +Os valores de `dp[0][i]` e `dp[i][0]` são `0` para qualquer valor de `i`, visto que possui um prefixo vazio (de valor `0` e resultado nulo). + +Agora vamos calcular o `dp[i][j]` para qualquer valor de `i` e `j`. Para representar isso vamos dizer que `S[1..i] = *A` e `T[1..j] = *B`, onde `*` representa uma sequencia de letras qualquer (podem ter diferenças entre `S` e `T`), onde o valor `A` representa uma letra qualquer e `B` para qualquer letra DIFERENTE de `A`. +Como `A != B`, nosso comprimento da maior subsequência comum não inclui o valor de `A` ou `B` como ultimo caractere. Portanto é possivel utilizar estes caracteres para simplificar. +Se utilizarmos o valor de `A`, o tamanho da nossa subsequência será `dp[i - 1][j]` (visto que nossos prefixos serão `S[1..i - 1]` and `T[1..j]`). Agora, utilizando o valor de `B`, teremos os prefixos `S[1..i]` e `T[1..j - 1]`, então o tamanho desta subsequência será `dp[i][j - 1]`. +Entendendo que estamos procurando pelo comprimento da MAIOR subsequência comum, escolheremos o VALOR MÁXIMO de `dp[i][j - 1]` e `dp[i - 1][j]`. + +Mas e se `S[1..i] = *A` e `T[1..j] = *A`? Podemos dizer que o comprimento da nossa subsequência é igual ao comprimento da subsequência com os prefixos iguais a `S[1..i - 1]` e `T[1..j - 1]`, SOMADOS a letra `A`. Então, é possivel dizer que `dp[i][j] = dp[i - 1][j - 1] + 1` se `S[i] = T[j]`. + +Com esta lógica, podemos ver que é possivel preencher a tabela `dp` linha por linha e coluna por coluna. Portanto é possivel resumir o algoritmo nestes seguintes passos: + +- Supondo que possuimos as strings `S` de comprimento N, e `T` de comprimento M (numeradas a partir de 1 a X). Vamos criar a tabela `dp`, de tamanho `(N + 1) x (M + 1)` a partir de 0. +- Agora vamos preencher a 0° linha e a 0° coluna de `dp` com o valor 0. +- Então podemos seguir o seguinte algoritmo: + ``` + for i in range(1..N): + for j in range(1..M): + if(S[i] == T[j]) + dp[i][j] = dp[i - 1][j - 1] + 1 + else + dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + ``` + +#### Complexidade de tempo + +`O(N * M)` em qualquer caso. + +#### Complexidade de espaço + +`O(N * M)` - implementação simples. +`O(min {N, M})` - para a implementação de duas camadas (`dp[i][j]` depende apenas das camadas `i` e `j`, resultando no armazenamento maximo de duas camadas). + +#### Exemplo + +Deduzindo que as duas strings/palavras sejam `ABCB` e `BBCB`, montaremos a seguinte tabela: + +``` +# # A B C B +# 0 0 0 0 0 +B 0 ? ? ? ? +B 0 ? ? ? ? +C 0 ? ? ? ? +B 0 ? ? ? ? +``` + +Agora, iniciaremos o preenchimento da tabela a partir da 1° linha. +Como `S[1] = A` e `T[1] = B`, o `dp[1][1]` será o valor máximo de `dp[0][1] = 0` e `dp[1][0] = 0`. Desta forma, `dp[1][1] = 0`. +Mas agora, se considerarmos `S[2] = B = T[1]`, então `dp[1][2] = dp[0][1] + 1 = 1`. O `dp[1][3]` será igual a `1`, visto que `A != C`, onde escolheremos `max{dp[1][2], dp[0][3]}` e `dp[1][4] = dp[0][3] + 1 = 1`. + +``` +# # A B C B +# 0 0 0 0 0 +B 0 0 1 1 1 +B 0 ? ? ? ? +C 0 ? ? ? ? +B 0 ? ? ? ? +``` + +Agora, basta preencher a outra parte da tabela: + +``` +# # A B C B +# 0 0 0 0 0 +B 0 0 1 1 1 +B 0 0 1 1 2 +C 0 0 1 2 2 +B 0 0 1 2 3 +``` + +Sendo o comprimento da maior subsequência comum igual a: `dp[4][4] = 3`. + +#### Explicação em vídeo + +- [Vídeo do canal OnlineBioinfo Bioinformática explicando sobre o algoritmo LCS](https://youtu.be/cX_hFqA8wDI) diff --git "a/pt-br/Programa\303\247\303\243o Din\303\242mica/Trocando moedas.md" "b/pt-br/Programa\303\247\303\243o Din\303\242mica/Trocando moedas.md" new file mode 100644 index 00000000..763ee879 --- /dev/null +++ "b/pt-br/Programa\303\247\303\243o Din\303\242mica/Trocando moedas.md" @@ -0,0 +1,62 @@ +# Trocando moedas + +#### Declaração do problema + +Dado um valor `N`, se quisermos fazer a mudança para` N` centavos, e temos um suprimento infinito de cada uma das moedas com valor de `S = {S1, S2, .., Sm}`, de quantas maneiras podemos fazer o troco? A ordem das moedas não importa. + +#### Abordagem + +Seja `dp[i]` o comprimento da moeda de troca do prefixo `N[1..i]`. Nossa resposta é `dp[N]`. Preenchemos `dp[0]` como 1 porque só existe uma maneira de obter 0 moedas (não escolhemos moedas). + +Agora vamos tentar calcular `dp[i]` para qualquer `i`. `dp[0..i]` armazenará cada subproblema de `0` a` N`. É por isso que a resposta será `dp[N]`. Primeiro, precisamos iterar cada tipo de moeda para escolhê-los um por um. Em seguida, iteramos os subproblemas da moeda atual que escolhemos antes para `N` centavos. É por isso que devemos fazer a tabela dp com colunas `N`. + +Estes são os códigos para o algoritmo de troca de moeda: + +``` +para coin_val em S: + para i no intervalo (coin_val, n + 1): + dp[i] + = dp[i - coin_val] +``` + +Na segunda iteração, para cada centavo que pode ser trocado, nós o pegamos subtraindo a i-ésima coluna pelo valor da moeda que pegamos e adicionando-o à coluna atual. Portanto, `dp[i]` armazenará o subproblema atual. + +#### Complexidade de tempo +`O(n * s)` em qualquer caso + +#### Complexidade do Espaço +`O(n)` - implementação simples. Precisamos apenas do array 1D para armazenar a resposta. + +#### Exemplo +Digamos que temos 3 tipos de moeda `[1,2,3]` e queremos mudar para `7` centavos. Portanto, definiremos nossa tabela assim. + +``` +[1, 0, 0, 0, 0, 0, 0, 0] +``` + +0ª coluna armazenará 1, pois só há uma maneira de obter 0 centavos. + +* Para a primeira iteração, pegamos uma moeda que tem o valor 1. Então, para todos os subproblemas, há apenas uma maneira de fazer alterações. Por 7 centavos, a única maneira é `{1,1,1,1,1,1,1}`. Na iteração final, nossa tabela fica como: + +``` +[1, 1, 1, 1, 1, 1, 1, 1] +``` + +* Para a segunda iteração, pegamos uma moeda com o valor 2. A partir daqui, todos os subproblemas que podem ser divididos por 2 armazenarão outra nova maneira de fazer alterações. Então, quando a iteração parou na 2ª coluna, será como `dp[2] + = dp[0]`. Sabemos que `dp[0]` armazenou um valor de 1. Portanto, dp[2] armazenará o valor de `1 + 1 = 2`. A partir daqui sabemos que por 2 centavos, existem 2 maneiras `{1,1}` e `{2}`. E essa operação vai continuar. Agora nossa mesa é como: + +``` +[1, 1, 2, 2, 3, 3, 4, 4] +``` + +4 maneiras de ganhar 7 centavos usando o valor de 1 e 2. `{{1,1,1,1,1,1,1}, {1,1,1,1,1,2}, {1,1, 1,2,2}, {1,2,2,2}}` + +* Para a iteração final (3ª iteração), pegamos uma moeda que tem o valor 3. Como antes, agora todas as colunas que podem ser divididas por 3 serão armazenadas de outra maneira. E o resultado final será assim: + +``` +[1, 1, 2, 3, 4, 5, 7, 8] +``` + +Portanto, a resposta final é **8**. 8 maneiras de fazer troco de 7 centavos usando todos os tipos de moedas. `{{1,1,1,1,1,1,1}, {1,1,1,1,1,2}, {1,1,1,2,2}, {1,2,2,2}, {1,1,1,1,3}, {1,3,3}, {2,2,3}, {1,1,2,3}}` + +#### Explicação em vídeo + +[Total de maneiras exclusivas de fazer a mudança em back to back SWE](https://www.youtube.com/watch?v=DJ4a7cmjZY0) diff --git a/pt-br/README.md b/pt-br/README.md new file mode 100644 index 00000000..1c4f97d1 --- /dev/null +++ b/pt-br/README.md @@ -0,0 +1,30 @@ +# Nome do Algoritmo + +Escreva uma breve descrição do algoritmo como: + +1. Complexidade de tempo +2. Complexidade do Espaço +3. Aplicativos +4. Nome do fundador +5. etc ... + +## Passos + +Descreva o algoritmo em etapas claras, de forma simples e compreensível. + +## Exemplo + +Rastreie o algoritmo com dados de entrada de amostra. + +## Implementação + +Links para sua implementação em linguagens de programação. +NOTA: O link deve estar apenas em outros repositórios desta organização. + +## URL do vídeo + +Anexe um URL de um vídeo que explica o algoritmo. + +## Outras + +Qualquer outra informação é sempre bem-vinda e deve ser incluída nesta seção. diff --git a/ru/README.md b/ru/README.md new file mode 100644 index 00000000..71964fa8 --- /dev/null +++ b/ru/README.md @@ -0,0 +1,31 @@ +# Имя алгоритма + +Напишите краткое описание алгоритма, например: + +1. Временная сложность +2. Пространственная сложность +3. Приложения +4. Имя основателя +5. и т.д. + +## Шаги + +Опишите алгоритм в ясных, простых и понятных шагах. + +## Пример + +Проконтролируйте алгоритм на примере входных данных. + +## Реализация + +Ссылки на реализацию на языках программирования. + +ПРИМЕЧАНИЕ: Ссылка должна быть только в других репозиториях этой организации. + +## URL-адрес видео + +Прикрепите URL-адрес видео, объясняющего алгоритм. + +## Другие + +Любая другая информация всегда приветствуется и должна быть включена в этот раздел. diff --git "a/ru/\320\220\320\273\320\263\320\276\321\200\320\270\321\202\320\274\321\213 \320\237\320\276\320\270\321\201\320\272\320\260/\320\221\320\270\320\275\320\260\321\200\320\275\321\213\320\271 \320\237\320\276\320\270\321\201\320\272.md" "b/ru/\320\220\320\273\320\263\320\276\321\200\320\270\321\202\320\274\321\213 \320\237\320\276\320\270\321\201\320\272\320\260/\320\221\320\270\320\275\320\260\321\200\320\275\321\213\320\271 \320\237\320\276\320\270\321\201\320\272.md" new file mode 100644 index 00000000..a35ed96c --- /dev/null +++ "b/ru/\320\220\320\273\320\263\320\276\321\200\320\270\321\202\320\274\321\213 \320\237\320\276\320\270\321\201\320\272\320\260/\320\221\320\270\320\275\320\260\321\200\320\275\321\213\320\271 \320\237\320\276\320\270\321\201\320\272.md" @@ -0,0 +1,47 @@ +# Бинарный поиск (алгоритм "разделяй и властвуй") + +#### Постановка задачи + +Дан остортированный массив из `n` элементов. Написать функцию поиска индекса заданного (целевого) элемента. + +#### Подход + +- Поиск массива путем многократного деления массива на половины. +- Изначально рассмотрим фактический массив и выберем элемент в среднем индексе. +- Сохраняем нижний индекс (0) и верхний индекс (длина массива). +- Если элемент равен целевому элементу, то возвращаем индекс. +- Если элемент больше целевого элемента, то рассматриваем только левую половину массива (нижний индекс = 0, верхний индекс = `middle - 1`). +- Если элемент меньше целевого элемента, то рассматриваем только правую половину массива (нижний индекс = `middle + 1`, верхний индекс = длина массива). +- Возвращаем `-(индекс вставки + 1)`, если целевой элемент не найден в массиве (если нижний индекс больше или равен верхнему индексу). Некоторые более простые реализации просто возвращают `-1`, если элемент не найден. Смещение 1 должно быть добавлено, так как индекс вставки может быть `0` (искомое значение может быть меньше всех элементов в массиве). Поскольку индексация начинается с `0`, это должно быть отличимо от случая, когда целевой элемент имеет индекс `0`. + +#### Временная сложность + +- O(log n) - в худшем случае; +- O(1) - в лучшем случае (если средний элемент изначального массива является целевым элементом). + +##### Пространственная сложность + +- O(1) - для итеративного подхода; +- O(1) - для рекурсивного подхода если используется оптимизация хвостовых вызовов, `O(log n)` из-за стека вызовов рекурсии в противном случае. + +#### Пример + +```python +arr = [1,2,3,4,5,6,7] + +target = 2 +``` + +Изначально элемент в среднем индексе - `4`, который больше `2`. Поэтому мы ищем левую половину массива, т. е. `[1,2,3]`. + +Здесь мы находим средний элемент, равный целевому элементу, поэтому возвращаем его индекс, т. е. `1`. + +``` +target = 9 +``` + +#### Видео обзоры + +#### Визуальное представление + +- [Tute Board](https://boardhub.github.io/tute/?wd=binarySearchAlgo2) diff --git "a/ru/\320\220\320\273\320\263\320\276\321\200\320\270\321\202\320\274\321\213 \320\241\320\276\321\200\321\202\320\270\321\200\320\276\320\262\320\272\320\270/\320\244\320\273\320\260\320\263 \320\235\320\270\320\264\320\265\321\200\320\273\320\260\320\275\320\264\320\276\320\262.md" "b/ru/\320\220\320\273\320\263\320\276\321\200\320\270\321\202\320\274\321\213 \320\241\320\276\321\200\321\202\320\270\321\200\320\276\320\262\320\272\320\270/\320\244\320\273\320\260\320\263 \320\235\320\270\320\264\320\265\321\200\320\273\320\260\320\275\320\264\320\276\320\262.md" new file mode 100644 index 00000000..93fa214e --- /dev/null +++ "b/ru/\320\220\320\273\320\263\320\276\321\200\320\270\321\202\320\274\321\213 \320\241\320\276\321\200\321\202\320\270\321\200\320\276\320\262\320\272\320\270/\320\244\320\273\320\260\320\263 \320\235\320\270\320\264\320\265\321\200\320\273\320\260\320\275\320\264\320\276\320\262.md" @@ -0,0 +1,34 @@ +# Задача флага Нидерландов + +#### Постановка задачи + +Дан массив с несколькими цветами (красный, белый и синий), нужно упорядочить его таким образом, чтобы все цвета были сгруппированы вместе. Мы будем использовать целые числа `0`, `1` и `2` для представления красного, белого и синего цветов соответственно. + +Нужно отсортировать массив на месте без использования дополнительной памяти и стандартной функции сортировки. + +#### Алгоритм + +1. Создайте три указателя - `low`, `mid` и `high`. +1. Установите `low` и `mid` в начало массива, а `high` в конец массива. +1. Сравните `nums[mid]` со значением `1`. + - Если `nums[mid]` равен 1, просто увеличьте mid. + - Если `nums[mid]` равен 0, поменяйте `nums[mid]` и `nums[low]`, а затем увеличьте `mid` и `low` на 1. + - Если `nums[mid]` равен 2, поменяйте `nums[mid]` и `nums[high]`, а затем уменьшите `high` на 1. +1. Продолжайте шаги 3 до тех пор, пока `mid <= high`. + +#### Временная сложность + +- O(n) + +#### Пространственная сложность + +- O(1) + +#### Пример + +```python +nums = [2, 0, 2, 1, 1, 0] + +print(dutch_flag_sort(nums)) +# Output: [0, 0, 1, 1, 2, 2] +``` diff --git a/uz/Boshlang'ich Matematika/Arifmetik progressiya.md b/uz/Boshlang'ich Matematika/Arifmetik progressiya.md new file mode 100644 index 00000000..ea04d925 --- /dev/null +++ b/uz/Boshlang'ich Matematika/Arifmetik progressiya.md @@ -0,0 +1,41 @@ +# Arifmetik Progressiya + +**Arifmetik progressiya** – ikkinchisidan boshlab har bir son oʻzidan oldingi songa shu qator uchun oʻzgarmas bir son **d** (progressiya ayirmasi)ni qoʻshishdan hosil boʻladigan sonlar qatori. +Masalan, 2, 4, 6, 8, 10 sonlar qatori Arifmetik progressiyadir. Chunki, bu qatordagi har bir son oldingisidan bir xilga, 2ga farq qiladi. +

+ +

+ +**Arifmetik Progressiyada:** + +1. Arifmetik Progressiyaning birinchi elementi uning `birinchi hadi` deyiladi. +2. hadlari orasidagi farqi esa Arifmetik Progressiyaning `ayirmasi` deyiladi. +3. Arifmetik Progressiyaning o'suvchi yoki kamayuvchi bo'lishini uning `ayirmasi` ifodalayadi. Agar Arifmetik Progressiya `ayirmasi` musbat bo'lsa (`d>0`), `o'suvchi` agarda manfiy bo'lsa (`d<0`), kamayuvchi bo'ladi. + +**Arifmetik Progressiyaning `n`chi hadini topish:** + +a1 - birinchi hadi va `d` esa arifmetik progressiya ayirmasi. Shulardan kelib chiqqan holatda umumiy formula quyidagicha bo'ladi: +

+ +

+ +**Arifmetik Progressiyaning birinchi `n`ta hadini yig'indisini topish:** + +

+ +

+ +**Arifmetik Progressiyaga oid masalalarni yechishni umumiy formulalari:** + + Agar a1 - birinchi xadi va uning ayirmasi - `d` bo'lsa: +- **an** = a1 + (n-1)*d. +- **Arifmetik o'rtanchasini topish:** Sn / n. +- **Dastlabki `n`tasini yig'indisi** `S = 0.5 n [ 2a + (n-1) d ]`. + +# Manba + +- [Arifmetik Progressiya](https://uz.khanacademy.org/math/algebra/sequences/introduction-to-arithmetic-squences/a/using-formulas-of-arithmetic-sequences) + +# YouTube + +- [Video materialga bog'ich](https://youtu.be/UVDpqDlBhyE) diff --git a/uz/Boshlang'ich Matematika/Eng katta sonni topish.md b/uz/Boshlang'ich Matematika/Eng katta sonni topish.md new file mode 100644 index 00000000..e69de29b diff --git a/uz/Boshlang'ich Matematika/Fibonachi sonlari.md b/uz/Boshlang'ich Matematika/Fibonachi sonlari.md new file mode 100644 index 00000000..c65daca2 --- /dev/null +++ b/uz/Boshlang'ich Matematika/Fibonachi sonlari.md @@ -0,0 +1,47 @@ +# Fibonachi sonlari + +Matematikada Fibonachi sonlari deb nomlanadigan sonlar qatori mavjud bo'lib, bu sonlar qatorida har bir son o'zidan +avval kelgan ikkitda ketma-ket sonlarning yig'indisidan iboratdir. Fibonachi sonlar qatorining birinchi va ikkinchi +hadlari mos ravishda 0 va 1ga tengdir. Quyidagi qator ham Fibonachi qatori hisoblanadi: +`[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...]` + +## Foydalanish + +Biz Fibonachi sonlar qatorini asosan kompyterlarda qidirish algorithmi sifatida ko'rishimiz mumkin. Bundan tashqari bu +qatorni bir hayotimizning quyidagi jabhalarida uchratib turishimiz mumkin: + +- Daraxt barglarining o'zagida va daraxt shoxlarida uchratib turishimiz mumkin. + +Hozirgi kunda Fibonachi sonlar qatori va Oltin nisbatga fizika, kvant mehanikasi va kriptografiya sohasida izlanish olib +boruvchilar tomonidan katta qiziqishlar bildirilmoqda. + +## Namuna + +Fibonachi sonlarning 8chi hadini topishni ko'rib chiqamiz: + + +1-had | `f1 = 0` + +2-had | `f2 = 1 ` + +3-had | `f3 = f1+f2`=1 + +4-had | `f4 = f2+f3`=2 + +5-had | `f5 = f3+f4`=3 + +6-had | `f6 = f4+f5`=5 + +7-had | `f7 = f5+f6`=8 + +8-had | `f8 = f6+f7`=13 + +f(8)=21 + +## Video bog'ich + +- [YouTube](https://youtu.be/FQiRf4jb3PU) + +## Boshqa manbalar + +- [Wikipedia](https://uz.wikipedia.org/wiki/Fibonachchi_sonlari) diff --git a/uz/Boshlang'ich Matematika/Geometrik progressiya.md b/uz/Boshlang'ich Matematika/Geometrik progressiya.md new file mode 100644 index 00000000..e69de29b diff --git a/uz/Boshlang'ich Matematika/O'rtacha qiymat.md b/uz/Boshlang'ich Matematika/O'rtacha qiymat.md new file mode 100644 index 00000000..e69de29b diff --git a/uz/Boshlang'ich Matematika/Raqamlar sonini topish.md b/uz/Boshlang'ich Matematika/Raqamlar sonini topish.md new file mode 100644 index 00000000..e69de29b