diff --git a/.DS_Store b/.DS_Store
deleted file mode 100644
index dd05b9be5a8c..000000000000
Binary files a/.DS_Store and /dev/null differ
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 000000000000..3d685994a1aa
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,136 @@
+---
+Language: Java
+AccessModifierOffset: -4
+AlignAfterOpenBracket: DontAlign
+AlignConsecutiveMacros: false
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: Right
+AlignOperands: false
+AlignTrailingComments: false
+AllowAllArgumentsOnNextLine: true
+AllowAllConstructorInitializersOnNextLine: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: Never
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: false
+AllowShortLambdasOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: true
+AllowShortLoopsOnASingleLine: true
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: MultiLine
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterCaseLabel: false
+ AfterClass: false
+ AfterControlStatement: false
+ AfterEnum: false
+ AfterFunction: false
+ AfterNamespace: false
+ AfterObjCDeclaration: false
+ AfterStruct: false
+ AfterUnion: false
+ AfterExternBlock: false
+ BeforeCatch: false
+ BeforeElse: false
+ IndentBraces: false
+ SplitEmptyFunction: true
+ SplitEmptyRecord: true
+ SplitEmptyNamespace: true
+BreakBeforeBinaryOperators: All
+BreakBeforeBraces: Custom
+BreakBeforeInheritanceComma: false
+BreakInheritanceList: BeforeColon
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeComma
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: true
+ColumnLimit: 300
+CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DeriveLineEnding: true
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: false
+ForEachMacros:
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
+IncludeBlocks: Preserve
+IncludeCategories:
+ - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
+ Priority: 2
+ SortPriority: 0
+ - Regex: '^(<|"(gtest|gmock|isl|json)/)'
+ Priority: 3
+ SortPriority: 0
+ - Regex: '.*'
+ Priority: 1
+ SortPriority: 0
+IncludeIsMainRegex: '(Test)?$'
+IncludeIsMainSourceRegex: ''
+IndentCaseLabels: false
+IndentGotoLabels: true
+IndentPPDirectives: None
+IndentWidth: 4
+IndentWrappedFunctionNames: false
+InsertNewlineAtEOF: true
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: Inner
+ObjCBinPackProtocolList: Auto
+ObjCBlockIndentWidth: 4
+ObjCSpaceAfterProperty: true
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakAssignment: 2
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyBreakTemplateDeclaration: 10
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerAlignment: Left
+ReflowComments: true
+SortIncludes: true
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: true
+SpaceAfterLogicalNot: false
+SpaceAfterTemplateKeyword: true
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatements
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceInEmptyBlock: false
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInConditionalStatement: false
+SpacesInContainerLiterals: false
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+SpaceBeforeSquareBrackets: false
+Standard: Latest
+StatementMacros:
+ - Q_UNUSED
+ - QT_REQUIRE_VERSION
+TabWidth: 8
+UseCRLF: false
+UseTab: Never
+...
diff --git a/.classpath b/.classpath
deleted file mode 100644
index 67d5f6d35842..000000000000
--- a/.classpath
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
new file mode 100644
index 000000000000..bcea8e797ffb
--- /dev/null
+++ b/.devcontainer/Dockerfile
@@ -0,0 +1,25 @@
+# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.238.0/containers/java/.devcontainer/base.Dockerfile
+
+# [Choice] Java version (use -bullseye variants on local arm64/Apple Silicon): 11, 17, 11-bullseye, 17-bullseye, 11-buster, 17-buster
+ARG VARIANT="21-bullseye"
+FROM mcr.microsoft.com/vscode/devcontainers/java:1.1.0-${VARIANT}
+
+# [Option] Install Maven
+ARG INSTALL_MAVEN="false"
+ARG MAVEN_VERSION=""
+# [Option] Install Gradle
+ARG INSTALL_GRADLE="false"
+ARG GRADLE_VERSION=""
+RUN if [ "${INSTALL_MAVEN}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/sdkman/bin/sdkman-init.sh && sdk install maven \"${MAVEN_VERSION}\""; fi \
+ && if [ "${INSTALL_GRADLE}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/sdkman/bin/sdkman-init.sh && sdk install gradle \"${GRADLE_VERSION}\""; fi
+
+# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
+ARG NODE_VERSION="none"
+RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
+
+# [Optional] Uncomment this section to install additional OS packages.
+# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
+# && apt-get -y install --no-install-recommends
+
+# [Optional] Uncomment this line to install global node packages.
+# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g " 2>&1
\ No newline at end of file
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 000000000000..fdc7cdbd25f9
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,47 @@
+// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
+// https://github.com/microsoft/vscode-dev-containers/tree/v0.238.0/containers/java
+{
+ "name": "Java",
+ "build": {
+ "dockerfile": "Dockerfile",
+ "args": {
+ // Update the VARIANT arg to pick a Java version: 11, 17
+ // Append -bullseye or -buster to pin to an OS version.
+ // Use the -bullseye variants on local arm64/Apple Silicon.
+ "VARIANT": "21-bullseye",
+ // Options
+ "INSTALL_MAVEN": "true",
+ "INSTALL_GRADLE": "true",
+ "NODE_VERSION": "lts/*"
+ }
+ },
+
+ // Configure tool-specific properties.
+ "customizations": {
+ // Configure properties specific to VS Code.
+ "vscode": {
+ // Set *default* container specific settings.json values on container create.
+ "settings": {
+ },
+
+ // Add the IDs of extensions you want installed when the container is created.
+ "extensions": [
+ "vscjava.vscode-java-pack",
+ "GitHub.copilot",
+ ]
+ }
+ },
+
+ // Use 'forwardPorts' to make a list of ports inside the container available locally.
+ // "forwardPorts": [],
+
+ // Use 'postCreateCommand' to run commands after the container is created.
+ "postCreateCommand": "java -version",
+
+ // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
+ "remoteUser": "vscode",
+ "features": {
+ "git": "os-provided",
+ "github-cli": "latest"
+ }
+}
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 000000000000..9a0617e18a06
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1 @@
+* @DenizAltunkapan @yanglbme @vil02 @alxkm
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 000000000000..9c906c381608
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,45 @@
+name: "Bug report"
+description: "Create a report to help us improve"
+title: "[BUG] "
+labels: ["bug"]
+body:
+ - type: textarea
+ id: description
+ attributes:
+ label: "Description"
+ description: "A clear and concise description of what the bug is."
+ validations:
+ required: true
+ - type: textarea
+ id: steps
+ attributes:
+ label: "Steps to reproduce"
+ description: "Steps to reproduce the behavior (if applicable)"
+ placeholder: |
+ 1. Go to '...'
+ 2. Click on '....'
+ 3. Scroll down to '....'
+ 4. See error
+ validations:
+ required: false
+ - type: textarea
+ id: exceptedbhv
+ attributes:
+ label: "Excepted behavior"
+ description: "A clear and concise description of what you expected to happen."
+ validations:
+ required: true
+ - type: textarea
+ id: screenshots
+ attributes:
+ label: "Screenshots"
+ description: "If applicable, add screenshots to help explain your problem."
+ validations:
+ required: false
+ - type: textarea
+ id: context
+ attributes:
+ label: "Additional context"
+ description: "Is there anything else we should know about this bug report?"
+ validations:
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 000000000000..875cc4efab00
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,5 @@
+blank_issues_enabled: false
+contact_links:
+ - name: Discord community
+ url: https://the-algorithms.com/discord/
+ 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 000000000000..98ff394158be
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,34 @@
+name: "Feature Request"
+description: "Suggest an idea for this project"
+title: "[FEATURE REQUEST] "
+labels: ["enhancement"]
+body:
+ - type: textarea
+ id: description
+ attributes:
+ label: What would you like to Propose?
+ description: Provide a clear and concise explanation of your Proposal.
+ validations:
+ required: true
+ - type: markdown
+ attributes:
+ value: |
+ For new implementations, please specify the name and problem statement for the algorithm.
+ For algorithm enhancements, specify what needs to be changed and why. For example:
+ - Adding tests.
+ - Optimizing logic.
+ - Refactoring the file and folders for better structure.
+ - type: textarea
+ id: needdetails
+ attributes:
+ label: "Issue details"
+ description: "Write down all the issue/algorithm details description mentioned above."
+ validations:
+ required: true
+ - type: textarea
+ id: extrainfo
+ attributes:
+ label: "Additional Information"
+ description: "Add any other information or screenshots about the request here."
+ validations:
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/other.yml b/.github/ISSUE_TEMPLATE/other.yml
new file mode 100644
index 000000000000..bf8b29f481c8
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/other.yml
@@ -0,0 +1,19 @@
+name: Other
+description: Use this for any other issues. Do NOT create blank issues
+title: "[OTHER]"
+labels: ["awaiting triage"]
+body:
+ - 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
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 000000000000..2e5622f7b51d
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,18 @@
+---
+version: 2
+updates:
+ - package-ecosystem: "docker"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+
+ - package-ecosystem: "github-actions"
+ directory: "/.github/workflows/"
+ schedule:
+ interval: "daily"
+
+ - package-ecosystem: "maven"
+ directory: "/"
+ schedule:
+ interval: "daily"
+...
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 000000000000..d9cc4c3c35c5
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,16 @@
+
+
+
+
+- [ ] I have read [CONTRIBUTING.md](https://github.com/TheAlgorithms/Java/blob/master/CONTRIBUTING.md).
+- [ ] This pull request is all my own work -- I have not plagiarized it.
+- [ ] All filenames are in PascalCase.
+- [ ] All functions and variable names follow Java naming conventions.
+- [ ] All new algorithms have a URL in their comments that points to Wikipedia or other similar explanations.
+- [ ] All new code is formatted with `clang-format -i --style=file path/to/your/file.java`
\ No newline at end of file
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 000000000000..3918e89533d5
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,40 @@
+name: Build
+on: [push, pull_request]
+
+permissions:
+ contents: read
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up JDK
+ uses: actions/setup-java@v4
+ with:
+ java-version: 21
+ distribution: 'temurin'
+ - name: Build with Maven
+ run: mvn --batch-mode --update-snapshots verify
+ - name: Upload coverage to codecov (tokenless)
+ if: >-
+ github.event_name == 'pull_request' &&
+ github.event.pull_request.head.repo.full_name != github.repository
+ uses: codecov/codecov-action@v5
+ with:
+ fail_ci_if_error: true
+ - name: Upload coverage to codecov (with token)
+ if: >
+ github.repository == 'TheAlgorithms/Java' &&
+ (github.event_name != 'pull_request' ||
+ github.event.pull_request.head.repo.full_name == github.repository)
+ uses: codecov/codecov-action@v5
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ fail_ci_if_error: true
+ - name: Checkstyle
+ run: mvn checkstyle:check
+ - name: SpotBugs
+ run: mvn spotbugs:check
+ - name: PMD
+ run: mvn pmd:check
diff --git a/.github/workflows/clang-format-lint.yml b/.github/workflows/clang-format-lint.yml
new file mode 100644
index 000000000000..6f23946db999
--- /dev/null
+++ b/.github/workflows/clang-format-lint.yml
@@ -0,0 +1,19 @@
+name: Clang format linter
+on:
+ push: {}
+ pull_request: {}
+
+permissions:
+ contents: read
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - uses: DoozyX/clang-format-lint-action@v0.20
+ with:
+ source: './src'
+ extensions: 'java'
+ clangFormatVersion: 16
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 000000000000..d1133c251b65
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,66 @@
+---
+name: "CodeQL"
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - master
+ pull_request:
+ schedule:
+ - cron: '53 3 * * 0'
+
+jobs:
+ analyzeJava:
+ name: AnalyzeJava
+ runs-on: 'ubuntu-latest'
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Set up JDK
+ uses: actions/setup-java@v4
+ with:
+ java-version: 21
+ distribution: 'temurin'
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v3
+ with:
+ languages: 'java-kotlin'
+
+ - name: Build
+ run: mvn --batch-mode --update-snapshots verify
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v3
+ with:
+ category: "/language:java-kotlin"
+
+ analyzeActions:
+ name: AnalyzeActions
+ runs-on: 'ubuntu-latest'
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v3
+ with:
+ languages: 'actions'
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v3
+ with:
+ category: "/language:actions"
+...
diff --git a/.github/workflows/infer.yml b/.github/workflows/infer.yml
new file mode 100644
index 000000000000..b0ee2fee8243
--- /dev/null
+++ b/.github/workflows/infer.yml
@@ -0,0 +1,64 @@
+---
+name: Infer
+
+'on':
+ workflow_dispatch:
+ push:
+ branches:
+ - master
+ pull_request:
+
+permissions:
+ contents: read
+
+jobs:
+ run_infer:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Set up JDK
+ uses: actions/setup-java@v4
+ with:
+ java-version: 21
+ distribution: 'temurin'
+
+ - name: Set up OCaml
+ uses: ocaml/setup-ocaml@v3
+ with:
+ ocaml-compiler: 5
+
+ - name: Get current year/weak
+ run: echo "year_week=$(date +'%Y_%U')" >> $GITHUB_ENV
+
+ - name: Cache infer build
+ id: cache-infer
+ uses: actions/cache@v4
+ with:
+ path: infer
+ key: ${{ runner.os }}-infer-${{ env.year_week }}
+
+ - name: Build infer
+ if: steps.cache-infer.outputs.cache-hit != 'true'
+ run: |
+ cd ..
+ git clone https://github.com/facebook/infer.git
+ cd infer
+ git checkout 01aaa268f9d38723ba69c139e10f9e2a04b40b1c
+ ./build-infer.sh java
+ cp -r infer ../Java
+
+ - name: Add infer to PATH
+ run: |
+ echo "infer/bin" >> $GITHUB_PATH
+
+ - name: Display infer version
+ run: |
+ which infer
+ infer --version
+
+ - name: Run infer
+ run: |
+ mvn clean
+ infer --fail-on-issue --print-logs --no-progress-bar -- mvn test
+...
diff --git a/.github/workflows/project_structure.yml b/.github/workflows/project_structure.yml
new file mode 100644
index 000000000000..dbc725655721
--- /dev/null
+++ b/.github/workflows/project_structure.yml
@@ -0,0 +1,25 @@
+---
+name: ProjectStructure
+
+'on':
+ workflow_dispatch:
+ push:
+ branches:
+ - master
+ pull_request:
+
+permissions:
+ contents: read
+
+jobs:
+ check_structure:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ with:
+ python-version: '3.13'
+
+ - name: Check project structure
+ run: python3 .github/workflows/scripts/check_structure.py
+...
diff --git a/.github/workflows/scripts/check_structure.py b/.github/workflows/scripts/check_structure.py
new file mode 100644
index 000000000000..914f64369207
--- /dev/null
+++ b/.github/workflows/scripts/check_structure.py
@@ -0,0 +1,27 @@
+import pathlib
+import sys
+
+
+def _is_java_file_properly_located(java_file: pathlib.Path) -> bool:
+ main_parents = java_file.parent.parents
+ return (
+ pathlib.Path("src/main/java/com/thealgorithms/") in main_parents
+ or pathlib.Path("src/test/java/com/thealgorithms/") in main_parents
+ )
+
+
+def _find_misplaced_java_files() -> list[pathlib.Path]:
+ return [
+ java_file
+ for java_file in pathlib.Path(".").rglob("*.java")
+ if not _is_java_file_properly_located(java_file)
+ ]
+
+
+if __name__ == "__main__":
+ misplaced_files = _find_misplaced_java_files()
+ if misplaced_files:
+ print("The following java files are not located in the correct directory:")
+ for _ in misplaced_files:
+ print(_)
+ sys.exit(1)
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
new file mode 100644
index 000000000000..186b3e1d2f5a
--- /dev/null
+++ b/.github/workflows/stale.yml
@@ -0,0 +1,23 @@
+name: 'Close stale issues and PRs'
+on:
+ schedule:
+ - cron: '0 0 * * *'
+permissions:
+ contents: read
+jobs:
+ stale:
+ permissions:
+ issues: write
+ pull-requests: write
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/stale@v9
+ with:
+ stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution!'
+ close-issue-message: 'Please reopen this issue once you have made the required changes. If you need help, feel free to ask in our [Discord](https://the-algorithms.com/discord) server or ping one of the maintainers here. Thank you for your contribution!'
+ stale-pr-message: 'This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution!'
+ close-pr-message: 'Please reopen this pull request once you have made the required changes. If you need help, feel free to ask in our [Discord](https://the-algorithms.com/discord) server or ping one of the maintainers here. Thank you for your contribution!'
+ exempt-issue-labels: 'dont-close'
+ exempt-pr-labels: 'dont-close'
+ days-before-stale: 30
+ days-before-close: 7
diff --git a/.github/workflows/update-directorymd.yml b/.github/workflows/update-directorymd.yml
new file mode 100644
index 000000000000..53ad221e7742
--- /dev/null
+++ b/.github/workflows/update-directorymd.yml
@@ -0,0 +1,42 @@
+name: Generate Directory Markdown
+
+on:
+ push:
+ branches: [master]
+ workflow_dispatch:
+
+permissions:
+ contents: write
+ pull-requests: write
+
+jobs:
+ generate-directory:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v4
+
+ - name: Run Directory Tree Generator
+ uses: DenizAltunkapan/directory-tree-generator@v2
+ with:
+ path: src
+ extensions: .java
+ show-extensions: false
+
+ - name: Commit changes
+ run: |
+ git config --global user.name "$GITHUB_ACTOR"
+ git config --global user.email "$GITHUB_ACTOR@users.noreply.github.com"
+ git add DIRECTORY.md
+ git diff --cached --quiet || git commit -m "Update DIRECTORY.md"
+
+ - name: Create Pull Request
+ uses: peter-evans/create-pull-request@v7
+ with:
+ token: ${{ secrets.REPO_SCOPED_TOKEN }}
+ branch: update-directory
+ base: master
+ title: "Update DIRECTORY.md"
+ body: "Automatically generated update of the directory tree."
+ commit-message: "Update DIRECTORY.md"
+ draft: false
diff --git a/.gitignore b/.gitignore
index ae3c1726048c..eb9d33c78a33 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,46 @@
-/bin/
+/gradle/wrapper/gradle-wrapper.properties
+
+##----------Android----------
+*.apk
+*.ap_
+*.dex
+*.class
+bin/
+gen/
+build/
+out/
+
+# Ignoring Gradle build artifacts and project files
+##----------Gradle----------
+.gradle/
+gradle-app.setting
+!gradle-wrapper.jar
+build/
+
+# Ignoring Maven build artifacts and project files
+##----------Maven----------
+*.classpath
+*.project
+*.settings
+/target/
+local.properties
+
+# Ignoring IntelliJ IDEA project files and configurations
+##----------IDEA----------
+*.iml
+.idea/
+*.ipr
+*.iws
+
+# Ignoring Android Studio Navigation editor temporary files
+.navigation/
+
+# Ignoring common system and editor-generated files
+##----------Other----------
+*~
+.DS_Store
+gradle.properties
+.vscode
+*.log
+
+/infer-out/
diff --git a/.gitpod.dockerfile b/.gitpod.dockerfile
new file mode 100644
index 000000000000..b912ecb35256
--- /dev/null
+++ b/.gitpod.dockerfile
@@ -0,0 +1,22 @@
+FROM gitpod/workspace-java-21:2025-06-18-16-47-14
+
+ENV LLVM_SCRIPT="tmp_llvm.sh"
+
+RUN test ! -f "$LLVM_SCRIPT" \
+ && wget https://apt.llvm.org/llvm.sh -O "$LLVM_SCRIPT" \
+ && chmod +x "$LLVM_SCRIPT"
+
+USER root
+
+RUN ./"$LLVM_SCRIPT" 16 \
+ && apt-get update \
+ && apt-get install -y --no-install-recommends \
+ clang-format-16=1:16.0.6~++20231112100510+7cbf1a259152-1~exp1~20231112100554.106 \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+
+RUN ln -s "$(command -v clang-format-16)" "/usr/bin/clang-format"
+
+USER gitpod
+
+RUN rm "$LLVM_SCRIPT"
diff --git a/.gitpod.yml b/.gitpod.yml
new file mode 100644
index 000000000000..21d69f6e2122
--- /dev/null
+++ b/.gitpod.yml
@@ -0,0 +1,13 @@
+---
+image:
+ file: .gitpod.dockerfile
+
+tasks:
+ - init: |
+ mvn dependency:resolve
+ mvn compile
+
+vscode:
+ extensions:
+ - xaver.clang-format
+
diff --git a/.inferconfig b/.inferconfig
new file mode 100644
index 000000000000..6af4f9e2e818
--- /dev/null
+++ b/.inferconfig
@@ -0,0 +1,24 @@
+{
+ "report-block-list-path-regex": [
+ "src/main/java/com/thealgorithms/ciphers/a5/CompositeLFSR.java",
+ "src/main/java/com/thealgorithms/datastructures/crdt/GCounter.java",
+ "src/main/java/com/thealgorithms/datastructures/crdt/PNCounter.java",
+ "src/main/java/com/thealgorithms/datastructures/graphs/KahnsAlgorithm.java",
+ "src/main/java/com/thealgorithms/datastructures/heaps/GenericHeap.java",
+ "src/main/java/com/thealgorithms/datastructures/lists/DoublyLinkedList.java",
+ "src/main/java/com/thealgorithms/datastructures/trees/CreateBinaryTreeFromInorderPreorder.java",
+ "src/main/java/com/thealgorithms/divideandconquer/ClosestPair.java",
+ "src/main/java/com/thealgorithms/dynamicprogramming/Fibonacci.java",
+ "src/main/java/com/thealgorithms/maths/SimpsonIntegration.java",
+ "src/main/java/com/thealgorithms/others/Dijkstra.java",
+ "src/main/java/com/thealgorithms/sorts/TopologicalSort.java",
+ "src/main/java/com/thealgorithms/strings/AhoCorasick.java",
+ "src/test/java/com/thealgorithms/datastructures/caches/LRUCacheTest.java",
+ "src/test/java/com/thealgorithms/datastructures/lists/SkipListTest.java",
+ "src/test/java/com/thealgorithms/datastructures/trees/KDTreeTest.java",
+ "src/test/java/com/thealgorithms/datastructures/trees/LazySegmentTreeTest.java",
+ "src/test/java/com/thealgorithms/searches/QuickSelectTest.java",
+ "src/test/java/com/thealgorithms/stacks/PostfixToInfixTest.java",
+ "src/test/java/com/thealgorithms/strings/HorspoolSearchTest.java"
+ ]
+}
diff --git a/.project b/.project
deleted file mode 100644
index ea54703d8788..000000000000
--- a/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
- Java
-
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
-
- org.eclipse.jdt.core.javanature
-
-
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000000..f2f8dd9ffdea
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,31 @@
+## How to contribute?
+
+NOTE: *We DO NOT add leetcode problems. They are just applications of basic principles that can be found in other algorithms included in the repository.*
+
+### Did you find a bug?
+
+**Ensure the bug was not already reported** by searching on GitHub under [Project Issues](https://github.com/TheAlgorithms/Java/issues).
+ - If it is mentioned in the issues and you want to fix it, [fork](https://github.com/TheAlgorithms/Java/fork) the repository and submit your implementation in a pull request. The project maintainers will evaluate it.
+ - If the bug is **NOT** mentioned in the issues, [open a new issue](https://github.com/TheAlgorithms/Java/issues/new). Be sure to include a **title**, a clear **description** and a **test case** demonstrating the expected behavior that is not occurring.
+
+NOTE: *Please avoid opening issues asking to be "assigned" to a particular algorithm. This merely creates unnecessary noise for maintainers. Instead, please submit your implementation in a pull request and project maintainers will evaluate it.*
+
+
+
+### Do you want to contribute to the documentation?
+ - [Fork](https://github.com/TheAlgorithms/Java/fork) the repository and make necessary changes.
+ - Create a pull request.
+ - It will be put under review for approval.
+ - If approved, the requested changes will be merged to the repository.
+
+### Do you want to add a new feature?
+
+- [Open a new issue](https://github.com/TheAlgorithms/Java/issues/new).
+- Be sure to include a **title**, a clear **description** and a **test case** demonstrating the new feature you want to add to the project.
+
+
+### Do you have questions about the source code?
+
+- Ask any question about how to use the repository in the [TheAlgorithms room in GITTER](https://gitter.im/TheAlgorithms/community?source=orgpage#) or [open a new issue](https://github.com/TheAlgorithms/Java/issues/new)
+
+:+1::tada: That's all you need to know about the process now it's your turn to help us improve the repository, thank you again! :+1::tada:
\ No newline at end of file
diff --git a/Conversions/BinaryToDecimal.java b/Conversions/BinaryToDecimal.java
deleted file mode 100644
index 9e5494eebd85..000000000000
--- a/Conversions/BinaryToDecimal.java
+++ /dev/null
@@ -1,33 +0,0 @@
-import java.util.Scanner;
-
-/**
- * This class converts a Binary number to a Decimal number
- *
- * @author Unknown
- *
- */
-class BinaryToDecimal
-{
-
- /**
- * Main Method
- *
- * @param args Command line arguments
- */
- public static void main(String args[])
- {
- Scanner sc=new Scanner(System.in);
- int n,k,d,s=0,c=0;
- System.out.print("Binary number: ");
- n=sc.nextInt();
- k=n;
- while(k!=0)
- {
- d=k%10;
- s+=d*(int)Math.pow(2,c++);
- k/=10;
- }
- System.out.println("Decimal equivalent:"+s);
- sc.close();
- }
-}
diff --git a/Conversions/BinaryToOctal.java b/Conversions/BinaryToOctal.java
deleted file mode 100644
index cb04fe54be5a..000000000000
--- a/Conversions/BinaryToOctal.java
+++ /dev/null
@@ -1,43 +0,0 @@
-import java.util.Scanner;
-
-/**
- * Converts any Binary number to an Octal Number
- *
- * @author Zachary Jones
- *
- */
-public class BinaryToOctal {
-
- /**
- * Main method
- *
- * @param args Command line arguments
- */
- public static void main(String args[]) {
- Scanner sc = new Scanner(System.in);
- int b = sc.nextInt();
- System.out.println("Octal equivalent: " + convertBinaryToOctal(b));
- sc.close();
-
- }
-
- /**
- * This method converts a binary number to
- * an octal number.
- *
- * @param b The binary number
- * @return The octal number
- */
- public static int convertBinaryToOctal(int b) {
- int o = 0, r=0, j =1 ;
- while(b!=0)
- {
- r = b % 10;
- o = o + r * j;
- j = j * 2;
- b = b / 10;
- }
- return o;
- }
-
-}
diff --git a/Conversions/DecimalToBinary.java b/Conversions/DecimalToBinary.java
deleted file mode 100644
index 671cedf201d2..000000000000
--- a/Conversions/DecimalToBinary.java
+++ /dev/null
@@ -1,32 +0,0 @@
-import java.util.Scanner;
-
-/**
- * This class converts a Decimal number to a Binary number
- *
- * @author Unknown
- *
- */
-class DecimalToBinary
-{
- /**
- * Main Method
- *
- * @param args Command Line Arguments
- */
- public static void main(String args[])
- {
- Scanner sc=new Scanner(System.in);
- int n,k,s=0,c=0,d;
- System.out.print("Decimal number: ");
- n=sc.nextInt();
- k=n;
- while(k!=0)
- {
- d=k%2;
- s=s+d*(int)Math.pow(10,c++);
- k/=2;
- }//converting decimal to binary
- System.out.println("Binary equivalent:"+s);
- sc.close();
- }
-}
diff --git a/Conversions/OctalToBinary.java b/Conversions/OctalToBinary.java
deleted file mode 100644
index 23c9a46adf8e..000000000000
--- a/Conversions/OctalToBinary.java
+++ /dev/null
@@ -1,34 +0,0 @@
-import java.util.Scanner;
-
-/**
- * Converts any Octal number to a Binary number
- *
- * @author Zachary Jones
- *
- */
-public class OctalToBinary {
-
- /**
- * Main method
- *
- * @param args Command line arguments
- */
- public static void main(String args[]) {
- Scanner sc = new Scanner(System.in);
- int o = sc.nextInt();
- System.out.println("Binary equivalent: " + convertOctalToBinary(o));
- sc.close();
- }
-
- /**
- * This method converts an octal number
- * to a binary number.
- *
- * @param o The octal number
- * @return The binary number
- */
- public static int convertOctalToBinary(int o) {
-
- }
-
-}
diff --git a/Conversions/OctalToDecimal.java b/Conversions/OctalToDecimal.java
deleted file mode 100644
index fe82b5fff48e..000000000000
--- a/Conversions/OctalToDecimal.java
+++ /dev/null
@@ -1,34 +0,0 @@
-import java.util.Scanner;
-
-/**
- * Converts any Octal Number to a Decimal Number
- *
- * @author Zachary Jones
- *
- */
-public class OctalToDecimal {
-
- /**
- * Main method
- *
- * @param args Command line arguments
- */
- public static void main(String args[]) {
- Scanner sc = new Scanner(System.in);
- int o = sc.nextInt();
- System.out.println("Decimal equivalent: " + convertOctalToDecimal(o));
- sc.close();
- }
-
- /**
- * This method converts an octal number to
- * a decimal number.
- *
- * @param o The octal number
- * @return The decimal number
- */
- public static int convertOctalToDecimal(int o) {
-
- }
-
-}
diff --git a/DIRECTORY.md b/DIRECTORY.md
new file mode 100644
index 000000000000..9697dbc09869
--- /dev/null
+++ b/DIRECTORY.md
@@ -0,0 +1,1419 @@
+# Project Structure
+
+- 📁 **main**
+ - 📁 **java**
+ - 📁 **com**
+ - 📁 **thealgorithms**
+ - 📁 **audiofilters**
+ - 📄 [EMAFilter](src/main/java/com/thealgorithms/audiofilters/EMAFilter.java)
+ - 📄 [IIRFilter](src/main/java/com/thealgorithms/audiofilters/IIRFilter.java)
+ - 📁 **backtracking**
+ - 📄 [AllPathsFromSourceToTarget](src/main/java/com/thealgorithms/backtracking/AllPathsFromSourceToTarget.java)
+ - 📄 [ArrayCombination](src/main/java/com/thealgorithms/backtracking/ArrayCombination.java)
+ - 📄 [Combination](src/main/java/com/thealgorithms/backtracking/Combination.java)
+ - 📄 [CrosswordSolver](src/main/java/com/thealgorithms/backtracking/CrosswordSolver.java)
+ - 📄 [FloodFill](src/main/java/com/thealgorithms/backtracking/FloodFill.java)
+ - 📄 [KnightsTour](src/main/java/com/thealgorithms/backtracking/KnightsTour.java)
+ - 📄 [MColoring](src/main/java/com/thealgorithms/backtracking/MColoring.java)
+ - 📄 [MazeRecursion](src/main/java/com/thealgorithms/backtracking/MazeRecursion.java)
+ - 📄 [NQueens](src/main/java/com/thealgorithms/backtracking/NQueens.java)
+ - 📄 [ParenthesesGenerator](src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java)
+ - 📄 [Permutation](src/main/java/com/thealgorithms/backtracking/Permutation.java)
+ - 📄 [PowerSum](src/main/java/com/thealgorithms/backtracking/PowerSum.java)
+ - 📄 [SubsequenceFinder](src/main/java/com/thealgorithms/backtracking/SubsequenceFinder.java)
+ - 📄 [WordPatternMatcher](src/main/java/com/thealgorithms/backtracking/WordPatternMatcher.java)
+ - 📄 [WordSearch](src/main/java/com/thealgorithms/backtracking/WordSearch.java)
+ - 📁 **bitmanipulation**
+ - 📄 [BcdConversion](src/main/java/com/thealgorithms/bitmanipulation/BcdConversion.java)
+ - 📄 [BinaryPalindromeCheck](src/main/java/com/thealgorithms/bitmanipulation/BinaryPalindromeCheck.java)
+ - 📄 [BitSwap](src/main/java/com/thealgorithms/bitmanipulation/BitSwap.java)
+ - 📄 [BooleanAlgebraGates](src/main/java/com/thealgorithms/bitmanipulation/BooleanAlgebraGates.java)
+ - 📄 [ClearLeftmostSetBit](src/main/java/com/thealgorithms/bitmanipulation/ClearLeftmostSetBit.java)
+ - 📄 [CountLeadingZeros](src/main/java/com/thealgorithms/bitmanipulation/CountLeadingZeros.java)
+ - 📄 [CountSetBits](src/main/java/com/thealgorithms/bitmanipulation/CountSetBits.java)
+ - 📄 [FindNthBit](src/main/java/com/thealgorithms/bitmanipulation/FindNthBit.java)
+ - 📄 [FirstDifferentBit](src/main/java/com/thealgorithms/bitmanipulation/FirstDifferentBit.java)
+ - 📄 [GenerateSubsets](src/main/java/com/thealgorithms/bitmanipulation/GenerateSubsets.java)
+ - 📄 [GrayCodeConversion](src/main/java/com/thealgorithms/bitmanipulation/GrayCodeConversion.java)
+ - 📄 [HammingDistance](src/main/java/com/thealgorithms/bitmanipulation/HammingDistance.java)
+ - 📄 [HigherLowerPowerOfTwo](src/main/java/com/thealgorithms/bitmanipulation/HigherLowerPowerOfTwo.java)
+ - 📄 [HighestSetBit](src/main/java/com/thealgorithms/bitmanipulation/HighestSetBit.java)
+ - 📄 [IndexOfRightMostSetBit](src/main/java/com/thealgorithms/bitmanipulation/IndexOfRightMostSetBit.java)
+ - 📄 [IsEven](src/main/java/com/thealgorithms/bitmanipulation/IsEven.java)
+ - 📄 [IsPowerTwo](src/main/java/com/thealgorithms/bitmanipulation/IsPowerTwo.java)
+ - 📄 [LowestSetBit](src/main/java/com/thealgorithms/bitmanipulation/LowestSetBit.java)
+ - 📄 [ModuloPowerOfTwo](src/main/java/com/thealgorithms/bitmanipulation/ModuloPowerOfTwo.java)
+ - 📄 [NextHigherSameBitCount](src/main/java/com/thealgorithms/bitmanipulation/NextHigherSameBitCount.java)
+ - 📄 [NonRepeatingNumberFinder](src/main/java/com/thealgorithms/bitmanipulation/NonRepeatingNumberFinder.java)
+ - 📄 [NumberAppearingOddTimes](src/main/java/com/thealgorithms/bitmanipulation/NumberAppearingOddTimes.java)
+ - 📄 [NumbersDifferentSigns](src/main/java/com/thealgorithms/bitmanipulation/NumbersDifferentSigns.java)
+ - 📄 [OneBitDifference](src/main/java/com/thealgorithms/bitmanipulation/OneBitDifference.java)
+ - 📄 [OnesComplement](src/main/java/com/thealgorithms/bitmanipulation/OnesComplement.java)
+ - 📄 [ParityCheck](src/main/java/com/thealgorithms/bitmanipulation/ParityCheck.java)
+ - 📄 [ReverseBits](src/main/java/com/thealgorithms/bitmanipulation/ReverseBits.java)
+ - 📄 [SingleBitOperations](src/main/java/com/thealgorithms/bitmanipulation/SingleBitOperations.java)
+ - 📄 [SingleElement](src/main/java/com/thealgorithms/bitmanipulation/SingleElement.java)
+ - 📄 [SwapAdjacentBits](src/main/java/com/thealgorithms/bitmanipulation/SwapAdjacentBits.java)
+ - 📄 [TwosComplement](src/main/java/com/thealgorithms/bitmanipulation/TwosComplement.java)
+ - 📄 [Xs3Conversion](src/main/java/com/thealgorithms/bitmanipulation/Xs3Conversion.java)
+ - 📁 **ciphers**
+ - 📄 [ADFGVXCipher](src/main/java/com/thealgorithms/ciphers/ADFGVXCipher.java)
+ - 📄 [AES](src/main/java/com/thealgorithms/ciphers/AES.java)
+ - 📄 [AESEncryption](src/main/java/com/thealgorithms/ciphers/AESEncryption.java)
+ - 📄 [AffineCipher](src/main/java/com/thealgorithms/ciphers/AffineCipher.java)
+ - 📄 [AtbashCipher](src/main/java/com/thealgorithms/ciphers/AtbashCipher.java)
+ - 📄 [Autokey](src/main/java/com/thealgorithms/ciphers/Autokey.java)
+ - 📄 [BaconianCipher](src/main/java/com/thealgorithms/ciphers/BaconianCipher.java)
+ - 📄 [Blowfish](src/main/java/com/thealgorithms/ciphers/Blowfish.java)
+ - 📄 [Caesar](src/main/java/com/thealgorithms/ciphers/Caesar.java)
+ - 📄 [ColumnarTranspositionCipher](src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java)
+ - 📄 [DES](src/main/java/com/thealgorithms/ciphers/DES.java)
+ - 📄 [DiffieHellman](src/main/java/com/thealgorithms/ciphers/DiffieHellman.java)
+ - 📄 [ECC](src/main/java/com/thealgorithms/ciphers/ECC.java)
+ - 📄 [HillCipher](src/main/java/com/thealgorithms/ciphers/HillCipher.java)
+ - 📄 [MonoAlphabetic](src/main/java/com/thealgorithms/ciphers/MonoAlphabetic.java)
+ - 📄 [PlayfairCipher](src/main/java/com/thealgorithms/ciphers/PlayfairCipher.java)
+ - 📄 [Polybius](src/main/java/com/thealgorithms/ciphers/Polybius.java)
+ - 📄 [ProductCipher](src/main/java/com/thealgorithms/ciphers/ProductCipher.java)
+ - 📄 [RSA](src/main/java/com/thealgorithms/ciphers/RSA.java)
+ - 📄 [RailFenceCipher](src/main/java/com/thealgorithms/ciphers/RailFenceCipher.java)
+ - 📄 [SimpleSubCipher](src/main/java/com/thealgorithms/ciphers/SimpleSubCipher.java)
+ - 📄 [Vigenere](src/main/java/com/thealgorithms/ciphers/Vigenere.java)
+ - 📄 [XORCipher](src/main/java/com/thealgorithms/ciphers/XORCipher.java)
+ - 📁 **a5**
+ - 📄 [A5Cipher](src/main/java/com/thealgorithms/ciphers/a5/A5Cipher.java)
+ - 📄 [A5KeyStreamGenerator](src/main/java/com/thealgorithms/ciphers/a5/A5KeyStreamGenerator.java)
+ - 📄 [BaseLFSR](src/main/java/com/thealgorithms/ciphers/a5/BaseLFSR.java)
+ - 📄 [CompositeLFSR](src/main/java/com/thealgorithms/ciphers/a5/CompositeLFSR.java)
+ - 📄 [LFSR](src/main/java/com/thealgorithms/ciphers/a5/LFSR.java)
+ - 📄 [Utils](src/main/java/com/thealgorithms/ciphers/a5/Utils.java)
+ - 📁 **conversions**
+ - 📄 [AffineConverter](src/main/java/com/thealgorithms/conversions/AffineConverter.java)
+ - 📄 [AnyBaseToAnyBase](src/main/java/com/thealgorithms/conversions/AnyBaseToAnyBase.java)
+ - 📄 [AnyBaseToDecimal](src/main/java/com/thealgorithms/conversions/AnyBaseToDecimal.java)
+ - 📄 [AnytoAny](src/main/java/com/thealgorithms/conversions/AnytoAny.java)
+ - 📄 [BinaryToDecimal](src/main/java/com/thealgorithms/conversions/BinaryToDecimal.java)
+ - 📄 [BinaryToHexadecimal](src/main/java/com/thealgorithms/conversions/BinaryToHexadecimal.java)
+ - 📄 [BinaryToOctal](src/main/java/com/thealgorithms/conversions/BinaryToOctal.java)
+ - 📄 [DecimalToAnyBase](src/main/java/com/thealgorithms/conversions/DecimalToAnyBase.java)
+ - 📄 [DecimalToBinary](src/main/java/com/thealgorithms/conversions/DecimalToBinary.java)
+ - 📄 [DecimalToHexadecimal](src/main/java/com/thealgorithms/conversions/DecimalToHexadecimal.java)
+ - 📄 [DecimalToOctal](src/main/java/com/thealgorithms/conversions/DecimalToOctal.java)
+ - 📄 [EndianConverter](src/main/java/com/thealgorithms/conversions/EndianConverter.java)
+ - 📄 [HexToOct](src/main/java/com/thealgorithms/conversions/HexToOct.java)
+ - 📄 [HexaDecimalToBinary](src/main/java/com/thealgorithms/conversions/HexaDecimalToBinary.java)
+ - 📄 [HexaDecimalToDecimal](src/main/java/com/thealgorithms/conversions/HexaDecimalToDecimal.java)
+ - 📄 [IPConverter](src/main/java/com/thealgorithms/conversions/IPConverter.java)
+ - 📄 [IPv6Converter](src/main/java/com/thealgorithms/conversions/IPv6Converter.java)
+ - 📄 [IntegerToEnglish](src/main/java/com/thealgorithms/conversions/IntegerToEnglish.java)
+ - 📄 [IntegerToRoman](src/main/java/com/thealgorithms/conversions/IntegerToRoman.java)
+ - 📄 [MorseCodeConverter](src/main/java/com/thealgorithms/conversions/MorseCodeConverter.java)
+ - 📄 [NumberToWords](src/main/java/com/thealgorithms/conversions/NumberToWords.java)
+ - 📄 [OctalToBinary](src/main/java/com/thealgorithms/conversions/OctalToBinary.java)
+ - 📄 [OctalToDecimal](src/main/java/com/thealgorithms/conversions/OctalToDecimal.java)
+ - 📄 [OctalToHexadecimal](src/main/java/com/thealgorithms/conversions/OctalToHexadecimal.java)
+ - 📄 [PhoneticAlphabetConverter](src/main/java/com/thealgorithms/conversions/PhoneticAlphabetConverter.java)
+ - 📄 [RgbHsvConversion](src/main/java/com/thealgorithms/conversions/RgbHsvConversion.java)
+ - 📄 [RomanToInteger](src/main/java/com/thealgorithms/conversions/RomanToInteger.java)
+ - 📄 [TurkishToLatinConversion](src/main/java/com/thealgorithms/conversions/TurkishToLatinConversion.java)
+ - 📄 [UnitConversions](src/main/java/com/thealgorithms/conversions/UnitConversions.java)
+ - 📄 [UnitsConverter](src/main/java/com/thealgorithms/conversions/UnitsConverter.java)
+ - 📄 [WordsToNumber](src/main/java/com/thealgorithms/conversions/WordsToNumber.java)
+ - 📁 **datastructures**
+ - 📄 [Node](src/main/java/com/thealgorithms/datastructures/Node.java)
+ - 📁 **bags**
+ - 📄 [Bag](src/main/java/com/thealgorithms/datastructures/bags/Bag.java)
+ - 📁 **bloomfilter**
+ - 📄 [BloomFilter](src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java)
+ - 📁 **buffers**
+ - 📄 [CircularBuffer](src/main/java/com/thealgorithms/datastructures/buffers/CircularBuffer.java)
+ - 📁 **caches**
+ - 📄 [FIFOCache](src/main/java/com/thealgorithms/datastructures/caches/FIFOCache.java)
+ - 📄 [LFUCache](src/main/java/com/thealgorithms/datastructures/caches/LFUCache.java)
+ - 📄 [LRUCache](src/main/java/com/thealgorithms/datastructures/caches/LRUCache.java)
+ - 📄 [MRUCache](src/main/java/com/thealgorithms/datastructures/caches/MRUCache.java)
+ - 📄 [RRCache](src/main/java/com/thealgorithms/datastructures/caches/RRCache.java)
+ - 📁 **crdt**
+ - 📄 [GCounter](src/main/java/com/thealgorithms/datastructures/crdt/GCounter.java)
+ - 📄 [GSet](src/main/java/com/thealgorithms/datastructures/crdt/GSet.java)
+ - 📄 [LWWElementSet](src/main/java/com/thealgorithms/datastructures/crdt/LWWElementSet.java)
+ - 📄 [ORSet](src/main/java/com/thealgorithms/datastructures/crdt/ORSet.java)
+ - 📄 [PNCounter](src/main/java/com/thealgorithms/datastructures/crdt/PNCounter.java)
+ - 📄 [TwoPSet](src/main/java/com/thealgorithms/datastructures/crdt/TwoPSet.java)
+ - 📁 **disjointsetunion**
+ - 📄 [DisjointSetUnion](src/main/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnion.java)
+ - 📄 [Node](src/main/java/com/thealgorithms/datastructures/disjointsetunion/Node.java)
+ - 📁 **dynamicarray**
+ - 📄 [DynamicArray](src/main/java/com/thealgorithms/datastructures/dynamicarray/DynamicArray.java)
+ - 📁 **graphs**
+ - 📄 [AStar](src/main/java/com/thealgorithms/datastructures/graphs/AStar.java)
+ - 📄 [BellmanFord](src/main/java/com/thealgorithms/datastructures/graphs/BellmanFord.java)
+ - 📄 [BipartiteGraphDFS](src/main/java/com/thealgorithms/datastructures/graphs/BipartiteGraphDFS.java)
+ - 📄 [BoruvkaAlgorithm](src/main/java/com/thealgorithms/datastructures/graphs/BoruvkaAlgorithm.java)
+ - 📄 [ConnectedComponent](src/main/java/com/thealgorithms/datastructures/graphs/ConnectedComponent.java)
+ - 📄 [Cycles](src/main/java/com/thealgorithms/datastructures/graphs/Cycles.java)
+ - 📄 [DijkstraAlgorithm](src/main/java/com/thealgorithms/datastructures/graphs/DijkstraAlgorithm.java)
+ - 📄 [DijkstraOptimizedAlgorithm](src/main/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithm.java)
+ - 📄 [EdmondsBlossomAlgorithm](src/main/java/com/thealgorithms/datastructures/graphs/EdmondsBlossomAlgorithm.java)
+ - 📄 [FloydWarshall](src/main/java/com/thealgorithms/datastructures/graphs/FloydWarshall.java)
+ - 📄 [FordFulkerson](src/main/java/com/thealgorithms/datastructures/graphs/FordFulkerson.java)
+ - 📄 [Graphs](src/main/java/com/thealgorithms/datastructures/graphs/Graphs.java)
+ - 📄 [HamiltonianCycle](src/main/java/com/thealgorithms/datastructures/graphs/HamiltonianCycle.java)
+ - 📄 [JohnsonsAlgorithm](src/main/java/com/thealgorithms/datastructures/graphs/JohnsonsAlgorithm.java)
+ - 📄 [KahnsAlgorithm](src/main/java/com/thealgorithms/datastructures/graphs/KahnsAlgorithm.java)
+ - 📄 [Kosaraju](src/main/java/com/thealgorithms/datastructures/graphs/Kosaraju.java)
+ - 📄 [Kruskal](src/main/java/com/thealgorithms/datastructures/graphs/Kruskal.java)
+ - 📄 [MatrixGraphs](src/main/java/com/thealgorithms/datastructures/graphs/MatrixGraphs.java)
+ - 📄 [PrimMST](src/main/java/com/thealgorithms/datastructures/graphs/PrimMST.java)
+ - 📄 [README](src/main/java/com/thealgorithms/datastructures/graphs/README.md)
+ - 📄 [TarjansAlgorithm](src/main/java/com/thealgorithms/datastructures/graphs/TarjansAlgorithm.java)
+ - 📄 [UndirectedAdjacencyListGraph](src/main/java/com/thealgorithms/datastructures/graphs/UndirectedAdjacencyListGraph.java)
+ - 📄 [WelshPowell](src/main/java/com/thealgorithms/datastructures/graphs/WelshPowell.java)
+ - 📁 **hashmap**
+ - 📄 [Readme](src/main/java/com/thealgorithms/datastructures/hashmap/Readme.md)
+ - 📁 **hashing**
+ - 📄 [GenericHashMapUsingArray](src/main/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArray.java)
+ - 📄 [GenericHashMapUsingArrayList](src/main/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArrayList.java)
+ - 📄 [HashMap](src/main/java/com/thealgorithms/datastructures/hashmap/hashing/HashMap.java)
+ - 📄 [HashMapCuckooHashing](src/main/java/com/thealgorithms/datastructures/hashmap/hashing/HashMapCuckooHashing.java)
+ - 📄 [Intersection](src/main/java/com/thealgorithms/datastructures/hashmap/hashing/Intersection.java)
+ - 📄 [LinearProbingHashMap](src/main/java/com/thealgorithms/datastructures/hashmap/hashing/LinearProbingHashMap.java)
+ - 📄 [MainCuckooHashing](src/main/java/com/thealgorithms/datastructures/hashmap/hashing/MainCuckooHashing.java)
+ - 📄 [MajorityElement](src/main/java/com/thealgorithms/datastructures/hashmap/hashing/MajorityElement.java)
+ - 📄 [Map](src/main/java/com/thealgorithms/datastructures/hashmap/hashing/Map.java)
+ - 📁 **heaps**
+ - 📄 [EmptyHeapException](src/main/java/com/thealgorithms/datastructures/heaps/EmptyHeapException.java)
+ - 📄 [FibonacciHeap](src/main/java/com/thealgorithms/datastructures/heaps/FibonacciHeap.java)
+ - 📄 [GenericHeap](src/main/java/com/thealgorithms/datastructures/heaps/GenericHeap.java)
+ - 📄 [Heap](src/main/java/com/thealgorithms/datastructures/heaps/Heap.java)
+ - 📄 [HeapElement](src/main/java/com/thealgorithms/datastructures/heaps/HeapElement.java)
+ - 📄 [KthElementFinder](src/main/java/com/thealgorithms/datastructures/heaps/KthElementFinder.java)
+ - 📄 [LeftistHeap](src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java)
+ - 📄 [MaxHeap](src/main/java/com/thealgorithms/datastructures/heaps/MaxHeap.java)
+ - 📄 [MedianFinder](src/main/java/com/thealgorithms/datastructures/heaps/MedianFinder.java)
+ - 📄 [MergeKSortedArrays](src/main/java/com/thealgorithms/datastructures/heaps/MergeKSortedArrays.java)
+ - 📄 [MinHeap](src/main/java/com/thealgorithms/datastructures/heaps/MinHeap.java)
+ - 📄 [MinPriorityQueue](src/main/java/com/thealgorithms/datastructures/heaps/MinPriorityQueue.java)
+ - 📄 [Readme](src/main/java/com/thealgorithms/datastructures/heaps/Readme.md)
+ - 📁 **lists**
+ - 📄 [CircleLinkedList](src/main/java/com/thealgorithms/datastructures/lists/CircleLinkedList.java)
+ - 📄 [CountSinglyLinkedListRecursion](src/main/java/com/thealgorithms/datastructures/lists/CountSinglyLinkedListRecursion.java)
+ - 📄 [CreateAndDetectLoop](src/main/java/com/thealgorithms/datastructures/lists/CreateAndDetectLoop.java)
+ - 📄 [CursorLinkedList](src/main/java/com/thealgorithms/datastructures/lists/CursorLinkedList.java)
+ - 📄 [DoublyLinkedList](src/main/java/com/thealgorithms/datastructures/lists/DoublyLinkedList.java)
+ - 📄 [MergeKSortedLinkedList](src/main/java/com/thealgorithms/datastructures/lists/MergeKSortedLinkedList.java)
+ - 📄 [MergeSortedArrayList](src/main/java/com/thealgorithms/datastructures/lists/MergeSortedArrayList.java)
+ - 📄 [MergeSortedSinglyLinkedList](src/main/java/com/thealgorithms/datastructures/lists/MergeSortedSinglyLinkedList.java)
+ - 📄 [QuickSortLinkedList](src/main/java/com/thealgorithms/datastructures/lists/QuickSortLinkedList.java)
+ - 📄 [README](src/main/java/com/thealgorithms/datastructures/lists/README.md)
+ - 📄 [RandomNode](src/main/java/com/thealgorithms/datastructures/lists/RandomNode.java)
+ - 📄 [ReverseKGroup](src/main/java/com/thealgorithms/datastructures/lists/ReverseKGroup.java)
+ - 📄 [RotateSinglyLinkedLists](src/main/java/com/thealgorithms/datastructures/lists/RotateSinglyLinkedLists.java)
+ - 📄 [SearchSinglyLinkedListRecursion](src/main/java/com/thealgorithms/datastructures/lists/SearchSinglyLinkedListRecursion.java)
+ - 📄 [SinglyLinkedList](src/main/java/com/thealgorithms/datastructures/lists/SinglyLinkedList.java)
+ - 📄 [SinglyLinkedListNode](src/main/java/com/thealgorithms/datastructures/lists/SinglyLinkedListNode.java)
+ - 📄 [SkipList](src/main/java/com/thealgorithms/datastructures/lists/SkipList.java)
+ - 📄 [SortedLinkedList](src/main/java/com/thealgorithms/datastructures/lists/SortedLinkedList.java)
+ - 📁 **queues**
+ - 📄 [CircularQueue](src/main/java/com/thealgorithms/datastructures/queues/CircularQueue.java)
+ - 📄 [Deque](src/main/java/com/thealgorithms/datastructures/queues/Deque.java)
+ - 📄 [GenericArrayListQueue](src/main/java/com/thealgorithms/datastructures/queues/GenericArrayListQueue.java)
+ - 📄 [LinkedQueue](src/main/java/com/thealgorithms/datastructures/queues/LinkedQueue.java)
+ - 📄 [PriorityQueues](src/main/java/com/thealgorithms/datastructures/queues/PriorityQueues.java)
+ - 📄 [Queue](src/main/java/com/thealgorithms/datastructures/queues/Queue.java)
+ - 📄 [QueueByTwoStacks](src/main/java/com/thealgorithms/datastructures/queues/QueueByTwoStacks.java)
+ - 📄 [README](src/main/java/com/thealgorithms/datastructures/queues/README.md)
+ - 📄 [SlidingWindowMaximum](src/main/java/com/thealgorithms/datastructures/queues/SlidingWindowMaximum.java)
+ - 📄 [TokenBucket](src/main/java/com/thealgorithms/datastructures/queues/TokenBucket.java)
+ - 📁 **stacks**
+ - 📄 [NodeStack](src/main/java/com/thealgorithms/datastructures/stacks/NodeStack.java)
+ - 📄 [README](src/main/java/com/thealgorithms/datastructures/stacks/README.md)
+ - 📄 [ReverseStack](src/main/java/com/thealgorithms/datastructures/stacks/ReverseStack.java)
+ - 📄 [Stack](src/main/java/com/thealgorithms/datastructures/stacks/Stack.java)
+ - 📄 [StackArray](src/main/java/com/thealgorithms/datastructures/stacks/StackArray.java)
+ - 📄 [StackArrayList](src/main/java/com/thealgorithms/datastructures/stacks/StackArrayList.java)
+ - 📄 [StackOfLinkedList](src/main/java/com/thealgorithms/datastructures/stacks/StackOfLinkedList.java)
+ - 📁 **trees**
+ - 📄 [AVLSimple](src/main/java/com/thealgorithms/datastructures/trees/AVLSimple.java)
+ - 📄 [AVLTree](src/main/java/com/thealgorithms/datastructures/trees/AVLTree.java)
+ - 📄 [BSTFromSortedArray](src/main/java/com/thealgorithms/datastructures/trees/BSTFromSortedArray.java)
+ - 📄 [BSTIterative](src/main/java/com/thealgorithms/datastructures/trees/BSTIterative.java)
+ - 📄 [BSTRecursive](src/main/java/com/thealgorithms/datastructures/trees/BSTRecursive.java)
+ - 📄 [BSTRecursiveGeneric](src/main/java/com/thealgorithms/datastructures/trees/BSTRecursiveGeneric.java)
+ - 📄 [BTree](src/main/java/com/thealgorithms/datastructures/trees/BTree.java)
+ - 📄 [BinaryTree](src/main/java/com/thealgorithms/datastructures/trees/BinaryTree.java)
+ - 📄 [BoundaryTraversal](src/main/java/com/thealgorithms/datastructures/trees/BoundaryTraversal.java)
+ - 📄 [CeilInBinarySearchTree](src/main/java/com/thealgorithms/datastructures/trees/CeilInBinarySearchTree.java)
+ - 📄 [CheckBinaryTreeIsValidBST](src/main/java/com/thealgorithms/datastructures/trees/CheckBinaryTreeIsValidBST.java)
+ - 📄 [CheckIfBinaryTreeBalanced](src/main/java/com/thealgorithms/datastructures/trees/CheckIfBinaryTreeBalanced.java)
+ - 📄 [CheckTreeIsSymmetric](src/main/java/com/thealgorithms/datastructures/trees/CheckTreeIsSymmetric.java)
+ - 📄 [CreateBinaryTreeFromInorderPreorder](src/main/java/com/thealgorithms/datastructures/trees/CreateBinaryTreeFromInorderPreorder.java)
+ - 📄 [FenwickTree](src/main/java/com/thealgorithms/datastructures/trees/FenwickTree.java)
+ - 📄 [GenericTree](src/main/java/com/thealgorithms/datastructures/trees/GenericTree.java)
+ - 📄 [InorderTraversal](src/main/java/com/thealgorithms/datastructures/trees/InorderTraversal.java)
+ - 📄 [KDTree](src/main/java/com/thealgorithms/datastructures/trees/KDTree.java)
+ - 📄 [LCA](src/main/java/com/thealgorithms/datastructures/trees/LCA.java)
+ - 📄 [LazySegmentTree](src/main/java/com/thealgorithms/datastructures/trees/LazySegmentTree.java)
+ - 📄 [LevelOrderTraversal](src/main/java/com/thealgorithms/datastructures/trees/LevelOrderTraversal.java)
+ - 📄 [PostOrderTraversal](src/main/java/com/thealgorithms/datastructures/trees/PostOrderTraversal.java)
+ - 📄 [PreOrderTraversal](src/main/java/com/thealgorithms/datastructures/trees/PreOrderTraversal.java)
+ - 📄 [PrintTopViewofTree](src/main/java/com/thealgorithms/datastructures/trees/PrintTopViewofTree.java)
+ - 📄 [QuadTree](src/main/java/com/thealgorithms/datastructures/trees/QuadTree.java)
+ - 📄 [README](src/main/java/com/thealgorithms/datastructures/trees/README.md)
+ - 📄 [RedBlackBST](src/main/java/com/thealgorithms/datastructures/trees/RedBlackBST.java)
+ - 📄 [SameTreesCheck](src/main/java/com/thealgorithms/datastructures/trees/SameTreesCheck.java)
+ - 📄 [SegmentTree](src/main/java/com/thealgorithms/datastructures/trees/SegmentTree.java)
+ - 📄 [SplayTree](src/main/java/com/thealgorithms/datastructures/trees/SplayTree.java)
+ - 📄 [Treap](src/main/java/com/thealgorithms/datastructures/trees/Treap.java)
+ - 📄 [TreeRandomNode](src/main/java/com/thealgorithms/datastructures/trees/TreeRandomNode.java)
+ - 📄 [Trie](src/main/java/com/thealgorithms/datastructures/trees/Trie.java)
+ - 📄 [VerticalOrderTraversal](src/main/java/com/thealgorithms/datastructures/trees/VerticalOrderTraversal.java)
+ - 📄 [ZigzagTraversal](src/main/java/com/thealgorithms/datastructures/trees/ZigzagTraversal.java)
+ - 📄 [nearestRightKey](src/main/java/com/thealgorithms/datastructures/trees/nearestRightKey.java)
+ - 📁 **devutils**
+ - 📁 **entities**
+ - 📄 [ProcessDetails](src/main/java/com/thealgorithms/devutils/entities/ProcessDetails.java)
+ - 📁 **nodes**
+ - 📄 [LargeTreeNode](src/main/java/com/thealgorithms/devutils/nodes/LargeTreeNode.java)
+ - 📄 [Node](src/main/java/com/thealgorithms/devutils/nodes/Node.java)
+ - 📄 [SimpleNode](src/main/java/com/thealgorithms/devutils/nodes/SimpleNode.java)
+ - 📄 [SimpleTreeNode](src/main/java/com/thealgorithms/devutils/nodes/SimpleTreeNode.java)
+ - 📄 [TreeNode](src/main/java/com/thealgorithms/devutils/nodes/TreeNode.java)
+ - 📁 **searches**
+ - 📄 [MatrixSearchAlgorithm](src/main/java/com/thealgorithms/devutils/searches/MatrixSearchAlgorithm.java)
+ - 📄 [SearchAlgorithm](src/main/java/com/thealgorithms/devutils/searches/SearchAlgorithm.java)
+ - 📁 **divideandconquer**
+ - 📄 [BinaryExponentiation](src/main/java/com/thealgorithms/divideandconquer/BinaryExponentiation.java)
+ - 📄 [ClosestPair](src/main/java/com/thealgorithms/divideandconquer/ClosestPair.java)
+ - 📄 [CountingInversions](src/main/java/com/thealgorithms/divideandconquer/CountingInversions.java)
+ - 📄 [MedianOfTwoSortedArrays](src/main/java/com/thealgorithms/divideandconquer/MedianOfTwoSortedArrays.java)
+ - 📄 [SkylineAlgorithm](src/main/java/com/thealgorithms/divideandconquer/SkylineAlgorithm.java)
+ - 📄 [StrassenMatrixMultiplication](src/main/java/com/thealgorithms/divideandconquer/StrassenMatrixMultiplication.java)
+ - 📄 [TilingProblem](src/main/java/com/thealgorithms/divideandconquer/TilingProblem.java)
+ - 📁 **dynamicprogramming**
+ - 📄 [Abbreviation](src/main/java/com/thealgorithms/dynamicprogramming/Abbreviation.java)
+ - 📄 [AllConstruct](src/main/java/com/thealgorithms/dynamicprogramming/AllConstruct.java)
+ - 📄 [AssignmentUsingBitmask](src/main/java/com/thealgorithms/dynamicprogramming/AssignmentUsingBitmask.java)
+ - 📄 [BoardPath](src/main/java/com/thealgorithms/dynamicprogramming/BoardPath.java)
+ - 📄 [BoundaryFill](src/main/java/com/thealgorithms/dynamicprogramming/BoundaryFill.java)
+ - 📄 [BruteForceKnapsack](src/main/java/com/thealgorithms/dynamicprogramming/BruteForceKnapsack.java)
+ - 📄 [CatalanNumber](src/main/java/com/thealgorithms/dynamicprogramming/CatalanNumber.java)
+ - 📄 [ClimbingStairs](src/main/java/com/thealgorithms/dynamicprogramming/ClimbingStairs.java)
+ - 📄 [CoinChange](src/main/java/com/thealgorithms/dynamicprogramming/CoinChange.java)
+ - 📄 [CountFriendsPairing](src/main/java/com/thealgorithms/dynamicprogramming/CountFriendsPairing.java)
+ - 📄 [DiceThrow](src/main/java/com/thealgorithms/dynamicprogramming/DiceThrow.java)
+ - 📄 [EditDistance](src/main/java/com/thealgorithms/dynamicprogramming/EditDistance.java)
+ - 📄 [EggDropping](src/main/java/com/thealgorithms/dynamicprogramming/EggDropping.java)
+ - 📄 [Fibonacci](src/main/java/com/thealgorithms/dynamicprogramming/Fibonacci.java)
+ - 📄 [KadaneAlgorithm](src/main/java/com/thealgorithms/dynamicprogramming/KadaneAlgorithm.java)
+ - 📄 [Knapsack](src/main/java/com/thealgorithms/dynamicprogramming/Knapsack.java)
+ - 📄 [KnapsackMemoization](src/main/java/com/thealgorithms/dynamicprogramming/KnapsackMemoization.java)
+ - 📄 [LevenshteinDistance](src/main/java/com/thealgorithms/dynamicprogramming/LevenshteinDistance.java)
+ - 📄 [LongestAlternatingSubsequence](src/main/java/com/thealgorithms/dynamicprogramming/LongestAlternatingSubsequence.java)
+ - 📄 [LongestArithmeticSubsequence](src/main/java/com/thealgorithms/dynamicprogramming/LongestArithmeticSubsequence.java)
+ - 📄 [LongestCommonSubsequence](src/main/java/com/thealgorithms/dynamicprogramming/LongestCommonSubsequence.java)
+ - 📄 [LongestIncreasingSubsequence](src/main/java/com/thealgorithms/dynamicprogramming/LongestIncreasingSubsequence.java)
+ - 📄 [LongestIncreasingSubsequenceNLogN](src/main/java/com/thealgorithms/dynamicprogramming/LongestIncreasingSubsequenceNLogN.java)
+ - 📄 [LongestPalindromicSubsequence](src/main/java/com/thealgorithms/dynamicprogramming/LongestPalindromicSubsequence.java)
+ - 📄 [LongestPalindromicSubstring](src/main/java/com/thealgorithms/dynamicprogramming/LongestPalindromicSubstring.java)
+ - 📄 [LongestValidParentheses](src/main/java/com/thealgorithms/dynamicprogramming/LongestValidParentheses.java)
+ - 📄 [MatrixChainMultiplication](src/main/java/com/thealgorithms/dynamicprogramming/MatrixChainMultiplication.java)
+ - 📄 [MatrixChainRecursiveTopDownMemoisation](src/main/java/com/thealgorithms/dynamicprogramming/MatrixChainRecursiveTopDownMemoisation.java)
+ - 📄 [MaximumSumOfNonAdjacentElements](src/main/java/com/thealgorithms/dynamicprogramming/MaximumSumOfNonAdjacentElements.java)
+ - 📄 [MinimumPathSum](src/main/java/com/thealgorithms/dynamicprogramming/MinimumPathSum.java)
+ - 📄 [MinimumSumPartition](src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java)
+ - 📄 [NewManShanksPrime](src/main/java/com/thealgorithms/dynamicprogramming/NewManShanksPrime.java)
+ - 📄 [OptimalJobScheduling](src/main/java/com/thealgorithms/dynamicprogramming/OptimalJobScheduling.java)
+ - 📄 [PalindromicPartitioning](src/main/java/com/thealgorithms/dynamicprogramming/PalindromicPartitioning.java)
+ - 📄 [PartitionProblem](src/main/java/com/thealgorithms/dynamicprogramming/PartitionProblem.java)
+ - 📄 [RegexMatching](src/main/java/com/thealgorithms/dynamicprogramming/RegexMatching.java)
+ - 📄 [RodCutting](src/main/java/com/thealgorithms/dynamicprogramming/RodCutting.java)
+ - 📄 [ShortestCommonSupersequenceLength](src/main/java/com/thealgorithms/dynamicprogramming/ShortestCommonSupersequenceLength.java)
+ - 📄 [SubsetCount](src/main/java/com/thealgorithms/dynamicprogramming/SubsetCount.java)
+ - 📄 [SubsetSum](src/main/java/com/thealgorithms/dynamicprogramming/SubsetSum.java)
+ - 📄 [SubsetSumSpaceOptimized](src/main/java/com/thealgorithms/dynamicprogramming/SubsetSumSpaceOptimized.java)
+ - 📄 [SumOfSubset](src/main/java/com/thealgorithms/dynamicprogramming/SumOfSubset.java)
+ - 📄 [TreeMatching](src/main/java/com/thealgorithms/dynamicprogramming/TreeMatching.java)
+ - 📄 [Tribonacci](src/main/java/com/thealgorithms/dynamicprogramming/Tribonacci.java)
+ - 📄 [UniquePaths](src/main/java/com/thealgorithms/dynamicprogramming/UniquePaths.java)
+ - 📄 [UniqueSubsequencesCount](src/main/java/com/thealgorithms/dynamicprogramming/UniqueSubsequencesCount.java)
+ - 📄 [WildcardMatching](src/main/java/com/thealgorithms/dynamicprogramming/WildcardMatching.java)
+ - 📄 [WineProblem](src/main/java/com/thealgorithms/dynamicprogramming/WineProblem.java)
+ - 📁 **geometry**
+ - 📄 [BresenhamLine](src/main/java/com/thealgorithms/geometry/BresenhamLine.java)
+ - 📄 [ConvexHull](src/main/java/com/thealgorithms/geometry/ConvexHull.java)
+ - 📄 [GrahamScan](src/main/java/com/thealgorithms/geometry/GrahamScan.java)
+ - 📄 [MidpointCircle](src/main/java/com/thealgorithms/geometry/MidpointCircle.java)
+ - 📄 [MidpointEllipse](src/main/java/com/thealgorithms/geometry/MidpointEllipse.java)
+ - 📄 [Point](src/main/java/com/thealgorithms/geometry/Point.java)
+ - 📁 **graph**
+ - 📄 [ConstrainedShortestPath](src/main/java/com/thealgorithms/graph/ConstrainedShortestPath.java)
+ - 📄 [StronglyConnectedComponentOptimized](src/main/java/com/thealgorithms/graph/StronglyConnectedComponentOptimized.java)
+ - 📄 [TravelingSalesman](src/main/java/com/thealgorithms/graph/TravelingSalesman.java)
+ - 📁 **greedyalgorithms**
+ - 📄 [ActivitySelection](src/main/java/com/thealgorithms/greedyalgorithms/ActivitySelection.java)
+ - 📄 [BandwidthAllocation](src/main/java/com/thealgorithms/greedyalgorithms/BandwidthAllocation.java)
+ - 📄 [BinaryAddition](src/main/java/com/thealgorithms/greedyalgorithms/BinaryAddition.java)
+ - 📄 [CoinChange](src/main/java/com/thealgorithms/greedyalgorithms/CoinChange.java)
+ - 📄 [DigitSeparation](src/main/java/com/thealgorithms/greedyalgorithms/DigitSeparation.java)
+ - 📄 [EgyptianFraction](src/main/java/com/thealgorithms/greedyalgorithms/EgyptianFraction.java)
+ - 📄 [FractionalKnapsack](src/main/java/com/thealgorithms/greedyalgorithms/FractionalKnapsack.java)
+ - 📄 [GaleShapley](src/main/java/com/thealgorithms/greedyalgorithms/GaleShapley.java)
+ - 📄 [JobSequencing](src/main/java/com/thealgorithms/greedyalgorithms/JobSequencing.java)
+ - 📄 [KCenters](src/main/java/com/thealgorithms/greedyalgorithms/KCenters.java)
+ - 📄 [MergeIntervals](src/main/java/com/thealgorithms/greedyalgorithms/MergeIntervals.java)
+ - 📄 [MinimizingLateness](src/main/java/com/thealgorithms/greedyalgorithms/MinimizingLateness.java)
+ - 📄 [MinimumWaitingTime](src/main/java/com/thealgorithms/greedyalgorithms/MinimumWaitingTime.java)
+ - 📄 [OptimalFileMerging](src/main/java/com/thealgorithms/greedyalgorithms/OptimalFileMerging.java)
+ - 📄 [StockProfitCalculator](src/main/java/com/thealgorithms/greedyalgorithms/StockProfitCalculator.java)
+ - 📁 **io**
+ - 📄 [BufferedReader](src/main/java/com/thealgorithms/io/BufferedReader.java)
+ - 📁 **lineclipping**
+ - 📄 [CohenSutherland](src/main/java/com/thealgorithms/lineclipping/CohenSutherland.java)
+ - 📄 [LiangBarsky](src/main/java/com/thealgorithms/lineclipping/LiangBarsky.java)
+ - 📁 **utils**
+ - 📄 [Line](src/main/java/com/thealgorithms/lineclipping/utils/Line.java)
+ - 📄 [Point](src/main/java/com/thealgorithms/lineclipping/utils/Point.java)
+ - 📁 **maths**
+ - 📄 [ADTFraction](src/main/java/com/thealgorithms/maths/ADTFraction.java)
+ - 📄 [AbsoluteMax](src/main/java/com/thealgorithms/maths/AbsoluteMax.java)
+ - 📄 [AbsoluteMin](src/main/java/com/thealgorithms/maths/AbsoluteMin.java)
+ - 📄 [AbsoluteValue](src/main/java/com/thealgorithms/maths/AbsoluteValue.java)
+ - 📄 [AliquotSum](src/main/java/com/thealgorithms/maths/AliquotSum.java)
+ - 📄 [AmicableNumber](src/main/java/com/thealgorithms/maths/AmicableNumber.java)
+ - 📄 [Area](src/main/java/com/thealgorithms/maths/Area.java)
+ - 📄 [Armstrong](src/main/java/com/thealgorithms/maths/Armstrong.java)
+ - 📄 [AutoCorrelation](src/main/java/com/thealgorithms/maths/AutoCorrelation.java)
+ - 📄 [AutomorphicNumber](src/main/java/com/thealgorithms/maths/AutomorphicNumber.java)
+ - 📄 [Average](src/main/java/com/thealgorithms/maths/Average.java)
+ - 📄 [BinaryPow](src/main/java/com/thealgorithms/maths/BinaryPow.java)
+ - 📄 [BinomialCoefficient](src/main/java/com/thealgorithms/maths/BinomialCoefficient.java)
+ - 📄 [CatalanNumbers](src/main/java/com/thealgorithms/maths/CatalanNumbers.java)
+ - 📄 [Ceil](src/main/java/com/thealgorithms/maths/Ceil.java)
+ - 📄 [ChineseRemainderTheorem](src/main/java/com/thealgorithms/maths/ChineseRemainderTheorem.java)
+ - 📄 [CircularConvolutionFFT](src/main/java/com/thealgorithms/maths/CircularConvolutionFFT.java)
+ - 📄 [CollatzConjecture](src/main/java/com/thealgorithms/maths/CollatzConjecture.java)
+ - 📄 [Combinations](src/main/java/com/thealgorithms/maths/Combinations.java)
+ - 📄 [Convolution](src/main/java/com/thealgorithms/maths/Convolution.java)
+ - 📄 [ConvolutionFFT](src/main/java/com/thealgorithms/maths/ConvolutionFFT.java)
+ - 📄 [CrossCorrelation](src/main/java/com/thealgorithms/maths/CrossCorrelation.java)
+ - 📄 [DeterminantOfMatrix](src/main/java/com/thealgorithms/maths/DeterminantOfMatrix.java)
+ - 📄 [DigitalRoot](src/main/java/com/thealgorithms/maths/DigitalRoot.java)
+ - 📄 [DistanceFormula](src/main/java/com/thealgorithms/maths/DistanceFormula.java)
+ - 📄 [DudeneyNumber](src/main/java/com/thealgorithms/maths/DudeneyNumber.java)
+ - 📄 [EulerMethod](src/main/java/com/thealgorithms/maths/EulerMethod.java)
+ - 📄 [EulersFunction](src/main/java/com/thealgorithms/maths/EulersFunction.java)
+ - 📄 [FFT](src/main/java/com/thealgorithms/maths/FFT.java)
+ - 📄 [FFTBluestein](src/main/java/com/thealgorithms/maths/FFTBluestein.java)
+ - 📄 [Factorial](src/main/java/com/thealgorithms/maths/Factorial.java)
+ - 📄 [FactorialRecursion](src/main/java/com/thealgorithms/maths/FactorialRecursion.java)
+ - 📄 [FastExponentiation](src/main/java/com/thealgorithms/maths/FastExponentiation.java)
+ - 📄 [FastInverseSqrt](src/main/java/com/thealgorithms/maths/FastInverseSqrt.java)
+ - 📄 [FibonacciJavaStreams](src/main/java/com/thealgorithms/maths/FibonacciJavaStreams.java)
+ - 📄 [FibonacciLoop](src/main/java/com/thealgorithms/maths/FibonacciLoop.java)
+ - 📄 [FibonacciNumberCheck](src/main/java/com/thealgorithms/maths/FibonacciNumberCheck.java)
+ - 📄 [FibonacciNumberGoldenRation](src/main/java/com/thealgorithms/maths/FibonacciNumberGoldenRation.java)
+ - 📄 [FindKthNumber](src/main/java/com/thealgorithms/maths/FindKthNumber.java)
+ - 📄 [FindMax](src/main/java/com/thealgorithms/maths/FindMax.java)
+ - 📄 [FindMaxRecursion](src/main/java/com/thealgorithms/maths/FindMaxRecursion.java)
+ - 📄 [FindMin](src/main/java/com/thealgorithms/maths/FindMin.java)
+ - 📄 [FindMinRecursion](src/main/java/com/thealgorithms/maths/FindMinRecursion.java)
+ - 📄 [Floor](src/main/java/com/thealgorithms/maths/Floor.java)
+ - 📄 [FrizzyNumber](src/main/java/com/thealgorithms/maths/FrizzyNumber.java)
+ - 📄 [GCD](src/main/java/com/thealgorithms/maths/GCD.java)
+ - 📄 [GCDRecursion](src/main/java/com/thealgorithms/maths/GCDRecursion.java)
+ - 📄 [Gaussian](src/main/java/com/thealgorithms/maths/Gaussian.java)
+ - 📄 [GenericRoot](src/main/java/com/thealgorithms/maths/GenericRoot.java)
+ - 📄 [GoldbachConjecture](src/main/java/com/thealgorithms/maths/GoldbachConjecture.java)
+ - 📄 [HarshadNumber](src/main/java/com/thealgorithms/maths/HarshadNumber.java)
+ - 📄 [HeronsFormula](src/main/java/com/thealgorithms/maths/HeronsFormula.java)
+ - 📄 [JosephusProblem](src/main/java/com/thealgorithms/maths/JosephusProblem.java)
+ - 📄 [JugglerSequence](src/main/java/com/thealgorithms/maths/JugglerSequence.java)
+ - 📄 [KaprekarNumbers](src/main/java/com/thealgorithms/maths/KaprekarNumbers.java)
+ - 📄 [KaratsubaMultiplication](src/main/java/com/thealgorithms/maths/KaratsubaMultiplication.java)
+ - 📄 [KeithNumber](src/main/java/com/thealgorithms/maths/KeithNumber.java)
+ - 📄 [KrishnamurthyNumber](src/main/java/com/thealgorithms/maths/KrishnamurthyNumber.java)
+ - 📄 [LeastCommonMultiple](src/main/java/com/thealgorithms/maths/LeastCommonMultiple.java)
+ - 📄 [LeonardoNumber](src/main/java/com/thealgorithms/maths/LeonardoNumber.java)
+ - 📄 [LinearDiophantineEquationsSolver](src/main/java/com/thealgorithms/maths/LinearDiophantineEquationsSolver.java)
+ - 📄 [LongDivision](src/main/java/com/thealgorithms/maths/LongDivision.java)
+ - 📄 [LucasSeries](src/main/java/com/thealgorithms/maths/LucasSeries.java)
+ - 📄 [MagicSquare](src/main/java/com/thealgorithms/maths/MagicSquare.java)
+ - 📄 [MathBuilder](src/main/java/com/thealgorithms/maths/MathBuilder.java)
+ - 📄 [MaxValue](src/main/java/com/thealgorithms/maths/MaxValue.java)
+ - 📄 [Means](src/main/java/com/thealgorithms/maths/Means.java)
+ - 📄 [Median](src/main/java/com/thealgorithms/maths/Median.java)
+ - 📄 [MinValue](src/main/java/com/thealgorithms/maths/MinValue.java)
+ - 📄 [Mode](src/main/java/com/thealgorithms/maths/Mode.java)
+ - 📄 [NonRepeatingElement](src/main/java/com/thealgorithms/maths/NonRepeatingElement.java)
+ - 📄 [NthUglyNumber](src/main/java/com/thealgorithms/maths/NthUglyNumber.java)
+ - 📄 [NumberOfDigits](src/main/java/com/thealgorithms/maths/NumberOfDigits.java)
+ - 📄 [PalindromeNumber](src/main/java/com/thealgorithms/maths/PalindromeNumber.java)
+ - 📄 [ParseInteger](src/main/java/com/thealgorithms/maths/ParseInteger.java)
+ - 📄 [PascalTriangle](src/main/java/com/thealgorithms/maths/PascalTriangle.java)
+ - 📄 [PerfectCube](src/main/java/com/thealgorithms/maths/PerfectCube.java)
+ - 📄 [PerfectNumber](src/main/java/com/thealgorithms/maths/PerfectNumber.java)
+ - 📄 [PerfectSquare](src/main/java/com/thealgorithms/maths/PerfectSquare.java)
+ - 📄 [Perimeter](src/main/java/com/thealgorithms/maths/Perimeter.java)
+ - 📄 [PiNilakantha](src/main/java/com/thealgorithms/maths/PiNilakantha.java)
+ - 📄 [PollardRho](src/main/java/com/thealgorithms/maths/PollardRho.java)
+ - 📄 [Pow](src/main/java/com/thealgorithms/maths/Pow.java)
+ - 📄 [PowerOfTwoOrNot](src/main/java/com/thealgorithms/maths/PowerOfTwoOrNot.java)
+ - 📄 [PowerUsingRecursion](src/main/java/com/thealgorithms/maths/PowerUsingRecursion.java)
+ - 📁 **Prime**
+ - 📄 [LiouvilleLambdaFunction](src/main/java/com/thealgorithms/maths/Prime/LiouvilleLambdaFunction.java)
+ - 📄 [MillerRabinPrimalityCheck](src/main/java/com/thealgorithms/maths/Prime/MillerRabinPrimalityCheck.java)
+ - 📄 [MobiusFunction](src/main/java/com/thealgorithms/maths/Prime/MobiusFunction.java)
+ - 📄 [PrimeCheck](src/main/java/com/thealgorithms/maths/Prime/PrimeCheck.java)
+ - 📄 [PrimeFactorization](src/main/java/com/thealgorithms/maths/Prime/PrimeFactorization.java)
+ - 📄 [SquareFreeInteger](src/main/java/com/thealgorithms/maths/Prime/SquareFreeInteger.java)
+ - 📄 [PronicNumber](src/main/java/com/thealgorithms/maths/PronicNumber.java)
+ - 📄 [PythagoreanTriple](src/main/java/com/thealgorithms/maths/PythagoreanTriple.java)
+ - 📄 [QuadraticEquationSolver](src/main/java/com/thealgorithms/maths/QuadraticEquationSolver.java)
+ - 📄 [ReverseNumber](src/main/java/com/thealgorithms/maths/ReverseNumber.java)
+ - 📄 [RomanNumeralUtil](src/main/java/com/thealgorithms/maths/RomanNumeralUtil.java)
+ - 📄 [SecondMinMax](src/main/java/com/thealgorithms/maths/SecondMinMax.java)
+ - 📄 [SieveOfEratosthenes](src/main/java/com/thealgorithms/maths/SieveOfEratosthenes.java)
+ - 📄 [SimpsonIntegration](src/main/java/com/thealgorithms/maths/SimpsonIntegration.java)
+ - 📄 [SolovayStrassenPrimalityTest](src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java)
+ - 📄 [SquareRootWithBabylonianMethod](src/main/java/com/thealgorithms/maths/SquareRootWithBabylonianMethod.java)
+ - 📄 [SquareRootWithNewtonRaphsonMethod](src/main/java/com/thealgorithms/maths/SquareRootWithNewtonRaphsonMethod.java)
+ - 📄 [StandardDeviation](src/main/java/com/thealgorithms/maths/StandardDeviation.java)
+ - 📄 [StandardScore](src/main/java/com/thealgorithms/maths/StandardScore.java)
+ - 📄 [StrobogrammaticNumber](src/main/java/com/thealgorithms/maths/StrobogrammaticNumber.java)
+ - 📄 [SumOfArithmeticSeries](src/main/java/com/thealgorithms/maths/SumOfArithmeticSeries.java)
+ - 📄 [SumOfDigits](src/main/java/com/thealgorithms/maths/SumOfDigits.java)
+ - 📄 [SumOfOddNumbers](src/main/java/com/thealgorithms/maths/SumOfOddNumbers.java)
+ - 📄 [SumWithoutArithmeticOperators](src/main/java/com/thealgorithms/maths/SumWithoutArithmeticOperators.java)
+ - 📄 [TrinomialTriangle](src/main/java/com/thealgorithms/maths/TrinomialTriangle.java)
+ - 📄 [TwinPrime](src/main/java/com/thealgorithms/maths/TwinPrime.java)
+ - 📄 [UniformNumbers](src/main/java/com/thealgorithms/maths/UniformNumbers.java)
+ - 📄 [VampireNumber](src/main/java/com/thealgorithms/maths/VampireNumber.java)
+ - 📄 [VectorCrossProduct](src/main/java/com/thealgorithms/maths/VectorCrossProduct.java)
+ - 📄 [Volume](src/main/java/com/thealgorithms/maths/Volume.java)
+ - 📁 **matrix**
+ - 📄 [InverseOfMatrix](src/main/java/com/thealgorithms/matrix/InverseOfMatrix.java)
+ - 📄 [MatrixRank](src/main/java/com/thealgorithms/matrix/MatrixRank.java)
+ - 📄 [MatrixTranspose](src/main/java/com/thealgorithms/matrix/MatrixTranspose.java)
+ - 📄 [MedianOfMatrix](src/main/java/com/thealgorithms/matrix/MedianOfMatrix.java)
+ - 📄 [MirrorOfMatrix](src/main/java/com/thealgorithms/matrix/MirrorOfMatrix.java)
+ - 📄 [PrintAMatrixInSpiralOrder](src/main/java/com/thealgorithms/matrix/PrintAMatrixInSpiralOrder.java)
+ - 📄 [RotateMatrixBy90Degrees](src/main/java/com/thealgorithms/matrix/RotateMatrixBy90Degrees.java)
+ - 📄 [SolveSystem](src/main/java/com/thealgorithms/matrix/SolveSystem.java)
+ - 📁 **matrixexponentiation**
+ - 📄 [Fibonacci](src/main/java/com/thealgorithms/matrix/matrixexponentiation/Fibonacci.java)
+ - 📁 **utils**
+ - 📄 [MatrixUtil](src/main/java/com/thealgorithms/matrix/utils/MatrixUtil.java)
+ - 📁 **misc**
+ - 📄 [ColorContrastRatio](src/main/java/com/thealgorithms/misc/ColorContrastRatio.java)
+ - 📄 [MapReduce](src/main/java/com/thealgorithms/misc/MapReduce.java)
+ - 📄 [MedianOfRunningArray](src/main/java/com/thealgorithms/misc/MedianOfRunningArray.java)
+ - 📄 [MedianOfRunningArrayByte](src/main/java/com/thealgorithms/misc/MedianOfRunningArrayByte.java)
+ - 📄 [MedianOfRunningArrayDouble](src/main/java/com/thealgorithms/misc/MedianOfRunningArrayDouble.java)
+ - 📄 [MedianOfRunningArrayFloat](src/main/java/com/thealgorithms/misc/MedianOfRunningArrayFloat.java)
+ - 📄 [MedianOfRunningArrayInteger](src/main/java/com/thealgorithms/misc/MedianOfRunningArrayInteger.java)
+ - 📄 [MedianOfRunningArrayLong](src/main/java/com/thealgorithms/misc/MedianOfRunningArrayLong.java)
+ - 📄 [PalindromePrime](src/main/java/com/thealgorithms/misc/PalindromePrime.java)
+ - 📄 [PalindromeSinglyLinkedList](src/main/java/com/thealgorithms/misc/PalindromeSinglyLinkedList.java)
+ - 📄 [RangeInSortedArray](src/main/java/com/thealgorithms/misc/RangeInSortedArray.java)
+ - 📄 [ShuffleArray](src/main/java/com/thealgorithms/misc/ShuffleArray.java)
+ - 📄 [Sparsity](src/main/java/com/thealgorithms/misc/Sparsity.java)
+ - 📄 [ThreeSumProblem](src/main/java/com/thealgorithms/misc/ThreeSumProblem.java)
+ - 📄 [TwoSumProblem](src/main/java/com/thealgorithms/misc/TwoSumProblem.java)
+ - 📁 **others**
+ - 📄 [ArrayLeftRotation](src/main/java/com/thealgorithms/others/ArrayLeftRotation.java)
+ - 📄 [ArrayRightRotation](src/main/java/com/thealgorithms/others/ArrayRightRotation.java)
+ - 📄 [BFPRT](src/main/java/com/thealgorithms/others/BFPRT.java)
+ - 📄 [BankersAlgorithm](src/main/java/com/thealgorithms/others/BankersAlgorithm.java)
+ - 📄 [BoyerMoore](src/main/java/com/thealgorithms/others/BoyerMoore.java)
+ - 📄 [BrianKernighanAlgorithm](src/main/java/com/thealgorithms/others/BrianKernighanAlgorithm.java)
+ - 📄 [CRC16](src/main/java/com/thealgorithms/others/CRC16.java)
+ - 📄 [CRC32](src/main/java/com/thealgorithms/others/CRC32.java)
+ - 📄 [CRCAlgorithm](src/main/java/com/thealgorithms/others/CRCAlgorithm.java)
+ - 📄 [Conway](src/main/java/com/thealgorithms/others/Conway.java)
+ - 📄 [Damm](src/main/java/com/thealgorithms/others/Damm.java)
+ - 📄 [Dijkstra](src/main/java/com/thealgorithms/others/Dijkstra.java)
+ - 📄 [FloydTriangle](src/main/java/com/thealgorithms/others/FloydTriangle.java)
+ - 📄 [GaussLegendre](src/main/java/com/thealgorithms/others/GaussLegendre.java)
+ - 📄 [HappyNumbersSeq](src/main/java/com/thealgorithms/others/HappyNumbersSeq.java)
+ - 📄 [Huffman](src/main/java/com/thealgorithms/others/Huffman.java)
+ - 📄 [Implementing_auto_completing_features_using_trie](src/main/java/com/thealgorithms/others/Implementing_auto_completing_features_using_trie.java)
+ - 📄 [InsertDeleteInArray](src/main/java/com/thealgorithms/others/InsertDeleteInArray.java)
+ - 📄 [KochSnowflake](src/main/java/com/thealgorithms/others/KochSnowflake.java)
+ - 📄 [Krishnamurthy](src/main/java/com/thealgorithms/others/Krishnamurthy.java)
+ - 📄 [LineSweep](src/main/java/com/thealgorithms/others/LineSweep.java)
+ - 📄 [LinearCongruentialGenerator](src/main/java/com/thealgorithms/others/LinearCongruentialGenerator.java)
+ - 📄 [LowestBasePalindrome](src/main/java/com/thealgorithms/others/LowestBasePalindrome.java)
+ - 📄 [Luhn](src/main/java/com/thealgorithms/others/Luhn.java)
+ - 📄 [Mandelbrot](src/main/java/com/thealgorithms/others/Mandelbrot.java)
+ - 📄 [MaximumSlidingWindow](src/main/java/com/thealgorithms/others/MaximumSlidingWindow.java)
+ - 📄 [MaximumSumOfDistinctSubarraysWithLengthK](src/main/java/com/thealgorithms/others/MaximumSumOfDistinctSubarraysWithLengthK.java)
+ - 📄 [MemoryManagementAlgorithms](src/main/java/com/thealgorithms/others/MemoryManagementAlgorithms.java)
+ - 📄 [MiniMaxAlgorithm](src/main/java/com/thealgorithms/others/MiniMaxAlgorithm.java)
+ - 📄 [PageRank](src/main/java/com/thealgorithms/others/PageRank.java)
+ - 📄 [PasswordGen](src/main/java/com/thealgorithms/others/PasswordGen.java)
+ - 📄 [PerlinNoise](src/main/java/com/thealgorithms/others/PerlinNoise.java)
+ - 📄 [PrintAMatrixInSpiralOrder](src/main/java/com/thealgorithms/others/PrintAMatrixInSpiralOrder.java)
+ - 📄 [QueueUsingTwoStacks](src/main/java/com/thealgorithms/others/QueueUsingTwoStacks.java)
+ - 📄 [RemoveDuplicateFromString](src/main/java/com/thealgorithms/others/RemoveDuplicateFromString.java)
+ - 📄 [ReverseStackUsingRecursion](src/main/java/com/thealgorithms/others/ReverseStackUsingRecursion.java)
+ - 📄 [SkylineProblem](src/main/java/com/thealgorithms/others/SkylineProblem.java)
+ - 📄 [TwoPointers](src/main/java/com/thealgorithms/others/TwoPointers.java)
+ - 📄 [Verhoeff](src/main/java/com/thealgorithms/others/Verhoeff.java)
+ - 📁 **cn**
+ - 📄 [HammingDistance](src/main/java/com/thealgorithms/others/cn/HammingDistance.java)
+ - 📁 **puzzlesandgames**
+ - 📄 [Sudoku](src/main/java/com/thealgorithms/puzzlesandgames/Sudoku.java)
+ - 📄 [TowerOfHanoi](src/main/java/com/thealgorithms/puzzlesandgames/TowerOfHanoi.java)
+ - 📄 [WordBoggle](src/main/java/com/thealgorithms/puzzlesandgames/WordBoggle.java)
+ - 📁 **randomized**
+ - 📄 [KargerMinCut](src/main/java/com/thealgorithms/randomized/KargerMinCut.java)
+ - 📄 [MonteCarloIntegration](src/main/java/com/thealgorithms/randomized/MonteCarloIntegration.java)
+ - 📄 [RandomizedClosestPair](src/main/java/com/thealgorithms/randomized/RandomizedClosestPair.java)
+ - 📄 [RandomizedMatrixMultiplicationVerification](src/main/java/com/thealgorithms/randomized/RandomizedMatrixMultiplicationVerification.java)
+ - 📄 [RandomizedQuickSort](src/main/java/com/thealgorithms/randomized/RandomizedQuickSort.java)
+ - 📄 [ReservoirSampling](src/main/java/com/thealgorithms/randomized/ReservoirSampling.java)
+ - 📁 **recursion**
+ - 📄 [FibonacciSeries](src/main/java/com/thealgorithms/recursion/FibonacciSeries.java)
+ - 📄 [GenerateSubsets](src/main/java/com/thealgorithms/recursion/GenerateSubsets.java)
+ - 📁 **scheduling**
+ - 📄 [AgingScheduling](src/main/java/com/thealgorithms/scheduling/AgingScheduling.java)
+ - 📄 [EDFScheduling](src/main/java/com/thealgorithms/scheduling/EDFScheduling.java)
+ - 📄 [FCFSScheduling](src/main/java/com/thealgorithms/scheduling/FCFSScheduling.java)
+ - 📄 [FairShareScheduling](src/main/java/com/thealgorithms/scheduling/FairShareScheduling.java)
+ - 📄 [GangScheduling](src/main/java/com/thealgorithms/scheduling/GangScheduling.java)
+ - 📄 [HighestResponseRatioNextScheduling](src/main/java/com/thealgorithms/scheduling/HighestResponseRatioNextScheduling.java)
+ - 📄 [JobSchedulingWithDeadline](src/main/java/com/thealgorithms/scheduling/JobSchedulingWithDeadline.java)
+ - 📄 [LotteryScheduling](src/main/java/com/thealgorithms/scheduling/LotteryScheduling.java)
+ - 📄 [MLFQScheduler](src/main/java/com/thealgorithms/scheduling/MLFQScheduler.java)
+ - 📄 [MultiAgentScheduling](src/main/java/com/thealgorithms/scheduling/MultiAgentScheduling.java)
+ - 📄 [NonPreemptivePriorityScheduling](src/main/java/com/thealgorithms/scheduling/NonPreemptivePriorityScheduling.java)
+ - 📄 [PreemptivePriorityScheduling](src/main/java/com/thealgorithms/scheduling/PreemptivePriorityScheduling.java)
+ - 📄 [ProportionalFairScheduling](src/main/java/com/thealgorithms/scheduling/ProportionalFairScheduling.java)
+ - 📄 [RRScheduling](src/main/java/com/thealgorithms/scheduling/RRScheduling.java)
+ - 📄 [RandomScheduling](src/main/java/com/thealgorithms/scheduling/RandomScheduling.java)
+ - 📄 [SJFScheduling](src/main/java/com/thealgorithms/scheduling/SJFScheduling.java)
+ - 📄 [SRTFScheduling](src/main/java/com/thealgorithms/scheduling/SRTFScheduling.java)
+ - 📄 [SelfAdjustingScheduling](src/main/java/com/thealgorithms/scheduling/SelfAdjustingScheduling.java)
+ - 📄 [SlackTimeScheduling](src/main/java/com/thealgorithms/scheduling/SlackTimeScheduling.java)
+ - 📁 **diskscheduling**
+ - 📄 [CircularLookScheduling](src/main/java/com/thealgorithms/scheduling/diskscheduling/CircularLookScheduling.java)
+ - 📄 [CircularScanScheduling](src/main/java/com/thealgorithms/scheduling/diskscheduling/CircularScanScheduling.java)
+ - 📄 [LookScheduling](src/main/java/com/thealgorithms/scheduling/diskscheduling/LookScheduling.java)
+ - 📄 [SSFScheduling](src/main/java/com/thealgorithms/scheduling/diskscheduling/SSFScheduling.java)
+ - 📄 [ScanScheduling](src/main/java/com/thealgorithms/scheduling/diskscheduling/ScanScheduling.java)
+ - 📁 **searches**
+ - 📄 [BM25InvertedIndex](src/main/java/com/thealgorithms/searches/BM25InvertedIndex.java)
+ - 📄 [BinarySearch](src/main/java/com/thealgorithms/searches/BinarySearch.java)
+ - 📄 [BinarySearch2dArray](src/main/java/com/thealgorithms/searches/BinarySearch2dArray.java)
+ - 📄 [BoyerMoore](src/main/java/com/thealgorithms/searches/BoyerMoore.java)
+ - 📄 [BreadthFirstSearch](src/main/java/com/thealgorithms/searches/BreadthFirstSearch.java)
+ - 📄 [DepthFirstSearch](src/main/java/com/thealgorithms/searches/DepthFirstSearch.java)
+ - 📄 [ExponentalSearch](src/main/java/com/thealgorithms/searches/ExponentalSearch.java)
+ - 📄 [FibonacciSearch](src/main/java/com/thealgorithms/searches/FibonacciSearch.java)
+ - 📄 [HowManyTimesRotated](src/main/java/com/thealgorithms/searches/HowManyTimesRotated.java)
+ - 📄 [InterpolationSearch](src/main/java/com/thealgorithms/searches/InterpolationSearch.java)
+ - 📄 [IterativeBinarySearch](src/main/java/com/thealgorithms/searches/IterativeBinarySearch.java)
+ - 📄 [IterativeTernarySearch](src/main/java/com/thealgorithms/searches/IterativeTernarySearch.java)
+ - 📄 [JumpSearch](src/main/java/com/thealgorithms/searches/JumpSearch.java)
+ - 📄 [KMPSearch](src/main/java/com/thealgorithms/searches/KMPSearch.java)
+ - 📄 [LinearSearch](src/main/java/com/thealgorithms/searches/LinearSearch.java)
+ - 📄 [LinearSearchThread](src/main/java/com/thealgorithms/searches/LinearSearchThread.java)
+ - 📄 [LowerBound](src/main/java/com/thealgorithms/searches/LowerBound.java)
+ - 📄 [MonteCarloTreeSearch](src/main/java/com/thealgorithms/searches/MonteCarloTreeSearch.java)
+ - 📄 [OrderAgnosticBinarySearch](src/main/java/com/thealgorithms/searches/OrderAgnosticBinarySearch.java)
+ - 📄 [PerfectBinarySearch](src/main/java/com/thealgorithms/searches/PerfectBinarySearch.java)
+ - 📄 [QuickSelect](src/main/java/com/thealgorithms/searches/QuickSelect.java)
+ - 📄 [RabinKarpAlgorithm](src/main/java/com/thealgorithms/searches/RabinKarpAlgorithm.java)
+ - 📄 [RandomSearch](src/main/java/com/thealgorithms/searches/RandomSearch.java)
+ - 📄 [RecursiveBinarySearch](src/main/java/com/thealgorithms/searches/RecursiveBinarySearch.java)
+ - 📄 [RowColumnWiseSorted2dArrayBinarySearch](src/main/java/com/thealgorithms/searches/RowColumnWiseSorted2dArrayBinarySearch.java)
+ - 📄 [SaddlebackSearch](src/main/java/com/thealgorithms/searches/SaddlebackSearch.java)
+ - 📄 [SearchInARowAndColWiseSortedMatrix](src/main/java/com/thealgorithms/searches/SearchInARowAndColWiseSortedMatrix.java)
+ - 📄 [SortOrderAgnosticBinarySearch](src/main/java/com/thealgorithms/searches/SortOrderAgnosticBinarySearch.java)
+ - 📄 [SquareRootBinarySearch](src/main/java/com/thealgorithms/searches/SquareRootBinarySearch.java)
+ - 📄 [TernarySearch](src/main/java/com/thealgorithms/searches/TernarySearch.java)
+ - 📄 [UnionFind](src/main/java/com/thealgorithms/searches/UnionFind.java)
+ - 📄 [UpperBound](src/main/java/com/thealgorithms/searches/UpperBound.java)
+ - 📁 **slidingwindow**
+ - 📄 [LongestSubarrayWithSumLessOrEqualToK](src/main/java/com/thealgorithms/slidingwindow/LongestSubarrayWithSumLessOrEqualToK.java)
+ - 📄 [LongestSubstringWithoutRepeatingCharacters](src/main/java/com/thealgorithms/slidingwindow/LongestSubstringWithoutRepeatingCharacters.java)
+ - 📄 [MaxSumKSizeSubarray](src/main/java/com/thealgorithms/slidingwindow/MaxSumKSizeSubarray.java)
+ - 📄 [MinSumKSizeSubarray](src/main/java/com/thealgorithms/slidingwindow/MinSumKSizeSubarray.java)
+ - 📄 [ShortestCoprimeSegment](src/main/java/com/thealgorithms/slidingwindow/ShortestCoprimeSegment.java)
+ - 📁 **sorts**
+ - 📄 [AdaptiveMergeSort](src/main/java/com/thealgorithms/sorts/AdaptiveMergeSort.java)
+ - 📄 [BeadSort](src/main/java/com/thealgorithms/sorts/BeadSort.java)
+ - 📄 [BinaryInsertionSort](src/main/java/com/thealgorithms/sorts/BinaryInsertionSort.java)
+ - 📄 [BitonicSort](src/main/java/com/thealgorithms/sorts/BitonicSort.java)
+ - 📄 [BogoSort](src/main/java/com/thealgorithms/sorts/BogoSort.java)
+ - 📄 [BubbleSort](src/main/java/com/thealgorithms/sorts/BubbleSort.java)
+ - 📄 [BubbleSortRecursive](src/main/java/com/thealgorithms/sorts/BubbleSortRecursive.java)
+ - 📄 [BucketSort](src/main/java/com/thealgorithms/sorts/BucketSort.java)
+ - 📄 [CircleSort](src/main/java/com/thealgorithms/sorts/CircleSort.java)
+ - 📄 [CocktailShakerSort](src/main/java/com/thealgorithms/sorts/CocktailShakerSort.java)
+ - 📄 [CombSort](src/main/java/com/thealgorithms/sorts/CombSort.java)
+ - 📄 [CountingSort](src/main/java/com/thealgorithms/sorts/CountingSort.java)
+ - 📄 [CycleSort](src/main/java/com/thealgorithms/sorts/CycleSort.java)
+ - 📄 [DarkSort](src/main/java/com/thealgorithms/sorts/DarkSort.java)
+ - 📄 [DualPivotQuickSort](src/main/java/com/thealgorithms/sorts/DualPivotQuickSort.java)
+ - 📄 [DutchNationalFlagSort](src/main/java/com/thealgorithms/sorts/DutchNationalFlagSort.java)
+ - 📄 [ExchangeSort](src/main/java/com/thealgorithms/sorts/ExchangeSort.java)
+ - 📄 [FlashSort](src/main/java/com/thealgorithms/sorts/FlashSort.java)
+ - 📄 [GnomeSort](src/main/java/com/thealgorithms/sorts/GnomeSort.java)
+ - 📄 [HeapSort](src/main/java/com/thealgorithms/sorts/HeapSort.java)
+ - 📄 [InsertionSort](src/main/java/com/thealgorithms/sorts/InsertionSort.java)
+ - 📄 [IntrospectiveSort](src/main/java/com/thealgorithms/sorts/IntrospectiveSort.java)
+ - 📄 [LinkListSort](src/main/java/com/thealgorithms/sorts/LinkListSort.java)
+ - 📄 [MergeSort](src/main/java/com/thealgorithms/sorts/MergeSort.java)
+ - 📄 [MergeSortNoExtraSpace](src/main/java/com/thealgorithms/sorts/MergeSortNoExtraSpace.java)
+ - 📄 [MergeSortRecursive](src/main/java/com/thealgorithms/sorts/MergeSortRecursive.java)
+ - 📄 [OddEvenSort](src/main/java/com/thealgorithms/sorts/OddEvenSort.java)
+ - 📄 [PancakeSort](src/main/java/com/thealgorithms/sorts/PancakeSort.java)
+ - 📄 [PatienceSort](src/main/java/com/thealgorithms/sorts/PatienceSort.java)
+ - 📄 [PigeonholeSort](src/main/java/com/thealgorithms/sorts/PigeonholeSort.java)
+ - 📄 [QuickSort](src/main/java/com/thealgorithms/sorts/QuickSort.java)
+ - 📄 [RadixSort](src/main/java/com/thealgorithms/sorts/RadixSort.java)
+ - 📄 [SelectionSort](src/main/java/com/thealgorithms/sorts/SelectionSort.java)
+ - 📄 [SelectionSortRecursive](src/main/java/com/thealgorithms/sorts/SelectionSortRecursive.java)
+ - 📄 [ShellSort](src/main/java/com/thealgorithms/sorts/ShellSort.java)
+ - 📄 [SimpleSort](src/main/java/com/thealgorithms/sorts/SimpleSort.java)
+ - 📄 [SlowSort](src/main/java/com/thealgorithms/sorts/SlowSort.java)
+ - 📄 [SortAlgorithm](src/main/java/com/thealgorithms/sorts/SortAlgorithm.java)
+ - 📄 [SortUtils](src/main/java/com/thealgorithms/sorts/SortUtils.java)
+ - 📄 [SortUtilsRandomGenerator](src/main/java/com/thealgorithms/sorts/SortUtilsRandomGenerator.java)
+ - 📄 [SpreadSort](src/main/java/com/thealgorithms/sorts/SpreadSort.java)
+ - 📄 [StalinSort](src/main/java/com/thealgorithms/sorts/StalinSort.java)
+ - 📄 [StoogeSort](src/main/java/com/thealgorithms/sorts/StoogeSort.java)
+ - 📄 [StrandSort](src/main/java/com/thealgorithms/sorts/StrandSort.java)
+ - 📄 [SwapSort](src/main/java/com/thealgorithms/sorts/SwapSort.java)
+ - 📄 [TimSort](src/main/java/com/thealgorithms/sorts/TimSort.java)
+ - 📄 [TopologicalSort](src/main/java/com/thealgorithms/sorts/TopologicalSort.java)
+ - 📄 [TreeSort](src/main/java/com/thealgorithms/sorts/TreeSort.java)
+ - 📄 [WaveSort](src/main/java/com/thealgorithms/sorts/WaveSort.java)
+ - 📄 [WiggleSort](src/main/java/com/thealgorithms/sorts/WiggleSort.java)
+ - 📁 **stacks**
+ - 📄 [BalancedBrackets](src/main/java/com/thealgorithms/stacks/BalancedBrackets.java)
+ - 📄 [CelebrityFinder](src/main/java/com/thealgorithms/stacks/CelebrityFinder.java)
+ - 📄 [DecimalToAnyUsingStack](src/main/java/com/thealgorithms/stacks/DecimalToAnyUsingStack.java)
+ - 📄 [DuplicateBrackets](src/main/java/com/thealgorithms/stacks/DuplicateBrackets.java)
+ - 📄 [GreatestElementConstantTime](src/main/java/com/thealgorithms/stacks/GreatestElementConstantTime.java)
+ - 📄 [InfixToPostfix](src/main/java/com/thealgorithms/stacks/InfixToPostfix.java)
+ - 📄 [InfixToPrefix](src/main/java/com/thealgorithms/stacks/InfixToPrefix.java)
+ - 📄 [LargestRectangle](src/main/java/com/thealgorithms/stacks/LargestRectangle.java)
+ - 📄 [MaximumMinimumWindow](src/main/java/com/thealgorithms/stacks/MaximumMinimumWindow.java)
+ - 📄 [MinStackUsingSingleStack](src/main/java/com/thealgorithms/stacks/MinStackUsingSingleStack.java)
+ - 📄 [MinStackUsingTwoStacks](src/main/java/com/thealgorithms/stacks/MinStackUsingTwoStacks.java)
+ - 📄 [NextGreaterElement](src/main/java/com/thealgorithms/stacks/NextGreaterElement.java)
+ - 📄 [NextSmallerElement](src/main/java/com/thealgorithms/stacks/NextSmallerElement.java)
+ - 📄 [PalindromeWithStack](src/main/java/com/thealgorithms/stacks/PalindromeWithStack.java)
+ - 📄 [PostfixEvaluator](src/main/java/com/thealgorithms/stacks/PostfixEvaluator.java)
+ - 📄 [PostfixToInfix](src/main/java/com/thealgorithms/stacks/PostfixToInfix.java)
+ - 📄 [PrefixEvaluator](src/main/java/com/thealgorithms/stacks/PrefixEvaluator.java)
+ - 📄 [PrefixToInfix](src/main/java/com/thealgorithms/stacks/PrefixToInfix.java)
+ - 📄 [SmallestElementConstantTime](src/main/java/com/thealgorithms/stacks/SmallestElementConstantTime.java)
+ - 📄 [SortStack](src/main/java/com/thealgorithms/stacks/SortStack.java)
+ - 📄 [StackPostfixNotation](src/main/java/com/thealgorithms/stacks/StackPostfixNotation.java)
+ - 📄 [StackUsingTwoQueues](src/main/java/com/thealgorithms/stacks/StackUsingTwoQueues.java)
+ - 📁 **strings**
+ - 📄 [AhoCorasick](src/main/java/com/thealgorithms/strings/AhoCorasick.java)
+ - 📄 [Alphabetical](src/main/java/com/thealgorithms/strings/Alphabetical.java)
+ - 📄 [Anagrams](src/main/java/com/thealgorithms/strings/Anagrams.java)
+ - 📄 [CharactersSame](src/main/java/com/thealgorithms/strings/CharactersSame.java)
+ - 📄 [CheckVowels](src/main/java/com/thealgorithms/strings/CheckVowels.java)
+ - 📄 [CountChar](src/main/java/com/thealgorithms/strings/CountChar.java)
+ - 📄 [CountWords](src/main/java/com/thealgorithms/strings/CountWords.java)
+ - 📄 [HammingDistance](src/main/java/com/thealgorithms/strings/HammingDistance.java)
+ - 📄 [HorspoolSearch](src/main/java/com/thealgorithms/strings/HorspoolSearch.java)
+ - 📄 [Isomorphic](src/main/java/com/thealgorithms/strings/Isomorphic.java)
+ - 📄 [KMP](src/main/java/com/thealgorithms/strings/KMP.java)
+ - 📄 [LetterCombinationsOfPhoneNumber](src/main/java/com/thealgorithms/strings/LetterCombinationsOfPhoneNumber.java)
+ - 📄 [LongestCommonPrefix](src/main/java/com/thealgorithms/strings/LongestCommonPrefix.java)
+ - 📄 [LongestNonRepetitiveSubstring](src/main/java/com/thealgorithms/strings/LongestNonRepetitiveSubstring.java)
+ - 📄 [LongestPalindromicSubstring](src/main/java/com/thealgorithms/strings/LongestPalindromicSubstring.java)
+ - 📄 [Lower](src/main/java/com/thealgorithms/strings/Lower.java)
+ - 📄 [Manacher](src/main/java/com/thealgorithms/strings/Manacher.java)
+ - 📄 [MyAtoi](src/main/java/com/thealgorithms/strings/MyAtoi.java)
+ - 📄 [Palindrome](src/main/java/com/thealgorithms/strings/Palindrome.java)
+ - 📄 [Pangram](src/main/java/com/thealgorithms/strings/Pangram.java)
+ - 📄 [PermuteString](src/main/java/com/thealgorithms/strings/PermuteString.java)
+ - 📄 [RabinKarp](src/main/java/com/thealgorithms/strings/RabinKarp.java)
+ - 📄 [ReturnSubsequence](src/main/java/com/thealgorithms/strings/ReturnSubsequence.java)
+ - 📄 [ReverseString](src/main/java/com/thealgorithms/strings/ReverseString.java)
+ - 📄 [ReverseStringRecursive](src/main/java/com/thealgorithms/strings/ReverseStringRecursive.java)
+ - 📄 [ReverseWordsInString](src/main/java/com/thealgorithms/strings/ReverseWordsInString.java)
+ - 📄 [Rotation](src/main/java/com/thealgorithms/strings/Rotation.java)
+ - 📄 [StringCompression](src/main/java/com/thealgorithms/strings/StringCompression.java)
+ - 📄 [StringMatchFiniteAutomata](src/main/java/com/thealgorithms/strings/StringMatchFiniteAutomata.java)
+ - 📄 [Upper](src/main/java/com/thealgorithms/strings/Upper.java)
+ - 📄 [ValidParentheses](src/main/java/com/thealgorithms/strings/ValidParentheses.java)
+ - 📄 [WordLadder](src/main/java/com/thealgorithms/strings/WordLadder.java)
+ - 📁 **zigZagPattern**
+ - 📄 [README](src/main/java/com/thealgorithms/strings/zigZagPattern/README.md)
+ - 📄 [ZigZagPattern](src/main/java/com/thealgorithms/strings/zigZagPattern/ZigZagPattern.java)
+ - 📁 **tree**
+ - 📄 [HeavyLightDecomposition](src/main/java/com/thealgorithms/tree/HeavyLightDecomposition.java)
+- 📁 **test**
+ - 📁 **java**
+ - 📁 **com**
+ - 📁 **thealgorithms**
+ - 📁 **audiofilters**
+ - 📄 [EMAFilterTest](src/test/java/com/thealgorithms/audiofilters/EMAFilterTest.java)
+ - 📄 [IIRFilterTest](src/test/java/com/thealgorithms/audiofilters/IIRFilterTest.java)
+ - 📁 **backtracking**
+ - 📄 [AllPathsFromSourceToTargetTest](src/test/java/com/thealgorithms/backtracking/AllPathsFromSourceToTargetTest.java)
+ - 📄 [ArrayCombinationTest](src/test/java/com/thealgorithms/backtracking/ArrayCombinationTest.java)
+ - 📄 [CombinationTest](src/test/java/com/thealgorithms/backtracking/CombinationTest.java)
+ - 📄 [CrosswordSolverTest](src/test/java/com/thealgorithms/backtracking/CrosswordSolverTest.java)
+ - 📄 [FloodFillTest](src/test/java/com/thealgorithms/backtracking/FloodFillTest.java)
+ - 📄 [KnightsTourTest](src/test/java/com/thealgorithms/backtracking/KnightsTourTest.java)
+ - 📄 [MColoringTest](src/test/java/com/thealgorithms/backtracking/MColoringTest.java)
+ - 📄 [MazeRecursionTest](src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java)
+ - 📄 [NQueensTest](src/test/java/com/thealgorithms/backtracking/NQueensTest.java)
+ - 📄 [ParenthesesGeneratorTest](src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java)
+ - 📄 [PermutationTest](src/test/java/com/thealgorithms/backtracking/PermutationTest.java)
+ - 📄 [PowerSumTest](src/test/java/com/thealgorithms/backtracking/PowerSumTest.java)
+ - 📄 [SubsequenceFinderTest](src/test/java/com/thealgorithms/backtracking/SubsequenceFinderTest.java)
+ - 📄 [WordPatternMatcherTest](src/test/java/com/thealgorithms/backtracking/WordPatternMatcherTest.java)
+ - 📄 [WordSearchTest](src/test/java/com/thealgorithms/backtracking/WordSearchTest.java)
+ - 📁 **bitmanipulation**
+ - 📄 [BcdConversionTest](src/test/java/com/thealgorithms/bitmanipulation/BcdConversionTest.java)
+ - 📄 [BinaryPalindromeCheckTest](src/test/java/com/thealgorithms/bitmanipulation/BinaryPalindromeCheckTest.java)
+ - 📄 [BitSwapTest](src/test/java/com/thealgorithms/bitmanipulation/BitSwapTest.java)
+ - 📄 [BooleanAlgebraGatesTest](src/test/java/com/thealgorithms/bitmanipulation/BooleanAlgebraGatesTest.java)
+ - 📄 [ClearLeftmostSetBitTest](src/test/java/com/thealgorithms/bitmanipulation/ClearLeftmostSetBitTest.java)
+ - 📄 [CountLeadingZerosTest](src/test/java/com/thealgorithms/bitmanipulation/CountLeadingZerosTest.java)
+ - 📄 [CountSetBitsTest](src/test/java/com/thealgorithms/bitmanipulation/CountSetBitsTest.java)
+ - 📄 [FindNthBitTest](src/test/java/com/thealgorithms/bitmanipulation/FindNthBitTest.java)
+ - 📄 [FirstDifferentBitTest](src/test/java/com/thealgorithms/bitmanipulation/FirstDifferentBitTest.java)
+ - 📄 [GenerateSubsetsTest](src/test/java/com/thealgorithms/bitmanipulation/GenerateSubsetsTest.java)
+ - 📄 [GrayCodeConversionTest](src/test/java/com/thealgorithms/bitmanipulation/GrayCodeConversionTest.java)
+ - 📄 [HammingDistanceTest](src/test/java/com/thealgorithms/bitmanipulation/HammingDistanceTest.java)
+ - 📄 [HigherLowerPowerOfTwoTest](src/test/java/com/thealgorithms/bitmanipulation/HigherLowerPowerOfTwoTest.java)
+ - 📄 [HighestSetBitTest](src/test/java/com/thealgorithms/bitmanipulation/HighestSetBitTest.java)
+ - 📄 [IndexOfRightMostSetBitTest](src/test/java/com/thealgorithms/bitmanipulation/IndexOfRightMostSetBitTest.java)
+ - 📄 [IsEvenTest](src/test/java/com/thealgorithms/bitmanipulation/IsEvenTest.java)
+ - 📄 [IsPowerTwoTest](src/test/java/com/thealgorithms/bitmanipulation/IsPowerTwoTest.java)
+ - 📄 [LowestSetBitTest](src/test/java/com/thealgorithms/bitmanipulation/LowestSetBitTest.java)
+ - 📄 [ModuloPowerOfTwoTest](src/test/java/com/thealgorithms/bitmanipulation/ModuloPowerOfTwoTest.java)
+ - 📄 [NextHigherSameBitCountTest](src/test/java/com/thealgorithms/bitmanipulation/NextHigherSameBitCountTest.java)
+ - 📄 [NonRepeatingNumberFinderTest](src/test/java/com/thealgorithms/bitmanipulation/NonRepeatingNumberFinderTest.java)
+ - 📄 [NumberAppearingOddTimesTest](src/test/java/com/thealgorithms/bitmanipulation/NumberAppearingOddTimesTest.java)
+ - 📄 [NumbersDifferentSignsTest](src/test/java/com/thealgorithms/bitmanipulation/NumbersDifferentSignsTest.java)
+ - 📄 [OneBitDifferenceTest](src/test/java/com/thealgorithms/bitmanipulation/OneBitDifferenceTest.java)
+ - 📄 [OnesComplementTest](src/test/java/com/thealgorithms/bitmanipulation/OnesComplementTest.java)
+ - 📄 [ParityCheckTest](src/test/java/com/thealgorithms/bitmanipulation/ParityCheckTest.java)
+ - 📄 [ReverseBitsTest](src/test/java/com/thealgorithms/bitmanipulation/ReverseBitsTest.java)
+ - 📄 [SingleBitOperationsTest](src/test/java/com/thealgorithms/bitmanipulation/SingleBitOperationsTest.java)
+ - 📄 [SingleElementTest](src/test/java/com/thealgorithms/bitmanipulation/SingleElementTest.java)
+ - 📄 [SwapAdjacentBitsTest](src/test/java/com/thealgorithms/bitmanipulation/SwapAdjacentBitsTest.java)
+ - 📄 [TwosComplementTest](src/test/java/com/thealgorithms/bitmanipulation/TwosComplementTest.java)
+ - 📄 [Xs3ConversionTest](src/test/java/com/thealgorithms/bitmanipulation/Xs3ConversionTest.java)
+ - 📁 **ciphers**
+ - 📄 [ADFGVXCipherTest](src/test/java/com/thealgorithms/ciphers/ADFGVXCipherTest.java)
+ - 📄 [AESEncryptionTest](src/test/java/com/thealgorithms/ciphers/AESEncryptionTest.java)
+ - 📄 [AffineCipherTest](src/test/java/com/thealgorithms/ciphers/AffineCipherTest.java)
+ - 📄 [AtbashTest](src/test/java/com/thealgorithms/ciphers/AtbashTest.java)
+ - 📄 [AutokeyTest](src/test/java/com/thealgorithms/ciphers/AutokeyTest.java)
+ - 📄 [BaconianCipherTest](src/test/java/com/thealgorithms/ciphers/BaconianCipherTest.java)
+ - 📄 [BlowfishTest](src/test/java/com/thealgorithms/ciphers/BlowfishTest.java)
+ - 📄 [CaesarTest](src/test/java/com/thealgorithms/ciphers/CaesarTest.java)
+ - 📄 [ColumnarTranspositionCipherTest](src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java)
+ - 📄 [DESTest](src/test/java/com/thealgorithms/ciphers/DESTest.java)
+ - 📄 [DiffieHellmanTest](src/test/java/com/thealgorithms/ciphers/DiffieHellmanTest.java)
+ - 📄 [ECCTest](src/test/java/com/thealgorithms/ciphers/ECCTest.java)
+ - 📄 [HillCipherTest](src/test/java/com/thealgorithms/ciphers/HillCipherTest.java)
+ - 📄 [MonoAlphabeticTest](src/test/java/com/thealgorithms/ciphers/MonoAlphabeticTest.java)
+ - 📄 [PlayfairTest](src/test/java/com/thealgorithms/ciphers/PlayfairTest.java)
+ - 📄 [PolybiusTest](src/test/java/com/thealgorithms/ciphers/PolybiusTest.java)
+ - 📄 [RSATest](src/test/java/com/thealgorithms/ciphers/RSATest.java)
+ - 📄 [RailFenceTest](src/test/java/com/thealgorithms/ciphers/RailFenceTest.java)
+ - 📄 [SimpleSubCipherTest](src/test/java/com/thealgorithms/ciphers/SimpleSubCipherTest.java)
+ - 📄 [VigenereTest](src/test/java/com/thealgorithms/ciphers/VigenereTest.java)
+ - 📄 [XORCipherTest](src/test/java/com/thealgorithms/ciphers/XORCipherTest.java)
+ - 📁 **a5**
+ - 📄 [A5CipherTest](src/test/java/com/thealgorithms/ciphers/a5/A5CipherTest.java)
+ - 📄 [A5KeyStreamGeneratorTest](src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java)
+ - 📄 [LFSRTest](src/test/java/com/thealgorithms/ciphers/a5/LFSRTest.java)
+ - 📁 **conversions**
+ - 📄 [AffineConverterTest](src/test/java/com/thealgorithms/conversions/AffineConverterTest.java)
+ - 📄 [AnyBaseToDecimalTest](src/test/java/com/thealgorithms/conversions/AnyBaseToDecimalTest.java)
+ - 📄 [AnytoAnyTest](src/test/java/com/thealgorithms/conversions/AnytoAnyTest.java)
+ - 📄 [BinaryToDecimalTest](src/test/java/com/thealgorithms/conversions/BinaryToDecimalTest.java)
+ - 📄 [BinaryToHexadecimalTest](src/test/java/com/thealgorithms/conversions/BinaryToHexadecimalTest.java)
+ - 📄 [BinaryToOctalTest](src/test/java/com/thealgorithms/conversions/BinaryToOctalTest.java)
+ - 📄 [DecimalToAnyBaseTest](src/test/java/com/thealgorithms/conversions/DecimalToAnyBaseTest.java)
+ - 📄 [DecimalToBinaryTest](src/test/java/com/thealgorithms/conversions/DecimalToBinaryTest.java)
+ - 📄 [DecimalToHexadecimalTest](src/test/java/com/thealgorithms/conversions/DecimalToHexadecimalTest.java)
+ - 📄 [DecimalToOctalTest](src/test/java/com/thealgorithms/conversions/DecimalToOctalTest.java)
+ - 📄 [EndianConverterTest](src/test/java/com/thealgorithms/conversions/EndianConverterTest.java)
+ - 📄 [HexToOctTest](src/test/java/com/thealgorithms/conversions/HexToOctTest.java)
+ - 📄 [HexaDecimalToBinaryTest](src/test/java/com/thealgorithms/conversions/HexaDecimalToBinaryTest.java)
+ - 📄 [HexaDecimalToDecimalTest](src/test/java/com/thealgorithms/conversions/HexaDecimalToDecimalTest.java)
+ - 📄 [IPConverterTest](src/test/java/com/thealgorithms/conversions/IPConverterTest.java)
+ - 📄 [IPv6ConverterTest](src/test/java/com/thealgorithms/conversions/IPv6ConverterTest.java)
+ - 📄 [IntegerToEnglishTest](src/test/java/com/thealgorithms/conversions/IntegerToEnglishTest.java)
+ - 📄 [IntegerToRomanTest](src/test/java/com/thealgorithms/conversions/IntegerToRomanTest.java)
+ - 📄 [MorseCodeConverterTest](src/test/java/com/thealgorithms/conversions/MorseCodeConverterTest.java)
+ - 📄 [NumberToWordsTest](src/test/java/com/thealgorithms/conversions/NumberToWordsTest.java)
+ - 📄 [OctalToBinaryTest](src/test/java/com/thealgorithms/conversions/OctalToBinaryTest.java)
+ - 📄 [OctalToDecimalTest](src/test/java/com/thealgorithms/conversions/OctalToDecimalTest.java)
+ - 📄 [OctalToHexadecimalTest](src/test/java/com/thealgorithms/conversions/OctalToHexadecimalTest.java)
+ - 📄 [PhoneticAlphabetConverterTest](src/test/java/com/thealgorithms/conversions/PhoneticAlphabetConverterTest.java)
+ - 📄 [RomanToIntegerTest](src/test/java/com/thealgorithms/conversions/RomanToIntegerTest.java)
+ - 📄 [TurkishToLatinConversionTest](src/test/java/com/thealgorithms/conversions/TurkishToLatinConversionTest.java)
+ - 📄 [UnitConversionsTest](src/test/java/com/thealgorithms/conversions/UnitConversionsTest.java)
+ - 📄 [UnitsConverterTest](src/test/java/com/thealgorithms/conversions/UnitsConverterTest.java)
+ - 📄 [WordsToNumberTest](src/test/java/com/thealgorithms/conversions/WordsToNumberTest.java)
+ - 📁 **datastructures**
+ - 📁 **bag**
+ - 📄 [BagTest](src/test/java/com/thealgorithms/datastructures/bag/BagTest.java)
+ - 📁 **bloomfilter**
+ - 📄 [BloomFilterTest](src/test/java/com/thealgorithms/datastructures/bloomfilter/BloomFilterTest.java)
+ - 📁 **buffers**
+ - 📄 [CircularBufferTest](src/test/java/com/thealgorithms/datastructures/buffers/CircularBufferTest.java)
+ - 📁 **caches**
+ - 📄 [FIFOCacheTest](src/test/java/com/thealgorithms/datastructures/caches/FIFOCacheTest.java)
+ - 📄 [LFUCacheTest](src/test/java/com/thealgorithms/datastructures/caches/LFUCacheTest.java)
+ - 📄 [LRUCacheTest](src/test/java/com/thealgorithms/datastructures/caches/LRUCacheTest.java)
+ - 📄 [MRUCacheTest](src/test/java/com/thealgorithms/datastructures/caches/MRUCacheTest.java)
+ - 📄 [RRCacheTest](src/test/java/com/thealgorithms/datastructures/caches/RRCacheTest.java)
+ - 📁 **crdt**
+ - 📄 [GCounterTest](src/test/java/com/thealgorithms/datastructures/crdt/GCounterTest.java)
+ - 📄 [GSetTest](src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java)
+ - 📄 [LWWElementSetTest](src/test/java/com/thealgorithms/datastructures/crdt/LWWElementSetTest.java)
+ - 📄 [ORSetTest](src/test/java/com/thealgorithms/datastructures/crdt/ORSetTest.java)
+ - 📄 [PNCounterTest](src/test/java/com/thealgorithms/datastructures/crdt/PNCounterTest.java)
+ - 📄 [TwoPSetTest](src/test/java/com/thealgorithms/datastructures/crdt/TwoPSetTest.java)
+ - 📁 **disjointsetunion**
+ - 📄 [DisjointSetUnionTest](src/test/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnionTest.java)
+ - 📁 **dynamicarray**
+ - 📄 [DynamicArrayTest](src/test/java/com/thealgorithms/datastructures/dynamicarray/DynamicArrayTest.java)
+ - 📁 **graphs**
+ - 📄 [AStarTest](src/test/java/com/thealgorithms/datastructures/graphs/AStarTest.java)
+ - 📄 [BipartiteGraphDFSTest](src/test/java/com/thealgorithms/datastructures/graphs/BipartiteGraphDFSTest.java)
+ - 📄 [BoruvkaAlgorithmTest](src/test/java/com/thealgorithms/datastructures/graphs/BoruvkaAlgorithmTest.java)
+ - 📄 [DijkstraAlgorithmTest](src/test/java/com/thealgorithms/datastructures/graphs/DijkstraAlgorithmTest.java)
+ - 📄 [DijkstraOptimizedAlgorithmTest](src/test/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithmTest.java)
+ - 📄 [EdmondsBlossomAlgorithmTest](src/test/java/com/thealgorithms/datastructures/graphs/EdmondsBlossomAlgorithmTest.java)
+ - 📄 [FloydWarshallTest](src/test/java/com/thealgorithms/datastructures/graphs/FloydWarshallTest.java)
+ - 📄 [FordFulkersonTest](src/test/java/com/thealgorithms/datastructures/graphs/FordFulkersonTest.java)
+ - 📄 [HamiltonianCycleTest](src/test/java/com/thealgorithms/datastructures/graphs/HamiltonianCycleTest.java)
+ - 📄 [JohnsonsAlgorithmTest](src/test/java/com/thealgorithms/datastructures/graphs/JohnsonsAlgorithmTest.java)
+ - 📄 [KahnsAlgorithmTest](src/test/java/com/thealgorithms/datastructures/graphs/KahnsAlgorithmTest.java)
+ - 📄 [KosarajuTest](src/test/java/com/thealgorithms/datastructures/graphs/KosarajuTest.java)
+ - 📄 [KruskalTest](src/test/java/com/thealgorithms/datastructures/graphs/KruskalTest.java)
+ - 📄 [MatrixGraphsTest](src/test/java/com/thealgorithms/datastructures/graphs/MatrixGraphsTest.java)
+ - 📄 [PrimMSTTest](src/test/java/com/thealgorithms/datastructures/graphs/PrimMSTTest.java)
+ - 📄 [TarjansAlgorithmTest](src/test/java/com/thealgorithms/datastructures/graphs/TarjansAlgorithmTest.java)
+ - 📄 [WelshPowellTest](src/test/java/com/thealgorithms/datastructures/graphs/WelshPowellTest.java)
+ - 📁 **hashmap**
+ - 📁 **hashing**
+ - 📄 [GenericHashMapUsingArrayListTest](src/test/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArrayListTest.java)
+ - 📄 [GenericHashMapUsingArrayTest](src/test/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArrayTest.java)
+ - 📄 [HashMapCuckooHashingTest](src/test/java/com/thealgorithms/datastructures/hashmap/hashing/HashMapCuckooHashingTest.java)
+ - 📄 [HashMapTest](src/test/java/com/thealgorithms/datastructures/hashmap/hashing/HashMapTest.java)
+ - 📄 [IntersectionTest](src/test/java/com/thealgorithms/datastructures/hashmap/hashing/IntersectionTest.java)
+ - 📄 [LinearProbingHashMapTest](src/test/java/com/thealgorithms/datastructures/hashmap/hashing/LinearProbingHashMapTest.java)
+ - 📄 [MajorityElementTest](src/test/java/com/thealgorithms/datastructures/hashmap/hashing/MajorityElementTest.java)
+ - 📄 [MapTest](src/test/java/com/thealgorithms/datastructures/hashmap/hashing/MapTest.java)
+ - 📁 **heaps**
+ - 📄 [FibonacciHeapTest](src/test/java/com/thealgorithms/datastructures/heaps/FibonacciHeapTest.java)
+ - 📄 [GenericHeapTest](src/test/java/com/thealgorithms/datastructures/heaps/GenericHeapTest.java)
+ - 📄 [HeapElementTest](src/test/java/com/thealgorithms/datastructures/heaps/HeapElementTest.java)
+ - 📄 [KthElementFinderTest](src/test/java/com/thealgorithms/datastructures/heaps/KthElementFinderTest.java)
+ - 📄 [LeftistHeapTest](src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java)
+ - 📄 [MaxHeapTest](src/test/java/com/thealgorithms/datastructures/heaps/MaxHeapTest.java)
+ - 📄 [MedianFinderTest](src/test/java/com/thealgorithms/datastructures/heaps/MedianFinderTest.java)
+ - 📄 [MergeKSortedArraysTest](src/test/java/com/thealgorithms/datastructures/heaps/MergeKSortedArraysTest.java)
+ - 📄 [MinHeapTest](src/test/java/com/thealgorithms/datastructures/heaps/MinHeapTest.java)
+ - 📄 [MinPriorityQueueTest](src/test/java/com/thealgorithms/datastructures/heaps/MinPriorityQueueTest.java)
+ - 📁 **lists**
+ - 📄 [CircleLinkedListTest](src/test/java/com/thealgorithms/datastructures/lists/CircleLinkedListTest.java)
+ - 📄 [CountSinglyLinkedListRecursionTest](src/test/java/com/thealgorithms/datastructures/lists/CountSinglyLinkedListRecursionTest.java)
+ - 📄 [CreateAndDetectLoopTest](src/test/java/com/thealgorithms/datastructures/lists/CreateAndDetectLoopTest.java)
+ - 📄 [CursorLinkedListTest](src/test/java/com/thealgorithms/datastructures/lists/CursorLinkedListTest.java)
+ - 📄 [MergeKSortedLinkedListTest](src/test/java/com/thealgorithms/datastructures/lists/MergeKSortedLinkedListTest.java)
+ - 📄 [MergeSortedArrayListTest](src/test/java/com/thealgorithms/datastructures/lists/MergeSortedArrayListTest.java)
+ - 📄 [MergeSortedSinglyLinkedListTest](src/test/java/com/thealgorithms/datastructures/lists/MergeSortedSinglyLinkedListTest.java)
+ - 📄 [QuickSortLinkedListTest](src/test/java/com/thealgorithms/datastructures/lists/QuickSortLinkedListTest.java)
+ - 📄 [ReverseKGroupTest](src/test/java/com/thealgorithms/datastructures/lists/ReverseKGroupTest.java)
+ - 📄 [RotateSinglyLinkedListsTest](src/test/java/com/thealgorithms/datastructures/lists/RotateSinglyLinkedListsTest.java)
+ - 📄 [SearchSinglyLinkedListRecursionTest](src/test/java/com/thealgorithms/datastructures/lists/SearchSinglyLinkedListRecursionTest.java)
+ - 📄 [SinglyLinkedListTest](src/test/java/com/thealgorithms/datastructures/lists/SinglyLinkedListTest.java)
+ - 📄 [SkipListTest](src/test/java/com/thealgorithms/datastructures/lists/SkipListTest.java)
+ - 📄 [SortedLinkedListTest](src/test/java/com/thealgorithms/datastructures/lists/SortedLinkedListTest.java)
+ - 📁 **queues**
+ - 📄 [CircularQueueTest](src/test/java/com/thealgorithms/datastructures/queues/CircularQueueTest.java)
+ - 📄 [DequeTest](src/test/java/com/thealgorithms/datastructures/queues/DequeTest.java)
+ - 📄 [GenericArrayListQueueTest](src/test/java/com/thealgorithms/datastructures/queues/GenericArrayListQueueTest.java)
+ - 📄 [LinkedQueueTest](src/test/java/com/thealgorithms/datastructures/queues/LinkedQueueTest.java)
+ - 📄 [PriorityQueuesTest](src/test/java/com/thealgorithms/datastructures/queues/PriorityQueuesTest.java)
+ - 📄 [QueueByTwoStacksTest](src/test/java/com/thealgorithms/datastructures/queues/QueueByTwoStacksTest.java)
+ - 📄 [QueueTest](src/test/java/com/thealgorithms/datastructures/queues/QueueTest.java)
+ - 📄 [SlidingWindowMaximumTest](src/test/java/com/thealgorithms/datastructures/queues/SlidingWindowMaximumTest.java)
+ - 📄 [TokenBucketTest](src/test/java/com/thealgorithms/datastructures/queues/TokenBucketTest.java)
+ - 📁 **stacks**
+ - 📄 [NodeStackTest](src/test/java/com/thealgorithms/datastructures/stacks/NodeStackTest.java)
+ - 📄 [ReverseStackTest](src/test/java/com/thealgorithms/datastructures/stacks/ReverseStackTest.java)
+ - 📄 [StackArrayListTest](src/test/java/com/thealgorithms/datastructures/stacks/StackArrayListTest.java)
+ - 📄 [StackArrayTest](src/test/java/com/thealgorithms/datastructures/stacks/StackArrayTest.java)
+ - 📄 [StackOfLinkedListTest](src/test/java/com/thealgorithms/datastructures/stacks/StackOfLinkedListTest.java)
+ - 📁 **trees**
+ - 📄 [AVLTreeTest](src/test/java/com/thealgorithms/datastructures/trees/AVLTreeTest.java)
+ - 📄 [BSTFromSortedArrayTest](src/test/java/com/thealgorithms/datastructures/trees/BSTFromSortedArrayTest.java)
+ - 📄 [BSTIterativeTest](src/test/java/com/thealgorithms/datastructures/trees/BSTIterativeTest.java)
+ - 📄 [BSTRecursiveTest](src/test/java/com/thealgorithms/datastructures/trees/BSTRecursiveTest.java)
+ - 📄 [BTreeTest](src/test/java/com/thealgorithms/datastructures/trees/BTreeTest.java)
+ - 📄 [BinaryTreeTest](src/test/java/com/thealgorithms/datastructures/trees/BinaryTreeTest.java)
+ - 📄 [BoundaryTraversalTest](src/test/java/com/thealgorithms/datastructures/trees/BoundaryTraversalTest.java)
+ - 📄 [CeilInBinarySearchTreeTest](src/test/java/com/thealgorithms/datastructures/trees/CeilInBinarySearchTreeTest.java)
+ - 📄 [CheckBinaryTreeIsValidBSTTest](src/test/java/com/thealgorithms/datastructures/trees/CheckBinaryTreeIsValidBSTTest.java)
+ - 📄 [CheckIfBinaryTreeBalancedTest](src/test/java/com/thealgorithms/datastructures/trees/CheckIfBinaryTreeBalancedTest.java)
+ - 📄 [CheckTreeIsSymmetricTest](src/test/java/com/thealgorithms/datastructures/trees/CheckTreeIsSymmetricTest.java)
+ - 📄 [CreateBinaryTreeFromInorderPreorderTest](src/test/java/com/thealgorithms/datastructures/trees/CreateBinaryTreeFromInorderPreorderTest.java)
+ - 📄 [InorderTraversalTest](src/test/java/com/thealgorithms/datastructures/trees/InorderTraversalTest.java)
+ - 📄 [KDTreeTest](src/test/java/com/thealgorithms/datastructures/trees/KDTreeTest.java)
+ - 📄 [LazySegmentTreeTest](src/test/java/com/thealgorithms/datastructures/trees/LazySegmentTreeTest.java)
+ - 📄 [LevelOrderTraversalTest](src/test/java/com/thealgorithms/datastructures/trees/LevelOrderTraversalTest.java)
+ - 📄 [PostOrderTraversalTest](src/test/java/com/thealgorithms/datastructures/trees/PostOrderTraversalTest.java)
+ - 📄 [PreOrderTraversalTest](src/test/java/com/thealgorithms/datastructures/trees/PreOrderTraversalTest.java)
+ - 📄 [QuadTreeTest](src/test/java/com/thealgorithms/datastructures/trees/QuadTreeTest.java)
+ - 📄 [SameTreesCheckTest](src/test/java/com/thealgorithms/datastructures/trees/SameTreesCheckTest.java)
+ - 📄 [SplayTreeTest](src/test/java/com/thealgorithms/datastructures/trees/SplayTreeTest.java)
+ - 📄 [TreapTest](src/test/java/com/thealgorithms/datastructures/trees/TreapTest.java)
+ - 📄 [TreeTestUtils](src/test/java/com/thealgorithms/datastructures/trees/TreeTestUtils.java)
+ - 📄 [TrieTest](src/test/java/com/thealgorithms/datastructures/trees/TrieTest.java)
+ - 📄 [VerticalOrderTraversalTest](src/test/java/com/thealgorithms/datastructures/trees/VerticalOrderTraversalTest.java)
+ - 📄 [ZigzagTraversalTest](src/test/java/com/thealgorithms/datastructures/trees/ZigzagTraversalTest.java)
+ - 📁 **divideandconquer**
+ - 📄 [BinaryExponentiationTest](src/test/java/com/thealgorithms/divideandconquer/BinaryExponentiationTest.java)
+ - 📄 [ClosestPairTest](src/test/java/com/thealgorithms/divideandconquer/ClosestPairTest.java)
+ - 📄 [CountingInversionsTest](src/test/java/com/thealgorithms/divideandconquer/CountingInversionsTest.java)
+ - 📄 [MedianOfTwoSortedArraysTest](src/test/java/com/thealgorithms/divideandconquer/MedianOfTwoSortedArraysTest.java)
+ - 📄 [SkylineAlgorithmTest](src/test/java/com/thealgorithms/divideandconquer/SkylineAlgorithmTest.java)
+ - 📄 [StrassenMatrixMultiplicationTest](src/test/java/com/thealgorithms/divideandconquer/StrassenMatrixMultiplicationTest.java)
+ - 📄 [TilingProblemTest](src/test/java/com/thealgorithms/divideandconquer/TilingProblemTest.java)
+ - 📁 **dynamicprogramming**
+ - 📄 [AbbreviationTest](src/test/java/com/thealgorithms/dynamicprogramming/AbbreviationTest.java)
+ - 📄 [AllConstructTest](src/test/java/com/thealgorithms/dynamicprogramming/AllConstructTest.java)
+ - 📄 [AssignmentUsingBitmaskTest](src/test/java/com/thealgorithms/dynamicprogramming/AssignmentUsingBitmaskTest.java)
+ - 📄 [BoardPathTest](src/test/java/com/thealgorithms/dynamicprogramming/BoardPathTest.java)
+ - 📄 [BoundaryFillTest](src/test/java/com/thealgorithms/dynamicprogramming/BoundaryFillTest.java)
+ - 📄 [BruteForceKnapsackTest](src/test/java/com/thealgorithms/dynamicprogramming/BruteForceKnapsackTest.java)
+ - 📄 [CatalanNumberTest](src/test/java/com/thealgorithms/dynamicprogramming/CatalanNumberTest.java)
+ - 📄 [ClimbStairsTest](src/test/java/com/thealgorithms/dynamicprogramming/ClimbStairsTest.java)
+ - 📄 [CoinChangeTest](src/test/java/com/thealgorithms/dynamicprogramming/CoinChangeTest.java)
+ - 📄 [CountFriendsPairingTest](src/test/java/com/thealgorithms/dynamicprogramming/CountFriendsPairingTest.java)
+ - 📄 [DPTest](src/test/java/com/thealgorithms/dynamicprogramming/DPTest.java)
+ - 📄 [EditDistanceTest](src/test/java/com/thealgorithms/dynamicprogramming/EditDistanceTest.java)
+ - 📄 [EggDroppingTest](src/test/java/com/thealgorithms/dynamicprogramming/EggDroppingTest.java)
+ - 📄 [FibonacciTest](src/test/java/com/thealgorithms/dynamicprogramming/FibonacciTest.java)
+ - 📄 [KadaneAlgorithmTest](src/test/java/com/thealgorithms/dynamicprogramming/KadaneAlgorithmTest.java)
+ - 📄 [KnapsackMemoizationTest](src/test/java/com/thealgorithms/dynamicprogramming/KnapsackMemoizationTest.java)
+ - 📄 [KnapsackTest](src/test/java/com/thealgorithms/dynamicprogramming/KnapsackTest.java)
+ - 📄 [LevenshteinDistanceTests](src/test/java/com/thealgorithms/dynamicprogramming/LevenshteinDistanceTests.java)
+ - 📄 [LongestAlternatingSubsequenceTest](src/test/java/com/thealgorithms/dynamicprogramming/LongestAlternatingSubsequenceTest.java)
+ - 📄 [LongestArithmeticSubsequenceTest](src/test/java/com/thealgorithms/dynamicprogramming/LongestArithmeticSubsequenceTest.java)
+ - 📄 [LongestCommonSubsequenceTest](src/test/java/com/thealgorithms/dynamicprogramming/LongestCommonSubsequenceTest.java)
+ - 📄 [LongestIncreasingSubsequenceNLogNTest](src/test/java/com/thealgorithms/dynamicprogramming/LongestIncreasingSubsequenceNLogNTest.java)
+ - 📄 [LongestIncreasingSubsequenceTests](src/test/java/com/thealgorithms/dynamicprogramming/LongestIncreasingSubsequenceTests.java)
+ - 📄 [LongestPalindromicSubstringTest](src/test/java/com/thealgorithms/dynamicprogramming/LongestPalindromicSubstringTest.java)
+ - 📄 [LongestValidParenthesesTest](src/test/java/com/thealgorithms/dynamicprogramming/LongestValidParenthesesTest.java)
+ - 📄 [MatrixChainMultiplicationTest](src/test/java/com/thealgorithms/dynamicprogramming/MatrixChainMultiplicationTest.java)
+ - 📄 [MatrixChainRecursiveTopDownMemoisationTest](src/test/java/com/thealgorithms/dynamicprogramming/MatrixChainRecursiveTopDownMemoisationTest.java)
+ - 📄 [MaximumSumOfNonAdjacentElementsTest](src/test/java/com/thealgorithms/dynamicprogramming/MaximumSumOfNonAdjacentElementsTest.java)
+ - 📄 [MinimumPathSumTest](src/test/java/com/thealgorithms/dynamicprogramming/MinimumPathSumTest.java)
+ - 📄 [MinimumSumPartitionTest](src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java)
+ - 📄 [NewManShanksPrimeTest](src/test/java/com/thealgorithms/dynamicprogramming/NewManShanksPrimeTest.java)
+ - 📄 [OptimalJobSchedulingTest](src/test/java/com/thealgorithms/dynamicprogramming/OptimalJobSchedulingTest.java)
+ - 📄 [PalindromicPartitioningTest](src/test/java/com/thealgorithms/dynamicprogramming/PalindromicPartitioningTest.java)
+ - 📄 [PartitionProblemTest](src/test/java/com/thealgorithms/dynamicprogramming/PartitionProblemTest.java)
+ - 📄 [RegexMatchingTest](src/test/java/com/thealgorithms/dynamicprogramming/RegexMatchingTest.java)
+ - 📄 [RodCuttingTest](src/test/java/com/thealgorithms/dynamicprogramming/RodCuttingTest.java)
+ - 📄 [ShortestCommonSupersequenceLengthTest](src/test/java/com/thealgorithms/dynamicprogramming/ShortestCommonSupersequenceLengthTest.java)
+ - 📄 [SubsetCountTest](src/test/java/com/thealgorithms/dynamicprogramming/SubsetCountTest.java)
+ - 📄 [SubsetSumSpaceOptimizedTest](src/test/java/com/thealgorithms/dynamicprogramming/SubsetSumSpaceOptimizedTest.java)
+ - 📄 [SubsetSumTest](src/test/java/com/thealgorithms/dynamicprogramming/SubsetSumTest.java)
+ - 📄 [SumOfSubsetTest](src/test/java/com/thealgorithms/dynamicprogramming/SumOfSubsetTest.java)
+ - 📄 [TreeMatchingTest](src/test/java/com/thealgorithms/dynamicprogramming/TreeMatchingTest.java)
+ - 📄 [TribonacciTest](src/test/java/com/thealgorithms/dynamicprogramming/TribonacciTest.java)
+ - 📄 [UniquePathsTests](src/test/java/com/thealgorithms/dynamicprogramming/UniquePathsTests.java)
+ - 📄 [UniqueSubsequencesCountTest](src/test/java/com/thealgorithms/dynamicprogramming/UniqueSubsequencesCountTest.java)
+ - 📄 [WildcardMatchingTest](src/test/java/com/thealgorithms/dynamicprogramming/WildcardMatchingTest.java)
+ - 📄 [WineProblemTest](src/test/java/com/thealgorithms/dynamicprogramming/WineProblemTest.java)
+ - 📁 **geometry**
+ - 📄 [BresenhamLineTest](src/test/java/com/thealgorithms/geometry/BresenhamLineTest.java)
+ - 📄 [ConvexHullTest](src/test/java/com/thealgorithms/geometry/ConvexHullTest.java)
+ - 📄 [GrahamScanTest](src/test/java/com/thealgorithms/geometry/GrahamScanTest.java)
+ - 📄 [MidpointCircleTest](src/test/java/com/thealgorithms/geometry/MidpointCircleTest.java)
+ - 📄 [MidpointEllipseTest](src/test/java/com/thealgorithms/geometry/MidpointEllipseTest.java)
+ - 📁 **graph**
+ - 📄 [ConstrainedShortestPathTest](src/test/java/com/thealgorithms/graph/ConstrainedShortestPathTest.java)
+ - 📄 [StronglyConnectedComponentOptimizedTest](src/test/java/com/thealgorithms/graph/StronglyConnectedComponentOptimizedTest.java)
+ - 📄 [TravelingSalesmanTest](src/test/java/com/thealgorithms/graph/TravelingSalesmanTest.java)
+ - 📁 **greedyalgorithms**
+ - 📄 [ActivitySelectionTest](src/test/java/com/thealgorithms/greedyalgorithms/ActivitySelectionTest.java)
+ - 📄 [BandwidthAllocationTest](src/test/java/com/thealgorithms/greedyalgorithms/BandwidthAllocationTest.java)
+ - 📄 [BinaryAdditionTest](src/test/java/com/thealgorithms/greedyalgorithms/BinaryAdditionTest.java)
+ - 📄 [CoinChangeTest](src/test/java/com/thealgorithms/greedyalgorithms/CoinChangeTest.java)
+ - 📄 [DigitSeparationTest](src/test/java/com/thealgorithms/greedyalgorithms/DigitSeparationTest.java)
+ - 📄 [EgyptianFractionTest](src/test/java/com/thealgorithms/greedyalgorithms/EgyptianFractionTest.java)
+ - 📄 [FractionalKnapsackTest](src/test/java/com/thealgorithms/greedyalgorithms/FractionalKnapsackTest.java)
+ - 📄 [GaleShapleyTest](src/test/java/com/thealgorithms/greedyalgorithms/GaleShapleyTest.java)
+ - 📄 [JobSequencingTest](src/test/java/com/thealgorithms/greedyalgorithms/JobSequencingTest.java)
+ - 📄 [KCentersTest](src/test/java/com/thealgorithms/greedyalgorithms/KCentersTest.java)
+ - 📄 [MergeIntervalsTest](src/test/java/com/thealgorithms/greedyalgorithms/MergeIntervalsTest.java)
+ - 📄 [MinimizingLatenessTest](src/test/java/com/thealgorithms/greedyalgorithms/MinimizingLatenessTest.java)
+ - 📄 [MinimumWaitingTimeTest](src/test/java/com/thealgorithms/greedyalgorithms/MinimumWaitingTimeTest.java)
+ - 📄 [OptimalFileMergingTest](src/test/java/com/thealgorithms/greedyalgorithms/OptimalFileMergingTest.java)
+ - 📄 [StockProfitCalculatorTest](src/test/java/com/thealgorithms/greedyalgorithms/StockProfitCalculatorTest.java)
+ - 📁 **io**
+ - 📄 [BufferedReaderTest](src/test/java/com/thealgorithms/io/BufferedReaderTest.java)
+ - 📁 **lineclipping**
+ - 📄 [CohenSutherlandTest](src/test/java/com/thealgorithms/lineclipping/CohenSutherlandTest.java)
+ - 📄 [LiangBarskyTest](src/test/java/com/thealgorithms/lineclipping/LiangBarskyTest.java)
+ - 📁 **maths**
+ - 📄 [ADTFractionTest](src/test/java/com/thealgorithms/maths/ADTFractionTest.java)
+ - 📄 [AbsoluteMaxTest](src/test/java/com/thealgorithms/maths/AbsoluteMaxTest.java)
+ - 📄 [AbsoluteMinTest](src/test/java/com/thealgorithms/maths/AbsoluteMinTest.java)
+ - 📄 [AbsoluteValueTest](src/test/java/com/thealgorithms/maths/AbsoluteValueTest.java)
+ - 📄 [AliquotSumTest](src/test/java/com/thealgorithms/maths/AliquotSumTest.java)
+ - 📄 [AmicableNumberTest](src/test/java/com/thealgorithms/maths/AmicableNumberTest.java)
+ - 📄 [AreaTest](src/test/java/com/thealgorithms/maths/AreaTest.java)
+ - 📄 [ArmstrongTest](src/test/java/com/thealgorithms/maths/ArmstrongTest.java)
+ - 📄 [AutoCorrelationTest](src/test/java/com/thealgorithms/maths/AutoCorrelationTest.java)
+ - 📄 [AutomorphicNumberTest](src/test/java/com/thealgorithms/maths/AutomorphicNumberTest.java)
+ - 📄 [AverageTest](src/test/java/com/thealgorithms/maths/AverageTest.java)
+ - 📄 [BinaryPowTest](src/test/java/com/thealgorithms/maths/BinaryPowTest.java)
+ - 📄 [BinomialCoefficientTest](src/test/java/com/thealgorithms/maths/BinomialCoefficientTest.java)
+ - 📄 [CatalanNumbersTest](src/test/java/com/thealgorithms/maths/CatalanNumbersTest.java)
+ - 📄 [CeilTest](src/test/java/com/thealgorithms/maths/CeilTest.java)
+ - 📄 [ChineseRemainderTheoremTest](src/test/java/com/thealgorithms/maths/ChineseRemainderTheoremTest.java)
+ - 📄 [CollatzConjectureTest](src/test/java/com/thealgorithms/maths/CollatzConjectureTest.java)
+ - 📄 [CombinationsTest](src/test/java/com/thealgorithms/maths/CombinationsTest.java)
+ - 📄 [ConvolutionFFTTest](src/test/java/com/thealgorithms/maths/ConvolutionFFTTest.java)
+ - 📄 [ConvolutionTest](src/test/java/com/thealgorithms/maths/ConvolutionTest.java)
+ - 📄 [CrossCorrelationTest](src/test/java/com/thealgorithms/maths/CrossCorrelationTest.java)
+ - 📄 [DeterminantOfMatrixTest](src/test/java/com/thealgorithms/maths/DeterminantOfMatrixTest.java)
+ - 📄 [DigitalRootTest](src/test/java/com/thealgorithms/maths/DigitalRootTest.java)
+ - 📄 [DistanceFormulaTest](src/test/java/com/thealgorithms/maths/DistanceFormulaTest.java)
+ - 📄 [DudeneyNumberTest](src/test/java/com/thealgorithms/maths/DudeneyNumberTest.java)
+ - 📄 [EulerMethodTest](src/test/java/com/thealgorithms/maths/EulerMethodTest.java)
+ - 📄 [EulersFunctionTest](src/test/java/com/thealgorithms/maths/EulersFunctionTest.java)
+ - 📄 [FFTTest](src/test/java/com/thealgorithms/maths/FFTTest.java)
+ - 📄 [FactorialRecursionTest](src/test/java/com/thealgorithms/maths/FactorialRecursionTest.java)
+ - 📄 [FactorialTest](src/test/java/com/thealgorithms/maths/FactorialTest.java)
+ - 📄 [FastExponentiationTest](src/test/java/com/thealgorithms/maths/FastExponentiationTest.java)
+ - 📄 [FastInverseSqrtTests](src/test/java/com/thealgorithms/maths/FastInverseSqrtTests.java)
+ - 📄 [FibonacciJavaStreamsTest](src/test/java/com/thealgorithms/maths/FibonacciJavaStreamsTest.java)
+ - 📄 [FibonacciLoopTest](src/test/java/com/thealgorithms/maths/FibonacciLoopTest.java)
+ - 📄 [FibonacciNumberCheckTest](src/test/java/com/thealgorithms/maths/FibonacciNumberCheckTest.java)
+ - 📄 [FibonacciNumberGoldenRationTest](src/test/java/com/thealgorithms/maths/FibonacciNumberGoldenRationTest.java)
+ - 📄 [FindKthNumberTest](src/test/java/com/thealgorithms/maths/FindKthNumberTest.java)
+ - 📄 [FindMaxRecursionTest](src/test/java/com/thealgorithms/maths/FindMaxRecursionTest.java)
+ - 📄 [FindMaxTest](src/test/java/com/thealgorithms/maths/FindMaxTest.java)
+ - 📄 [FindMinRecursionTest](src/test/java/com/thealgorithms/maths/FindMinRecursionTest.java)
+ - 📄 [FindMinTest](src/test/java/com/thealgorithms/maths/FindMinTest.java)
+ - 📄 [FloorTest](src/test/java/com/thealgorithms/maths/FloorTest.java)
+ - 📄 [FrizzyNumberTest](src/test/java/com/thealgorithms/maths/FrizzyNumberTest.java)
+ - 📄 [GCDRecursionTest](src/test/java/com/thealgorithms/maths/GCDRecursionTest.java)
+ - 📄 [GCDTest](src/test/java/com/thealgorithms/maths/GCDTest.java)
+ - 📄 [GaussianTest](src/test/java/com/thealgorithms/maths/GaussianTest.java)
+ - 📄 [GenericRootTest](src/test/java/com/thealgorithms/maths/GenericRootTest.java)
+ - 📄 [GoldbachConjectureTest](src/test/java/com/thealgorithms/maths/GoldbachConjectureTest.java)
+ - 📄 [HarshadNumberTest](src/test/java/com/thealgorithms/maths/HarshadNumberTest.java)
+ - 📄 [HeronsFormulaTest](src/test/java/com/thealgorithms/maths/HeronsFormulaTest.java)
+ - 📄 [JosephusProblemTest](src/test/java/com/thealgorithms/maths/JosephusProblemTest.java)
+ - 📄 [KaprekarNumbersTest](src/test/java/com/thealgorithms/maths/KaprekarNumbersTest.java)
+ - 📄 [KaratsubaMultiplicationTest](src/test/java/com/thealgorithms/maths/KaratsubaMultiplicationTest.java)
+ - 📄 [KrishnamurthyNumberTest](src/test/java/com/thealgorithms/maths/KrishnamurthyNumberTest.java)
+ - 📄 [LeastCommonMultipleTest](src/test/java/com/thealgorithms/maths/LeastCommonMultipleTest.java)
+ - 📄 [LeonardoNumberTest](src/test/java/com/thealgorithms/maths/LeonardoNumberTest.java)
+ - 📄 [LongDivisionTest](src/test/java/com/thealgorithms/maths/LongDivisionTest.java)
+ - 📄 [LucasSeriesTest](src/test/java/com/thealgorithms/maths/LucasSeriesTest.java)
+ - 📄 [MathBuilderTest](src/test/java/com/thealgorithms/maths/MathBuilderTest.java)
+ - 📄 [MaxValueTest](src/test/java/com/thealgorithms/maths/MaxValueTest.java)
+ - 📄 [MeansTest](src/test/java/com/thealgorithms/maths/MeansTest.java)
+ - 📄 [MedianTest](src/test/java/com/thealgorithms/maths/MedianTest.java)
+ - 📄 [MinValueTest](src/test/java/com/thealgorithms/maths/MinValueTest.java)
+ - 📄 [ModeTest](src/test/java/com/thealgorithms/maths/ModeTest.java)
+ - 📄 [NonRepeatingElementTest](src/test/java/com/thealgorithms/maths/NonRepeatingElementTest.java)
+ - 📄 [NthUglyNumberTest](src/test/java/com/thealgorithms/maths/NthUglyNumberTest.java)
+ - 📄 [NumberOfDigitsTest](src/test/java/com/thealgorithms/maths/NumberOfDigitsTest.java)
+ - 📄 [PalindromeNumberTest](src/test/java/com/thealgorithms/maths/PalindromeNumberTest.java)
+ - 📄 [ParseIntegerTest](src/test/java/com/thealgorithms/maths/ParseIntegerTest.java)
+ - 📄 [PascalTriangleTest](src/test/java/com/thealgorithms/maths/PascalTriangleTest.java)
+ - 📄 [PerfectCubeTest](src/test/java/com/thealgorithms/maths/PerfectCubeTest.java)
+ - 📄 [PerfectNumberTest](src/test/java/com/thealgorithms/maths/PerfectNumberTest.java)
+ - 📄 [PerfectSquareTest](src/test/java/com/thealgorithms/maths/PerfectSquareTest.java)
+ - 📄 [PerimeterTest](src/test/java/com/thealgorithms/maths/PerimeterTest.java)
+ - 📄 [PollardRhoTest](src/test/java/com/thealgorithms/maths/PollardRhoTest.java)
+ - 📄 [PowTest](src/test/java/com/thealgorithms/maths/PowTest.java)
+ - 📄 [PowerOfTwoOrNotTest](src/test/java/com/thealgorithms/maths/PowerOfTwoOrNotTest.java)
+ - 📄 [PowerUsingRecursionTest](src/test/java/com/thealgorithms/maths/PowerUsingRecursionTest.java)
+ - 📄 [PronicNumberTest](src/test/java/com/thealgorithms/maths/PronicNumberTest.java)
+ - 📄 [PythagoreanTripleTest](src/test/java/com/thealgorithms/maths/PythagoreanTripleTest.java)
+ - 📄 [QuadraticEquationSolverTest](src/test/java/com/thealgorithms/maths/QuadraticEquationSolverTest.java)
+ - 📄 [ReverseNumberTest](src/test/java/com/thealgorithms/maths/ReverseNumberTest.java)
+ - 📄 [SecondMinMaxTest](src/test/java/com/thealgorithms/maths/SecondMinMaxTest.java)
+ - 📄 [SieveOfEratosthenesTest](src/test/java/com/thealgorithms/maths/SieveOfEratosthenesTest.java)
+ - 📄 [SolovayStrassenPrimalityTestTest](src/test/java/com/thealgorithms/maths/SolovayStrassenPrimalityTestTest.java)
+ - 📄 [SquareFreeIntegerTest](src/test/java/com/thealgorithms/maths/SquareFreeIntegerTest.java)
+ - 📄 [SquareRootWithNewtonRaphsonTestMethod](src/test/java/com/thealgorithms/maths/SquareRootWithNewtonRaphsonTestMethod.java)
+ - 📄 [SquareRootwithBabylonianMethodTest](src/test/java/com/thealgorithms/maths/SquareRootwithBabylonianMethodTest.java)
+ - 📄 [StandardDeviationTest](src/test/java/com/thealgorithms/maths/StandardDeviationTest.java)
+ - 📄 [StandardScoreTest](src/test/java/com/thealgorithms/maths/StandardScoreTest.java)
+ - 📄 [StrobogrammaticNumberTest](src/test/java/com/thealgorithms/maths/StrobogrammaticNumberTest.java)
+ - 📄 [SumOfArithmeticSeriesTest](src/test/java/com/thealgorithms/maths/SumOfArithmeticSeriesTest.java)
+ - 📄 [SumOfDigitsTest](src/test/java/com/thealgorithms/maths/SumOfDigitsTest.java)
+ - 📄 [SumOfOddNumbersTest](src/test/java/com/thealgorithms/maths/SumOfOddNumbersTest.java)
+ - 📄 [SumWithoutArithmeticOperatorsTest](src/test/java/com/thealgorithms/maths/SumWithoutArithmeticOperatorsTest.java)
+ - 📄 [TestArmstrong](src/test/java/com/thealgorithms/maths/TestArmstrong.java)
+ - 📄 [TwinPrimeTest](src/test/java/com/thealgorithms/maths/TwinPrimeTest.java)
+ - 📄 [UniformNumbersTest](src/test/java/com/thealgorithms/maths/UniformNumbersTest.java)
+ - 📄 [VampireNumberTest](src/test/java/com/thealgorithms/maths/VampireNumberTest.java)
+ - 📄 [VolumeTest](src/test/java/com/thealgorithms/maths/VolumeTest.java)
+ - 📁 **prime**
+ - 📄 [LiouvilleLambdaFunctionTest](src/test/java/com/thealgorithms/maths/prime/LiouvilleLambdaFunctionTest.java)
+ - 📄 [MillerRabinPrimalityCheckTest](src/test/java/com/thealgorithms/maths/prime/MillerRabinPrimalityCheckTest.java)
+ - 📄 [MobiusFunctionTest](src/test/java/com/thealgorithms/maths/prime/MobiusFunctionTest.java)
+ - 📄 [PrimeCheckTest](src/test/java/com/thealgorithms/maths/prime/PrimeCheckTest.java)
+ - 📄 [PrimeFactorizationTest](src/test/java/com/thealgorithms/maths/prime/PrimeFactorizationTest.java)
+ - 📁 **matrix**
+ - 📄 [InverseOfMatrixTest](src/test/java/com/thealgorithms/matrix/InverseOfMatrixTest.java)
+ - 📄 [MatrixRankTest](src/test/java/com/thealgorithms/matrix/MatrixRankTest.java)
+ - 📄 [MatrixTransposeTest](src/test/java/com/thealgorithms/matrix/MatrixTransposeTest.java)
+ - 📄 [MatrixUtilTest](src/test/java/com/thealgorithms/matrix/MatrixUtilTest.java)
+ - 📄 [MedianOfMatrixTest](src/test/java/com/thealgorithms/matrix/MedianOfMatrixTest.java)
+ - 📄 [MirrorOfMatrixTest](src/test/java/com/thealgorithms/matrix/MirrorOfMatrixTest.java)
+ - 📄 [SolveSystemTest](src/test/java/com/thealgorithms/matrix/SolveSystemTest.java)
+ - 📄 [TestPrintMatrixInSpiralOrder](src/test/java/com/thealgorithms/matrix/TestPrintMatrixInSpiralOrder.java)
+ - 📁 **misc**
+ - 📄 [ColorContrastRatioTest](src/test/java/com/thealgorithms/misc/ColorContrastRatioTest.java)
+ - 📄 [MapReduceTest](src/test/java/com/thealgorithms/misc/MapReduceTest.java)
+ - 📄 [MedianOfRunningArrayTest](src/test/java/com/thealgorithms/misc/MedianOfRunningArrayTest.java)
+ - 📄 [PalindromePrimeTest](src/test/java/com/thealgorithms/misc/PalindromePrimeTest.java)
+ - 📄 [PalindromeSinglyLinkedListTest](src/test/java/com/thealgorithms/misc/PalindromeSinglyLinkedListTest.java)
+ - 📄 [RangeInSortedArrayTest](src/test/java/com/thealgorithms/misc/RangeInSortedArrayTest.java)
+ - 📄 [ShuffleArrayTest](src/test/java/com/thealgorithms/misc/ShuffleArrayTest.java)
+ - 📄 [SparsityTest](src/test/java/com/thealgorithms/misc/SparsityTest.java)
+ - 📄 [ThreeSumProblemTest](src/test/java/com/thealgorithms/misc/ThreeSumProblemTest.java)
+ - 📄 [TwoSumProblemTest](src/test/java/com/thealgorithms/misc/TwoSumProblemTest.java)
+ - 📁 **others**
+ - 📄 [ArrayLeftRotationTest](src/test/java/com/thealgorithms/others/ArrayLeftRotationTest.java)
+ - 📄 [ArrayRightRotationTest](src/test/java/com/thealgorithms/others/ArrayRightRotationTest.java)
+ - 📄 [BFPRTTest](src/test/java/com/thealgorithms/others/BFPRTTest.java)
+ - 📄 [BestFitCPUTest](src/test/java/com/thealgorithms/others/BestFitCPUTest.java)
+ - 📄 [BoyerMooreTest](src/test/java/com/thealgorithms/others/BoyerMooreTest.java)
+ - 📄 [CRC16Test](src/test/java/com/thealgorithms/others/CRC16Test.java)
+ - 📄 [CRCAlgorithmTest](src/test/java/com/thealgorithms/others/CRCAlgorithmTest.java)
+ - 📄 [ConwayTest](src/test/java/com/thealgorithms/others/ConwayTest.java)
+ - 📄 [CountFriendsPairingTest](src/test/java/com/thealgorithms/others/CountFriendsPairingTest.java)
+ - 📄 [FirstFitCPUTest](src/test/java/com/thealgorithms/others/FirstFitCPUTest.java)
+ - 📄 [FloydTriangleTest](src/test/java/com/thealgorithms/others/FloydTriangleTest.java)
+ - 📄 [KadaneAlogrithmTest](src/test/java/com/thealgorithms/others/KadaneAlogrithmTest.java)
+ - 📄 [LineSweepTest](src/test/java/com/thealgorithms/others/LineSweepTest.java)
+ - 📄 [LinkListSortTest](src/test/java/com/thealgorithms/others/LinkListSortTest.java)
+ - 📄 [LowestBasePalindromeTest](src/test/java/com/thealgorithms/others/LowestBasePalindromeTest.java)
+ - 📄 [MaximumSlidingWindowTest](src/test/java/com/thealgorithms/others/MaximumSlidingWindowTest.java)
+ - 📄 [MaximumSumOfDistinctSubarraysWithLengthKTest](src/test/java/com/thealgorithms/others/MaximumSumOfDistinctSubarraysWithLengthKTest.java)
+ - 📄 [NewManShanksPrimeTest](src/test/java/com/thealgorithms/others/NewManShanksPrimeTest.java)
+ - 📄 [NextFitTest](src/test/java/com/thealgorithms/others/NextFitTest.java)
+ - 📄 [PasswordGenTest](src/test/java/com/thealgorithms/others/PasswordGenTest.java)
+ - 📄 [QueueUsingTwoStacksTest](src/test/java/com/thealgorithms/others/QueueUsingTwoStacksTest.java)
+ - 📄 [RemoveDuplicateFromStringTest](src/test/java/com/thealgorithms/others/RemoveDuplicateFromStringTest.java)
+ - 📄 [ReverseStackUsingRecursionTest](src/test/java/com/thealgorithms/others/ReverseStackUsingRecursionTest.java)
+ - 📄 [SkylineProblemTest](src/test/java/com/thealgorithms/others/SkylineProblemTest.java)
+ - 📄 [TestPrintMatrixInSpiralOrder](src/test/java/com/thealgorithms/others/TestPrintMatrixInSpiralOrder.java)
+ - 📄 [TwoPointersTest](src/test/java/com/thealgorithms/others/TwoPointersTest.java)
+ - 📄 [WorstFitCPUTest](src/test/java/com/thealgorithms/others/WorstFitCPUTest.java)
+ - 📁 **cn**
+ - 📄 [HammingDistanceTest](src/test/java/com/thealgorithms/others/cn/HammingDistanceTest.java)
+ - 📁 **puzzlesandgames**
+ - 📄 [SudokuTest](src/test/java/com/thealgorithms/puzzlesandgames/SudokuTest.java)
+ - 📄 [TowerOfHanoiTest](src/test/java/com/thealgorithms/puzzlesandgames/TowerOfHanoiTest.java)
+ - 📄 [WordBoggleTest](src/test/java/com/thealgorithms/puzzlesandgames/WordBoggleTest.java)
+ - 📁 **randomized**
+ - 📄 [KargerMinCutTest](src/test/java/com/thealgorithms/randomized/KargerMinCutTest.java)
+ - 📄 [MonteCarloIntegrationTest](src/test/java/com/thealgorithms/randomized/MonteCarloIntegrationTest.java)
+ - 📄 [RandomizedClosestPairTest](src/test/java/com/thealgorithms/randomized/RandomizedClosestPairTest.java)
+ - 📄 [RandomizedMatrixMultiplicationVerificationTest](src/test/java/com/thealgorithms/randomized/RandomizedMatrixMultiplicationVerificationTest.java)
+ - 📄 [RandomizedQuickSortTest](src/test/java/com/thealgorithms/randomized/RandomizedQuickSortTest.java)
+ - 📄 [ReservoirSamplingTest](src/test/java/com/thealgorithms/randomized/ReservoirSamplingTest.java)
+ - 📁 **recursion**
+ - 📄 [FibonacciSeriesTest](src/test/java/com/thealgorithms/recursion/FibonacciSeriesTest.java)
+ - 📄 [GenerateSubsetsTest](src/test/java/com/thealgorithms/recursion/GenerateSubsetsTest.java)
+ - 📁 **scheduling**
+ - 📄 [AgingSchedulingTest](src/test/java/com/thealgorithms/scheduling/AgingSchedulingTest.java)
+ - 📄 [EDFSchedulingTest](src/test/java/com/thealgorithms/scheduling/EDFSchedulingTest.java)
+ - 📄 [FCFSSchedulingTest](src/test/java/com/thealgorithms/scheduling/FCFSSchedulingTest.java)
+ - 📄 [FairShareSchedulingTest](src/test/java/com/thealgorithms/scheduling/FairShareSchedulingTest.java)
+ - 📄 [GangSchedulingTest](src/test/java/com/thealgorithms/scheduling/GangSchedulingTest.java)
+ - 📄 [HighestResponseRatioNextSchedulingTest](src/test/java/com/thealgorithms/scheduling/HighestResponseRatioNextSchedulingTest.java)
+ - 📄 [JobSchedulingWithDeadlineTest](src/test/java/com/thealgorithms/scheduling/JobSchedulingWithDeadlineTest.java)
+ - 📄 [LotterySchedulingTest](src/test/java/com/thealgorithms/scheduling/LotterySchedulingTest.java)
+ - 📄 [MLFQSchedulerTest](src/test/java/com/thealgorithms/scheduling/MLFQSchedulerTest.java)
+ - 📄 [MultiAgentSchedulingTest](src/test/java/com/thealgorithms/scheduling/MultiAgentSchedulingTest.java)
+ - 📄 [NonPreemptivePrioritySchedulingTest](src/test/java/com/thealgorithms/scheduling/NonPreemptivePrioritySchedulingTest.java)
+ - 📄 [PreemptivePrioritySchedulingTest](src/test/java/com/thealgorithms/scheduling/PreemptivePrioritySchedulingTest.java)
+ - 📄 [ProportionalFairSchedulingTest](src/test/java/com/thealgorithms/scheduling/ProportionalFairSchedulingTest.java)
+ - 📄 [RRSchedulingTest](src/test/java/com/thealgorithms/scheduling/RRSchedulingTest.java)
+ - 📄 [RandomSchedulingTest](src/test/java/com/thealgorithms/scheduling/RandomSchedulingTest.java)
+ - 📄 [SJFSchedulingTest](src/test/java/com/thealgorithms/scheduling/SJFSchedulingTest.java)
+ - 📄 [SRTFSchedulingTest](src/test/java/com/thealgorithms/scheduling/SRTFSchedulingTest.java)
+ - 📄 [SelfAdjustingSchedulingTest](src/test/java/com/thealgorithms/scheduling/SelfAdjustingSchedulingTest.java)
+ - 📄 [SlackTimeSchedulingTest](src/test/java/com/thealgorithms/scheduling/SlackTimeSchedulingTest.java)
+ - 📁 **diskscheduling**
+ - 📄 [CircularLookSchedulingTest](src/test/java/com/thealgorithms/scheduling/diskscheduling/CircularLookSchedulingTest.java)
+ - 📄 [CircularScanSchedulingTest](src/test/java/com/thealgorithms/scheduling/diskscheduling/CircularScanSchedulingTest.java)
+ - 📄 [LookSchedulingTest](src/test/java/com/thealgorithms/scheduling/diskscheduling/LookSchedulingTest.java)
+ - 📄 [SSFSchedulingTest](src/test/java/com/thealgorithms/scheduling/diskscheduling/SSFSchedulingTest.java)
+ - 📄 [ScanSchedulingTest](src/test/java/com/thealgorithms/scheduling/diskscheduling/ScanSchedulingTest.java)
+ - 📁 **searches**
+ - 📄 [BM25InvertedIndexTest](src/test/java/com/thealgorithms/searches/BM25InvertedIndexTest.java)
+ - 📄 [BinarySearch2dArrayTest](src/test/java/com/thealgorithms/searches/BinarySearch2dArrayTest.java)
+ - 📄 [BinarySearchTest](src/test/java/com/thealgorithms/searches/BinarySearchTest.java)
+ - 📄 [BoyerMooreTest](src/test/java/com/thealgorithms/searches/BoyerMooreTest.java)
+ - 📄 [BreadthFirstSearchTest](src/test/java/com/thealgorithms/searches/BreadthFirstSearchTest.java)
+ - 📄 [DepthFirstSearchTest](src/test/java/com/thealgorithms/searches/DepthFirstSearchTest.java)
+ - 📄 [ExponentialSearchTest](src/test/java/com/thealgorithms/searches/ExponentialSearchTest.java)
+ - 📄 [FibonacciSearchTest](src/test/java/com/thealgorithms/searches/FibonacciSearchTest.java)
+ - 📄 [HowManyTimesRotatedTest](src/test/java/com/thealgorithms/searches/HowManyTimesRotatedTest.java)
+ - 📄 [InterpolationSearchTest](src/test/java/com/thealgorithms/searches/InterpolationSearchTest.java)
+ - 📄 [IterativeBinarySearchTest](src/test/java/com/thealgorithms/searches/IterativeBinarySearchTest.java)
+ - 📄 [IterativeTernarySearchTest](src/test/java/com/thealgorithms/searches/IterativeTernarySearchTest.java)
+ - 📄 [JumpSearchTest](src/test/java/com/thealgorithms/searches/JumpSearchTest.java)
+ - 📄 [KMPSearchTest](src/test/java/com/thealgorithms/searches/KMPSearchTest.java)
+ - 📄 [LinearSearchTest](src/test/java/com/thealgorithms/searches/LinearSearchTest.java)
+ - 📄 [LinearSearchThreadTest](src/test/java/com/thealgorithms/searches/LinearSearchThreadTest.java)
+ - 📄 [LowerBoundTest](src/test/java/com/thealgorithms/searches/LowerBoundTest.java)
+ - 📄 [MonteCarloTreeSearchTest](src/test/java/com/thealgorithms/searches/MonteCarloTreeSearchTest.java)
+ - 📄 [OrderAgnosticBinarySearchTest](src/test/java/com/thealgorithms/searches/OrderAgnosticBinarySearchTest.java)
+ - 📄 [PerfectBinarySearchTest](src/test/java/com/thealgorithms/searches/PerfectBinarySearchTest.java)
+ - 📄 [QuickSelectTest](src/test/java/com/thealgorithms/searches/QuickSelectTest.java)
+ - 📄 [RabinKarpAlgorithmTest](src/test/java/com/thealgorithms/searches/RabinKarpAlgorithmTest.java)
+ - 📄 [RandomSearchTest](src/test/java/com/thealgorithms/searches/RandomSearchTest.java)
+ - 📄 [RecursiveBinarySearchTest](src/test/java/com/thealgorithms/searches/RecursiveBinarySearchTest.java)
+ - 📄 [RowColumnWiseSorted2dArrayBinarySearchTest](src/test/java/com/thealgorithms/searches/RowColumnWiseSorted2dArrayBinarySearchTest.java)
+ - 📄 [SaddlebackSearchTest](src/test/java/com/thealgorithms/searches/SaddlebackSearchTest.java)
+ - 📄 [SearchInARowAndColWiseSortedMatrixTest](src/test/java/com/thealgorithms/searches/SearchInARowAndColWiseSortedMatrixTest.java)
+ - 📄 [SortOrderAgnosticBinarySearchTest](src/test/java/com/thealgorithms/searches/SortOrderAgnosticBinarySearchTest.java)
+ - 📄 [SquareRootBinarySearchTest](src/test/java/com/thealgorithms/searches/SquareRootBinarySearchTest.java)
+ - 📄 [TernarySearchTest](src/test/java/com/thealgorithms/searches/TernarySearchTest.java)
+ - 📄 [TestSearchInARowAndColWiseSortedMatrix](src/test/java/com/thealgorithms/searches/TestSearchInARowAndColWiseSortedMatrix.java)
+ - 📄 [UnionFindTest](src/test/java/com/thealgorithms/searches/UnionFindTest.java)
+ - 📄 [UpperBoundTest](src/test/java/com/thealgorithms/searches/UpperBoundTest.java)
+ - 📁 **slidingwindow**
+ - 📄 [LongestSubarrayWithSumLessOrEqualToKTest](src/test/java/com/thealgorithms/slidingwindow/LongestSubarrayWithSumLessOrEqualToKTest.java)
+ - 📄 [LongestSubstringWithoutRepeatingCharactersTest](src/test/java/com/thealgorithms/slidingwindow/LongestSubstringWithoutRepeatingCharactersTest.java)
+ - 📄 [MaxSumKSizeSubarrayTest](src/test/java/com/thealgorithms/slidingwindow/MaxSumKSizeSubarrayTest.java)
+ - 📄 [MinSumKSizeSubarrayTest](src/test/java/com/thealgorithms/slidingwindow/MinSumKSizeSubarrayTest.java)
+ - 📄 [ShortestCoprimeSegmentTest](src/test/java/com/thealgorithms/slidingwindow/ShortestCoprimeSegmentTest.java)
+ - 📁 **sorts**
+ - 📄 [AdaptiveMergeSortTest](src/test/java/com/thealgorithms/sorts/AdaptiveMergeSortTest.java)
+ - 📄 [BeadSortTest](src/test/java/com/thealgorithms/sorts/BeadSortTest.java)
+ - 📄 [BinaryInsertionSortTest](src/test/java/com/thealgorithms/sorts/BinaryInsertionSortTest.java)
+ - 📄 [BitonicSortTest](src/test/java/com/thealgorithms/sorts/BitonicSortTest.java)
+ - 📄 [BogoSortTest](src/test/java/com/thealgorithms/sorts/BogoSortTest.java)
+ - 📄 [BubbleSortRecursiveTest](src/test/java/com/thealgorithms/sorts/BubbleSortRecursiveTest.java)
+ - 📄 [BubbleSortTest](src/test/java/com/thealgorithms/sorts/BubbleSortTest.java)
+ - 📄 [BucketSortTest](src/test/java/com/thealgorithms/sorts/BucketSortTest.java)
+ - 📄 [CircleSortTest](src/test/java/com/thealgorithms/sorts/CircleSortTest.java)
+ - 📄 [CocktailShakerSortTest](src/test/java/com/thealgorithms/sorts/CocktailShakerSortTest.java)
+ - 📄 [CombSortTest](src/test/java/com/thealgorithms/sorts/CombSortTest.java)
+ - 📄 [CountingSortTest](src/test/java/com/thealgorithms/sorts/CountingSortTest.java)
+ - 📄 [CycleSortTest](src/test/java/com/thealgorithms/sorts/CycleSortTest.java)
+ - 📄 [DarkSortTest](src/test/java/com/thealgorithms/sorts/DarkSortTest.java)
+ - 📄 [DualPivotQuickSortTest](src/test/java/com/thealgorithms/sorts/DualPivotQuickSortTest.java)
+ - 📄 [DutchNationalFlagSortTest](src/test/java/com/thealgorithms/sorts/DutchNationalFlagSortTest.java)
+ - 📄 [ExchangeSortTest](src/test/java/com/thealgorithms/sorts/ExchangeSortTest.java)
+ - 📄 [FlashSortTest](src/test/java/com/thealgorithms/sorts/FlashSortTest.java)
+ - 📄 [GnomeSortTest](src/test/java/com/thealgorithms/sorts/GnomeSortTest.java)
+ - 📄 [HeapSortTest](src/test/java/com/thealgorithms/sorts/HeapSortTest.java)
+ - 📄 [InsertionSortTest](src/test/java/com/thealgorithms/sorts/InsertionSortTest.java)
+ - 📄 [IntrospectiveSortTest](src/test/java/com/thealgorithms/sorts/IntrospectiveSortTest.java)
+ - 📄 [MergeSortNoExtraSpaceTest](src/test/java/com/thealgorithms/sorts/MergeSortNoExtraSpaceTest.java)
+ - 📄 [MergeSortRecursiveTest](src/test/java/com/thealgorithms/sorts/MergeSortRecursiveTest.java)
+ - 📄 [MergeSortTest](src/test/java/com/thealgorithms/sorts/MergeSortTest.java)
+ - 📄 [OddEvenSortTest](src/test/java/com/thealgorithms/sorts/OddEvenSortTest.java)
+ - 📄 [PancakeSortTest](src/test/java/com/thealgorithms/sorts/PancakeSortTest.java)
+ - 📄 [PatienceSortTest](src/test/java/com/thealgorithms/sorts/PatienceSortTest.java)
+ - 📄 [PigeonholeSortTest](src/test/java/com/thealgorithms/sorts/PigeonholeSortTest.java)
+ - 📄 [QuickSortTest](src/test/java/com/thealgorithms/sorts/QuickSortTest.java)
+ - 📄 [RadixSortTest](src/test/java/com/thealgorithms/sorts/RadixSortTest.java)
+ - 📄 [SelectionSortRecursiveTest](src/test/java/com/thealgorithms/sorts/SelectionSortRecursiveTest.java)
+ - 📄 [SelectionSortTest](src/test/java/com/thealgorithms/sorts/SelectionSortTest.java)
+ - 📄 [ShellSortTest](src/test/java/com/thealgorithms/sorts/ShellSortTest.java)
+ - 📄 [SimpleSortTest](src/test/java/com/thealgorithms/sorts/SimpleSortTest.java)
+ - 📄 [SlowSortTest](src/test/java/com/thealgorithms/sorts/SlowSortTest.java)
+ - 📄 [SortUtilsRandomGeneratorTest](src/test/java/com/thealgorithms/sorts/SortUtilsRandomGeneratorTest.java)
+ - 📄 [SortUtilsTest](src/test/java/com/thealgorithms/sorts/SortUtilsTest.java)
+ - 📄 [SortingAlgorithmTest](src/test/java/com/thealgorithms/sorts/SortingAlgorithmTest.java)
+ - 📄 [SpreadSortTest](src/test/java/com/thealgorithms/sorts/SpreadSortTest.java)
+ - 📄 [StalinSortTest](src/test/java/com/thealgorithms/sorts/StalinSortTest.java)
+ - 📄 [StoogeSortTest](src/test/java/com/thealgorithms/sorts/StoogeSortTest.java)
+ - 📄 [StrandSortTest](src/test/java/com/thealgorithms/sorts/StrandSortTest.java)
+ - 📄 [SwapSortTest](src/test/java/com/thealgorithms/sorts/SwapSortTest.java)
+ - 📄 [TimSortTest](src/test/java/com/thealgorithms/sorts/TimSortTest.java)
+ - 📄 [TopologicalSortTest](src/test/java/com/thealgorithms/sorts/TopologicalSortTest.java)
+ - 📄 [TreeSortTest](src/test/java/com/thealgorithms/sorts/TreeSortTest.java)
+ - 📄 [WaveSortTest](src/test/java/com/thealgorithms/sorts/WaveSortTest.java)
+ - 📄 [WiggleSortTest](src/test/java/com/thealgorithms/sorts/WiggleSortTest.java)
+ - 📁 **stacks**
+ - 📄 [BalancedBracketsTest](src/test/java/com/thealgorithms/stacks/BalancedBracketsTest.java)
+ - 📄 [CelebrityFinderTest](src/test/java/com/thealgorithms/stacks/CelebrityFinderTest.java)
+ - 📄 [DecimalToAnyUsingStackTest](src/test/java/com/thealgorithms/stacks/DecimalToAnyUsingStackTest.java)
+ - 📄 [DuplicateBracketsTest](src/test/java/com/thealgorithms/stacks/DuplicateBracketsTest.java)
+ - 📄 [GreatestElementConstantTimeTest](src/test/java/com/thealgorithms/stacks/GreatestElementConstantTimeTest.java)
+ - 📄 [InfixToPostfixTest](src/test/java/com/thealgorithms/stacks/InfixToPostfixTest.java)
+ - 📄 [InfixToPrefixTest](src/test/java/com/thealgorithms/stacks/InfixToPrefixTest.java)
+ - 📄 [LargestRectangleTest](src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java)
+ - 📄 [MinStackUsingSingleStackTest](src/test/java/com/thealgorithms/stacks/MinStackUsingSingleStackTest.java)
+ - 📄 [MinStackUsingTwoStacksTest](src/test/java/com/thealgorithms/stacks/MinStackUsingTwoStacksTest.java)
+ - 📄 [NextGreaterElementTest](src/test/java/com/thealgorithms/stacks/NextGreaterElementTest.java)
+ - 📄 [NextSmallerElementTest](src/test/java/com/thealgorithms/stacks/NextSmallerElementTest.java)
+ - 📄 [PalindromeWithStackTest](src/test/java/com/thealgorithms/stacks/PalindromeWithStackTest.java)
+ - 📄 [PostfixEvaluatorTest](src/test/java/com/thealgorithms/stacks/PostfixEvaluatorTest.java)
+ - 📄 [PostfixToInfixTest](src/test/java/com/thealgorithms/stacks/PostfixToInfixTest.java)
+ - 📄 [PrefixEvaluatorTest](src/test/java/com/thealgorithms/stacks/PrefixEvaluatorTest.java)
+ - 📄 [PrefixToInfixTest](src/test/java/com/thealgorithms/stacks/PrefixToInfixTest.java)
+ - 📄 [SmallestElementConstantTimeTest](src/test/java/com/thealgorithms/stacks/SmallestElementConstantTimeTest.java)
+ - 📄 [SortStackTest](src/test/java/com/thealgorithms/stacks/SortStackTest.java)
+ - 📄 [StackPostfixNotationTest](src/test/java/com/thealgorithms/stacks/StackPostfixNotationTest.java)
+ - 📄 [StackUsingTwoQueuesTest](src/test/java/com/thealgorithms/stacks/StackUsingTwoQueuesTest.java)
+ - 📁 **strings**
+ - 📄 [AhoCorasickTest](src/test/java/com/thealgorithms/strings/AhoCorasickTest.java)
+ - 📄 [AlphabeticalTest](src/test/java/com/thealgorithms/strings/AlphabeticalTest.java)
+ - 📄 [AnagramsTest](src/test/java/com/thealgorithms/strings/AnagramsTest.java)
+ - 📄 [CharactersSameTest](src/test/java/com/thealgorithms/strings/CharactersSameTest.java)
+ - 📄 [CheckVowelsTest](src/test/java/com/thealgorithms/strings/CheckVowelsTest.java)
+ - 📄 [CountCharTest](src/test/java/com/thealgorithms/strings/CountCharTest.java)
+ - 📄 [CountWordsTest](src/test/java/com/thealgorithms/strings/CountWordsTest.java)
+ - 📄 [HammingDistanceTest](src/test/java/com/thealgorithms/strings/HammingDistanceTest.java)
+ - 📄 [HorspoolSearchTest](src/test/java/com/thealgorithms/strings/HorspoolSearchTest.java)
+ - 📄 [IsomorphicTest](src/test/java/com/thealgorithms/strings/IsomorphicTest.java)
+ - 📄 [LetterCombinationsOfPhoneNumberTest](src/test/java/com/thealgorithms/strings/LetterCombinationsOfPhoneNumberTest.java)
+ - 📄 [LongestCommonPrefixTest](src/test/java/com/thealgorithms/strings/LongestCommonPrefixTest.java)
+ - 📄 [LongestNonRepetitiveSubstringTest](src/test/java/com/thealgorithms/strings/LongestNonRepetitiveSubstringTest.java)
+ - 📄 [LongestPalindromicSubstringTest](src/test/java/com/thealgorithms/strings/LongestPalindromicSubstringTest.java)
+ - 📄 [LowerTest](src/test/java/com/thealgorithms/strings/LowerTest.java)
+ - 📄 [ManacherTest](src/test/java/com/thealgorithms/strings/ManacherTest.java)
+ - 📄 [MyAtoiTest](src/test/java/com/thealgorithms/strings/MyAtoiTest.java)
+ - 📄 [PalindromeTest](src/test/java/com/thealgorithms/strings/PalindromeTest.java)
+ - 📄 [PangramTest](src/test/java/com/thealgorithms/strings/PangramTest.java)
+ - 📄 [PermuteStringTest](src/test/java/com/thealgorithms/strings/PermuteStringTest.java)
+ - 📄 [ReturnSubsequenceTest](src/test/java/com/thealgorithms/strings/ReturnSubsequenceTest.java)
+ - 📄 [ReverseStringRecursiveTest](src/test/java/com/thealgorithms/strings/ReverseStringRecursiveTest.java)
+ - 📄 [ReverseStringTest](src/test/java/com/thealgorithms/strings/ReverseStringTest.java)
+ - 📄 [ReverseWordsInStringTest](src/test/java/com/thealgorithms/strings/ReverseWordsInStringTest.java)
+ - 📄 [RotationTest](src/test/java/com/thealgorithms/strings/RotationTest.java)
+ - 📄 [StringCompressionTest](src/test/java/com/thealgorithms/strings/StringCompressionTest.java)
+ - 📄 [StringMatchFiniteAutomataTest](src/test/java/com/thealgorithms/strings/StringMatchFiniteAutomataTest.java)
+ - 📄 [UpperTest](src/test/java/com/thealgorithms/strings/UpperTest.java)
+ - 📄 [ValidParenthesesTest](src/test/java/com/thealgorithms/strings/ValidParenthesesTest.java)
+ - 📄 [WordLadderTest](src/test/java/com/thealgorithms/strings/WordLadderTest.java)
+ - 📁 **zigZagPattern**
+ - 📄 [ZigZagPatternTest](src/test/java/com/thealgorithms/strings/zigZagPattern/ZigZagPatternTest.java)
+ - 📁 **tree**
+ - 📄 [HeavyLightDecompositionTest](src/test/java/com/thealgorithms/tree/HeavyLightDecompositionTest.java)
\ No newline at end of file
diff --git a/DecimalToOctal.java b/DecimalToOctal.java
deleted file mode 100644
index 1efa00f8b938..000000000000
--- a/DecimalToOctal.java
+++ /dev/null
@@ -1,33 +0,0 @@
-import java.util.Scanner;
-
-/**
- * This class converts Decimal numbers to Octal Numbers
- *
- * @author Unknown
- *
- */
-class Decimal_Octal
-{
- /**
- * Main Method
- *
- * @param args Command line Arguments
- */
- public static void main(String[] args)
- {
- Scanner sc=new Scanner(System.in);
- int n,k,d,s=0,c=0;
- System.out.print("Decimal number: ");
- n=sc.nextInt();
- k=n;
- while(k!=0)
- {
- d=k%8;
- s+=d*(int)Math.pow(10,c++);
- k/=8;
- }
-
- System.out.println("Octal equivalent:"+s);
- sc.close();
- }
-}
diff --git a/Dijkshtra.java b/Dijkshtra.java
deleted file mode 100644
index 377c487ee35a..000000000000
--- a/Dijkshtra.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-@author : Mayank K Jha
-
-*/
-
-
-public class Solution {
-
-public static void main(String[] args) throws IOException {
- Scanner in =new Scanner(System.in);
-
- int n=in.nextInt(); //n = Number of nodes or vertices
- int m=in.nextInt(); //m = Number of Edges
- long w[][]=new long [n+1][n+1]; //Adjacency Matrix
-
- //Initializing Matrix with Certain Maximum Value for path b/w any two vertices
- for (long[] row: w)
- Arrays.fill(row, 1000000l);
- //From above,we Have assumed that,initially path b/w any two Pair of vertices is Infinite such that Infinite = 1000000l
- //For simplicity , We can also take path Value = Long.MAX_VALUE , but i have taken Max Value = 1000000l .
-
- //Taking Input as Edge Location b/w a pair of vertices
- for(int i=0;icmp){ //Comparing previous edge value with current value - Cycle Case
- w[x][y]=cmp; w[y][x]=cmp;
- }
- }
-
- //Implementing Dijkshtra's Algorithm
-
- Stack t=new Stack();
- int src=in.nextInt();
- for(int i=1;i<=n;i++){
- if(i!=src){t.push(i);}}
- Stack p=new Stack();
- p.push(src);
- w[src][src]=0;
- while(!t.isEmpty()){int min=989997979,loc=-1;
- for(int i=0;iub)
- {
- return -1;
- }
-
- int mid=(lb+ub)/2;
-
- if (keyarray[mid])
- {
- return (BS(array, key, mid+1, ub));
- }
- else
- {
- return mid;
- }
- }
-
-
- /**
- * This is the main method of Binary Search
- *
- * @author Unknown
- * @param args Command line parameters
- */
-
- public static void main(String[] args)
- {
- Scanner input=new Scanner(System.in);
- int array[]=new int[10] ;
- int key;
-
- //Input
- System.out.println("Enter an array of 10 numbers : ");
- for (int i=0; i<10 ;i++ )
- {
- array[i]=input.nextInt();
- }
- System.out.println("Enter the number to be searched : ");
- key=input.nextInt();
-
- int index=BS(array, key, 0, 9);
- if (index!=-1)
- {
- System.out.println("Number found at index number : " + index);
- }
- else
- {
- System.out.println("Not found");
- }
- input.close();
- }
-}
diff --git a/Searches/LinearSearch.java b/Searches/LinearSearch.java
deleted file mode 100644
index 0a1bb7cc58cc..000000000000
--- a/Searches/LinearSearch.java
+++ /dev/null
@@ -1,62 +0,0 @@
-import java.util.Scanner;
-
-public class LinearSearch{
- /**
- * The main method
- * @param args Command line arguments
- */
- public static void main(String[] args){
-
- Scanner input = new Scanner(System.in);
- int[] myArray;
- int size = 0;
-
- //Prompt user to create array and its elements
- System.out.print("Enter the array size: ");
- size = input.nextInt();
- myArray = new int[size];
- for (int i = 0; i < size; i++){
- System.out.print("For index " + i + ", enter an integer: ");
- myArray[i] = input.nextInt();
- }
-
- //Prompt user to search for particular element
- System.out.print("Enter integer to search for: ");
- int key = input.nextInt();
-
- //Output array and index of target element, if found
- printarray(myArray);
- System.out.printf("The integer %d is found in index %d\n", key, linearsearch(myArray, key));
-
- input.close();
- }
-
- /**
- * Linear search method
- *
- * @param list List to be searched
- * @param key Key being searched for
- * @return Location of the key
- */
- public static int linearsearch(int[] list, int key){
-
- for (int i = 0; i< list.length; i++){
- if (list[i] == key){
- return i;
- }
-
- } return -1;
- }
- /**
- * Helper Method
- *
- * @param a array to be printed
- */
- public static void printarray(int[] a){
- System.out.print("The array is: ");
- for( int d: a){
- System.out.print(d+" ");
- }
- System.out.println();
- }
-}
diff --git a/Sorts/BubbleSort.java b/Sorts/BubbleSort.java
deleted file mode 100644
index 1abe69368045..000000000000
--- a/Sorts/BubbleSort.java
+++ /dev/null
@@ -1,58 +0,0 @@
-import java.util.Scanner;
-
-/**
- * This class implements BubbleSort
- *
- * @author Unknown
- *
- */
-
-class BubbleSort
-{
- /**
- * Main Method
- *
- * @param args Command line arguments
- */
- public static void main(String[] args)
- {
- int size = 6;
- int array[]=new int[size];
- boolean swap;
- int last = size - 1;
- Scanner input=new Scanner(System.in);
-
-
- //Input
- System.out.println("Enter any 6 Numbers for Unsorted Array : ");
- for(int i=0; i<6; i++)
- {
- array[i]=input.nextInt();
- }
-
- //Sorting
- do
- {
- swap = false;
- for (int count = 0; count < last; count++)
- {
- if (array[count] > array[count + 1])
- {
- int temp = array[count];
- array[count] = array[count + 1];
- array[count + 1] = temp;
- swap = true;
- }
- }
-
- last--;
- } while (swap);
-
- //Output
- for(int i=0; i<6; i++)
- {
- System.out.print(array[i]+"\t");
- }
- input.close();
- }
-}
diff --git a/Sorts/HeapSort.java b/Sorts/HeapSort.java
deleted file mode 100644
index 6b3a3fdcc490..000000000000
--- a/Sorts/HeapSort.java
+++ /dev/null
@@ -1,174 +0,0 @@
-import java.util.Scanner;
-
-/**
- * Heap Sort Algorithm
- * Implements MinHeap
- *
- * @author Unknown
- *
- */
-public class HeapSort {
- /** Array to store heap */
- private int[] heap;
- /** The size of the heap */
- private int size;
-
- /**
- * Constructor
- *
- * @param heap array of unordered integers
- */
- public HeapSort(int[] heap) {
- this.setHeap(heap);
- this.setSize(heap.length);
- }
-
- /**
- * Setter for variable size
- *
- * @param length new size
- */
- private void setSize(int length) {
- this.size = length;
- }
-
- /**
- * Setter for variable heap
- *
- * @param heap array of unordered elements
- */
- private void setHeap(int[] heap) {
- this.heap = heap;
- }
-
- /**
- * Swaps index of first with second
- *
- * @param first First index to switch
- * @param second Second index to switch
- */
- private void swap(int first, int second) {
- int temp = this.heap[first];
- this.heap[first] = this.heap[second];
- this.heap[second] = temp;
- }
-
- /**
- * Heapifies subtree from top as root to last as last child
- *
- * @param rootIndex index of root
- * @param lastChild index of last child
- */
- private void heapSubtree(int rootIndex, int lastChild) {
- int leftIndex = rootIndex * 2 + 1;
- int rightIndex = rootIndex * 2 + 2;
- int root = this.heap[rootIndex];
- if (rightIndex <= lastChild) { // if has right and left children
- int left = this.heap[leftIndex];
- int right = this.heap[rightIndex];
- if (left < right && left < root) {
- this.swap(leftIndex, rootIndex);
- this.heapSubtree(leftIndex, lastChild);
- } else if (right < root) {
- this.swap(rightIndex, rootIndex);
- this.heapSubtree(rightIndex, lastChild);
- }
- } else if (leftIndex <= lastChild) { // if no right child, but has left child
- int left = this.heap[leftIndex];
- if (left < root) {
- this.swap(leftIndex, rootIndex);
- this.heapSubtree(leftIndex, lastChild);
- }
- }
- }
-
- /**
- * Makes heap with root as root
- *
- * @param root index of root of heap
- */
- private void makeMinHeap(int root) {
- int leftIndex = root * 2 + 1;
- int rightIndex = root * 2 + 2;
- boolean hasLeftChild = leftIndex < this.heap.length;
- boolean hasRightChild = rightIndex < this.heap.length;
- if (hasRightChild) { //if has left and right
- this.makeMinHeap(leftIndex);
- this.makeMinHeap(rightIndex);
- this.heapSubtree(root, this.heap.length - 1);
- } else if (hasLeftChild) {
- this.heapSubtree(root, this.heap.length - 1);
- }
- }
-
- /**
- * Gets the root of heap
- *
- * @return root of heap
- */
- private int getRoot() {
- this.swap(0, this.size - 1);
- this.size--;
- this.heapSubtree(0, this.size - 1);
- return this.heap[this.size]; // return old root
- }
-
- /**
- * Sorts heap with heap sort; displays ordered elements to console.
- *
- * @return sorted array of sorted elements
- */
- public final int[] sort() {
- this.makeMinHeap(0); // make min heap using index 0 as root.
- int[] sorted = new int[this.size];
- int index = 0;
- while (this.size > 0) {
- int min = this.getRoot();
- sorted[index] = min;
- index++;
- }
- return sorted;
- }
-
- /**
- * Gets input to sort
- *
- * @return unsorted array of integers to sort
- */
- public static int[] getInput() {
- final int numElements = 6;
- int[] unsorted = new int[numElements];
- Scanner input = new Scanner(System.in);
- System.out.println("Enter any 6 Numbers for Unsorted Array : ");
- for (int i = 0; i < numElements; i++) {
- unsorted[i] = input.nextInt();
- }
- input.close();
- return unsorted;
- }
-
- /**
- * Prints elements in heap
- *
- * @param heap array representing heap
- */
- public static void printData(int[] heap) {
- System.out.println("Sorted Elements:");
- for (int i = 0; i < heap.length; i++) {
- System.out.print(" " + heap[i] + " ");
- }
- }
-
- /**
- * Main method
- *
- * @param args the command line arguments
- */
- public static void main(String[] args) {
- int[] heap = getInput();
- HeapSort data = new HeapSort(heap);
- int[] sorted = data.sort();
- printData(sorted);
- }
-
-}
diff --git a/Sorts/InsertionSort.java b/Sorts/InsertionSort.java
deleted file mode 100644
index d9d86566354b..000000000000
--- a/Sorts/InsertionSort.java
+++ /dev/null
@@ -1,49 +0,0 @@
-import java.util.Scanner;
-
-/**
- * This class implements Insertion Sort
- *
- * @author Unknown
- *
- */
-class InsertionSort
-{
- /**
- * Main Method
- *
- * @param args Command line arguments
- */
- public static void main(String[] args)
- {
- int array[]=new int[6];
- Scanner input=new Scanner(System.in);
-
- //Input
- System.out.println("Enter any 6 Numbers for Unsorted Array : ");
- for(int i=0; i<6; i++)
- {
- array[i]=input.nextInt();
- }
-
- //Sorting
- for(int i=0; i<6; i++)
- {
- int temp=array[i];
- int j=i-1;
- while(j>=0 && temp 0; lastSortedIndex--){
-
- //If our extracted element is smaller than element to the right, switch them.
- if (sortedArray[lastSortedIndex-1] > extractedElement){
- //move the element to the left of extractedElement to the right in sortedArray
- sortedArray[lastSortedIndex] = sortedArray[lastSortedIndex-1];
- //And move the current extractedElement to the left one (since it's smaller).
- sortedArray[lastSortedIndex-1] = extractedElement;
- }
- else{
- //insert element where it is.
- sortedArray[lastSortedIndex] = extractedElement;
- //Terminating loop since element is in the right spot.
- break;
- }
-
- }
-
- }
-
- return sortedArray;
-
- }
-
-}
diff --git a/Sorts/MergeSort.java b/Sorts/MergeSort.java
deleted file mode 100644
index f574281d65c0..000000000000
--- a/Sorts/MergeSort.java
+++ /dev/null
@@ -1,109 +0,0 @@
-import java.util.Scanner;
-
-/**
- * This class implements MergeSort
- * @author Unknown
- *
- */
-public class MergeSort {
- /** Array for mergeSort*/
- private int[] array;
- /** Temp Merge Array*/
- private int[] tempMergArr;
- /** Length of the array*/
- private int length;
-
- /**
- * Sorts inputArr with merge sort algorithm
- *
- * @param inputArr Array to be sorted
- */
- public final void sort(int inputArr[]) {
- this.array = inputArr;
- this.length = inputArr.length;
- this.tempMergArr = new int[this.length];
- this.mergeSort(0, this.length - 1);
- }
-
- /**
- * Partitions Array into recursively smaller pieces
- *
- * @param lowerIndex lower bound to include in the first partition
- * @param higherIndex upper bound to include in the third partition
- */
- private void mergeSort(int lowerIndex, int higherIndex) {
- if (lowerIndex < higherIndex) {
- int middle = lowerIndex + (higherIndex - lowerIndex) / 2;
- // Below step sorts the left side of the array
- this.mergeSort(lowerIndex, middle);
- // Below step sorts the right side of the array
- this.mergeSort(middle + 1, higherIndex);
- // Now merge both sides
- this.mergeParts(lowerIndex, middle, higherIndex);
- }
- }
-
- /**
- * Merges partitions
- *
- * @param lowerIndex The lower index
- * @param middle The middle index
- * @param higherIndex The higher index
- */
- private void mergeParts(int lowerIndex, int middle, int higherIndex) {
- for (int i = lowerIndex; i <= higherIndex; i++) {
- this.tempMergArr[i] = this.array[i];
- }
- int i = lowerIndex;
- int j = middle + 1;
- int k = lowerIndex;
- while (i <= middle && j <= higherIndex) {
- if (this.tempMergArr[i] <= this.tempMergArr[j]) {
- this.array[k] = this.tempMergArr[i];
- i++;
- } else {
- this.array[k] = this.tempMergArr[j];
- j++;
- }
- k++;
- }
- while (i <= middle) {
- this.array[k] = this.tempMergArr[i];
- k++;
- i++;
- }
-
- }
-
- /**
- * Gets input to sort
- *
- * @return unsorted array of integers to sort
- */
- public static int[] getInput() {
- final int numElements = 6;
- int[] unsorted = new int[numElements];
- Scanner input = new Scanner(System.in);
- System.out.println("Enter any 6 Numbers for Unsorted Array : ");
- for (int i = 0; i < numElements; i++) {
- unsorted[i] = input.nextInt();
- }
- input.close();
- return unsorted;
- }
-
- /**
- * Main Method
- *
- * @param args Command line arguments
- */
- public static void main(String args[]) {
- int[] inputArr = getInput();
- MergeSort mergeSort = new MergeSort();
- mergeSort.sort(inputArr);
- for (int i : inputArr) {
- System.out.print(i);
- System.out.print(" ");
- }
- }
-}
diff --git a/Sorts/Quicksort.java b/Sorts/Quicksort.java
deleted file mode 100644
index 11533f0b0e6d..000000000000
--- a/Sorts/Quicksort.java
+++ /dev/null
@@ -1,102 +0,0 @@
-import java.util.Scanner;
-
-/**
- * Implementation of QuickSort
- *
- * @author Unknown
- *
- */
-
-public class Quicksort{
-
- /**
- * The main method
- *
- * @param args Command line arguments
- */
- public static void main(String[] args){
- Scanner input = new Scanner(System.in);
- int[] array;
- int size = 0;
-
- //Prompt user to create array and its elements
- System.out.print("Enter the size of the array: ");
- size = input.nextInt();
- array = new int[size];
- for (int i = 0; i < size; i++){
- System.out.print("For index " + i + ", give an integer input: ");
- array[i] = input.nextInt();
- }
-
- //Output inputted array
- System.out.println("The array is: ");
- printarray(array);
- System.out.println();
-
- //Run quicksort, and output sorted array
- quicksort(array, 0, array.length - 1);
- System.out.println("The sorted array is: ");
- printarray(array);
- System.out.println();
-
- input.close();
- }
-
- /**
- * QuickSort method
- *
- * @param ar Array to perform QuickSort
- * @param start Start of the array
- * @param end End of the array
- */
- public static void quicksort(int[] ar, int start, int end){
- int[] array;
-
- int i = start, j = end;
- if (end-start >= 1){
- int pivot = ar[end];
- while (i< j){
- while (ar[i]=pivot && j>start){
- j--;
- }
- if (i mx)
- mx = arr[i];
- return mx;
- }
-
- static void countSort(int arr[], int n, int exp)
- {
- int output[] = new int[n];
- int i;
- int count[] = new int[10];
- Arrays.fill(count,0);
-
- for (i = 0; i < n; i++)
- count[ (arr[i]/exp)%10 ]++;
-
- for (i = 1; i < 10; i++)
- count[i] += count[i - 1];
-
- for (i = n - 1; i >= 0; i--)
- {
- output[count[ (arr[i]/exp)%10 ] - 1] = arr[i];
- count[ (arr[i]/exp)%10 ]--;
- }
-
- for (i = 0; i < n; i++)
- arr[i] = output[i];
- }
-
- static void radixsort(int arr[], int n)
- {
-
- int m = getMax(arr, n);
-
-
- for (int exp = 1; m/exp > 0; exp *= 10)
- countSort(arr, n, exp);
- }
-
-
- static void print(int arr[], int n)
- {
- for (int i=0; i
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/countwords.java b/countwords.java
deleted file mode 100644
index c11540de32f8..000000000000
--- a/countwords.java
+++ /dev/null
@@ -1,33 +0,0 @@
-import java.util.Scanner;
-
-/**
- * You enter a string into this program, and it will return how
- * many words were in that particular string
- *
- * @author Unknown
- *
- */
-class CountTheWords
-{
- /**
- * The main method
- *
- * @param args Command line arguments
- */
- public static void main(String args[])
- {
- System.out.println("Enter the string");
- Scanner sc = new Scanner(System.in);
- String s=sc.nextLine();
- int count = 1;
- for (int i = 0; i < s.length()-1; i++)
- {
- if((s.charAt(i) == ' ') && (s.charAt(i+1) != ' '))
- {
- count++;
- }
- }
- System.out.println("Number of words in the string = "+count);
- sc.close();
- }
-}
\ No newline at end of file
diff --git a/data_structures/AVLTree.java b/data_structures/AVLTree.java
deleted file mode 100644
index a3bde289fe15..000000000000
--- a/data_structures/AVLTree.java
+++ /dev/null
@@ -1,212 +0,0 @@
-public class AVLtree {
-
- private Node root;
-
- private class Node {
- private int key;
- private int balance;
- private int height;
- private Node left, right, parent;
-
- Node(int k, Node p) {
- key = k;
- parent = p;
- }
- }
-
- public boolean insert(int key) {
- if (root == null)
- root = new Node(key, null);
- else {
- Node n = root;
- Node parent;
- while (true) {
- if (n.key == key)
- return false;
-
- parent = n;
-
- boolean goLeft = n.key > key;
- n = goLeft ? n.left : n.right;
-
- if (n == null) {
- if (goLeft) {
- parent.left = new Node(key, parent);
- } else {
- parent.right = new Node(key, parent);
- }
- rebalance(parent);
- break;
- }
- }
- }
- return true;
- }
-
- private void delete(Node node){
- if(node.left == null && node.right == null){
- if(node.parent == null) root = null;
- else{
- Node parent = node.parent;
- if(parent.left == node){
- parent.left = null;
- }else parent.right = null;
- rebalance(parent);
- }
- return;
- }
- if(node.left!=null){
- Node child = node.left;
- while (child.right!=null) child = child.right;
- node.key = child.key;
- delete(child);
- }else{
- Node child = node.right;
- while (child.left!=null) child = child.left;
- node.key = child.key;
- delete(child);
- }
- }
-
- public void delete(int delKey) {
- if (root == null)
- return;
- Node node = root;
- Node child = root;
-
- while (child != null) {
- node = child;
- child = delKey >= node.key ? node.right : node.left;
- if (delKey == node.key) {
- delete(node);
- return;
- }
- }
- }
-
- private void rebalance(Node n) {
- setBalance(n);
-
- if (n.balance == -2) {
- if (height(n.left.left) >= height(n.left.right))
- n = rotateRight(n);
- else
- n = rotateLeftThenRight(n);
-
- } else if (n.balance == 2) {
- if (height(n.right.right) >= height(n.right.left))
- n = rotateLeft(n);
- else
- n = rotateRightThenLeft(n);
- }
-
- if (n.parent != null) {
- rebalance(n.parent);
- } else {
- root = n;
- }
- }
-
- private Node rotateLeft(Node a) {
-
- Node b = a.right;
- b.parent = a.parent;
-
- a.right = b.left;
-
- if (a.right != null)
- a.right.parent = a;
-
- b.left = a;
- a.parent = b;
-
- if (b.parent != null) {
- if (b.parent.right == a) {
- b.parent.right = b;
- } else {
- b.parent.left = b;
- }
- }
-
- setBalance(a, b);
-
- return b;
- }
-
- private Node rotateRight(Node a) {
-
- Node b = a.left;
- b.parent = a.parent;
-
- a.left = b.right;
-
- if (a.left != null)
- a.left.parent = a;
-
- b.right = a;
- a.parent = b;
-
- if (b.parent != null) {
- if (b.parent.right == a) {
- b.parent.right = b;
- } else {
- b.parent.left = b;
- }
- }
-
- setBalance(a, b);
-
- return b;
- }
-
- private Node rotateLeftThenRight(Node n) {
- n.left = rotateLeft(n.left);
- return rotateRight(n);
- }
-
- private Node rotateRightThenLeft(Node n) {
- n.right = rotateRight(n.right);
- return rotateLeft(n);
- }
-
- private int height(Node n) {
- if (n == null)
- return -1;
- return n.height;
- }
-
- private void setBalance(Node... nodes) {
- for (Node n : nodes)
- reheight(n);
- n.balance = height(n.right) - height(n.left);
- }
-
- public void printBalance() {
- printBalance(root);
- }
-
- private void printBalance(Node n) {
- if (n != null) {
- printBalance(n.left);
- System.out.printf("%s ", n.balance);
- printBalance(n.right);
- }
- }
-
- private void reheight(Node node){
- if(node!=null){
- node.height=1 + Math.max(height(node.left), height(node.right));
- }
- }
-
- public static void main(String[] args) {
- AVLtree tree = new AVLtree();
-
- System.out.println("Inserting values 1 to 10");
- for (int i = 1; i < 10; i++)
- tree.insert(i);
-
- System.out.print("Printing balance: ");
- tree.printBalance();
- }
-}
diff --git a/data_structures/CircleLinkedList.java b/data_structures/CircleLinkedList.java
deleted file mode 100644
index cf03cd7cdfd2..000000000000
--- a/data_structures/CircleLinkedList.java
+++ /dev/null
@@ -1,42 +0,0 @@
-public class CircleLinkedList{
- private static class Node{
- Node next;
- E value;
- private Node(E value, Node next){
- this.value = value;
- this.next = next;
- }
- }
- private int size; //For better O.O design this should be private allows for better black box design
- private Node head; //this will point to dummy node;
- public CircleLinkedList(){ //constructer for class.. here we will make a dummy node for circly linked list implementation with reduced error catching as our list will never be empty;
- head = new Node(null,head); //creation of the dummy node
- size = 0;
- }
- public int getSize(){ return size;} // getter for the size... needed because size is private.
- public void append(E value){ // for the sake of simplistiy this class will only contain the append function or addLast other add functions can be implemented however this is the basses of them all really.
- if(value == null){
- throw new NullPointerException("Cannot add null element to the list"); // we do not want to add null elements to the list.
- }
- head.next = new Node(value,head); //head.next points to the last element;
- size++;}
- public E remove(int pos){
- if(pos>size || pos< 0){
- throw new IndexOutOfBoundsException("position cannot be greater than size or negative"); //catching errors
- }
- Node iterator = head.next;
- Node before = head; //we need to keep track of the element before the element we want to remove we can see why bellow.
- for(int i = 1; i<=pos; i++){
- iterator = iterator.next;
- before = before.next;
- }
- E saved = iterator.value;
- before.next = iterator.next; // assigning the next referance to the the element following the element we want to remove... the last element will be assigned to the head.
- iterator.next = null; // scrubbing
- iterator.value = null;
- return saved;
-
- }
-
- }
-
diff --git a/data_structures/DoublyLinkedList.java b/data_structures/DoublyLinkedList.java
deleted file mode 100644
index c3229d9c336d..000000000000
--- a/data_structures/DoublyLinkedList.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/**
- * This class implements a DoublyLinkedList. This is done using the classes
- * LinkedList and Link.
- *
- * A linked list is simplar to an array, it holds values. However,
- * links in a linked list do not have indees. With a linked list
- * you do not need to predetermine it's size as it grows and shrinks
- * as it is edited. This is an example of a double ended, doubly
- * linked list. Each link references the next link and the previous
- * one.
- *
- * @author Unknown
- *
- */
-
-class DoublyLinkedList{
- /** Head refers to the front of the list */
- private Link head;
- /** Tail refers to the back of the list */
- private Link tail;
-
- /**
- * Constructor
- */
- public DoublyLinkedList(){
- head = null;
- tail = null;
- }
-
- /**
- * Insert an element at the head
- *
- * @param x Element to be inserted
- */
- public void insertHead(int x){
- Link newLink = new Link(x); //Create a new link with a value attached to it
- if(isEmpty()) //Set the first element added to be the tail
- tail = newLink;
- else
- head.previous = newLink; // newLink <-- currenthead(head)
- newLink.next = head; // newLink <--> currenthead(head)
- head = newLink; // newLink(head) <--> oldhead
- }
-
- /**
- * Insert an element at the tail
- *
- * @param x Element to be inserted
- */
- public void insertTail(int x){
- Link newLink = new Link(x);
- newLink.next = null; // currentTail(tail) newlink -->
- tail.next = newLink; // currentTail(tail) --> newLink -->
- newLink.previous = tail; // currentTail(tail) <--> newLink -->
- tail = newLink; // oldTail <--> newLink(tail) -->
- }
-
- /**
- * Delete the element at the head
- *
- * @return The new head
- */
- public Link deleteHead(){
- Link temp = head;
- head = head.next; // oldHead <--> 2ndElement(head)
- head.previous = null; // oldHead --> 2ndElement(head) nothing pointing at old head so will be removed
- if(head == null)
- tail = null;
- return temp;
- }
-
- /**
- * Delete the element at the tail
- *
- * @return The new tail
- */
- public Link deleteTail(){
- Link temp = tail;
- tail = tail.previous; // 2ndLast(tail) <--> oldTail --> null
- tail.next = null; // 2ndLast(tail) --> null
- return temp;
- }
-
- /**
- * Delete the element from somewhere in the list
- *
- * @param x element to be deleted
- * @return Link deleted
- */
- public Link delete(int x){
- Link current = head;
-
- while(current.value != x) //Find the position to delete
- current = current.next;
-
- if(current == head)
- deleteHead();
-
- else if(current == tail)
- deleteTail();
-
- else{ //Before: 1 <--> 2(current) <--> 3
- current.previous.next = current.next; // 1 --> 3
- current.next.previous = current.previous; // 1 <--> 3
- }
- return current;
- }
-
- /**
- * Inserts element and reorders
- *
- * @param x Element to be added
- */
- public void insertOrdered(int x){
- Link newLink = new Link(x);
- Link current = head;
- while(current != null && x > current.value) //Find the position to insert
- current = current.next;
-
- if(current == head)
- insertHead(x);
-
- else if(current == null)
- insertTail(x);
-
- else{ //Before: 1 <--> 2(current) <--> 3
- newLink.previous = current.previous; // 1 <-- newLink
- current.previous.next = newLink; // 1 <--> newLink
- newLink.next = current; // 1 <--> newLink --> 2(current) <--> 3
- current.previous = newLink; // 1 <--> newLink <--> 2(current) <--> 3
- }
- }
-
- /**
- * Returns true if list is empty
- *
- * @return true if list is empty
- */
- public boolean isEmpty(){
- return(head == null);
- }
-
- /**
- * Prints contents of the list
- */
- public void display(){ //Prints contents of the list
- Link current = head;
- while(current!=null){
- current.displayLink();
- current = current.next;
- }
- System.out.println();
- }
-}
-
-/**
- * This class is used to implement the nodes of the
- * linked list.
- *
- * @author Unknown
- *
- */
-class Link{
- /** Value of node */
- public int value;
- /** This points to the link in front of the new link */
- public Link next;
- /** This points to the link behind the new link */
- public Link previous;
-
- /**
- * Constructor
- *
- * @param value Value of node
- */
- public Link(int value){
- this.value = value;
- }
-
- /**
- * Displays the node
- */
- public void displayLink(){
- System.out.print(value+" ");
- }
-
- /**
- * Main Method
- *
- * @param args Command line arguments
- */
- public static void main(String args[]){
- DoublyLinkedList myList = new DoublyLinkedList();
-
- myList.insertHead(13);
- myList.insertHead(7);
- myList.insertHead(10);
- myList.display(); // <-- 10(head) <--> 7 <--> 13(tail) -->
-
- myList.insertTail(11);
- myList.display(); // <-- 10(head) <--> 7 <--> 13 <--> 11(tail) -->
-
- myList.deleteTail();
- myList.display(); // <-- 10(head) <--> 7 <--> 13(tail) -->
-
- myList.delete(7);
- myList.display(); // <-- 10(head) <--> 13(tail) -->
-
- myList.insertOrdered(23);
- myList.insertOrdered(67);
- myList.insertOrdered(3);
- myList.display(); // <-- 3(head) <--> 10 <--> 13 <--> 23 <--> 67(tail) -->
- }
-}
\ No newline at end of file
diff --git a/data_structures/Graphs.java b/data_structures/Graphs.java
deleted file mode 100644
index a3eb0ff6b8ba..000000000000
--- a/data_structures/Graphs.java
+++ /dev/null
@@ -1,32 +0,0 @@
-
-/**
- * This class implements the Graph data structure
- * using the classes Graph and Graphs.
- *
- * @author Zachary Jones
- *
- */
-class Graph {
-
-}
-
-/**
- * This class is used to test the Graph
- * class above.
- *
- * @author Zachary Jones
- *
- */
-
-public class Graphs {
-
- /**
- * Main method
- *
- * @param args Command line arguments
- */
- public static void main(String args[]) {
-
- }
-
-}
diff --git a/data_structures/PriorityQueues.java b/data_structures/PriorityQueues.java
deleted file mode 100644
index acb6b552537e..000000000000
--- a/data_structures/PriorityQueues.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/**
- * This class implements a PriorityQueue.
- *
- * A priority queue adds elements into positions based on their priority.
- * So the most important elements are placed at the front/on the top.
- * In this example I give numbers that are bigger, a higher priority.
- * Queues in theory have no fixed size but when using an array
- * implementation it does.
- *
- * @author Unknown
- *
- */
-class PriorityQueue{
- /** The max size of the queue */
- private int maxSize;
- /** The array for the queue */
- private int[] queueArray;
- /** How many items are in the queue */
- private int nItems;
-
- /**
- * Constructor
- *
- * @param size Size of the queue
- */
- public PriorityQueue(int size){
- maxSize = size;
- queueArray = new int[size];
- nItems = 0;
- }
-
- /**
- * Inserts an element in it's appropriate place
- *
- * @param value Value to be inserted
- */
- public void insert(int value){
- if(nItems == 0){
- queueArray[0] = value;
- }
- else{
- int j = nItems;
- while(j > 0 && queueArray[j-1] > value){
- queueArray[j] = queueArray[j-1]; //Shifts every element up to make room for insertion
- j--;
- }
- queueArray[j] = value; //Once the correct position is found the value is inserted
- }
- nItems++;
- }
-
- /**
- * Remove the element from the front of the queue
- *
- * @return The element removed
- */
- public int remove(){
- return queueArray[--nItems];
- }
-
- /**
- * Checks what's at the front of the queue
- *
- * @return element at the front of the queue
- */
- public int peek(){
- return queueArray[nItems-1];
- }
-
- /**
- * Returns true if the queue is empty
- *
- * @return true if the queue is empty
- */
- public boolean isEmpty(){
- return(nItems == 0);
- }
-
- /**
- * Returns true if the queue is full
- *
- * @return true if the queue is full
- */
- public boolean isFull(){
- return(nItems == maxSize);
- }
-
- /**
- * Returns the number of elements in the queue
- *
- * @return number of elements in the queue
- */
- public int getSize(){
- return nItems;
- }
-}
-
-/**
- * This class implements the PriorityQueue class above.
- *
- * @author Unknown
- *
- */
-public class PriorityQueues{
- /**
- * Main method
- *
- * @param args Command Line Arguments
- */
- public static void main(String args[]){
- PriorityQueue myQueue = new PriorityQueue(4);
- myQueue.insert(10);
- myQueue.insert(2);
- myQueue.insert(5);
- myQueue.insert(3);
- //[2, 3, 5, 10] Here higher numbers have higher priority, so they are on the top
-
- for(int i = 3; i>=0; i--)
- System.out.print(myQueue.remove() + " "); //will print the queue in reverse order [10, 5, 3, 2]
-
- //As you can see, a Priority Queue can be used as a sorting algotithm
- }
-}
\ No newline at end of file
diff --git a/data_structures/Queues.java b/data_structures/Queues.java
deleted file mode 100644
index 84638cb24751..000000000000
--- a/data_structures/Queues.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/**
- * This implements Queues by using the class Queue.
- *
- * A queue data structure functions the same as a real world queue.
- * The elements that are added first are the first to be removed.
- * New elements are added to the back/rear of the queue.
- *
- * @author Unknown
- *
- */
-class Queue{
- /** Max size of the queue */
- private int maxSize;
- /** The array representing the queue */
- private int[] queueArray;
- /** Front of the queue */
- private int front;
- /** Rear of the queue */
- private int rear;
- /** How many items are in the queue */
- private int nItems;
-
- /**
- * Constructor
- *
- * @param size Size of the new queue
- */
- public Queue(int size){
- maxSize = size;
- queueArray = new int[size];
- front = 0;
- rear = -1;
- nItems = 0;
- }
-
- /**
- * Inserts an element at the rear of the queue
- *
- * @param x element to be added
- * @return True if the element was added successfully
- */
- public boolean insert(int x){
- if(isFull())
- return false;
- if(rear == maxSize-1) //If the back of the queue is the end of the array wrap around to the front
- rear = -1;
- rear++;
- queueArray[rear] = x;
- nItems++;
- return true;
- }
-
- /**
- * Remove an element from the front of the queue
- *
- * @return the new front of the queue
- */
- public int remove(){ //Remove an element from the front of the queue
- if(isEmpty()){
- System.out.println("Queue is empty");
- return -1;
- }
- int temp = queueArray[front];
- front++;
- if(front == maxSize) //Dealing with wrap-around again
- front = 0;
- nItems--;
- return temp;
- }
-
- /**
- * Checks what's at the front of the queue
- *
- * @return element at the front of the queue
- */
- public int peekFront(){
- return queueArray[front];
- }
-
- /**
- * Checks what's at the rear of the queue
- *
- * @return element at the rear of the queue
- */
- public int peekRear(){
- return queueArray[rear];
- }
-
- /**
- * Returns true if the queue is empty
- *
- * @return true if the queue is empty
- */
- public boolean isEmpty(){
- return(nItems == 0);
- }
-
- /**
- * Returns true if the queue is full
- *
- * @return true if the queue is full
- */
- public boolean isFull(){
- return(nItems == maxSize);
- }
-
- /**
- * Returns the number of elements in the queue
- *
- * @return number of elements in the queue
- */
- public int getSize(){
- return nItems;
- }
-}
-
-/**
- * This class is the example for the Queue class
- *
- * @author Unknown
- *
- */
-public class Queues{
- /**
- * Main method
- *
- * @param args Command line arguments
- */
- public static void main(String args[]){
- Queue myQueue = new Queue(4);
- myQueue.insert(10);
- myQueue.insert(2);
- myQueue.insert(5);
- myQueue.insert(3);
- //[10(front), 2, 5, 3(rear)]
-
- System.out.println(myQueue.isFull()); //Will print true
-
- myQueue.remove(); //Will make 2 the new front, making 10 no longer part of the queue
- //[10, 2(front), 5, 3(rear)]
-
- myQueue.insert(7); //Insert 7 at the rear which will be index 0 because of wrap around
- // [7(rear), 2(front), 5, 3]
-
- System.out.println(myQueue.peekFront()); //Will print 2
- System.out.println(myQueue.peekRear()); //Will print 7
- }
-}
\ No newline at end of file
diff --git a/data_structures/SinglyLinkedList.java b/data_structures/SinglyLinkedList.java
deleted file mode 100644
index 4523739b3a98..000000000000
--- a/data_structures/SinglyLinkedList.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/**
- * This class implements a SinglyLinked List. This is done
- * using SinglyLinkedList class and a LinkForLinkedList Class.
- *
- * A linked list is implar to an array, it hold values.
- * However, links in a linked list do not have indexes. With
- * a linked list you do not need to predetermine it's size as
- * it gorws and shrinks as it is edited. This is an example of
- * a singly linked list. Elements can only be added/removed
- * at the head/front of the list.
- *
- * @author Unknown
- *
- */
-class SinglyLinkedList{
- /**Head refered to the front of the list */
- private LinkForLinkedList head;
-
- /**
- * Constructor of SinglyLinkedList
- */
- public SinglyLinkedList(){
- head = null;
- }
-
- /**
- * This method inserts an element at the head
- *
- * @param x Element to be added
- */
- public void insertHead(int x){
- LinkForLinkedList newLink = new LinkForLinkedList(x); //Create a new link with a value attached to it
- newLink.next = head; //Set the new link to point to the current head
- head = newLink; //Now set the new link to be the head
- }
-
- /**
- * This method deletes an element at the head
- *
- * @return The element deleted
- */
- public LinkForLinkedList deleteHead(){
- LinkForLinkedList temp = head;
- head = head.next; //Make the second element in the list the new head, the Java garbage collector will later remove the old head
- return temp;
- }
-
- /**
- * Checks if the list is empty
- *
- * @return true is list is empty
- */
- public boolean isEmpty(){
- return(head == null);
- }
-
- /**
- * Prints contents of the list
- */
- public void display(){
- LinkForLinkedList current = head;
- while(current!=null){
- current.displayLink();
- current = current.next;
- }
- System.out.println();
- }
-
- /**
- * Main method
- *
- * @param args Command line arguments
- */
- public static void main(String args[]){
- SinglyLinkedList myList = new SinglyLinkedList();
-
- System.out.println(myList.isEmpty()); //Will print true
-
- myList.insertHead(5);
- myList.insertHead(7);
- myList.insertHead(10);
-
- myList.display(); // 10(head) --> 7 --> 5
-
- myList.deleteHead();
-
- myList.display(); // 7(head) --> 5
- }
-}
-
-/**
- * This class is the nodes of the SinglyLinked List.
- * They consist of a vlue and a pointer to the node
- * after them.
- *
- * @author Unknown
- *
- */
-class LinkForLinkedList{
- /** The value of the node */
- public int value;
- /** Point to the next node */
- public LinkForLinkedList next; //This is what the link will point to
-
- /**
- * Constructor
- *
- * @param valuein Value to be put in the node
- */
- public LinkForLinkedList(int valuein){
- value = valuein;
- }
-
- /**
- * Prints out the value of the node
- */
- public void displayLink(){
- System.out.print(value+" ");
- }
-
-}
\ No newline at end of file
diff --git a/data_structures/Stacks.java b/data_structures/Stacks.java
deleted file mode 100644
index dbb2a6217bcf..000000000000
--- a/data_structures/Stacks.java
+++ /dev/null
@@ -1,207 +0,0 @@
-import java.util.ArrayList;
-
-/**
- * This class implements a Stack using two different implementations.
- * Stack is used with a regular array and Stack2 uses an ArrayList.
- *
- * A stack is exactly what it sounds like. An element gets added to the top of
- * the stack and only the element on the top may be removed. This is an example
- * of an array implementation of a Stack. So an element can only be added/removed
- * from the end of the array. In theory stack have no fixed size, but with an
- * array implementation it does.
- *
- * @author Unknown
- *
- */
-class Stack{
- /** The max size of the Stack */
- private int maxSize;
- /** The array representation of the Stack */
- private int[] stackArray;
- /** The top of the stack */
- private int top;
-
- /**
- * Constructor
- *
- * @param size Size of the Stack
- */
- public Stack(int size){
- maxSize = size;
- stackArray = new int[maxSize];
- top = -1;
- }
-
- /**
- * Adds an element to the top of the stack
- *
- * @param value The element added
- */
- public void push(int value){
- top++;
- stackArray[top] = value;
- }
-
- /**
- * Removes the top element of the stack and returns the value you've removed
- *
- * @return value popped off the Stack
- */
- public int pop(){
- return stackArray[top--];
- }
-
- /**
- * Returns the element at the top of the stack
- *
- * @return element at the top of the stack
- */
- public int peek(){
- return stackArray[top];
- }
-
- /**
- * Returns true if the stack is empty
- *
- * @return true if the stack is empty
- */
- public boolean isEmpty(){
- return(top == -1);
- }
-
- /**
- * Returns true if the stack is full
- *
- * @return true if the stack is full
- */
- public boolean isFull(){
- return(top+1 == maxSize);
- }
-
- /**
- * Deletes everything in the Stack
- *
- * Doesn't delete elements in the array
- * but if you call push method after calling
- * makeEmpty it will overwrite previous
- * values
- */
- public void makeEmpty(){ //Doesn't delete elements in the array but if you call
- top = -1; //push method after calling makeEmpty it will overwrite previous values
- }
-}
-
-/**
- * This is an ArrayList Implementation of stack, Where size is not
- * a problem we can extend the stack as much as we want.
- *
- * @author Unknown
- *
- */
-class Stack2{
- /** ArrayList representation of the stack */
- ArrayList stackList;
-
- /**
- * Constructor
- */
- Stack2(){
- stackList=new ArrayList<>();
- }
-
- /**
- * Adds value to the end of list which
- * is the top for stack
- *
- * @param value value to be added
- */
- void push(int value){
- stackList.add(value);
- }
-
- /**
- * Pops last element of list which is indeed
- * the top for Stack
- *
- * @return Element popped
- */
- int pop(){
-
- if(!isEmpty()){ // checks for an empty Stack
-
- int popValue=stackList.get(stackList.size()-1);
- stackList.remove(stackList.size()-1); //removes the poped element from the list
- return popValue;
- }
- else{
- System.out.print("The stack is already empty ");
- return -1;
- }
-
- }
-
- /**
- * Checks for empty Stack
- *
- * @return true if stack is empty
- */
- boolean isEmpty(){
- if(stackList.isEmpty())
- return true;
-
- else return false;
-
- }
-
- /**
- * Top element of stack
- *
- * @return top element of stack
- */
- int peek(){
- return stackList.get(stackList.size()-1);
- }
- }
-
-/**
- * This class implements the Stack and Stack2 created above
- *
- * @author Unknown
- *
- */
-public class Stacks{
- /**
- * Main method
- *
- * @param args Command line arguments
- */
- public static void main(String args[]){
- Stack myStack = new Stack(4); //Declare a stack of maximum size 4
- //Populate the stack
- myStack.push(5);
- myStack.push(8);
- myStack.push(2);
- myStack.push(9);
-
- System.out.println("*********************Stack Array Implementation*********************");
- System.out.println(myStack.isEmpty()); //will print false
- System.out.println(myStack.isFull()); //will print true
- System.out.println(myStack.peek()); //will print 9
- System.out.println(myStack.pop()); //will print 9
- System.out.println(myStack.peek()); // will print 2
-
- Stack2 myStack2 = new Stack2(); //Declare a stack of maximum size 4
- //Populate the stack
- myStack2.push(5);
- myStack2.push(8);
- myStack2.push(2);
- myStack2.push(9);
-
- System.out.println("*********************Stack List Implementation*********************");
- System.out.println(myStack2.isEmpty()); //will print false
- System.out.println(myStack2.peek()); //will print 9
- System.out.println(myStack2.pop()); //will print 9
- System.out.println(myStack2.peek()); // will print 2
- System.out.println(myStack2.pop()); //will print 2
- }
-}
diff --git a/data_structures/Trees/BinaryTree.java b/data_structures/Trees/BinaryTree.java
deleted file mode 100644
index 3d05f1767819..000000000000
--- a/data_structures/Trees/BinaryTree.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/**
- * This entire class is used to build a Binary Tree data structure.
- * There is the Node Class and the Tree Class, both explained below.
- *
- * @author Unknown
- *
- */
-
-
-/**
- * This class implements the nodes that will go on the Binary Tree.
- * They consist of the data in them, the node to the left, the node
- * to the right, and the parent from which they came from.
- *
- * @author Unknown
- *
- */
-class Node{
- /** Data for the node */
- public int data;
- /** The Node to the left of this one */
- public Node left;
- /** The Node to the right of this one */
- public Node right;
- /** The parent of this node */
- public Node parent;
-
- /**
- * Constructor of Node
- *
- * @param value Value to put in the node
- */
- public Node(int value){
- data = value;
- left = null;
- right = null;
- parent = null;
- }
-}
-
-
-/**
- * A binary tree is a data structure in which an element
- * has two successors(children). The left child is usually
- * smaller than the parent, and the right child is usually
- * bigger.
- *
- * @author Unknown
- *
- */
-class Tree{
- /** The root of the Binary Tree */
- private Node root;
-
- /**
- * Constructor
- */
- public Tree(){
- root = null;
- }
-
- /**
- * Method to find a Node with a certain value
- *
- * @param key Value being looked for
- * @return The node if it finds it, otherwise returns the parent
- */
- public Node find(int key){
- Node current = root;
- Node last = root;
- while(current != null){
- last = current;
- if(key < current.data)
- current = current.left;
- else if(key > current.data)
- current = current.right;
- //If you find the value return it
- else
- return current;
- }
- return last;
- }
-
- /**
- * Inserts certain value into the Binary Tree
- *
- * @param value Value to be inserted
- */
- public void put(int value){
- Node newNode = new Node(value);
- if(root == null)
- root = newNode;
- else{
- //This will return the soon to be parent of the value you're inserting
- Node parent = find(value);
-
- //This if/else assigns the new node to be either the left or right child of the parent
- if(value < parent.data){
- parent.left = newNode;
- parent.left.parent = parent;
- return;
- }
- else{
- parent.right = newNode;
- parent.right.parent = parent;
- return;
- }
- }
- }
-
- /**
- * Deletes a given value from the Binary Tree
- *
- * @param value Value to be deleted
- * @return If the value was deleted
- */
- public boolean remove(int value){
- //temp is the node to be deleted
- Node temp = find(value);
-
- //If the value doesn't exist
- if(temp.data != value)
- return false;
-
- //No children
- if(temp.right == null && temp.left == null){
- if(temp == root)
- root = null;
-
- //This if/else assigns the new node to be either the left or right child of the parent
- else if(temp.parent.data < temp.data)
- temp.parent.right = null;
- else
- temp.parent.left = null;
- return true;
- }
-
- //Two children
- else if(temp.left != null && temp.right != null){
- Node successor = findSuccessor(temp);
-
- //The left tree of temp is made the left tree of the successor
- successor.left = temp.left;
- successor.left.parent = successor;
-
- //If the successor has a right child, the child's grandparent is it's new parent
- if(successor.right != null && successor.parent != temp){
- successor.right.parent = successor.parent;
- successor.parent.left = successor.right;
- successor.right = temp.right;
- successor.right.parent = successor;
- }
- if(temp == root){
- successor.parent = null;
- root = successor;
- return true;
- }
-
- //If you're not deleting the root
- else{
- successor.parent = temp.parent;
-
- //This if/else assigns the new node to be either the left or right child of the parent
- if(temp.parent.data < temp.data)
- temp.parent.right = successor;
- else
- temp.parent.left = successor;
- return true;
- }
- }
- //One child
- else{
- //If it has a right child
- if(temp.right != null){
- if(temp == root){
- root = temp.right; return true;}
-
- temp.right.parent = temp.parent;
-
- //Assigns temp to left or right child
- if(temp.data < temp.parent.data)
- temp.parent.left = temp.right;
- else
- temp.parent.right = temp.right;
- return true;
- }
- //If it has a left child
- else{
- if(temp == root){
- root = temp.left; return true;}
-
- temp.left.parent = temp.parent;
-
- //Assigns temp to left or right side
- if(temp.data < temp.parent.data)
- temp.parent.left = temp.left;
- else
- temp.parent.right = temp.left;
- return true;
- }
- }
- }
-
- /**
- * This method finds the Successor to the Node given.
- * Move right once and go left down the tree as far as you can
- *
- * @param n Node that you want to find the Successor of
- * @return The Successor of the node
- */
- public Node findSuccessor(Node n){
- if(n.right == null)
- return n;
- Node current = n.right;
- Node parent = n.right;
- while(current != null){
- parent = current;
- current = current.left;
- }
- return parent;
- }
-
- /**
- * Returns the root of the Binary Tree
- *
- * @return the root of the Binary Tree
- */
- public Node getRoot(){
- return root;
- }
-
- /**
- * Prints leftChild - root - rightChild
- *
- * @param localRoot The local root of the binary tree
- */
- public void inOrder(Node localRoot){
- if(localRoot != null){
- inOrder(localRoot.left);
- System.out.print(localRoot.data + " ");
- inOrder(localRoot.right);
- }
- }
-
- /**
- * Prints root - leftChild - rightChild
- *
- * @param localRoot The local root of the binary tree
- */
- public void preOrder(Node localRoot){
- if(localRoot != null){
- System.out.print(localRoot.data + " ");
- preOrder(localRoot.left);
- preOrder(localRoot.right);
- }
- }
-
- /**
- * Prints rightChild - leftChild - root
- *
- * @param localRoot The local root of the binary tree
- */
- public void postOrder(Node localRoot){
- if(localRoot != null){
- postOrder(localRoot.left);
- postOrder(localRoot.right);
- System.out.print(localRoot.data + " ");
- }
- }
-}
diff --git a/data_structures/heaps/EmptyHeapException.java b/data_structures/heaps/EmptyHeapException.java
deleted file mode 100644
index b7d853c56845..000000000000
--- a/data_structures/heaps/EmptyHeapException.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- *
- */
-package heaps;
-
-/**
- * @author Nicolas Renard
- * Exception to be thrown if the getElement method is used on an empty heap.
- *
- */
-@SuppressWarnings("serial")
-public class EmptyHeapException extends Exception {
-
- public EmptyHeapException(String message) {
- super(message);
- }
-
-}
diff --git a/data_structures/heaps/Heap.java b/data_structures/heaps/Heap.java
deleted file mode 100644
index 02b2ba270918..000000000000
--- a/data_structures/heaps/Heap.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package heaps;
-
-/**
- * Interface common to heap data structures.
- *
Heaps are tree-like data structures that allow storing elements in a specific
- * way. Each node corresponds to an element and has one parent node (except for the root) and
- * at most two children nodes. Every element contains a key, and those keys
- * indicate how the tree shall be built. For instance, for a min-heap, the key of a node shall
- * be greater than or equal to its parent's and lower than or equal to its children's (the opposite rule applies to a
- * max-heap).
- *
All heap-related operations (inserting or deleting an element, extracting the min or max) are performed in
- * O(log n) time.
- * @author Nicolas Renard
- *
- *
- */
-public interface Heap {
-
- /**
- *
- * @return the top element in the heap, the one with lowest key for min-heap or with
- * the highest key for max-heap
- * @throws Exception if heap is empty
- */
- public abstract HeapElement getElement() throws EmptyHeapException;
- /**
- * Inserts an element in the heap. Adds it to then end and toggle it until it finds its
- * right position.
- *
- * @param element an instance of the HeapElement class.
- */
- public abstract void insertElement(HeapElement element);
-
- /**
- * Delete an element in the heap.
- *
- * @param elementIndex int containing the position in the heap of the element to be deleted.
- */
- public abstract void deleteElement(int elementIndex);
-
-}
diff --git a/data_structures/heaps/HeapElement.java b/data_structures/heaps/HeapElement.java
deleted file mode 100644
index e0cc93ccbfe0..000000000000
--- a/data_structures/heaps/HeapElement.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/**
- *
- */
-package heaps;
-
-import java.lang.Double;
-import java.lang.Object;
-
-/**
- * Class for heap elements.
- *
A heap element contains two attributes: a key which will be used to build the tree (int
- * or double, either primitive type or object) and any kind of IMMUTABLE object the user sees fit
- * to carry any information he/she likes. Be aware that the use of a mutable object might
- * jeopardize the integrity of this information.
- * @author Nicolas Renard
- *
- */
-public class HeapElement {
- private final double key;
- private final Object additionalInfo;
-
- // Constructors
-
- /**
- *
- * @param key : a number of primitive type 'double'
- * @param info : any kind of IMMUTABLE object. May be null, since the purpose is only to carry
- * additional information of use for the user
- */
- public HeapElement(double key, Object info) {
- this.key = key;
- this.additionalInfo = info;
- }
-
- /**
- *
- * @param key : a number of primitive type 'int'
- * @param info : any kind of IMMUTABLE object. May be null, since the purpose is only to carry
- * additional information of use for the user
- */
- public HeapElement(int key, Object info) {
- this.key = key;
- this.additionalInfo = info;
- }
-
- /**
- *
- * @param key : a number of object type 'Integer'
- * @param info : any kind of IMMUTABLE object. May be null, since the purpose is only to carry
- * additional information of use for the user
- */
- public HeapElement(Integer key, Object info) {
- this.key = key;
- this.additionalInfo = info;
- }
-
- /**
- *
- * @param key : a number of object type 'Double'
- * @param info : any kind of IMMUTABLE object. May be null, since the purpose is only to carry
- * additional information of use for the user
- */
- public HeapElement(Double key, Object info) {
- this.key = key;
- this.additionalInfo = info;
- }
-
- /**
- *
- * @param key : a number of primitive type 'double'
- */
- public HeapElement(double key) {
- this.key = key;
- this.additionalInfo = null;
- }
-
- /**
- *
- * @param key : a number of primitive type 'int'
- */
- public HeapElement(int key) {
- this.key = key;
- this.additionalInfo = null;
- }
-
- /**
- *
- * @param key : a number of object type 'Integer'
- */
- public HeapElement(Integer key) {
- this.key = key;
- this.additionalInfo = null;
- }
-
- /**
- *
- * @param key : a number of object type 'Double'
- */
- public HeapElement(Double key) {
- this.key = key;
- this.additionalInfo = null;
- }
-
- // Getters
- /**
- * @return the object containing the additional info provided by the user.
- */
- public Object getInfo() {
- return additionalInfo;
- }
- /**
- * @return the key value of the element
- */
- public double getKey() {
- return key;
- }
-
- // Overridden object methods
-
- public String toString() {
- return "Key: " + key + " - " +additionalInfo.toString();
- }
- /**
- *
- * @param otherHeapElement
- * @return true if the keys on both elements are identical and the additional info objects
- * are identical.
- */
- public boolean equals(HeapElement otherHeapElement) {
- return (this.key == otherHeapElement.key) && (this.additionalInfo.equals(otherHeapElement.additionalInfo));
- }
-}
diff --git a/data_structures/heaps/MaxHeap.java b/data_structures/heaps/MaxHeap.java
deleted file mode 100644
index 5f774e3534a8..000000000000
--- a/data_structures/heaps/MaxHeap.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package heaps;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Heap tree where a node's key is higher than or equal to its parent's and lower than or equal
- * to its children's.
- * @author Nicolas Renard
- *
- */
-public class MaxHeap implements Heap {
-
- private final List maxHeap;
-
- public MaxHeap(List listElements) throws Exception {
- maxHeap = new ArrayList();
- for (HeapElement heapElement : listElements) {
- if (heapElement != null) insertElement(heapElement);
- else System.out.println("Null element. Not added to heap");
- }
- if (maxHeap.size() == 0) System.out.println("No element has been added, empty heap.");
- }
-
- // Get the element at a given index. The key for the list is equal to index value - 1
- public HeapElement getElement(int elementIndex) {
- if ((elementIndex <= 0) && (elementIndex > maxHeap.size())) throw new IndexOutOfBoundsException("Index out of heap range");
- return maxHeap.get(elementIndex - 1);
- }
-
- // Get the key of the element at a given index
- private double getElementKey(int elementIndex) {
- return maxHeap.get(elementIndex - 1).getKey();
- }
-
- // Swaps two elements in the heap
- private void swap(int index1, int index2) {
- HeapElement temporaryElement = maxHeap.get(index1 - 1);
- maxHeap.set(index1 - 1, maxHeap.get(index2 - 1));
- maxHeap.set(index2 - 1, temporaryElement);
- }
-
- // Toggle an element up to its right place as long as its key is lower than its parent's
- private void toggleUp(int elementIndex) {
- double key = maxHeap.get(elementIndex - 1).getKey();
- while (getElementKey((int) Math.floor(elementIndex/2)) < key) {
- swap(elementIndex, (int) Math.floor(elementIndex/2));
- elementIndex = (int) Math.floor(elementIndex/2);
- }
- }
-
- // Toggle an element down to its right place as long as its key is higher
- // than any of its children's
- private void toggleDown(int elementIndex) {
- double key = maxHeap.get(elementIndex - 1).getKey();
- boolean wrongOrder = (key < getElementKey(elementIndex*2)) || (key < getElementKey(Math.min(elementIndex*2, maxHeap.size())));
- while ((2*elementIndex <= maxHeap.size()) && wrongOrder) {
- // Check whether it shall swap the element with its left child or its right one if any.
- if ((2*elementIndex < maxHeap.size()) && (getElementKey(elementIndex*2 + 1) > getElementKey(elementIndex*2))) {
- swap(elementIndex, 2*elementIndex + 1);
- elementIndex = 2*elementIndex + 1;
- }
- else {
- swap(elementIndex, 2*elementIndex);
- elementIndex = 2*elementIndex;
- }
- wrongOrder = (key < getElementKey(elementIndex*2)) || (key < getElementKey(Math.min(elementIndex*2, maxHeap.size())));
-
- }
- }
-
- private HeapElement extractMax() {
- HeapElement result = maxHeap.get(0);
- deleteElement(0);
- return result;
- }
-
- @Override
- public void insertElement(HeapElement element) {
- maxHeap.add(element);
- toggleUp(maxHeap.size());
-
- }
-
- @Override
- public void deleteElement(int elementIndex) {
- if (maxHeap.isEmpty())
- try {
- throw new EmptyHeapException("Attempt to delete an element from an empty heap");
- } catch (EmptyHeapException e) {
- e.printStackTrace();
- }
- if ((elementIndex > maxHeap.size()) && (elementIndex <= 0)) throw new IndexOutOfBoundsException("Index out of heap range");
- // The last element in heap replaces the one to be deleted
- maxHeap.set(elementIndex - 1, getElement(maxHeap.size()));
- maxHeap.remove(maxHeap.size());
- // Shall the new element be moved up...
- if (getElementKey(elementIndex) > getElementKey((int) Math.floor(elementIndex/2))) toggleUp(elementIndex);
- // ... or down ?
- else if (((2*elementIndex <= maxHeap.size()) && (getElementKey(elementIndex) < getElementKey(elementIndex*2))) ||
- ((2*elementIndex < maxHeap.size()) && (getElementKey(elementIndex) < getElementKey(elementIndex*2)))) toggleDown(elementIndex);
- }
-
- @Override
- public HeapElement getElement() throws EmptyHeapException {
- try {
- return extractMax();
- } catch (Exception e) {
- throw new EmptyHeapException("Heap is empty. Error retrieving element");
- }
- }
-
-}
-
-
diff --git a/data_structures/heaps/MinHeap.java b/data_structures/heaps/MinHeap.java
deleted file mode 100644
index fbf2b86ffc3e..000000000000
--- a/data_structures/heaps/MinHeap.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- *
- */
-package heaps;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Heap tree where a node's key is higher than or equal to its parent's and lower than or equal
- * to its children's.
- * @author Nicolas Renard
- *
- */
-public class MinHeap implements Heap {
-
- private final List minHeap;
-
- public MinHeap(List listElements) throws Exception {
- minHeap = new ArrayList();
- for (HeapElement heapElement : listElements) {
- if (heapElement != null) insertElement(heapElement);
- else System.out.println("Null element. Not added to heap");
- }
- if (minHeap.size() == 0) System.out.println("No element has been added, empty heap.");
- }
-
- // Get the element at a given index. The key for the list is equal to index value - 1
- public HeapElement getElement(int elementIndex) {
- if ((elementIndex <= 0) && (elementIndex > minHeap.size())) throw new IndexOutOfBoundsException("Index out of heap range");
- return minHeap.get(elementIndex - 1);
- }
-
- // Get the key of the element at a given index
- private double getElementKey(int elementIndex) {
- return minHeap.get(elementIndex - 1).getKey();
- }
-
- // Swaps two elements in the heap
- private void swap(int index1, int index2) {
- HeapElement temporaryElement = minHeap.get(index1 - 1);
- minHeap.set(index1 - 1, minHeap.get(index2 - 1));
- minHeap.set(index2 - 1, temporaryElement);
- }
-
- // Toggle an element up to its right place as long as its key is lower than its parent's
- private void toggleUp(int elementIndex) {
- double key = minHeap.get(elementIndex - 1).getKey();
- while (getElementKey((int) Math.floor(elementIndex/2)) > key) {
- swap(elementIndex, (int) Math.floor(elementIndex/2));
- elementIndex = (int) Math.floor(elementIndex/2);
- }
- }
-
- // Toggle an element down to its right place as long as its key is higher
- // than any of its children's
- private void toggleDown(int elementIndex) {
- double key = minHeap.get(elementIndex - 1).getKey();
- boolean wrongOrder = (key > getElementKey(elementIndex*2)) || (key > getElementKey(Math.min(elementIndex*2, minHeap.size())));
- while ((2*elementIndex <= minHeap.size()) && wrongOrder) {
- // Check whether it shall swap the element with its left child or its right one if any.
- if ((2*elementIndex < minHeap.size()) && (getElementKey(elementIndex*2 + 1) < getElementKey(elementIndex*2))) {
- swap(elementIndex, 2*elementIndex + 1);
- elementIndex = 2*elementIndex + 1;
- }
- else {
- swap(elementIndex, 2*elementIndex);
- elementIndex = 2*elementIndex;
- }
- wrongOrder = (key > getElementKey(elementIndex*2)) || (key > getElementKey(Math.min(elementIndex*2, minHeap.size())));
-
- }
- }
-
- private HeapElement extractMin() {
- HeapElement result = minHeap.get(0);
- deleteElement(0);
- return result;
- }
-
- @Override
- public void insertElement(HeapElement element) {
- minHeap.add(element);
- toggleUp(minHeap.size());
-
- }
-
- @Override
- public void deleteElement(int elementIndex) {
- if (minHeap.isEmpty())
- try {
- throw new EmptyHeapException("Attempt to delete an element from an empty heap");
- } catch (EmptyHeapException e) {
- e.printStackTrace();
- }
- if ((elementIndex > minHeap.size()) && (elementIndex <= 0)) throw new IndexOutOfBoundsException("Index out of heap range");
- // The last element in heap replaces the one to be deleted
- minHeap.set(elementIndex - 1, getElement(minHeap.size()));
- minHeap.remove(minHeap.size());
- // Shall the new element be moved up...
- if (getElementKey(elementIndex) < getElementKey((int) Math.floor(elementIndex/2))) toggleUp(elementIndex);
- // ... or down ?
- else if (((2*elementIndex <= minHeap.size()) && (getElementKey(elementIndex) > getElementKey(elementIndex*2))) ||
- ((2*elementIndex < minHeap.size()) && (getElementKey(elementIndex) > getElementKey(elementIndex*2)))) toggleDown(elementIndex);
- }
-
- @Override
- public HeapElement getElement() throws EmptyHeapException {
- try {
- return extractMin();
- } catch (Exception e) {
- throw new EmptyHeapException("Heap is empty. Error retrieving element");
- }
- }
-}
diff --git a/dfs.java b/dfs.java
deleted file mode 100644
index 8ceba166e149..000000000000
--- a/dfs.java
+++ /dev/null
@@ -1,63 +0,0 @@
-import java.util.*;
-
-/**
- * Implementation of a Depth First Search
- *
- * @author Unknown
- *
- */
-
-public class dfs{
-
- /**
- * Implementation in code of a DFS
- *
- * @param a structure to be DFS'ed
- * @param vertices The vertices
- * @param source The source
- */
- public static void dfsImplement(byte [][] a,int vertices,int source){ //passing adjacency matrix and no of vertices
- byte []b=new byte[vertices]; //flag container containing status of each vertices
- Arrays.fill(b,(byte)-1); //status initialization
- /* code status
- -1 = ready
- 0 = waiting
- 1 = processed */
-
-
- Stack st=new Stack(vertices); //operational stack
- st.push(source); //assigning source
- while(!st.isEmpty()){
- b[st.peek()]=(byte)0; //assigning waiting status
- System.out.println(st.peek());
- int pop=st.pop();
- b[pop]=(byte)1; //assigning processed status
- for(int i=0;i
+
+
+ Custom PMD checks for TheAlgorithms/Java
+
+
+
+ Avoid using the main method.
+
+ 3
+
+
+
+
+
+
+
+
+
diff --git a/pmd-exclude.properties b/pmd-exclude.properties
new file mode 100644
index 000000000000..4c0ed625d884
--- /dev/null
+++ b/pmd-exclude.properties
@@ -0,0 +1,120 @@
+com.thealgorithms.ciphers.AES=UselessMainMethod
+com.thealgorithms.ciphers.AESEncryption=UselessMainMethod
+com.thealgorithms.ciphers.AffineCipher=UselessParentheses
+com.thealgorithms.ciphers.DES=UselessParentheses
+com.thealgorithms.ciphers.ProductCipher=UselessMainMethod
+com.thealgorithms.ciphers.RSA=UselessParentheses
+com.thealgorithms.conversions.AnyBaseToAnyBase=UselessMainMethod,UselessParentheses
+com.thealgorithms.conversions.AnytoAny=UselessParentheses
+com.thealgorithms.conversions.RgbHsvConversion=UselessMainMethod
+com.thealgorithms.datastructures.crdt.Pair=UnusedPrivateField
+com.thealgorithms.datastructures.graphs.AStar=UselessParentheses
+com.thealgorithms.datastructures.graphs.AdjacencyMatrixGraph=CollapsibleIfStatements,UnnecessaryFullyQualifiedName,UselessParentheses
+com.thealgorithms.datastructures.graphs.BellmanFord=UselessMainMethod
+com.thealgorithms.datastructures.graphs.BipartiteGraphDFS=CollapsibleIfStatements
+com.thealgorithms.datastructures.graphs.ConnectedComponent=UselessMainMethod
+com.thealgorithms.datastructures.graphs.Cycles=UselessMainMethod
+com.thealgorithms.datastructures.graphs.Graphs=UselessMainMethod
+com.thealgorithms.datastructures.graphs.KahnsAlgorithm=UselessMainMethod
+com.thealgorithms.datastructures.graphs.MatrixGraphs=UselessMainMethod
+com.thealgorithms.datastructures.hashmap.hashing.HashMapCuckooHashing=UselessParentheses
+com.thealgorithms.datastructures.hashmap.hashing.MainCuckooHashing=UselessMainMethod
+com.thealgorithms.datastructures.heaps.FibonacciHeap=UselessParentheses
+com.thealgorithms.datastructures.heaps.HeapNode=UselessParentheses
+com.thealgorithms.datastructures.lists.DoublyLinkedList=UselessParentheses
+com.thealgorithms.datastructures.lists.Link=UselessMainMethod
+com.thealgorithms.datastructures.lists.RandomNode=UselessMainMethod
+com.thealgorithms.datastructures.lists.SearchSinglyLinkedListRecursion=UselessParentheses
+com.thealgorithms.datastructures.lists.SinglyLinkedList=UnusedLocalVariable,UselessMainMethod
+com.thealgorithms.datastructures.queues.Deque=UselessMainMethod
+com.thealgorithms.datastructures.queues.PriorityQueue=UselessParentheses
+com.thealgorithms.datastructures.trees.BSTRecursiveGeneric=UselessMainMethod
+com.thealgorithms.datastructures.trees.CheckBinaryTreeIsValidBST=UselessParentheses
+com.thealgorithms.datastructures.trees.LCA=UselessMainMethod
+com.thealgorithms.datastructures.trees.NearestRightKey=UselessMainMethod
+com.thealgorithms.datastructures.trees.PrintTopViewofTree=UselessMainMethod
+com.thealgorithms.datastructures.trees.SegmentTree=UselessParentheses
+com.thealgorithms.devutils.nodes.LargeTreeNode=UselessParentheses
+com.thealgorithms.devutils.nodes.SimpleNode=UselessParentheses
+com.thealgorithms.devutils.nodes.SimpleTreeNode=UselessParentheses
+com.thealgorithms.devutils.nodes.TreeNode=UselessParentheses
+com.thealgorithms.divideandconquer.ClosestPair=UnnecessaryFullyQualifiedName,UselessMainMethod,UselessParentheses
+com.thealgorithms.divideandconquer.Point=UselessParentheses
+com.thealgorithms.dynamicprogramming.CatalanNumber=UselessMainMethod
+com.thealgorithms.dynamicprogramming.EggDropping=UselessMainMethod
+com.thealgorithms.dynamicprogramming.LongestPalindromicSubsequence=UselessMainMethod
+com.thealgorithms.dynamicprogramming.WineProblem=UselessParentheses
+com.thealgorithms.maths.BinomialCoefficient=UselessParentheses
+com.thealgorithms.maths.Complex=UselessParentheses
+com.thealgorithms.maths.DistanceFormulaTest=UnnecessaryFullyQualifiedName
+com.thealgorithms.maths.EulerMethod=UselessMainMethod
+com.thealgorithms.maths.GCDRecursion=UselessMainMethod
+com.thealgorithms.maths.Gaussian=UselessParentheses
+com.thealgorithms.maths.GcdSolutionWrapper=UselessParentheses
+com.thealgorithms.maths.HeronsFormula=UselessParentheses
+com.thealgorithms.maths.JugglerSequence=UselessMainMethod
+com.thealgorithms.maths.KaprekarNumbers=UselessParentheses
+com.thealgorithms.maths.KeithNumber=UselessMainMethod,UselessParentheses
+com.thealgorithms.maths.LeonardoNumber=UselessParentheses
+com.thealgorithms.maths.LinearDiophantineEquationsSolver=UselessMainMethod,UselessParentheses
+com.thealgorithms.maths.MagicSquare=UselessMainMethod
+com.thealgorithms.maths.PiNilakantha=UselessMainMethod
+com.thealgorithms.maths.Prime.PrimeCheck=UselessMainMethod
+com.thealgorithms.maths.PythagoreanTriple=UselessMainMethod
+com.thealgorithms.maths.RomanNumeralUtil=UselessParentheses
+com.thealgorithms.maths.SecondMinMax=UselessParentheses
+com.thealgorithms.maths.SecondMinMaxTest=UnnecessaryFullyQualifiedName
+com.thealgorithms.maths.SimpsonIntegration=UselessMainMethod
+com.thealgorithms.maths.StandardDeviation=UselessParentheses
+com.thealgorithms.maths.SumOfArithmeticSeries=UselessParentheses
+com.thealgorithms.maths.TrinomialTriangle=UselessMainMethod,UselessParentheses
+com.thealgorithms.maths.VectorCrossProduct=UselessMainMethod
+com.thealgorithms.maths.Volume=UselessParentheses
+com.thealgorithms.matrix.RotateMatrixBy90Degrees=UselessMainMethod
+com.thealgorithms.misc.Sparsity=UselessParentheses
+com.thealgorithms.others.BankersAlgorithm=UselessMainMethod
+com.thealgorithms.others.BrianKernighanAlgorithm=UselessMainMethod
+com.thealgorithms.others.CRC16=UselessMainMethod,UselessParentheses
+com.thealgorithms.others.CRC32=UselessMainMethod
+com.thealgorithms.others.Damm=UnnecessaryFullyQualifiedName,UselessMainMethod
+com.thealgorithms.others.Dijkstra=UselessMainMethod
+com.thealgorithms.others.GaussLegendre=UselessMainMethod
+com.thealgorithms.others.HappyNumbersSeq=UselessMainMethod
+com.thealgorithms.others.Huffman=UselessMainMethod
+com.thealgorithms.others.InsertDeleteInArray=UselessMainMethod
+com.thealgorithms.others.KochSnowflake=UselessMainMethod
+com.thealgorithms.others.Krishnamurthy=UselessMainMethod
+com.thealgorithms.others.LinearCongruentialGenerator=UselessMainMethod
+com.thealgorithms.others.Luhn=UnnecessaryFullyQualifiedName,UselessMainMethod
+com.thealgorithms.others.Mandelbrot=UselessMainMethod,UselessParentheses
+com.thealgorithms.others.MiniMaxAlgorithm=UselessMainMethod,UselessParentheses
+com.thealgorithms.others.PageRank=UselessMainMethod,UselessParentheses
+com.thealgorithms.others.PerlinNoise=UselessMainMethod,UselessParentheses
+com.thealgorithms.others.QueueUsingTwoStacks=UselessParentheses
+com.thealgorithms.others.Trieac=UselessMainMethod,UselessParentheses
+com.thealgorithms.others.Verhoeff=UnnecessaryFullyQualifiedName,UselessMainMethod
+com.thealgorithms.puzzlesandgames.Sudoku=UselessMainMethod
+com.thealgorithms.searches.HowManyTimesRotated=UselessMainMethod
+com.thealgorithms.searches.InterpolationSearch=UselessParentheses
+com.thealgorithms.searches.KMPSearch=UselessParentheses
+com.thealgorithms.searches.RabinKarpAlgorithm=UselessParentheses
+com.thealgorithms.searches.RecursiveBinarySearch=UselessMainMethod
+com.thealgorithms.sorts.BogoSort=UselessMainMethod
+com.thealgorithms.sorts.CircleSort=EmptyControlStatement
+com.thealgorithms.sorts.DutchNationalFlagSort=UselessParentheses
+com.thealgorithms.sorts.MergeSortNoExtraSpace=UselessParentheses
+com.thealgorithms.sorts.RadixSort=UselessParentheses
+com.thealgorithms.sorts.TreeSort=UselessMainMethod
+com.thealgorithms.sorts.WiggleSort=UselessParentheses
+com.thealgorithms.stacks.LargestRectangle=UselessMainMethod
+com.thealgorithms.stacks.MaximumMinimumWindow=UselessMainMethod
+com.thealgorithms.stacks.PostfixToInfix=UselessParentheses
+com.thealgorithms.strings.Alphabetical=UselessMainMethod
+com.thealgorithms.strings.HorspoolSearch=UnnecessaryFullyQualifiedName,UselessParentheses
+com.thealgorithms.strings.KMP=UselessMainMethod
+com.thealgorithms.strings.Lower=UselessMainMethod
+com.thealgorithms.strings.Palindrome=UselessParentheses
+com.thealgorithms.strings.Pangram=UselessMainMethod
+com.thealgorithms.strings.RabinKarp=UselessMainMethod
+com.thealgorithms.strings.Rotation=UselessMainMethod
+com.thealgorithms.strings.Upper=UselessMainMethod
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 000000000000..f5f1e0be12f7
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,159 @@
+
+
+ 4.0.0
+ com.thealgorithms
+ Java
+ 1.0-SNAPSHOT
+ jar
+
+
+ UTF-8
+ 21
+ 21
+ 3.27.3
+
+
+
+
+
+ org.junit
+ junit-bom
+ 5.13.3
+ pom
+ import
+
+
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+ org.mockito
+ mockito-core
+ 5.18.0
+ test
+
+
+ org.apache.commons
+ commons-lang3
+ 3.18.0
+
+
+ org.apache.commons
+ commons-collections4
+ 4.5.0
+
+
+
+
+
+
+ maven-surefire-plugin
+ 3.5.3
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.14.0
+
+ 21
+ 21
+
+ -Xlint:all
+ -Xlint:-auxiliaryclass
+ -Werror
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.13
+
+
+
+ prepare-agent
+
+
+
+ generate-code-coverage-report
+ test
+
+ report
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ 3.6.0
+
+ checkstyle.xml
+ true
+ true
+ warning
+
+
+
+ com.puppycrawl.tools
+ checkstyle
+ 10.26.1
+
+
+
+
+ com.github.spotbugs
+ spotbugs-maven-plugin
+ 4.9.3.2
+
+ spotbugs-exclude.xml
+ true
+
+
+ com.mebigfatguy.fb-contrib
+ fb-contrib
+ 7.6.11
+
+
+ com.h3xstream.findsecbugs
+ findsecbugs-plugin
+ 1.14.0
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-pmd-plugin
+ 3.27.0
+
+
+ /rulesets/java/maven-pmd-plugin-default.xml
+ /category/java/security.xml
+ file://${basedir}/pmd-custom_ruleset.xml
+
+ true
+ true
+ false
+ pmd-exclude.properties
+
+
+
+
+
diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml
new file mode 100644
index 000000000000..bcc053611de6
--- /dev/null
+++ b/spotbugs-exclude.xml
@@ -0,0 +1,208 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/thealgorithms/audiofilters/EMAFilter.java b/src/main/java/com/thealgorithms/audiofilters/EMAFilter.java
new file mode 100644
index 000000000000..0dd23e937953
--- /dev/null
+++ b/src/main/java/com/thealgorithms/audiofilters/EMAFilter.java
@@ -0,0 +1,48 @@
+package com.thealgorithms.audiofilters;
+
+/**
+ * Exponential Moving Average (EMA) Filter for smoothing audio signals.
+ *
+ *
This filter applies an exponential moving average to a sequence of audio
+ * signal values, making it useful for smoothing out rapid fluctuations.
+ * The smoothing factor (alpha) controls the degree of smoothing.
+ *
+ *
Based on the definition from
+ * Wikipedia link.
+ */
+public class EMAFilter {
+ private final double alpha;
+ private double emaValue;
+ /**
+ * Constructs an EMA filter with a given smoothing factor.
+ *
+ * @param alpha Smoothing factor (0 < alpha <= 1)
+ * @throws IllegalArgumentException if alpha is not in (0, 1]
+ */
+ public EMAFilter(double alpha) {
+ if (alpha <= 0 || alpha > 1) {
+ throw new IllegalArgumentException("Alpha must be between 0 and 1.");
+ }
+ this.alpha = alpha;
+ this.emaValue = 0.0;
+ }
+ /**
+ * Applies the EMA filter to an audio signal array.
+ *
+ * @param audioSignal Array of audio samples to process
+ * @return Array of processed (smoothed) samples
+ */
+ public double[] apply(double[] audioSignal) {
+ if (audioSignal.length == 0) {
+ return new double[0];
+ }
+ double[] emaSignal = new double[audioSignal.length];
+ emaValue = audioSignal[0];
+ emaSignal[0] = emaValue;
+ for (int i = 1; i < audioSignal.length; i++) {
+ emaValue = alpha * audioSignal[i] + (1 - alpha) * emaValue;
+ emaSignal[i] = emaValue;
+ }
+ return emaSignal;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/audiofilters/IIRFilter.java b/src/main/java/com/thealgorithms/audiofilters/IIRFilter.java
new file mode 100644
index 000000000000..fbc095909541
--- /dev/null
+++ b/src/main/java/com/thealgorithms/audiofilters/IIRFilter.java
@@ -0,0 +1,93 @@
+package com.thealgorithms.audiofilters;
+
+/**
+ * N-Order IIR Filter Assumes inputs are normalized to [-1, 1]
+ *
+ * Based on the difference equation from
+ * Wikipedia link
+ */
+public class IIRFilter {
+
+ private final int order;
+ private final double[] coeffsA;
+ private final double[] coeffsB;
+ private final double[] historyX;
+ private final double[] historyY;
+
+ /**
+ * Construct an IIR Filter
+ *
+ * @param order the filter's order
+ * @throws IllegalArgumentException if order is zero or less
+ */
+ public IIRFilter(int order) throws IllegalArgumentException {
+ if (order < 1) {
+ throw new IllegalArgumentException("order must be greater than zero");
+ }
+
+ this.order = order;
+ coeffsA = new double[order + 1];
+ coeffsB = new double[order + 1];
+
+ // Sane defaults
+ coeffsA[0] = 1.0;
+ coeffsB[0] = 1.0;
+
+ historyX = new double[order];
+ historyY = new double[order];
+ }
+
+ /**
+ * Set coefficients
+ *
+ * @param aCoeffs Denominator coefficients
+ * @param bCoeffs Numerator coefficients
+ * @throws IllegalArgumentException if {@code aCoeffs} or {@code bCoeffs} is
+ * not of size {@code order}, or if {@code aCoeffs[0]} is 0.0
+ */
+ public void setCoeffs(double[] aCoeffs, double[] bCoeffs) throws IllegalArgumentException {
+ if (aCoeffs.length != order) {
+ throw new IllegalArgumentException("aCoeffs must be of size " + order + ", got " + aCoeffs.length);
+ }
+
+ if (aCoeffs[0] == 0.0) {
+ throw new IllegalArgumentException("aCoeffs.get(0) must not be zero");
+ }
+
+ if (bCoeffs.length != order) {
+ throw new IllegalArgumentException("bCoeffs must be of size " + order + ", got " + bCoeffs.length);
+ }
+
+ for (int i = 0; i < order; i++) {
+ coeffsA[i] = aCoeffs[i];
+ coeffsB[i] = bCoeffs[i];
+ }
+ }
+
+ /**
+ * Process a single sample
+ *
+ * @param sample the sample to process
+ * @return the processed sample
+ */
+ public double process(double sample) {
+ double result = 0.0;
+
+ // Process
+ for (int i = 1; i <= order; i++) {
+ result += (coeffsB[i] * historyX[i - 1] - coeffsA[i] * historyY[i - 1]);
+ }
+ result = (result + coeffsB[0] * sample) / coeffsA[0];
+
+ // Feedback
+ for (int i = order - 1; i > 0; i--) {
+ historyX[i] = historyX[i - 1];
+ historyY[i] = historyY[i - 1];
+ }
+
+ historyX[0] = sample;
+ historyY[0] = result;
+
+ return result;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/backtracking/AllPathsFromSourceToTarget.java b/src/main/java/com/thealgorithms/backtracking/AllPathsFromSourceToTarget.java
new file mode 100644
index 000000000000..c35a36d97a57
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/AllPathsFromSourceToTarget.java
@@ -0,0 +1,101 @@
+package com.thealgorithms.backtracking;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Program description - To find all possible paths from source to destination
+ * Wikipedia
+ *
+ * @author Siddhant Swarup Mallick
+ */
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class AllPathsFromSourceToTarget {
+
+ // No. of vertices in graph
+ private final int v;
+
+ // To store the paths from source to destination
+ static List> nm = new ArrayList<>();
+ // adjacency list
+ private ArrayList[] adjList;
+
+ // Constructor
+ public AllPathsFromSourceToTarget(int vertices) {
+
+ // initialise vertex count
+ this.v = vertices;
+
+ // initialise adjacency list
+ initAdjList();
+ }
+
+ // utility method to initialise adjacency list
+ private void initAdjList() {
+ adjList = new ArrayList[v];
+
+ for (int i = 0; i < v; i++) {
+ adjList[i] = new ArrayList<>();
+ }
+ }
+
+ // add edge from u to v
+ public void addEdge(int u, int v) {
+ // Add v to u's list.
+ adjList[u].add(v);
+ }
+
+ public void storeAllPaths(int s, int d) {
+ boolean[] isVisited = new boolean[v];
+ ArrayList pathList = new ArrayList<>();
+
+ // add source to path[]
+ pathList.add(s);
+ // Call recursive utility
+ storeAllPathsUtil(s, d, isVisited, pathList);
+ }
+
+ // A recursive function to print all paths from 'u' to 'd'.
+ // isVisited[] keeps track of vertices in current path.
+ // localPathList<> stores actual vertices in the current path
+ private void storeAllPathsUtil(Integer u, Integer d, boolean[] isVisited, List localPathList) {
+
+ if (u.equals(d)) {
+ nm.add(new ArrayList<>(localPathList));
+ return;
+ }
+
+ // Mark the current node
+ isVisited[u] = true;
+
+ // Recursion for all the vertices adjacent to current vertex
+
+ for (Integer i : adjList[u]) {
+ if (!isVisited[i]) {
+ // store current node in path[]
+ localPathList.add(i);
+ storeAllPathsUtil(i, d, isVisited, localPathList);
+
+ // remove current node in path[]
+ localPathList.remove(i);
+ }
+ }
+
+ // Mark the current node
+ isVisited[u] = false;
+ }
+
+ // Driver program
+ public static List> allPathsFromSourceToTarget(int vertices, int[][] a, int source, int destination) {
+ // Create a sample graph
+ AllPathsFromSourceToTarget g = new AllPathsFromSourceToTarget(vertices);
+ for (int[] i : a) {
+ g.addEdge(i[0], i[1]);
+ // edges are added
+ }
+ g.storeAllPaths(source, destination);
+ // method call to store all possible paths
+ return nm;
+ // returns all possible paths from source to destination
+ }
+}
diff --git a/src/main/java/com/thealgorithms/backtracking/ArrayCombination.java b/src/main/java/com/thealgorithms/backtracking/ArrayCombination.java
new file mode 100644
index 000000000000..f8cd0c40c20e
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/ArrayCombination.java
@@ -0,0 +1,54 @@
+package com.thealgorithms.backtracking;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class provides methods to find all combinations of integers from 0 to n-1
+ * of a specified length k using backtracking.
+ */
+public final class ArrayCombination {
+ private ArrayCombination() {
+ }
+
+ /**
+ * Generates all possible combinations of length k from the integers 0 to n-1.
+ *
+ * @param n The total number of elements (0 to n-1).
+ * @param k The desired length of each combination.
+ * @return A list containing all combinations of length k.
+ * @throws IllegalArgumentException if n or k are negative, or if k is greater than n.
+ */
+ public static List> combination(int n, int k) {
+ if (n < 0 || k < 0 || k > n) {
+ throw new IllegalArgumentException("Invalid input: n must be non-negative, k must be non-negative and less than or equal to n.");
+ }
+
+ List> combinations = new ArrayList<>();
+ combine(combinations, new ArrayList<>(), 0, n, k);
+ return combinations;
+ }
+
+ /**
+ * A helper method that uses backtracking to find combinations.
+ *
+ * @param combinations The list to store all valid combinations found.
+ * @param current The current combination being built.
+ * @param start The starting index for the current recursion.
+ * @param n The total number of elements (0 to n-1).
+ * @param k The desired length of each combination.
+ */
+ private static void combine(List> combinations, List current, int start, int n, int k) {
+ // Base case: combination found
+ if (current.size() == k) {
+ combinations.add(new ArrayList<>(current));
+ return;
+ }
+
+ for (int i = start; i < n; i++) {
+ current.add(i);
+ combine(combinations, current, i + 1, n, k);
+ current.remove(current.size() - 1); // Backtrack
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/backtracking/Combination.java b/src/main/java/com/thealgorithms/backtracking/Combination.java
new file mode 100644
index 000000000000..ecaf7428f986
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/Combination.java
@@ -0,0 +1,67 @@
+package com.thealgorithms.backtracking;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.TreeSet;
+
+/**
+ * Finds all permutations of given array
+ * @author Alan Piao (git-Alan Piao)
+ */
+public final class Combination {
+ private Combination() {
+ }
+
+ /**
+ * Find all combinations of given array using backtracking
+ * @param arr the array.
+ * @param n length of combination
+ * @param the type of elements in the array.
+ * @return a list of all combinations of length n. If n == 0, return null.
+ */
+ public static List> combination(T[] arr, int n) {
+ if (n < 0) {
+ throw new IllegalArgumentException("The combination length cannot be negative.");
+ }
+
+ if (n == 0) {
+ return Collections.emptyList();
+ }
+ T[] array = arr.clone();
+ Arrays.sort(array);
+
+ List> result = new LinkedList<>();
+ backtracking(array, n, 0, new TreeSet(), result);
+ return result;
+ }
+
+ /**
+ * Backtrack all possible combinations of a given array
+ * @param arr the array.
+ * @param n length of the combination
+ * @param index the starting index.
+ * @param currSet set that tracks current combination
+ * @param result the list contains all combination.
+ * @param the type of elements in the array.
+ */
+ private static void backtracking(T[] arr, int n, int index, TreeSet currSet, List> result) {
+ if (index + n - currSet.size() > arr.length) {
+ return;
+ }
+ if (currSet.size() == n - 1) {
+ for (int i = index; i < arr.length; i++) {
+ currSet.add(arr[i]);
+ result.add(new TreeSet<>(currSet));
+ currSet.remove(arr[i]);
+ }
+ return;
+ }
+ for (int i = index; i < arr.length; i++) {
+ currSet.add(arr[i]);
+ backtracking(arr, n, i + 1, currSet, result);
+ currSet.remove(arr[i]);
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/backtracking/CrosswordSolver.java b/src/main/java/com/thealgorithms/backtracking/CrosswordSolver.java
new file mode 100644
index 000000000000..6bfb026c7de9
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/CrosswordSolver.java
@@ -0,0 +1,125 @@
+package com.thealgorithms.backtracking;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * A class to solve a crossword puzzle using backtracking.
+ * Example:
+ * Input:
+ * puzzle = {
+ * {' ', ' ', ' '},
+ * {' ', ' ', ' '},
+ * {' ', ' ', ' '}
+ * }
+ * words = List.of("cat", "dog")
+ *
+ * Output:
+ * {
+ * {'c', 'a', 't'},
+ * {' ', ' ', ' '},
+ * {'d', 'o', 'g'}
+ * }
+ */
+public final class CrosswordSolver {
+ private CrosswordSolver() {
+ }
+
+ /**
+ * Checks if a word can be placed at the specified position in the crossword.
+ *
+ * @param puzzle The crossword puzzle represented as a 2D char array.
+ * @param word The word to be placed.
+ * @param row The row index where the word might be placed.
+ * @param col The column index where the word might be placed.
+ * @param vertical If true, the word is placed vertically; otherwise, horizontally.
+ * @return true if the word can be placed, false otherwise.
+ */
+ public static boolean isValid(char[][] puzzle, String word, int row, int col, boolean vertical) {
+ for (int i = 0; i < word.length(); i++) {
+ if (vertical) {
+ if (row + i >= puzzle.length || puzzle[row + i][col] != ' ') {
+ return false;
+ }
+ } else {
+ if (col + i >= puzzle[0].length || puzzle[row][col + i] != ' ') {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Places a word at the specified position in the crossword.
+ *
+ * @param puzzle The crossword puzzle represented as a 2D char array.
+ * @param word The word to be placed.
+ * @param row The row index where the word will be placed.
+ * @param col The column index where the word will be placed.
+ * @param vertical If true, the word is placed vertically; otherwise, horizontally.
+ */
+ public static void placeWord(char[][] puzzle, String word, int row, int col, boolean vertical) {
+ for (int i = 0; i < word.length(); i++) {
+ if (vertical) {
+ puzzle[row + i][col] = word.charAt(i);
+ } else {
+ puzzle[row][col + i] = word.charAt(i);
+ }
+ }
+ }
+
+ /**
+ * Removes a word from the specified position in the crossword.
+ *
+ * @param puzzle The crossword puzzle represented as a 2D char array.
+ * @param word The word to be removed.
+ * @param row The row index where the word is placed.
+ * @param col The column index where the word is placed.
+ * @param vertical If true, the word was placed vertically; otherwise, horizontally.
+ */
+ public static void removeWord(char[][] puzzle, String word, int row, int col, boolean vertical) {
+ for (int i = 0; i < word.length(); i++) {
+ if (vertical) {
+ puzzle[row + i][col] = ' ';
+ } else {
+ puzzle[row][col + i] = ' ';
+ }
+ }
+ }
+
+ /**
+ * Solves the crossword puzzle using backtracking.
+ *
+ * @param puzzle The crossword puzzle represented as a 2D char array.
+ * @param words The list of words to be placed.
+ * @return true if the crossword is solved, false otherwise.
+ */
+ public static boolean solveCrossword(char[][] puzzle, Collection words) {
+ // Create a mutable copy of the words list
+ List remainingWords = new ArrayList<>(words);
+
+ for (int row = 0; row < puzzle.length; row++) {
+ for (int col = 0; col < puzzle[0].length; col++) {
+ if (puzzle[row][col] == ' ') {
+ for (String word : new ArrayList<>(remainingWords)) {
+ for (boolean vertical : new boolean[] {true, false}) {
+ if (isValid(puzzle, word, row, col, vertical)) {
+ placeWord(puzzle, word, row, col, vertical);
+ remainingWords.remove(word);
+ if (solveCrossword(puzzle, remainingWords)) {
+ return true;
+ }
+ remainingWords.add(word);
+ removeWord(puzzle, word, row, col, vertical);
+ }
+ }
+ }
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/backtracking/FloodFill.java b/src/main/java/com/thealgorithms/backtracking/FloodFill.java
new file mode 100644
index 000000000000..c8219ca8ba7e
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/FloodFill.java
@@ -0,0 +1,62 @@
+package com.thealgorithms.backtracking;
+
+/**
+ * Java program for Flood fill algorithm.
+ * @author Akshay Dubey (Git-Akshay Dubey)
+ */
+public final class FloodFill {
+ private FloodFill() {
+ }
+
+ /**
+ * Get the color at the given coordinates of a 2D image
+ *
+ * @param image The image to be filled
+ * @param x The x co-ordinate of which color is to be obtained
+ * @param y The y co-ordinate of which color is to be obtained
+ */
+
+ public static int getPixel(final int[][] image, final int x, final int y) {
+ return image[x][y];
+ }
+
+ /**
+ * Put the color at the given coordinates of a 2D image
+ *
+ * @param image The image to be filled
+ * @param x The x co-ordinate at which color is to be filled
+ * @param y The y co-ordinate at which color is to be filled
+ */
+ public static void putPixel(final int[][] image, final int x, final int y, final int newColor) {
+ image[x][y] = newColor;
+ }
+
+ /**
+ * Fill the 2D image with new color
+ *
+ * @param image The image to be filled
+ * @param x The x co-ordinate at which color is to be filled
+ * @param y The y co-ordinate at which color is to be filled
+ * @param newColor The new color which to be filled in the image
+ * @param oldColor The old color which is to be replaced in the image
+ */
+ public static void floodFill(final int[][] image, final int x, final int y, final int newColor, final int oldColor) {
+ if (newColor == oldColor || x < 0 || x >= image.length || y < 0 || y >= image[x].length || getPixel(image, x, y) != oldColor) {
+ return;
+ }
+
+ putPixel(image, x, y, newColor);
+
+ /* Recursively check for horizontally & vertically adjacent coordinates */
+ floodFill(image, x + 1, y, newColor, oldColor);
+ floodFill(image, x - 1, y, newColor, oldColor);
+ floodFill(image, x, y + 1, newColor, oldColor);
+ floodFill(image, x, y - 1, newColor, oldColor);
+
+ /* Recursively check for diagonally adjacent coordinates */
+ floodFill(image, x + 1, y - 1, newColor, oldColor);
+ floodFill(image, x - 1, y + 1, newColor, oldColor);
+ floodFill(image, x + 1, y + 1, newColor, oldColor);
+ floodFill(image, x - 1, y - 1, newColor, oldColor);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/backtracking/KnightsTour.java b/src/main/java/com/thealgorithms/backtracking/KnightsTour.java
new file mode 100644
index 000000000000..2c2da659f3aa
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/KnightsTour.java
@@ -0,0 +1,156 @@
+package com.thealgorithms.backtracking;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * The KnightsTour class solves the Knight's Tour problem using backtracking.
+ *
+ * Problem Statement:
+ * Given an N*N board with a knight placed on the first block, the knight must
+ * move according to chess rules and visit each square on the board exactly once.
+ * The class outputs the sequence of moves for the knight.
+ *
+ * Example:
+ * Input: N = 8 (8x8 chess board)
+ * Output: The sequence of numbers representing the order in which the knight visits each square.
+ */
+public final class KnightsTour {
+ private KnightsTour() {
+ }
+
+ // The size of the chess board (12x12 grid, with 2 extra rows/columns as a buffer around a 8x8 area)
+ private static final int BASE = 12;
+
+ // Possible moves for a knight in chess
+ private static final int[][] MOVES = {
+ {1, -2},
+ {2, -1},
+ {2, 1},
+ {1, 2},
+ {-1, 2},
+ {-2, 1},
+ {-2, -1},
+ {-1, -2},
+ };
+
+ // Chess grid representing the board
+ static int[][] grid;
+
+ // Total number of cells the knight needs to visit
+ static int total;
+
+ /**
+ * Resets the chess board to its initial state.
+ * Initializes the grid with boundary cells marked as -1 and internal cells as 0.
+ * Sets the total number of cells the knight needs to visit.
+ */
+ public static void resetBoard() {
+ grid = new int[BASE][BASE];
+ total = (BASE - 4) * (BASE - 4);
+ for (int r = 0; r < BASE; r++) {
+ for (int c = 0; c < BASE; c++) {
+ if (r < 2 || r > BASE - 3 || c < 2 || c > BASE - 3) {
+ grid[r][c] = -1; // Mark boundary cells
+ }
+ }
+ }
+ }
+
+ /**
+ * Recursive method to solve the Knight's Tour problem.
+ *
+ * @param row The current row of the knight
+ * @param column The current column of the knight
+ * @param count The current move number
+ * @return True if a solution is found, False otherwise
+ */
+ static boolean solve(int row, int column, int count) {
+ if (count > total) {
+ return true;
+ }
+
+ List neighbor = neighbors(row, column);
+
+ if (neighbor.isEmpty() && count != total) {
+ return false;
+ }
+
+ // Sort neighbors by Warnsdorff's rule (fewest onward moves)
+ neighbor.sort(Comparator.comparingInt(a -> a[2]));
+
+ for (int[] nb : neighbor) {
+ int nextRow = nb[0];
+ int nextCol = nb[1];
+ grid[nextRow][nextCol] = count;
+ if (!orphanDetected(count, nextRow, nextCol) && solve(nextRow, nextCol, count + 1)) {
+ return true;
+ }
+ grid[nextRow][nextCol] = 0; // Backtrack
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns a list of valid neighboring cells where the knight can move.
+ *
+ * @param row The current row of the knight
+ * @param column The current column of the knight
+ * @return A list of arrays representing valid moves, where each array contains:
+ * {nextRow, nextCol, numberOfPossibleNextMoves}
+ */
+ static List neighbors(int row, int column) {
+ List neighbour = new ArrayList<>();
+
+ for (int[] m : MOVES) {
+ int x = m[0];
+ int y = m[1];
+ if (row + y >= 0 && row + y < BASE && column + x >= 0 && column + x < BASE && grid[row + y][column + x] == 0) {
+ int num = countNeighbors(row + y, column + x);
+ neighbour.add(new int[] {row + y, column + x, num});
+ }
+ }
+ return neighbour;
+ }
+
+ /**
+ * Counts the number of possible valid moves for a knight from a given position.
+ *
+ * @param row The row of the current position
+ * @param column The column of the current position
+ * @return The number of valid neighboring moves
+ */
+ static int countNeighbors(int row, int column) {
+ int num = 0;
+ for (int[] m : MOVES) {
+ int x = m[0];
+ int y = m[1];
+ if (row + y >= 0 && row + y < BASE && column + x >= 0 && column + x < BASE && grid[row + y][column + x] == 0) {
+ num++;
+ }
+ }
+ return num;
+ }
+
+ /**
+ * Detects if moving to a given position will create an orphan (a position with no further valid moves).
+ *
+ * @param count The current move number
+ * @param row The row of the current position
+ * @param column The column of the current position
+ * @return True if an orphan is detected, False otherwise
+ */
+ static boolean orphanDetected(int count, int row, int column) {
+ if (count < total - 1) {
+ List neighbor = neighbors(row, column);
+ for (int[] nb : neighbor) {
+ if (countNeighbors(nb[0], nb[1]) == 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/backtracking/MColoring.java b/src/main/java/com/thealgorithms/backtracking/MColoring.java
new file mode 100644
index 000000000000..d0188dfd13aa
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/MColoring.java
@@ -0,0 +1,96 @@
+package com.thealgorithms.backtracking;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.Set;
+
+/**
+ * Node class represents a graph node. Each node is associated with a color
+ * (initially 1) and contains a set of edges representing its adjacent nodes.
+ *
+ * @author Bama Charan Chhandogi (https://github.com/BamaCharanChhandogi)
+ */
+class Node {
+ int color = 1; // Initial color for each node
+ Set edges = new HashSet(); // Set of edges representing adjacent nodes
+}
+
+/**
+ * MColoring class solves the M-Coloring problem where the goal is to determine
+ * if it's possible to color a graph using at most M colors such that no two
+ * adjacent nodes have the same color.
+ */
+public final class MColoring {
+
+ private MColoring() {
+ } // Prevent instantiation of utility class
+
+ /**
+ * Determines whether it is possible to color the graph using at most M colors.
+ *
+ * @param nodes List of nodes representing the graph.
+ * @param n The total number of nodes in the graph.
+ * @param m The maximum number of allowed colors.
+ * @return true if the graph can be colored using M colors, false otherwise.
+ */
+ static boolean isColoringPossible(ArrayList nodes, int n, int m) {
+
+ // Visited array keeps track of whether each node has been processed.
+ ArrayList visited = new ArrayList();
+ for (int i = 0; i < n + 1; i++) {
+ visited.add(0); // Initialize all nodes as unvisited (0)
+ }
+
+ // The number of colors used so far (initially set to 1, since all nodes
+ // start with color 1).
+ int maxColors = 1;
+
+ // Loop through all the nodes to ensure every node is visited, in case the
+ // graph is disconnected.
+ for (int sv = 1; sv <= n; sv++) {
+ if (visited.get(sv) > 0) {
+ continue; // Skip nodes that are already visited
+ }
+
+ // If the node is unvisited, mark it as visited and add it to the queue for BFS.
+ visited.set(sv, 1);
+ Queue q = new LinkedList<>();
+ q.add(sv);
+
+ // Perform BFS to process all nodes and their adjacent nodes
+ while (q.size() != 0) {
+ int top = q.peek(); // Get the current node from the queue
+ q.remove();
+
+ // Check all adjacent nodes of the current node
+ for (int it : nodes.get(top).edges) {
+
+ // If the adjacent node has the same color as the current node, increment its
+ // color to avoid conflict.
+ if (nodes.get(top).color == nodes.get(it).color) {
+ nodes.get(it).color += 1;
+ }
+
+ // Keep track of the maximum number of colors used so far
+ maxColors = Math.max(maxColors, Math.max(nodes.get(top).color, nodes.get(it).color));
+
+ // If the number of colors used exceeds the allowed limit M, return false.
+ if (maxColors > m) {
+ return false;
+ }
+
+ // If the adjacent node hasn't been visited yet, mark it as visited and add it
+ // to the queue for further processing.
+ if (visited.get(it) == 0) {
+ visited.set(it, 1);
+ q.add(it);
+ }
+ }
+ }
+ }
+
+ return true; // Possible to color the entire graph with M or fewer colors.
+ }
+}
diff --git a/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java b/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java
new file mode 100644
index 000000000000..8247172e7ee0
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java
@@ -0,0 +1,125 @@
+package com.thealgorithms.backtracking;
+
+/**
+ * This class contains methods to solve a maze using recursive backtracking.
+ * The maze is represented as a 2D array where walls, paths, and visited/dead
+ * ends are marked with different integers.
+ *
+ * The goal is to find a path from a starting position to the target position
+ * (map[6][5]) while navigating through the maze.
+ */
+public final class MazeRecursion {
+
+ private MazeRecursion() {
+ }
+
+ /**
+ * This method solves the maze using the "down -> right -> up -> left"
+ * movement strategy.
+ *
+ * @param map The 2D array representing the maze (walls, paths, etc.)
+ * @return The solved maze with paths marked, or null if no solution exists.
+ */
+ public static int[][] solveMazeUsingFirstStrategy(int[][] map) {
+ if (setWay(map, 1, 1)) {
+ return map;
+ }
+ return null;
+ }
+
+ /**
+ * This method solves the maze using the "up -> right -> down -> left"
+ * movement strategy.
+ *
+ * @param map The 2D array representing the maze (walls, paths, etc.)
+ * @return The solved maze with paths marked, or null if no solution exists.
+ */
+ public static int[][] solveMazeUsingSecondStrategy(int[][] map) {
+ if (setWay2(map, 1, 1)) {
+ return map;
+ }
+ return null;
+ }
+
+ /**
+ * Attempts to find a path through the maze using a "down -> right -> up -> left"
+ * movement strategy. The path is marked with '2' for valid paths and '3' for dead ends.
+ *
+ * @param map The 2D array representing the maze (walls, paths, etc.)
+ * @param i The current x-coordinate of the ball (row index)
+ * @param j The current y-coordinate of the ball (column index)
+ * @return True if a path is found to (6,5), otherwise false
+ */
+ private static boolean setWay(int[][] map, int i, int j) {
+ if (map[6][5] == 2) {
+ return true;
+ }
+
+ // If the current position is unvisited (0), explore it
+ if (map[i][j] == 0) {
+ // Mark the current position as '2'
+ map[i][j] = 2;
+
+ // Move down
+ if (setWay(map, i + 1, j)) {
+ return true;
+ }
+ // Move right
+ else if (setWay(map, i, j + 1)) {
+ return true;
+ }
+ // Move up
+ else if (setWay(map, i - 1, j)) {
+ return true;
+ }
+ // Move left
+ else if (setWay(map, i, j - 1)) {
+ return true;
+ }
+
+ map[i][j] = 3; // Mark as dead end (3) if no direction worked
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ * Attempts to find a path through the maze using an alternative movement
+ * strategy "up -> right -> down -> left".
+ *
+ * @param map The 2D array representing the maze (walls, paths, etc.)
+ * @param i The current x-coordinate of the ball (row index)
+ * @param j The current y-coordinate of the ball (column index)
+ * @return True if a path is found to (6,5), otherwise false
+ */
+ private static boolean setWay2(int[][] map, int i, int j) {
+ if (map[6][5] == 2) {
+ return true;
+ }
+
+ if (map[i][j] == 0) {
+ map[i][j] = 2;
+
+ // Move up
+ if (setWay2(map, i - 1, j)) {
+ return true;
+ }
+ // Move right
+ else if (setWay2(map, i, j + 1)) {
+ return true;
+ }
+ // Move down
+ else if (setWay2(map, i + 1, j)) {
+ return true;
+ }
+ // Move left
+ else if (setWay2(map, i, j - 1)) {
+ return true;
+ }
+
+ map[i][j] = 3; // Mark as dead end (3) if no direction worked
+ return false;
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/backtracking/NQueens.java b/src/main/java/com/thealgorithms/backtracking/NQueens.java
new file mode 100644
index 000000000000..1a8e453e34cb
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/NQueens.java
@@ -0,0 +1,111 @@
+package com.thealgorithms.backtracking;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Problem statement: Given a N x N chess board. Return all arrangements in
+ * which N queens can be placed on the board such no two queens attack each
+ * other. Ex. N = 6 Solution= There are 4 possible ways Arrangement: 1 ".Q....",
+ * "...Q..", ".....Q", "Q.....", "..Q...", "....Q."
+ *
+ * Arrangement: 2 "..Q...", ".....Q", ".Q....", "....Q.", "Q.....", "...Q.."
+ *
+ * Arrangement: 3 "...Q..", "Q.....", "....Q.", ".Q....", ".....Q", "..Q..."
+ *
+ * Arrangement: 4 "....Q.", "..Q...", "Q.....", ".....Q", "...Q..", ".Q...."
+ *
+ * Solution: Brute Force approach:
+ *
+ * Generate all possible arrangement to place N queens on N*N board. Check each
+ * board if queens are placed safely. If it is safe, include arrangement in
+ * solution set. Otherwise, ignore it
+ *
+ * Optimized solution: This can be solved using backtracking in below steps
+ *
+ * Start with first column and place queen on first row Try placing queen in a
+ * row on second column If placing second queen in second column attacks any of
+ * the previous queens, change the row in second column otherwise move to next
+ * column and try to place next queen In case if there is no rows where a queen
+ * can be placed such that it doesn't attack previous queens, then go back to
+ * previous column and change row of previous queen. Keep doing this until last
+ * queen is not placed safely. If there is no such way then return an empty list
+ * as solution
+ */
+public final class NQueens {
+ private NQueens() {
+ }
+
+ public static List> getNQueensArrangements(int queens) {
+ List> arrangements = new ArrayList<>();
+ getSolution(queens, arrangements, new int[queens], 0);
+ return arrangements;
+ }
+
+ public static void placeQueens(final int queens) {
+ List> arrangements = new ArrayList>();
+ getSolution(queens, arrangements, new int[queens], 0);
+ if (arrangements.isEmpty()) {
+ System.out.println("There is no way to place " + queens + " queens on board of size " + queens + "x" + queens);
+ } else {
+ System.out.println("Arrangement for placing " + queens + " queens");
+ }
+ for (List arrangement : arrangements) {
+ arrangement.forEach(System.out::println);
+ System.out.println();
+ }
+ }
+
+ /**
+ * This is backtracking function which tries to place queen recursively
+ *
+ * @param boardSize: size of chess board
+ * @param solutions: this holds all possible arrangements
+ * @param columns: columns[i] = rowId where queen is placed in ith column.
+ * @param columnIndex: This is the column in which queen is being placed
+ */
+ private static void getSolution(int boardSize, List> solutions, int[] columns, int columnIndex) {
+ if (columnIndex == boardSize) {
+ // this means that all queens have been placed
+ List sol = new ArrayList();
+ for (int i = 0; i < boardSize; i++) {
+ StringBuilder sb = new StringBuilder();
+ for (int j = 0; j < boardSize; j++) {
+ sb.append(j == columns[i] ? "Q" : ".");
+ }
+ sol.add(sb.toString());
+ }
+ solutions.add(sol);
+ return;
+ }
+
+ // This loop tries to place queen in a row one by one
+ for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+ columns[columnIndex] = rowIndex;
+ if (isPlacedCorrectly(columns, rowIndex, columnIndex)) {
+ // If queen is placed successfully at rowIndex in column=columnIndex then try
+ // placing queen in next column
+ getSolution(boardSize, solutions, columns, columnIndex + 1);
+ }
+ }
+ }
+
+ /**
+ * This function checks if queen can be placed at row = rowIndex in column =
+ * columnIndex safely
+ *
+ * @param columns: columns[i] = rowId where queen is placed in ith column.
+ * @param rowIndex: row in which queen has to be placed
+ * @param columnIndex: column in which queen is being placed
+ * @return true: if queen can be placed safely false: otherwise
+ */
+ private static boolean isPlacedCorrectly(int[] columns, int rowIndex, int columnIndex) {
+ for (int i = 0; i < columnIndex; i++) {
+ int diff = Math.abs(columns[i] - rowIndex);
+ if (diff == 0 || columnIndex - i == diff) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java b/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java
new file mode 100644
index 000000000000..bf93f946ab7b
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java
@@ -0,0 +1,50 @@
+package com.thealgorithms.backtracking;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class generates all valid combinations of parentheses for a given number of pairs using backtracking.
+ */
+public final class ParenthesesGenerator {
+ private ParenthesesGenerator() {
+ }
+
+ /**
+ * Generates all valid combinations of parentheses for a given number of pairs.
+ *
+ * @param n The number of pairs of parentheses.
+ * @return A list of strings representing valid combinations of parentheses.
+ * @throws IllegalArgumentException if n is less than 0.
+ */
+ public static List generateParentheses(final int n) {
+ if (n < 0) {
+ throw new IllegalArgumentException("The number of pairs of parentheses cannot be negative");
+ }
+ List result = new ArrayList<>();
+ generateParenthesesHelper(result, "", 0, 0, n);
+ return result;
+ }
+
+ /**
+ * Helper function for generating all valid combinations of parentheses recursively.
+ *
+ * @param result The list to store valid combinations.
+ * @param current The current combination being formed.
+ * @param open The number of open parentheses.
+ * @param close The number of closed parentheses.
+ * @param n The total number of pairs of parentheses.
+ */
+ private static void generateParenthesesHelper(List result, final String current, final int open, final int close, final int n) {
+ if (current.length() == n * 2) {
+ result.add(current);
+ return;
+ }
+ if (open < n) {
+ generateParenthesesHelper(result, current + "(", open + 1, close, n);
+ }
+ if (close < open) {
+ generateParenthesesHelper(result, current + ")", open, close + 1, n);
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/backtracking/Permutation.java b/src/main/java/com/thealgorithms/backtracking/Permutation.java
new file mode 100644
index 000000000000..21d26e53980f
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/Permutation.java
@@ -0,0 +1,57 @@
+package com.thealgorithms.backtracking;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Finds all permutations of given array
+ * @author Alan Piao (Git-Alan Piao)
+ */
+public final class Permutation {
+ private Permutation() {
+ }
+
+ /**
+ * Find all permutations of given array using backtracking
+ * @param arr the array.
+ * @param the type of elements in the array.
+ * @return a list of all permutations.
+ */
+ public static List permutation(T[] arr) {
+ T[] array = arr.clone();
+ List result = new LinkedList<>();
+ backtracking(array, 0, result);
+ return result;
+ }
+
+ /**
+ * Backtrack all possible orders of a given array
+ * @param arr the array.
+ * @param index the starting index.
+ * @param result the list contains all permutations.
+ * @param the type of elements in the array.
+ */
+ private static void backtracking(T[] arr, int index, List result) {
+ if (index == arr.length) {
+ result.add(arr.clone());
+ }
+ for (int i = index; i < arr.length; i++) {
+ swap(index, i, arr);
+ backtracking(arr, index + 1, result);
+ swap(index, i, arr);
+ }
+ }
+
+ /**
+ * Swap two element for a given array
+ * @param a first index
+ * @param b second index
+ * @param arr the array.
+ * @param the type of elements in the array.
+ */
+ private static void swap(int a, int b, T[] arr) {
+ T temp = arr[a];
+ arr[a] = arr[b];
+ arr[b] = temp;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/backtracking/PowerSum.java b/src/main/java/com/thealgorithms/backtracking/PowerSum.java
new file mode 100644
index 000000000000..b34ba660ebd7
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/PowerSum.java
@@ -0,0 +1,51 @@
+package com.thealgorithms.backtracking;
+
+/**
+ * Problem Statement:
+ * Find the number of ways that a given integer, N, can be expressed as the sum of the Xth powers
+ * of unique, natural numbers.
+ * For example, if N=100 and X=3, we have to find all combinations of unique cubes adding up to 100.
+ * The only solution is 1^3 + 2^3 + 3^3 + 4^3. Therefore, the output will be 1.
+ *
+ * N is represented by the parameter 'targetSum' in the code.
+ * X is represented by the parameter 'power' in the code.
+ */
+public class PowerSum {
+
+ /**
+ * Calculates the number of ways to express the target sum as a sum of Xth powers of unique natural numbers.
+ *
+ * @param targetSum The target sum to achieve (N in the problem statement)
+ * @param power The power to raise natural numbers to (X in the problem statement)
+ * @return The number of ways to express the target sum
+ */
+ public int powSum(int targetSum, int power) {
+ // Special case: when both targetSum and power are zero
+ if (targetSum == 0 && power == 0) {
+ return 1; // by convention, one way to sum to zero: use nothing
+ }
+ return sumRecursive(targetSum, power, 1, 0);
+ }
+
+ /**
+ * Recursively calculates the number of ways to express the remaining sum as a sum of Xth powers.
+ *
+ * @param remainingSum The remaining sum to achieve
+ * @param power The power to raise natural numbers to (X in the problem statement)
+ * @param currentNumber The current natural number being considered
+ * @param currentSum The current sum of powered numbers
+ * @return The number of valid combinations
+ */
+ private int sumRecursive(int remainingSum, int power, int currentNumber, int currentSum) {
+ int newSum = currentSum + (int) Math.pow(currentNumber, power);
+
+ if (newSum == remainingSum) {
+ return 1;
+ }
+ if (newSum > remainingSum) {
+ return 0;
+ }
+
+ return sumRecursive(remainingSum, power, currentNumber + 1, newSum) + sumRecursive(remainingSum, power, currentNumber + 1, currentSum);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/backtracking/SubsequenceFinder.java b/src/main/java/com/thealgorithms/backtracking/SubsequenceFinder.java
new file mode 100644
index 000000000000..4a159dbfe0b1
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/SubsequenceFinder.java
@@ -0,0 +1,54 @@
+package com.thealgorithms.backtracking;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Class generates all subsequences for a given list of elements using backtracking
+ */
+public final class SubsequenceFinder {
+ private SubsequenceFinder() {
+ }
+
+ /**
+ * Find all subsequences of given list using backtracking
+ *
+ * @param sequence a list of items on the basis of which we need to generate all subsequences
+ * @param the type of elements in the array
+ * @return a list of all subsequences
+ */
+ public static List> generateAll(List sequence) {
+ List> allSubSequences = new ArrayList<>();
+ if (sequence.isEmpty()) {
+ allSubSequences.add(new ArrayList<>());
+ return allSubSequences;
+ }
+ List currentSubsequence = new ArrayList<>();
+ backtrack(sequence, currentSubsequence, 0, allSubSequences);
+ return allSubSequences;
+ }
+
+ /**
+ * Iterate through each branch of states
+ * We know that each state has exactly two branching
+ * It terminates when it reaches the end of the given sequence
+ *
+ * @param sequence all elements
+ * @param currentSubsequence current subsequence
+ * @param index current index
+ * @param allSubSequences contains all sequences
+ * @param the type of elements which we generate
+ */
+ private static void backtrack(List sequence, List currentSubsequence, final int index, List> allSubSequences) {
+ assert index <= sequence.size();
+ if (index == sequence.size()) {
+ allSubSequences.add(new ArrayList<>(currentSubsequence));
+ return;
+ }
+
+ backtrack(sequence, currentSubsequence, index + 1, allSubSequences);
+ currentSubsequence.add(sequence.get(index));
+ backtrack(sequence, currentSubsequence, index + 1, allSubSequences);
+ currentSubsequence.removeLast();
+ }
+}
diff --git a/src/main/java/com/thealgorithms/backtracking/WordPatternMatcher.java b/src/main/java/com/thealgorithms/backtracking/WordPatternMatcher.java
new file mode 100644
index 000000000000..1854cab20a7f
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/WordPatternMatcher.java
@@ -0,0 +1,86 @@
+package com.thealgorithms.backtracking;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Class to determine if a pattern matches a string using backtracking.
+ *
+ * Example:
+ * Pattern: "abab"
+ * Input String: "JavaPythonJavaPython"
+ * Output: true
+ *
+ * Pattern: "aaaa"
+ * Input String: "JavaJavaJavaJava"
+ * Output: true
+ *
+ * Pattern: "aabb"
+ * Input String: "JavaPythonPythonJava"
+ * Output: false
+ */
+public final class WordPatternMatcher {
+ private WordPatternMatcher() {
+ }
+
+ /**
+ * Determines if the given pattern matches the input string using backtracking.
+ *
+ * @param pattern The pattern to match.
+ * @param inputString The string to match against the pattern.
+ * @return True if the pattern matches the string, False otherwise.
+ */
+ public static boolean matchWordPattern(String pattern, String inputString) {
+ Map patternMap = new HashMap<>();
+ Map strMap = new HashMap<>();
+ return backtrack(pattern, inputString, 0, 0, patternMap, strMap);
+ }
+
+ /**
+ * Backtracking helper function to check if the pattern matches the string.
+ *
+ * @param pattern The pattern string.
+ * @param inputString The string to match against the pattern.
+ * @param patternIndex Current index in the pattern.
+ * @param strIndex Current index in the input string.
+ * @param patternMap Map to store pattern characters to string mappings.
+ * @param strMap Map to store string to pattern character mappings.
+ * @return True if the pattern matches, False otherwise.
+ */
+ private static boolean backtrack(String pattern, String inputString, int patternIndex, int strIndex, Map patternMap, Map strMap) {
+ if (patternIndex == pattern.length() && strIndex == inputString.length()) {
+ return true;
+ }
+ if (patternIndex == pattern.length() || strIndex == inputString.length()) {
+ return false;
+ }
+
+ char currentChar = pattern.charAt(patternIndex);
+ if (patternMap.containsKey(currentChar)) {
+ String mappedStr = patternMap.get(currentChar);
+ if (inputString.startsWith(mappedStr, strIndex)) {
+ return backtrack(pattern, inputString, patternIndex + 1, strIndex + mappedStr.length(), patternMap, strMap);
+ } else {
+ return false;
+ }
+ }
+
+ for (int end = strIndex + 1; end <= inputString.length(); end++) {
+ String substring = inputString.substring(strIndex, end);
+ if (strMap.containsKey(substring)) {
+ continue;
+ }
+
+ patternMap.put(currentChar, substring);
+ strMap.put(substring, currentChar);
+ if (backtrack(pattern, inputString, patternIndex + 1, end, patternMap, strMap)) {
+ return true;
+ }
+
+ patternMap.remove(currentChar);
+ strMap.remove(substring);
+ }
+
+ return false;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/backtracking/WordSearch.java b/src/main/java/com/thealgorithms/backtracking/WordSearch.java
new file mode 100644
index 000000000000..174ca90ccaab
--- /dev/null
+++ b/src/main/java/com/thealgorithms/backtracking/WordSearch.java
@@ -0,0 +1,109 @@
+package com.thealgorithms.backtracking;
+
+/**
+ * Word Search Problem
+ *
+ * This class solves the word search problem where given an m x n grid of characters (board)
+ * and a target word, the task is to check if the word exists in the grid.
+ * The word can be constructed from sequentially adjacent cells (horizontally or vertically),
+ * and the same cell may not be used more than once in constructing the word.
+ *
+ * Example:
+ * - For board =
+ * [
+ * ['A','B','C','E'],
+ * ['S','F','C','S'],
+ * ['A','D','E','E']
+ * ]
+ * and word = "ABCCED", -> returns true
+ * and word = "SEE", -> returns true
+ * and word = "ABCB", -> returns false
+ *
+ * Solution:
+ * - Depth First Search (DFS) with backtracking is used to explore possible paths from any cell
+ * matching the first letter of the word. DFS ensures that we search all valid paths, while
+ * backtracking helps in reverting decisions when a path fails to lead to a solution.
+ *
+ * Time Complexity: O(m * n * 3^L)
+ * - m = number of rows in the board
+ * - n = number of columns in the board
+ * - L = length of the word
+ * - For each cell, we look at 3 possible directions (since we exclude the previously visited direction),
+ * and we do this for L letters.
+ *
+ * Space Complexity: O(L)
+ * - Stack space for the recursive DFS function, where L is the maximum depth of recursion (length of the word).
+ */
+public class WordSearch {
+ private final int[] dx = {0, 0, 1, -1};
+ private final int[] dy = {1, -1, 0, 0};
+ private boolean[][] visited;
+ private char[][] board;
+ private String word;
+
+ /**
+ * Checks if the given (x, y) coordinates are valid positions in the board.
+ *
+ * @param x The row index.
+ * @param y The column index.
+ * @return True if the coordinates are within the bounds of the board; false otherwise.
+ */
+ private boolean isValid(int x, int y) {
+ return x >= 0 && x < board.length && y >= 0 && y < board[0].length;
+ }
+
+ /**
+ * Performs Depth First Search (DFS) from the cell (x, y)
+ * to search for the next character in the word.
+ *
+ * @param x The current row index.
+ * @param y The current column index.
+ * @param nextIdx The index of the next character in the word to be matched.
+ * @return True if a valid path is found to match the remaining characters of the word; false otherwise.
+ */
+ private boolean doDFS(int x, int y, int nextIdx) {
+ visited[x][y] = true;
+ if (nextIdx == word.length()) {
+ return true;
+ }
+
+ for (int i = 0; i < 4; ++i) {
+ int xi = x + dx[i];
+ int yi = y + dy[i];
+ if (isValid(xi, yi) && board[xi][yi] == word.charAt(nextIdx) && !visited[xi][yi]) {
+ boolean exists = doDFS(xi, yi, nextIdx + 1);
+ if (exists) {
+ return true;
+ }
+ }
+ }
+
+ visited[x][y] = false; // Backtrack
+ return false;
+ }
+
+ /**
+ * Main function to check if the word exists in the board. It initiates DFS from any
+ * cell that matches the first character of the word.
+ *
+ * @param board The 2D grid of characters (the board).
+ * @param word The target word to search for in the board.
+ * @return True if the word exists in the board; false otherwise.
+ */
+ public boolean exist(char[][] board, String word) {
+ this.board = board;
+ this.word = word;
+ for (int i = 0; i < board.length; ++i) {
+ for (int j = 0; j < board[0].length; ++j) {
+ if (board[i][j] == word.charAt(0)) {
+ visited = new boolean[board.length][board[0].length];
+ boolean exists = doDFS(i, j, 1);
+ if (exists) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/BcdConversion.java b/src/main/java/com/thealgorithms/bitmanipulation/BcdConversion.java
new file mode 100644
index 000000000000..e6bd35720d9f
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/BcdConversion.java
@@ -0,0 +1,82 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * This class provides methods to convert between BCD (Binary-Coded Decimal) and decimal numbers.
+ *
+ * BCD is a class of binary encodings of decimal numbers where each decimal digit is represented by a fixed number of binary digits, usually four or eight.
+ *
+ * For more information, refer to the
+ * Binary-Coded Decimal Wikipedia page.
+ *
+ * Example usage:
+ *
+ * int decimal = BcdConversion.bcdToDecimal(0x1234);
+ * System.out.println("BCD 0x1234 to decimal: " + decimal); // Output: 1234
+ *
+ * int bcd = BcdConversion.decimalToBcd(1234);
+ * System.out.println("Decimal 1234 to BCD: " + Integer.toHexString(bcd)); // Output: 0x1234
+ *
+ */
+public final class BcdConversion {
+ private BcdConversion() {
+ }
+
+ /**
+ * Converts a BCD (Binary-Coded Decimal) number to a decimal number.
+ *
Steps:
+ *
1. Validate the BCD number to ensure all digits are between 0 and 9.
+ *
2. Extract the last 4 bits (one BCD digit) from the BCD number.
+ *
3. Multiply the extracted digit by the corresponding power of 10 and add it to the decimal number.
+ *
4. Shift the BCD number right by 4 bits to process the next BCD digit.
+ *
5. Repeat steps 1-4 until the BCD number is zero.
+ *
+ * @param bcd The BCD number.
+ * @return The corresponding decimal number.
+ * @throws IllegalArgumentException if the BCD number contains invalid digits.
+ */
+ public static int bcdToDecimal(int bcd) {
+ int decimal = 0;
+ int multiplier = 1;
+
+ // Validate BCD digits
+ while (bcd > 0) {
+ int digit = bcd & 0xF;
+ if (digit > 9) {
+ throw new IllegalArgumentException("Invalid BCD digit: " + digit);
+ }
+ decimal += digit * multiplier;
+ multiplier *= 10;
+ bcd >>= 4;
+ }
+ return decimal;
+ }
+
+ /**
+ * Converts a decimal number to BCD (Binary-Coded Decimal).
+ *
Steps:
+ *
1. Check if the decimal number is within the valid range for BCD (0 to 9999).
+ *
2. Extract the last decimal digit from the decimal number.
+ *
3. Shift the digit to the correct BCD position and add it to the BCD number.
+ *
4. Remove the last decimal digit from the decimal number.
+ *
5. Repeat steps 2-4 until the decimal number is zero.
+ *
+ * @param decimal The decimal number.
+ * @return The corresponding BCD number.
+ * @throws IllegalArgumentException if the decimal number is greater than 9999.
+ */
+ public static int decimalToBcd(int decimal) {
+ if (decimal < 0 || decimal > 9999) {
+ throw new IllegalArgumentException("Value out of bounds for BCD representation: " + decimal);
+ }
+
+ int bcd = 0;
+ int shift = 0;
+ while (decimal > 0) {
+ int digit = decimal % 10;
+ bcd |= (digit << (shift * 4));
+ decimal /= 10;
+ shift++;
+ }
+ return bcd;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/BinaryPalindromeCheck.java b/src/main/java/com/thealgorithms/bitmanipulation/BinaryPalindromeCheck.java
new file mode 100644
index 000000000000..0d6fd140c720
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/BinaryPalindromeCheck.java
@@ -0,0 +1,43 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * This class contains a method to check if the binary representation of a number is a palindrome.
+ *
+ * A binary palindrome is a number whose binary representation is the same when read from left to right and right to left.
+ * For example, the number 9 has a binary representation of 1001, which is a palindrome.
+ * The number 10 has a binary representation of 1010, which is not a palindrome.
+ *
+ *
+ * @author Hardvan
+ */
+public final class BinaryPalindromeCheck {
+ private BinaryPalindromeCheck() {
+ }
+
+ /**
+ * Checks if the binary representation of a number is a palindrome.
+ *
+ * @param x The number to check.
+ * @return True if the binary representation is a palindrome, otherwise false.
+ */
+ public static boolean isBinaryPalindrome(int x) {
+ int reversed = reverseBits(x);
+ return x == reversed;
+ }
+
+ /**
+ * Helper function to reverse all the bits of an integer.
+ *
+ * @param x The number to reverse the bits of.
+ * @return The number with reversed bits.
+ */
+ private static int reverseBits(int x) {
+ int result = 0;
+ while (x > 0) {
+ result <<= 1;
+ result |= (x & 1);
+ x >>= 1;
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/BitSwap.java b/src/main/java/com/thealgorithms/bitmanipulation/BitSwap.java
new file mode 100644
index 000000000000..d8c207567ba6
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/BitSwap.java
@@ -0,0 +1,30 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * Utility class for performing bit-swapping operations on integers.
+ * This class cannot be instantiated.
+ */
+public final class BitSwap {
+ private BitSwap() {
+ }
+
+ /**
+ * Swaps two bits at specified positions in an integer.
+ *
+ * @param data The input integer whose bits need to be swapped
+ * @param posA The position of the first bit (0-based, from least significant)
+ * @param posB The position of the second bit (0-based, from least significant)
+ * @return The modified value with swapped bits
+ * @throws IllegalArgumentException if either position is negative or ≥ 32
+ */
+ public static int bitSwap(int data, final int posA, final int posB) {
+ if (posA < 0 || posA >= Integer.SIZE || posB < 0 || posB >= Integer.SIZE) {
+ throw new IllegalArgumentException("Bit positions must be between 0 and 31");
+ }
+
+ if (SingleBitOperations.getBit(data, posA) != SingleBitOperations.getBit(data, posB)) {
+ data ^= (1 << posA) ^ (1 << posB);
+ }
+ return data;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/BooleanAlgebraGates.java b/src/main/java/com/thealgorithms/bitmanipulation/BooleanAlgebraGates.java
new file mode 100644
index 000000000000..869466320831
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/BooleanAlgebraGates.java
@@ -0,0 +1,111 @@
+package com.thealgorithms.bitmanipulation;
+
+import java.util.List;
+
+/**
+ * Implements various Boolean algebra gates (AND, OR, NOT, XOR, NAND, NOR)
+ */
+public final class BooleanAlgebraGates {
+
+ private BooleanAlgebraGates() {
+ // Prevent instantiation
+ }
+
+ /**
+ * Represents a Boolean gate that takes multiple inputs and returns a result.
+ */
+ interface BooleanGate {
+ /**
+ * Evaluates the gate with the given inputs.
+ *
+ * @param inputs The input values for the gate.
+ * @return The result of the evaluation.
+ */
+ boolean evaluate(List inputs);
+ }
+
+ /**
+ * AND Gate implementation.
+ * Returns true if all inputs are true; otherwise, false.
+ */
+ static class ANDGate implements BooleanGate {
+ @Override
+ public boolean evaluate(List inputs) {
+ for (boolean input : inputs) {
+ if (!input) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /**
+ * OR Gate implementation.
+ * Returns true if at least one input is true; otherwise, false.
+ */
+ static class ORGate implements BooleanGate {
+ @Override
+ public boolean evaluate(List inputs) {
+ for (boolean input : inputs) {
+ if (input) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * NOT Gate implementation (Unary operation).
+ * Negates a single input value.
+ */
+ static class NOTGate {
+ /**
+ * Evaluates the negation of the input.
+ *
+ * @param input The input value to be negated.
+ * @return The negated value.
+ */
+ public boolean evaluate(boolean input) {
+ return !input;
+ }
+ }
+
+ /**
+ * XOR Gate implementation.
+ * Returns true if an odd number of inputs are true; otherwise, false.
+ */
+ static class XORGate implements BooleanGate {
+ @Override
+ public boolean evaluate(List inputs) {
+ boolean result = false;
+ for (boolean input : inputs) {
+ result ^= input;
+ }
+ return result;
+ }
+ }
+
+ /**
+ * NAND Gate implementation.
+ * Returns true if at least one input is false; otherwise, false.
+ */
+ static class NANDGate implements BooleanGate {
+ @Override
+ public boolean evaluate(List inputs) {
+ return !new ANDGate().evaluate(inputs); // Equivalent to negation of AND
+ }
+ }
+
+ /**
+ * NOR Gate implementation.
+ * Returns true if all inputs are false; otherwise, false.
+ */
+ static class NORGate implements BooleanGate {
+ @Override
+ public boolean evaluate(List inputs) {
+ return !new ORGate().evaluate(inputs); // Equivalent to negation of OR
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/ClearLeftmostSetBit.java b/src/main/java/com/thealgorithms/bitmanipulation/ClearLeftmostSetBit.java
new file mode 100644
index 000000000000..3e9a4a21183f
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/ClearLeftmostSetBit.java
@@ -0,0 +1,39 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * ClearLeftmostSetBit class contains a method to clear the leftmost set bit of a number.
+ * The leftmost set bit is the leftmost bit that is set to 1 in the binary representation of a number.
+ *
+ * Example:
+ * 26 (11010) -> 10 (01010)
+ * 1 (1) -> 0 (0)
+ * 7 (111) -> 3 (011)
+ * 6 (0110) -> 2 (0010)
+ *
+ * @author Hardvan
+ */
+public final class ClearLeftmostSetBit {
+ private ClearLeftmostSetBit() {
+ }
+
+ /**
+ * Clears the leftmost set bit (1) of a given number.
+ * Step 1: Find the position of the leftmost set bit
+ * Step 2: Create a mask with all bits set except for the leftmost set bit
+ * Step 3: Clear the leftmost set bit using AND with the mask
+ *
+ * @param num The input number.
+ * @return The number after clearing the leftmost set bit.
+ */
+ public static int clearLeftmostSetBit(int num) {
+ int pos = 0;
+ int temp = num;
+ while (temp > 0) {
+ temp >>= 1;
+ pos++;
+ }
+
+ int mask = ~(1 << (pos - 1));
+ return num & mask;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/CountLeadingZeros.java b/src/main/java/com/thealgorithms/bitmanipulation/CountLeadingZeros.java
new file mode 100644
index 000000000000..318334f0b951
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/CountLeadingZeros.java
@@ -0,0 +1,39 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * CountLeadingZeros class contains a method to count the number of leading zeros in the binary representation of a number.
+ * The number of leading zeros is the number of zeros before the leftmost 1 bit.
+ * For example, the number 5 has 29 leading zeros in its 32-bit binary representation.
+ * The number 0 has 32 leading zeros.
+ * The number 1 has 31 leading zeros.
+ * The number -1 has no leading zeros.
+ *
+ * @author Hardvan
+ */
+public final class CountLeadingZeros {
+ private CountLeadingZeros() {
+ }
+
+ /**
+ * Counts the number of leading zeros in the binary representation of a number.
+ * Method: Keep shifting the mask to the right until the leftmost bit is 1.
+ * The number of shifts is the number of leading zeros.
+ *
+ * @param num The input number.
+ * @return The number of leading zeros.
+ */
+ public static int countLeadingZeros(int num) {
+ if (num == 0) {
+ return 32;
+ }
+
+ int count = 0;
+ int mask = 1 << 31;
+ while ((mask & num) == 0) {
+ count++;
+ mask >>>= 1;
+ }
+
+ return count;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/CountSetBits.java b/src/main/java/com/thealgorithms/bitmanipulation/CountSetBits.java
new file mode 100644
index 000000000000..242f35fc35f2
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/CountSetBits.java
@@ -0,0 +1,79 @@
+package com.thealgorithms.bitmanipulation;
+
+public class CountSetBits {
+
+ /**
+ * The below algorithm is called as Brian Kernighan's algorithm
+ * We can use Brian Kernighan’s algorithm to improve the above naive algorithm’s performance.
+ The idea is to only consider the set bits of an integer by turning off its rightmost set bit
+ (after counting it), so the next iteration of the loop considers the next rightmost bit.
+
+ The expression n & (n-1) can be used to turn off the rightmost set bit of a number n. This
+ works as the expression n-1 flips all the bits after the rightmost set bit of n, including the
+ rightmost set bit itself. Therefore, n & (n-1) results in the last bit flipped of n.
+
+ For example, consider number 52, which is 00110100 in binary, and has a total 3 bits set.
+
+ 1st iteration of the loop: n = 52
+
+ 00110100 & (n)
+ 00110011 (n-1)
+ ~~~~~~~~
+ 00110000
+
+
+ 2nd iteration of the loop: n = 48
+
+ 00110000 & (n)
+ 00101111 (n-1)
+ ~~~~~~~~
+ 00100000
+
+
+ 3rd iteration of the loop: n = 32
+
+ 00100000 & (n)
+ 00011111 (n-1)
+ ~~~~~~~~
+ 00000000 (n = 0)
+
+ * @param num takes Long number whose number of set bit is to be found
+ * @return the count of set bits in the binary equivalent
+ */
+ public long countSetBits(long num) {
+ long cnt = 0;
+ while (num > 0) {
+ cnt++;
+ num &= (num - 1);
+ }
+ return cnt;
+ }
+
+ /**
+ * This approach takes O(1) running time to count the set bits, but requires a pre-processing.
+ *
+ * So, we divide our 32-bit input into 8-bit chunks, with four chunks. We have 8 bits in each chunk.
+ *
+ * Then the range is from 0-255 (0 to 2^7).
+ * So, we may need to count set bits from 0 to 255 in individual chunks.
+ *
+ * @param num takes a long number
+ * @return the count of set bits in the binary equivalent
+ */
+ public int lookupApproach(int num) {
+ int[] table = new int[256];
+ table[0] = 0;
+
+ for (int i = 1; i < 256; i++) {
+ table[i] = (i & 1) + table[i >> 1]; // i >> 1 equals to i/2
+ }
+
+ int res = 0;
+ for (int i = 0; i < 4; i++) {
+ res += table[num & 0xff];
+ num >>= 8;
+ }
+
+ return res;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/FindNthBit.java b/src/main/java/com/thealgorithms/bitmanipulation/FindNthBit.java
new file mode 100644
index 000000000000..7a35fc3feebf
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/FindNthBit.java
@@ -0,0 +1,46 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * A utility class to find the Nth bit of a given number.
+ *
+ *
This class provides a method to extract the value of the Nth bit (either 0 or 1)
+ * from the binary representation of a given integer.
+ *
+ *
Example:
+ *
{@code
+ * int result = FindNthBit.findNthBit(5, 2); // returns 0 as the 2nd bit of 5 (binary 101) is 0.
+ * }
+ *
+ *
Author: Tuhinm2002
+ */
+public final class FindNthBit {
+
+ /**
+ * Private constructor to prevent instantiation.
+ *
+ *
This is a utility class, and it should not be instantiated.
+ * Attempting to instantiate this class will throw an UnsupportedOperationException.
+ */
+ private FindNthBit() {
+ throw new UnsupportedOperationException("Utility class");
+ }
+
+ /**
+ * Finds the value of the Nth bit of the given number.
+ *
+ *
This method uses bitwise operations to extract the Nth bit from the
+ * binary representation of the given integer.
+ *
+ * @param num the integer number whose Nth bit is to be found
+ * @param n the bit position (1-based) to retrieve
+ * @return the value of the Nth bit (0 or 1)
+ * @throws IllegalArgumentException if the bit position is less than 1
+ */
+ public static int findNthBit(int num, int n) {
+ if (n < 1) {
+ throw new IllegalArgumentException("Bit position must be greater than or equal to 1.");
+ }
+ // Shifting the number to the right by (n - 1) positions and checking the last bit
+ return (num & (1 << (n - 1))) >> (n - 1);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/FirstDifferentBit.java b/src/main/java/com/thealgorithms/bitmanipulation/FirstDifferentBit.java
new file mode 100644
index 000000000000..9a761c572e2c
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/FirstDifferentBit.java
@@ -0,0 +1,33 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * This class provides a method to find the first differing bit
+ * between two integers.
+ *
+ * Example:
+ * x = 10 (1010 in binary)
+ * y = 12 (1100 in binary)
+ * The first differing bit is at index 1 (0-based)
+ * So, the output will be 1
+ *
+ * @author Hardvan
+ */
+public final class FirstDifferentBit {
+ private FirstDifferentBit() {
+ }
+
+ /**
+ * Identifies the index of the first differing bit between two integers.
+ * Steps:
+ * 1. XOR the two integers to get the differing bits
+ * 2. Find the index of the first set bit in XOR result
+ *
+ * @param x the first integer
+ * @param y the second integer
+ * @return the index of the first differing bit (0-based)
+ */
+ public static int firstDifferentBit(int x, int y) {
+ int diff = x ^ y;
+ return Integer.numberOfTrailingZeros(diff);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/GenerateSubsets.java b/src/main/java/com/thealgorithms/bitmanipulation/GenerateSubsets.java
new file mode 100644
index 000000000000..f1b812495c1b
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/GenerateSubsets.java
@@ -0,0 +1,44 @@
+package com.thealgorithms.bitmanipulation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class provides a method to generate all subsets (power set)
+ * of a given set using bit manipulation.
+ *
+ * @author Hardvan
+ */
+public final class GenerateSubsets {
+ private GenerateSubsets() {
+ }
+
+ /**
+ * Generates all subsets of a given set using bit manipulation.
+ * Steps:
+ * 1. Iterate over all numbers from 0 to 2^n - 1.
+ * 2. For each number, iterate over all bits from 0 to n - 1.
+ * 3. If the i-th bit of the number is set, add the i-th element of the set to the current subset.
+ * 4. Add the current subset to the list of subsets.
+ * 5. Return the list of subsets.
+ *
+ * @param set the input set of integers
+ * @return a list of all subsets represented as lists of integers
+ */
+ public static List> generateSubsets(int[] set) {
+ int n = set.length;
+ List> subsets = new ArrayList<>();
+
+ for (int mask = 0; mask < (1 << n); mask++) {
+ List subset = new ArrayList<>();
+ for (int i = 0; i < n; i++) {
+ if ((mask & (1 << i)) != 0) {
+ subset.add(set[i]);
+ }
+ }
+ subsets.add(subset);
+ }
+
+ return subsets;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/GrayCodeConversion.java b/src/main/java/com/thealgorithms/bitmanipulation/GrayCodeConversion.java
new file mode 100644
index 000000000000..83cd30c7d50a
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/GrayCodeConversion.java
@@ -0,0 +1,44 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * Gray code is a binary numeral system where two successive values differ in only one bit.
+ * This is a simple conversion between binary and Gray code.
+ * Example:
+ * 7 -> 0111 -> 0100 -> 4
+ * 4 -> 0100 -> 0111 -> 7
+ * 0 -> 0000 -> 0000 -> 0
+ * 1 -> 0001 -> 0000 -> 0
+ * 2 -> 0010 -> 0011 -> 3
+ * 3 -> 0011 -> 0010 -> 2
+ *
+ * @author Hardvan
+ */
+public final class GrayCodeConversion {
+ private GrayCodeConversion() {
+ }
+
+ /**
+ * Converts a binary number to Gray code.
+ *
+ * @param num The binary number.
+ * @return The corresponding Gray code.
+ */
+ public static int binaryToGray(int num) {
+ return num ^ (num >> 1);
+ }
+
+ /**
+ * Converts a Gray code number back to binary.
+ *
+ * @param gray The Gray code number.
+ * @return The corresponding binary number.
+ */
+ public static int grayToBinary(int gray) {
+ int binary = gray;
+ while (gray > 0) {
+ gray >>= 1;
+ binary ^= gray;
+ }
+ return binary;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/HammingDistance.java b/src/main/java/com/thealgorithms/bitmanipulation/HammingDistance.java
new file mode 100644
index 000000000000..4c24909ef234
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/HammingDistance.java
@@ -0,0 +1,29 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * The Hamming distance between two integers is the number of positions at which the corresponding bits are different.
+ * Given two integers x and y, calculate the Hamming distance.
+ * Example:
+ * Input: x = 1, y = 4
+ * Output: 2
+ * Explanation: 1 (0001) and 4 (0100) have 2 differing bits.
+ *
+ * @author Hardvan
+ */
+public final class HammingDistance {
+ private HammingDistance() {
+ }
+
+ /**
+ * Calculates the Hamming distance between two integers.
+ * The Hamming distance is the number of differing bits between the two integers.
+ *
+ * @param x The first integer.
+ * @param y The second integer.
+ * @return The Hamming distance (number of differing bits).
+ */
+ public static int hammingDistance(int x, int y) {
+ int xor = x ^ y;
+ return Integer.bitCount(xor);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/HigherLowerPowerOfTwo.java b/src/main/java/com/thealgorithms/bitmanipulation/HigherLowerPowerOfTwo.java
new file mode 100644
index 000000000000..0fb058b2b8a3
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/HigherLowerPowerOfTwo.java
@@ -0,0 +1,54 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * HigherLowerPowerOfTwo class has two methods to find the next higher and lower power of two.
+ *
+ * nextHigherPowerOfTwo method finds the next higher power of two.
+ * nextLowerPowerOfTwo method finds the next lower power of two.
+ * Both methods take an integer as input and return the next higher or lower power of two.
+ * If the input is less than 1, the next higher power of two is 1.
+ * If the input is less than or equal to 1, the next lower power of two is 0.
+ * nextHigherPowerOfTwo method uses bitwise operations to find the next higher power of two.
+ * nextLowerPowerOfTwo method uses Integer.highestOneBit method to find the next lower power of two.
+ * The time complexity of both methods is O(1).
+ * The space complexity of both methods is O(1).
+ *
+ *
+ * @author Hardvan
+ */
+public final class HigherLowerPowerOfTwo {
+ private HigherLowerPowerOfTwo() {
+ }
+
+ /**
+ * Finds the next higher power of two.
+ *
+ * @param x The given number.
+ * @return The next higher power of two.
+ */
+ public static int nextHigherPowerOfTwo(int x) {
+ if (x < 1) {
+ return 1;
+ }
+ x--;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ x |= x >> 16;
+ return x + 1;
+ }
+
+ /**
+ * Finds the next lower power of two.
+ *
+ * @param x The given number.
+ * @return The next lower power of two.
+ */
+ public static int nextLowerPowerOfTwo(int x) {
+ if (x < 1) {
+ return 0;
+ }
+ return Integer.highestOneBit(x);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/HighestSetBit.java b/src/main/java/com/thealgorithms/bitmanipulation/HighestSetBit.java
new file mode 100644
index 000000000000..2398b8214371
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/HighestSetBit.java
@@ -0,0 +1,54 @@
+package com.thealgorithms.bitmanipulation;
+
+import java.util.Optional;
+
+/**
+ * Find Highest Set Bit
+ *
+ * This class provides a utility method to calculate the position of the highest
+ * (most significant) bit that is set to 1 in a given non-negative integer.
+ * It is often used in bit manipulation tasks to find the left-most set bit in binary
+ * representation of a number.
+ *
+ * Example:
+ * - For input 18 (binary 10010), the highest set bit is at position 4 (zero-based index).
+ *
+ * @author Bama Charan Chhandogi
+ * @version 1.0
+ * @since 2021-06-23
+ */
+public final class HighestSetBit {
+
+ private HighestSetBit() {
+ }
+
+ /**
+ * Finds the highest (most significant) set bit in the given integer.
+ * The method returns the position (index) of the highest set bit as an {@link Optional}.
+ *
+ * - If the number is 0, no bits are set, and the method returns {@link Optional#empty()}.
+ * - If the number is negative, the method throws {@link IllegalArgumentException}.
+ *
+ * @param num The input integer for which the highest set bit is to be found. It must be non-negative.
+ * @return An {@link Optional} containing the index of the highest set bit (zero-based).
+ * Returns {@link Optional#empty()} if the number is 0.
+ * @throws IllegalArgumentException if the input number is negative.
+ */
+ public static Optional findHighestSetBit(int num) {
+ if (num < 0) {
+ throw new IllegalArgumentException("Input cannot be negative");
+ }
+
+ if (num == 0) {
+ return Optional.empty();
+ }
+
+ int position = 0;
+ while (num > 0) {
+ num >>= 1;
+ position++;
+ }
+
+ return Optional.of(position - 1); // Subtract 1 to convert to zero-based index
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/IndexOfRightMostSetBit.java b/src/main/java/com/thealgorithms/bitmanipulation/IndexOfRightMostSetBit.java
new file mode 100644
index 000000000000..1b8962344ea7
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/IndexOfRightMostSetBit.java
@@ -0,0 +1,44 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * Utility class for bit manipulation operations.
+ * This class provides methods to work with bitwise operations.
+ * Specifically, it includes a method to find the index of the rightmost set bit
+ * in an integer.
+ * This class is not meant to be instantiated.
+ *
+ * Author: Bama Charan Chhandogi (https://github.com/BamaCharanChhandogi)
+ */
+public final class IndexOfRightMostSetBit {
+
+ private IndexOfRightMostSetBit() {
+ }
+
+ /**
+ * Finds the index of the rightmost set bit in the given integer.
+ * The index is zero-based, meaning the rightmost bit has an index of 0.
+ *
+ * @param n the integer to check for the rightmost set bit
+ * @return the index of the rightmost set bit; -1 if there are no set bits
+ * (i.e., the input integer is 0)
+ */
+ public static int indexOfRightMostSetBit(int n) {
+ if (n == 0) {
+ return -1; // No set bits
+ }
+
+ // Handle negative numbers by finding the two's complement
+ if (n < 0) {
+ n = -n;
+ n = n & (~n + 1); // Isolate the rightmost set bit
+ }
+
+ int index = 0;
+ while ((n & 1) == 0) {
+ n = n >> 1;
+ index++;
+ }
+
+ return index;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/IsEven.java b/src/main/java/com/thealgorithms/bitmanipulation/IsEven.java
new file mode 100644
index 000000000000..09d5383322ff
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/IsEven.java
@@ -0,0 +1,14 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * Checks whether a number is even
+ * @author Bama Charan Chhandogi (https://github.com/BamaCharanChhandogi)
+ */
+
+public final class IsEven {
+ private IsEven() {
+ }
+ public static boolean isEven(int number) {
+ return (number & 1) == 0;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/IsPowerTwo.java b/src/main/java/com/thealgorithms/bitmanipulation/IsPowerTwo.java
new file mode 100644
index 000000000000..4cdf3c6faa3e
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/IsPowerTwo.java
@@ -0,0 +1,32 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * Utility class for checking if a number is a power of two.
+ * A power of two is a number that can be expressed as 2^n where n is a non-negative integer.
+ * This class provides a method to determine if a given integer is a power of two using bit manipulation.
+ *
+ * @author Bama Charan Chhandogi (https://github.com/BamaCharanChhandogi)
+ */
+public final class IsPowerTwo {
+ private IsPowerTwo() {
+ }
+
+ /**
+ * Checks if the given integer is a power of two.
+ *
+ * A number is considered a power of two if it is greater than zero and
+ * has exactly one '1' bit in its binary representation. This method
+ * uses the property that for any power of two (n), the expression
+ * (n & (n - 1)) will be zero.
+ *
+ * @param number the integer to check
+ * @return true if the number is a power of two, false otherwise
+ */
+ public static boolean isPowerTwo(int number) {
+ if (number <= 0) {
+ return false;
+ }
+ int ans = number & (number - 1);
+ return ans == 0;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/LowestSetBit.java b/src/main/java/com/thealgorithms/bitmanipulation/LowestSetBit.java
new file mode 100644
index 000000000000..127b6fa2c0b1
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/LowestSetBit.java
@@ -0,0 +1,34 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * Lowest Set Bit
+ * @author Prayas Kumar (https://github.com/prayas7102)
+ */
+
+public final class LowestSetBit {
+ // Private constructor to hide the default public one
+ private LowestSetBit() {
+ }
+ /**
+ * Isolates the lowest set bit of the given number. For example, if n = 18
+ * (binary: 10010), the result will be 2 (binary: 00010).
+ *
+ * @param n the number whose lowest set bit will be isolated
+ * @return the isolated lowest set bit of n
+ */
+ public static int isolateLowestSetBit(int n) {
+ // Isolate the lowest set bit using n & -n
+ return n & -n;
+ }
+ /**
+ * Clears the lowest set bit of the given number.
+ * For example, if n = 18 (binary: 10010), the result will be 16 (binary: 10000).
+ *
+ * @param n the number whose lowest set bit will be cleared
+ * @return the number after clearing its lowest set bit
+ */
+ public static int clearLowestSetBit(int n) {
+ // Clear the lowest set bit using n & (n - 1)
+ return n & (n - 1);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/ModuloPowerOfTwo.java b/src/main/java/com/thealgorithms/bitmanipulation/ModuloPowerOfTwo.java
new file mode 100644
index 000000000000..537a046f77e4
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/ModuloPowerOfTwo.java
@@ -0,0 +1,28 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * This class provides a method to compute the remainder
+ * of a number when divided by a power of two (2^n)
+ * without using division or modulo operations.
+ *
+ * @author Hardvan
+ */
+public final class ModuloPowerOfTwo {
+ private ModuloPowerOfTwo() {
+ }
+
+ /**
+ * Computes the remainder of a given integer when divided by 2^n.
+ *
+ * @param x the input number
+ * @param n the exponent (power of two)
+ * @return the remainder of x divided by 2^n
+ */
+ public static int moduloPowerOfTwo(int x, int n) {
+ if (n <= 0) {
+ throw new IllegalArgumentException("The exponent must be positive");
+ }
+
+ return x & ((1 << n) - 1);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/NextHigherSameBitCount.java b/src/main/java/com/thealgorithms/bitmanipulation/NextHigherSameBitCount.java
new file mode 100644
index 000000000000..6a764d806279
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/NextHigherSameBitCount.java
@@ -0,0 +1,30 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * This class provides a method to find the next higher number
+ * with the same number of set bits as the given number.
+ *
+ * @author Hardvan
+ */
+public final class NextHigherSameBitCount {
+ private NextHigherSameBitCount() {
+ }
+
+ /**
+ * Finds the next higher integer with the same number of set bits.
+ * Steps:
+ * 1. Find {@code c}, the rightmost set bit of {@code n}.
+ * 2. Find {@code r}, the rightmost set bit of {@code n + c}.
+ * 3. Swap the bits of {@code r} and {@code n} to the right of {@code c}.
+ * 4. Shift the bits of {@code r} and {@code n} to the right of {@code c} to the rightmost.
+ * 5. Combine the results of steps 3 and 4.
+ *
+ * @param n the input number
+ * @return the next higher integer with the same set bit count
+ */
+ public static int nextHigherSameBitCount(int n) {
+ int c = n & -n;
+ int r = n + c;
+ return (((r ^ n) >> 2) / c) | r;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/NonRepeatingNumberFinder.java b/src/main/java/com/thealgorithms/bitmanipulation/NonRepeatingNumberFinder.java
new file mode 100644
index 000000000000..17e1a73ec062
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/NonRepeatingNumberFinder.java
@@ -0,0 +1,35 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * A utility class to find the non-repeating number in an array where every other number repeats.
+ * This class contains a method to identify the single unique number using bit manipulation.
+ *
+ * The solution leverages the properties of the XOR operation, which states that:
+ * - x ^ x = 0 for any integer x (a number XORed with itself is zero)
+ * - x ^ 0 = x for any integer x (a number XORed with zero is the number itself)
+ *
+ * Using these properties, we can find the non-repeating number in linear time with constant space.
+ *
+ * Example:
+ * Given the input array [2, 3, 5, 2, 3], the output will be 5 since it does not repeat.
+ *
+ * @author Bama Charan Chhandogi (https://github.com/BamaCharanChhandogi)
+ */
+public final class NonRepeatingNumberFinder {
+ private NonRepeatingNumberFinder() {
+ }
+
+ /**
+ * Finds the non-repeating number in the given array.
+ *
+ * @param arr an array of integers where every number except one appears twice
+ * @return the integer that appears only once in the array or 0 if the array is empty
+ */
+ public static int findNonRepeatingNumber(int[] arr) {
+ int result = 0;
+ for (int num : arr) {
+ result ^= num;
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/NumberAppearingOddTimes.java b/src/main/java/com/thealgorithms/bitmanipulation/NumberAppearingOddTimes.java
new file mode 100644
index 000000000000..bd4868d4dbd5
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/NumberAppearingOddTimes.java
@@ -0,0 +1,41 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * This class provides a method to find the element that appears an
+ * odd number of times in an array. All other elements in the array
+ * must appear an even number of times for the logic to work.
+ *
+ * The solution uses the XOR operation, which has the following properties:
+ * - a ^ a = 0 (XOR-ing the same numbers cancels them out)
+ * - a ^ 0 = a
+ * - XOR is commutative and associative.
+ *
+ * Time Complexity: O(n), where n is the size of the array.
+ * Space Complexity: O(1), as no extra space is used.
+ *
+ * Usage Example:
+ * int result = NumberAppearingOddTimes.findOddOccurrence(new int[]{1, 2, 1, 2, 3});
+ * // result will be 3
+ *
+ * @author Lakshyajeet Singh Goyal (https://github.com/DarkMatter-999)
+ */
+
+public final class NumberAppearingOddTimes {
+ private NumberAppearingOddTimes() {
+ }
+
+ /**
+ * Finds the element in the array that appears an odd number of times.
+ *
+ * @param arr the input array containing integers, where all elements
+ * except one appear an even number of times.
+ * @return the integer that appears an odd number of times.
+ */
+ public static int findOddOccurrence(int[] arr) {
+ int result = 0;
+ for (int num : arr) {
+ result ^= num;
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/NumbersDifferentSigns.java b/src/main/java/com/thealgorithms/bitmanipulation/NumbersDifferentSigns.java
new file mode 100644
index 000000000000..a2da37aa81ee
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/NumbersDifferentSigns.java
@@ -0,0 +1,30 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * This class provides a method to determine whether two integers have
+ * different signs. It utilizes the XOR operation on the two numbers:
+ *
+ * - If two numbers have different signs, their most significant bits
+ * (sign bits) will differ, resulting in a negative XOR result.
+ * - If two numbers have the same sign, the XOR result will be non-negative.
+ *
+ * Time Complexity: O(1) - Constant time operation.
+ * Space Complexity: O(1) - No extra space used.
+ *
+ * @author Bama Charan Chhandogi
+ */
+public final class NumbersDifferentSigns {
+ private NumbersDifferentSigns() {
+ }
+
+ /**
+ * Determines if two integers have different signs using bitwise XOR.
+ *
+ * @param num1 the first integer
+ * @param num2 the second integer
+ * @return true if the two numbers have different signs, false otherwise
+ */
+ public static boolean differentSigns(int num1, int num2) {
+ return (num1 ^ num2) < 0;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/OneBitDifference.java b/src/main/java/com/thealgorithms/bitmanipulation/OneBitDifference.java
new file mode 100644
index 000000000000..afec0188e299
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/OneBitDifference.java
@@ -0,0 +1,32 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * This class provides a method to detect if two integers
+ * differ by exactly one bit flip.
+ *
+ * Example:
+ * 1 (0001) and 2 (0010) differ by exactly one bit flip.
+ * 7 (0111) and 3 (0011) differ by exactly one bit flip.
+ *
+ * @author Hardvan
+ */
+public final class OneBitDifference {
+ private OneBitDifference() {
+ }
+
+ /**
+ * Checks if two integers differ by exactly one bit.
+ *
+ * @param x the first integer
+ * @param y the second integer
+ * @return true if x and y differ by exactly one bit, false otherwise
+ */
+ public static boolean differByOneBit(int x, int y) {
+ if (x == y) {
+ return false;
+ }
+
+ int xor = x ^ y;
+ return (xor & (xor - 1)) == 0;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/OnesComplement.java b/src/main/java/com/thealgorithms/bitmanipulation/OnesComplement.java
new file mode 100644
index 000000000000..aae3a996e49d
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/OnesComplement.java
@@ -0,0 +1,37 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * @author - https://github.com/Monk-AbhinayVerma
+ * @Wikipedia - https://en.wikipedia.org/wiki/Ones%27_complement
+ * The class OnesComplement computes the complement of binary number
+ * and returns
+ * the complemented binary string.
+ * @return the complimented binary string
+ */
+public final class OnesComplement {
+ private OnesComplement() {
+ }
+
+ /**
+ * Returns the 1's complement of a binary string.
+ *
+ * @param binary A string representing a binary number (e.g., "1010").
+ * @return A string representing the 1's complement.
+ * @throws IllegalArgumentException if the input is null or contains characters other than '0' or '1'.
+ */
+ public static String onesComplement(String binary) {
+ if (binary == null || binary.isEmpty()) {
+ throw new IllegalArgumentException("Input must be a non-empty binary string.");
+ }
+
+ StringBuilder complement = new StringBuilder(binary.length());
+ for (char bit : binary.toCharArray()) {
+ switch (bit) {
+ case '0' -> complement.append('1');
+ case '1' -> complement.append('0');
+ default -> throw new IllegalArgumentException("Input must contain only '0' and '1'. Found: " + bit);
+ }
+ }
+ return complement.toString();
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/ParityCheck.java b/src/main/java/com/thealgorithms/bitmanipulation/ParityCheck.java
new file mode 100644
index 000000000000..5acab4d4a362
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/ParityCheck.java
@@ -0,0 +1,34 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * The ParityCheck class provides a method to check the parity of a given number.
+ *
+ * Parity is a mathematical term that describes the property of an integer's binary representation.
+ * The parity of a binary number is the number of 1s in its binary representation.
+ * If the number of 1s is even, the parity is even; otherwise, it is odd.
+ *
+ * For example, the binary representation of 5 is 101, which has two 1s, so the parity of 5 is even.
+ * The binary representation of 6 is 110, which has two 1s, so the parity of 6 is even.
+ * The binary representation of 7 is 111, which has three 1s, so the parity of 7 is odd.
+ *
+ * @author Hardvan
+ */
+public final class ParityCheck {
+ private ParityCheck() {
+ }
+
+ /**
+ * This method checks the parity of the given number.
+ *
+ * @param n the number to check the parity of
+ * @return true if the number has even parity, false otherwise
+ */
+ public static boolean checkParity(int n) {
+ int count = 0;
+ while (n > 0) {
+ count += n & 1;
+ n >>= 1;
+ }
+ return count % 2 == 0;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/ReverseBits.java b/src/main/java/com/thealgorithms/bitmanipulation/ReverseBits.java
new file mode 100644
index 000000000000..12c269d9be48
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/ReverseBits.java
@@ -0,0 +1,41 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * This class provides a method to reverse the bits of a 32-bit integer.
+ * Reversing the bits means that the least significant bit (LSB) becomes
+ * the most significant bit (MSB) and vice versa.
+ *
+ * Example:
+ * Input (binary): 00000010100101000001111010011100 (43261596)
+ * Output (binary): 00111001011110000010100101000000 (964176192)
+ *
+ * Time Complexity: O(32) - A fixed number of 32 iterations
+ * Space Complexity: O(1) - No extra space used
+ *
+ * Note:
+ * - If the input is negative, Java handles it using two’s complement representation.
+ * - This function works on 32-bit integers by default.
+ *
+ * @author Bama Charan Chhandogi
+ */
+public final class ReverseBits {
+ private ReverseBits() {
+ }
+
+ /**
+ * Reverses the bits of a 32-bit integer.
+ *
+ * @param n the integer whose bits are to be reversed
+ * @return the integer obtained by reversing the bits of the input
+ */
+ public static int reverseBits(int n) {
+ int result = 0;
+ int bitCount = 32;
+ for (int i = 0; i < bitCount; i++) {
+ result <<= 1; // Left shift the result to make space for the next bit
+ result |= (n & 1); // OR operation to set the least significant bit of result with the current bit of n
+ n >>= 1; // Right shift n to move on to the next bit
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/SingleBitOperations.java b/src/main/java/com/thealgorithms/bitmanipulation/SingleBitOperations.java
new file mode 100644
index 000000000000..624a4e2b858a
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/SingleBitOperations.java
@@ -0,0 +1,68 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * A utility class for performing single-bit operations on integers.
+ * These operations include flipping, setting, clearing, and getting
+ * individual bits at specified positions.
+ *
+ * Bit positions are zero-indexed (i.e., the least significant bit is at position 0).
+ * These methods leverage bitwise operations for optimal performance.
+ *
+ * Examples:
+ * - `flipBit(3, 1)` flips the bit at index 1 in binary `11` (result: `1`).
+ * - `setBit(4, 0)` sets the bit at index 0 in `100` (result: `101` or 5).
+ * - `clearBit(7, 1)` clears the bit at index 1 in `111` (result: `101` or 5).
+ * - `getBit(6, 0)` checks if the least significant bit is set (result: `0`).
+ *
+ * Time Complexity: O(1) for all operations.
+ *
+ * Author: lukasb1b (https://github.com/lukasb1b)
+ */
+public final class SingleBitOperations {
+ private SingleBitOperations() {
+ }
+
+ /**
+ * Flips (toggles) the bit at the specified position.
+ *
+ * @param num the input number
+ * @param bit the position of the bit to flip (0-indexed)
+ * @return the new number after flipping the specified bit
+ */
+ public static int flipBit(final int num, final int bit) {
+ return num ^ (1 << bit);
+ }
+
+ /**
+ * Sets the bit at the specified position to 1.
+ *
+ * @param num the input number
+ * @param bit the position of the bit to set (0-indexed)
+ * @return the new number after setting the specified bit to 1
+ */
+ public static int setBit(final int num, final int bit) {
+ return num | (1 << bit);
+ }
+
+ /**
+ * Clears the bit at the specified position (sets it to 0).
+ *
+ * @param num the input number
+ * @param bit the position of the bit to clear (0-indexed)
+ * @return the new number after clearing the specified bit
+ */
+ public static int clearBit(final int num, final int bit) {
+ return num & ~(1 << bit);
+ }
+
+ /**
+ * Gets the bit value (0 or 1) at the specified position.
+ *
+ * @param num the input number
+ * @param bit the position of the bit to retrieve (0-indexed)
+ * @return 1 if the bit is set, 0 otherwise
+ */
+ public static int getBit(final int num, final int bit) {
+ return (num >> bit) & 1;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/SingleElement.java b/src/main/java/com/thealgorithms/bitmanipulation/SingleElement.java
new file mode 100644
index 000000000000..85ebdf02db25
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/SingleElement.java
@@ -0,0 +1,39 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * Utility class to find the single non-duplicate element from an array
+ * where all other elements appear twice.
+ *
+ * The algorithm runs in O(n) time complexity and O(1) space complexity
+ * using bitwise XOR.
+ *
+ *
+ * @author Tuhin M
+ */
+public final class SingleElement {
+
+ /**
+ * Private constructor to prevent instantiation of this utility class.
+ * Throws an UnsupportedOperationException if attempted.
+ */
+ private SingleElement() {
+ throw new UnsupportedOperationException("Utility Class");
+ }
+
+ /**
+ * Finds the single non-duplicate element in an array where every other
+ * element appears exactly twice. Uses bitwise XOR to achieve O(n) time
+ * complexity and O(1) space complexity.
+ *
+ * @param arr the input array containing integers where every element
+ * except one appears exactly twice
+ * @return the single non-duplicate element
+ */
+ public static int findSingleElement(int[] arr) {
+ int ele = 0;
+ for (int i = 0; i < arr.length; i++) {
+ ele ^= arr[i];
+ }
+ return ele;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/SwapAdjacentBits.java b/src/main/java/com/thealgorithms/bitmanipulation/SwapAdjacentBits.java
new file mode 100644
index 000000000000..98a7de8bdf1a
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/SwapAdjacentBits.java
@@ -0,0 +1,57 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * A utility class to swap every pair of adjacent bits in a given integer.
+ * This operation shifts the even-positioned bits to odd positions and vice versa.
+ *
+ * Example:
+ * - Input: 2 (binary: `10`) → Output: 1 (binary: `01`)
+ * - Input: 43 (binary: `101011`) → Output: 23 (binary: `010111`)
+ *
+ * **Explanation of the Algorithm:**
+ * 1. Mask even-positioned bits: Using `0xAAAAAAAA` (binary: `101010...`),
+ * which selects bits in even positions.
+ * 2. Mask odd-positioned bits: Using `0x55555555` (binary: `010101...`),
+ * which selects bits in odd positions.
+ * 3. Shift bits:
+ * - Right-shift even-positioned bits by 1 to move them to odd positions.
+ * - Left-shift odd-positioned bits by 1 to move them to even positions.
+ * 4. Combine both shifted results using bitwise OR (`|`) to produce the final result.
+ *
+ * Use Case: This algorithm can be useful in applications involving low-level bit manipulation,
+ * such as encoding, data compression, or cryptographic transformations.
+ *
+ * Time Complexity: O(1) (constant time, since operations are bitwise).
+ *
+ * Author: Lakshyajeet Singh Goyal (https://github.com/DarkMatter-999)
+ */
+public final class SwapAdjacentBits {
+ private SwapAdjacentBits() {
+ }
+
+ /**
+ * Swaps every pair of adjacent bits of a given integer.
+ * Steps:
+ * 1. Mask the even-positioned bits.
+ * 2. Mask the odd-positioned bits.
+ * 3. Shift the even bits to the right and the odd bits to the left.
+ * 4. Combine the shifted bits.
+ *
+ * @param num the integer whose bits are to be swapped
+ * @return the integer after swapping every pair of adjacent bits
+ */
+ public static int swapAdjacentBits(int num) {
+ // mask the even bits (0xAAAAAAAA => 10101010...)
+ int evenBits = num & 0xAAAAAAAA;
+
+ // mask the odd bits (0x55555555 => 01010101...)
+ int oddBits = num & 0x55555555;
+
+ // right shift even bits and left shift odd bits
+ evenBits >>= 1;
+ oddBits <<= 1;
+
+ // combine shifted bits
+ return evenBits | oddBits;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/TwosComplement.java b/src/main/java/com/thealgorithms/bitmanipulation/TwosComplement.java
new file mode 100644
index 000000000000..9b8cecd791a6
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/TwosComplement.java
@@ -0,0 +1,62 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * This class provides a method to compute the Two's Complement of a given binary number.
+ *
+ *
In two's complement representation, a binary number's negative value is obtained
+ * by taking the one's complement (inverting all bits) and then adding 1 to the result.
+ * This method handles both small and large binary strings and ensures the output is
+ * correct for all binary inputs, including edge cases like all zeroes and all ones.
+ *
+ *
Algorithm originally suggested by Jon von Neumann.
+ *
+ * @author Abhinay Verma (https://github.com/Monk-AbhinayVerma)
+ */
+public final class TwosComplement {
+ private TwosComplement() {
+ }
+
+ /**
+ * Computes the Two's Complement of the given binary string.
+ * Steps:
+ * 1. Compute the One's Complement (invert all bits).
+ * 2. Add 1 to the One's Complement to get the Two's Complement.
+ * 3. Iterate from the rightmost bit to the left, adding 1 and carrying over as needed.
+ * 4. If a carry is still present after the leftmost bit, prepend '1' to handle overflow.
+ *
+ * @param binary The binary number as a string (only '0' and '1' characters allowed).
+ * @return The two's complement of the input binary string as a new binary string.
+ * @throws IllegalArgumentException If the input contains non-binary characters.
+ */
+ public static String twosComplement(String binary) {
+ if (!binary.matches("[01]+")) {
+ throw new IllegalArgumentException("Input must contain only '0' and '1'.");
+ }
+
+ StringBuilder onesComplement = new StringBuilder();
+ for (char bit : binary.toCharArray()) {
+ onesComplement.append(bit == '0' ? '1' : '0');
+ }
+
+ StringBuilder twosComplement = new StringBuilder(onesComplement);
+ boolean carry = true;
+
+ for (int i = onesComplement.length() - 1; i >= 0 && carry; i--) {
+ if (onesComplement.charAt(i) == '1') {
+ twosComplement.setCharAt(i, '0');
+ } else {
+ twosComplement.setCharAt(i, '1');
+ carry = false;
+ }
+ }
+
+ if (carry) {
+ twosComplement.insert(0, '1');
+ }
+
+ return twosComplement.toString();
+ }
+}
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/Xs3Conversion.java b/src/main/java/com/thealgorithms/bitmanipulation/Xs3Conversion.java
new file mode 100644
index 000000000000..b22abc0c04ff
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/Xs3Conversion.java
@@ -0,0 +1,58 @@
+package com.thealgorithms.bitmanipulation;
+
+/**
+ * This class provides methods to convert between XS-3 (Excess-3) and binary.
+ *
+ * Excess-3, also called XS-3, is a binary-coded decimal (BCD) code in which each decimal digit is represented by its corresponding 4-bit binary value plus 3.
+ *
+ * For more information, refer to the
+ * Excess-3 Wikipedia page.
+ *
+ * Example usage:
+ *
+ * int binary = Xs3Conversion.xs3ToBinary(0x4567);
+ * System.out.println("XS-3 0x4567 to binary: " + binary); // Output: 1234
+ *
+ * int xs3 = Xs3Conversion.binaryToXs3(1234);
+ * System.out.println("Binary 1234 to XS-3: " + Integer.toHexString(xs3)); // Output: 0x4567
+ *
+ */
+public final class Xs3Conversion {
+ private Xs3Conversion() {
+ }
+ /**
+ * Converts an XS-3 (Excess-3) number to binary.
+ *
+ * @param xs3 The XS-3 number.
+ * @return The corresponding binary number.
+ */
+ public static int xs3ToBinary(int xs3) {
+ int binary = 0;
+ int multiplier = 1;
+ while (xs3 > 0) {
+ int digit = (xs3 & 0xF) - 3; // Extract the last 4 bits (one XS-3 digit) and subtract 3
+ binary += digit * multiplier;
+ multiplier *= 10;
+ xs3 >>= 4; // Shift right by 4 bits to process the next XS-3 digit
+ }
+ return binary;
+ }
+
+ /**
+ * Converts a binary number to XS-3 (Excess-3).
+ *
+ * @param binary The binary number.
+ * @return The corresponding XS-3 number.
+ */
+ public static int binaryToXs3(int binary) {
+ int xs3 = 0;
+ int shift = 0;
+ while (binary > 0) {
+ int digit = (binary % 10) + 3; // Extract the last decimal digit and add 3
+ xs3 |= (digit << (shift * 4)); // Shift the digit to the correct XS-3 position
+ binary /= 10; // Remove the last decimal digit
+ shift++;
+ }
+ return xs3;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/ciphers/ADFGVXCipher.java b/src/main/java/com/thealgorithms/ciphers/ADFGVXCipher.java
new file mode 100644
index 000000000000..d915858f9e6f
--- /dev/null
+++ b/src/main/java/com/thealgorithms/ciphers/ADFGVXCipher.java
@@ -0,0 +1,167 @@
+package com.thealgorithms.ciphers;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The ADFGVX cipher is a fractionating transposition cipher that was used by
+ * the German Army during World War I. It combines a **Polybius square substitution**
+ * with a **columnar transposition** to enhance encryption strength.
+ *
+ * The name "ADFGVX" refers to the six letters (A, D, F, G, V, X) used as row and
+ * column labels in the Polybius square. This cipher was designed to secure
+ * communication and create complex, hard-to-break ciphertexts.
+ *
+ *
+ * Note: The key size directly affects the security and performance of the RSA algorithm.
+ * Larger keys are more secure but slower to compute.
+ *
+ * @author Nguyen Duy Tiep
+ * @version 23-Oct-17
+ */
+public class RSA {
+
+ private BigInteger modulus;
+ private BigInteger privateKey;
+ private BigInteger publicKey;
+
+ /**
+ * Constructor that generates RSA keys with the specified number of bits.
+ *
+ * @param bits The bit length of the keys to be generated. Common sizes include 512, 1024, 2048, etc.
+ */
+ public RSA(int bits) {
+ generateKeys(bits);
+ }
+
+ /**
+ * Encrypts a text message using the RSA public key.
+ *
+ * @param message The plaintext message to be encrypted.
+ * @throws IllegalArgumentException If the message is empty.
+ * @return The encrypted message represented as a String.
+ */
+ public synchronized String encrypt(String message) {
+ if (message.isEmpty()) {
+ throw new IllegalArgumentException("Message is empty");
+ }
+ return (new BigInteger(message.getBytes())).modPow(publicKey, modulus).toString();
+ }
+
+ /**
+ * Encrypts a BigInteger message using the RSA public key.
+ *
+ * @param message The plaintext message as a BigInteger.
+ * @return The encrypted message as a BigInteger.
+ */
+ public synchronized BigInteger encrypt(BigInteger message) {
+ return message.modPow(publicKey, modulus);
+ }
+
+ /**
+ * Decrypts an encrypted message (as String) using the RSA private key.
+ *
+ * @param encryptedMessage The encrypted message to be decrypted, represented as a String.
+ * @throws IllegalArgumentException If the message is empty.
+ * @return The decrypted plaintext message as a String.
+ */
+ public synchronized String decrypt(String encryptedMessage) {
+ if (encryptedMessage.isEmpty()) {
+ throw new IllegalArgumentException("Message is empty");
+ }
+ return new String((new BigInteger(encryptedMessage)).modPow(privateKey, modulus).toByteArray());
+ }
+
+ /**
+ * Decrypts an encrypted BigInteger message using the RSA private key.
+ *
+ * @param encryptedMessage The encrypted message as a BigInteger.
+ * @return The decrypted plaintext message as a BigInteger.
+ */
+ public synchronized BigInteger decrypt(BigInteger encryptedMessage) {
+ return encryptedMessage.modPow(privateKey, modulus);
+ }
+
+ /**
+ * Generates a new RSA key pair (public and private keys) with the specified bit length.
+ * Steps:
+ * 1. Generate two large prime numbers p and q.
+ * 2. Compute the modulus n = p * q.
+ * 3. Compute Euler's totient function: φ(n) = (p-1) * (q-1).
+ * 4. Choose a public key e (starting from 3) that is coprime with φ(n).
+ * 5. Compute the private key d as the modular inverse of e mod φ(n).
+ * The public key is (e, n) and the private key is (d, n).
+ *
+ * @param bits The bit length of the keys to be generated.
+ */
+ public final synchronized void generateKeys(int bits) {
+ SecureRandom random = new SecureRandom();
+ BigInteger p = new BigInteger(bits / 2, 100, random);
+ BigInteger q = new BigInteger(bits / 2, 100, random);
+ modulus = p.multiply(q);
+
+ BigInteger phi = (p.subtract(BigInteger.ONE)).multiply(q.subtract(BigInteger.ONE));
+
+ publicKey = BigInteger.valueOf(3L);
+ while (phi.gcd(publicKey).intValue() > 1) {
+ publicKey = publicKey.add(BigInteger.TWO);
+ }
+
+ privateKey = publicKey.modInverse(phi);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/ciphers/RailFenceCipher.java b/src/main/java/com/thealgorithms/ciphers/RailFenceCipher.java
new file mode 100644
index 000000000000..f81252980468
--- /dev/null
+++ b/src/main/java/com/thealgorithms/ciphers/RailFenceCipher.java
@@ -0,0 +1,147 @@
+package com.thealgorithms.ciphers;
+
+import java.util.Arrays;
+
+/**
+ * The rail fence cipher (also called a zigzag cipher) is a classical type of transposition cipher.
+ * It derives its name from the manner in which encryption is performed, in analogy to a fence built with horizontal rails.
+ * https://en.wikipedia.org/wiki/Rail_fence_cipher
+ * @author https://github.com/Krounosity
+ */
+
+public class RailFenceCipher {
+
+ // Encrypts the input string using the rail fence cipher method with the given number of rails.
+ public String encrypt(String str, int rails) {
+
+ // Base case of single rail or rails are more than the number of characters in the string
+ if (rails == 1 || rails >= str.length()) {
+ return str;
+ }
+
+ // Boolean flag to determine if the movement is downward or upward in the rail matrix.
+ boolean down = true;
+ // Create a 2D array to represent the rails (rows) and the length of the string (columns).
+ char[][] strRail = new char[rails][str.length()];
+
+ // Initialize all positions in the rail matrix with a placeholder character ('\n').
+ for (int i = 0; i < rails; i++) {
+ Arrays.fill(strRail[i], '\n');
+ }
+
+ int row = 0; // Start at the first row
+ int col = 0; // Start at the first column
+
+ int i = 0;
+
+ // Fill the rail matrix with characters from the string based on the rail pattern.
+ while (col < str.length()) {
+ // Change direction to down when at the first row.
+ if (row == 0) {
+ down = true;
+ }
+ // Change direction to up when at the last row.
+ else if (row == rails - 1) {
+ down = false;
+ }
+
+ // Place the character in the current position of the rail matrix.
+ strRail[row][col] = str.charAt(i);
+ col++; // Move to the next column.
+ // Move to the next row based on the direction.
+ if (down) {
+ row++;
+ } else {
+ row--;
+ }
+
+ i++;
+ }
+
+ // Construct the encrypted string by reading characters row by row.
+ StringBuilder encryptedString = new StringBuilder();
+ for (char[] chRow : strRail) {
+ for (char ch : chRow) {
+ if (ch != '\n') {
+ encryptedString.append(ch);
+ }
+ }
+ }
+ return encryptedString.toString();
+ }
+ // Decrypts the input string using the rail fence cipher method with the given number of rails.
+ public String decrypt(String str, int rails) {
+
+ // Base case of single rail or rails are more than the number of characters in the string
+ if (rails == 1 || rails >= str.length()) {
+ return str;
+ }
+ // Boolean flag to determine if the movement is downward or upward in the rail matrix.
+ boolean down = true;
+
+ // Create a 2D array to represent the rails (rows) and the length of the string (columns).
+ char[][] strRail = new char[rails][str.length()];
+
+ int row = 0; // Start at the first row
+ int col = 0; // Start at the first column
+
+ // Mark the pattern on the rail matrix using '*'.
+ while (col < str.length()) {
+ // Change direction to down when at the first row.
+ if (row == 0) {
+ down = true;
+ }
+ // Change direction to up when at the last row.
+ else if (row == rails - 1) {
+ down = false;
+ }
+
+ // Mark the current position in the rail matrix.
+ strRail[row][col] = '*';
+ col++; // Move to the next column.
+ // Move to the next row based on the direction.
+ if (down) {
+ row++;
+ } else {
+ row--;
+ }
+ }
+
+ int index = 0; // Index to track characters from the input string.
+ // Fill the rail matrix with characters from the input string based on the marked pattern.
+ for (int i = 0; i < rails; i++) {
+ for (int j = 0; j < str.length(); j++) {
+ if (strRail[i][j] == '*') {
+ strRail[i][j] = str.charAt(index++);
+ }
+ }
+ }
+
+ // Construct the decrypted string by following the zigzag pattern.
+ StringBuilder decryptedString = new StringBuilder();
+ row = 0; // Reset to the first row
+ col = 0; // Reset to the first column
+
+ while (col < str.length()) {
+ // Change direction to down when at the first row.
+ if (row == 0) {
+ down = true;
+ }
+ // Change direction to up when at the last row.
+ else if (row == rails - 1) {
+ down = false;
+ }
+ // Append the character from the rail matrix to the decrypted string.
+ decryptedString.append(strRail[row][col]);
+ col++; // Move to the next column.
+ // Move to the next row based on the direction.
+ if (down) {
+ row++;
+ } else {
+ row--;
+ }
+ }
+
+ return decryptedString.toString();
+ }
+}
diff --git a/src/main/java/com/thealgorithms/ciphers/SimpleSubCipher.java b/src/main/java/com/thealgorithms/ciphers/SimpleSubCipher.java
new file mode 100644
index 000000000000..f6c88ef730ec
--- /dev/null
+++ b/src/main/java/com/thealgorithms/ciphers/SimpleSubCipher.java
@@ -0,0 +1,85 @@
+package com.thealgorithms.ciphers;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The simple substitution cipher is a cipher that has been in use for many
+ * hundreds of years (an excellent history is given in Simon Singhs 'the Code
+ * Book'). It basically consists of substituting every plaintext character for a
+ * different ciphertext character. It differs from the Caesar cipher in that the
+ * cipher alphabet is not simply the alphabet shifted, it is completely jumbled.
+ */
+public class SimpleSubCipher {
+
+ /**
+ * Encrypt text by replacing each element with its opposite character.
+ *
+ * @param message
+ * @param cipherSmall
+ * @return Encrypted message
+ */
+ public String encode(String message, String cipherSmall) {
+ StringBuilder encoded = new StringBuilder();
+
+ // This map is used to encode
+ Map cipherMap = new HashMap<>();
+
+ char beginSmallLetter = 'a';
+ char beginCapitalLetter = 'A';
+
+ cipherSmall = cipherSmall.toLowerCase();
+ String cipherCapital = cipherSmall.toUpperCase();
+
+ // To handle Small and Capital letters
+ for (int i = 0; i < cipherSmall.length(); i++) {
+ cipherMap.put(beginSmallLetter++, cipherSmall.charAt(i));
+ cipherMap.put(beginCapitalLetter++, cipherCapital.charAt(i));
+ }
+
+ for (int i = 0; i < message.length(); i++) {
+ if (Character.isAlphabetic(message.charAt(i))) {
+ encoded.append(cipherMap.get(message.charAt(i)));
+ } else {
+ encoded.append(message.charAt(i));
+ }
+ }
+
+ return encoded.toString();
+ }
+
+ /**
+ * Decrypt message by replacing each element with its opposite character in
+ * cipher.
+ *
+ * @param encryptedMessage
+ * @param cipherSmall
+ * @return message
+ */
+ public String decode(String encryptedMessage, String cipherSmall) {
+ StringBuilder decoded = new StringBuilder();
+
+ Map cipherMap = new HashMap<>();
+
+ char beginSmallLetter = 'a';
+ char beginCapitalLetter = 'A';
+
+ cipherSmall = cipherSmall.toLowerCase();
+ String cipherCapital = cipherSmall.toUpperCase();
+
+ for (int i = 0; i < cipherSmall.length(); i++) {
+ cipherMap.put(cipherSmall.charAt(i), beginSmallLetter++);
+ cipherMap.put(cipherCapital.charAt(i), beginCapitalLetter++);
+ }
+
+ for (int i = 0; i < encryptedMessage.length(); i++) {
+ if (Character.isAlphabetic(encryptedMessage.charAt(i))) {
+ decoded.append(cipherMap.get(encryptedMessage.charAt(i)));
+ } else {
+ decoded.append(encryptedMessage.charAt(i));
+ }
+ }
+
+ return decoded.toString();
+ }
+}
diff --git a/src/main/java/com/thealgorithms/ciphers/Vigenere.java b/src/main/java/com/thealgorithms/ciphers/Vigenere.java
new file mode 100644
index 000000000000..0f117853bb85
--- /dev/null
+++ b/src/main/java/com/thealgorithms/ciphers/Vigenere.java
@@ -0,0 +1,106 @@
+package com.thealgorithms.ciphers;
+
+/**
+ * A Java implementation of the Vigenère Cipher.
+ *
+ * The Vigenère Cipher is a polyalphabetic substitution cipher that uses a
+ * keyword to shift letters in the plaintext by different amounts, depending
+ * on the corresponding character in the keyword. It wraps around the alphabet,
+ * ensuring the shifts are within 'A'-'Z' or 'a'-'z'.
+ *
+ * Non-alphabetic characters (like spaces, punctuation) are kept unchanged.
+ *
+ * Encryption Example:
+ * - Plaintext: "Hello World!"
+ * - Key: "suchsecret"
+ * - Encrypted Text: "Zynsg Yfvev!"
+ *
+ * Decryption Example:
+ * - Ciphertext: "Zynsg Yfvev!"
+ * - Key: "suchsecret"
+ * - Decrypted Text: "Hello World!"
+ *
+ * Wikipedia Reference:
+ * Vigenère Cipher - Wikipedia
+ *
+ * @author straiffix
+ * @author beingmartinbmc
+ */
+public class Vigenere {
+
+ /**
+ * Encrypts a given message using the Vigenère Cipher with the specified key.
+ * Steps:
+ * 1. Iterate over each character in the message.
+ * 2. If the character is a letter, shift it by the corresponding character in the key.
+ * 3. Preserve the case of the letter.
+ * 4. Preserve non-alphabetic characters.
+ * 5. Move to the next character in the key (cyclic).
+ * 6. Return the encrypted message.
+ *
+ * @param message The plaintext message to encrypt.
+ * @param key The keyword used for encryption.
+ * @throws IllegalArgumentException if the key is empty.
+ * @return The encrypted message.
+ */
+ public String encrypt(final String message, final String key) {
+ if (key.isEmpty()) {
+ throw new IllegalArgumentException("Key cannot be empty.");
+ }
+
+ StringBuilder result = new StringBuilder();
+ int j = 0;
+ for (int i = 0; i < message.length(); i++) {
+ char c = message.charAt(i);
+ if (Character.isLetter(c)) {
+ if (Character.isUpperCase(c)) {
+ result.append((char) ((c + key.toUpperCase().charAt(j) - 2 * 'A') % 26 + 'A'));
+ } else {
+ result.append((char) ((c + key.toLowerCase().charAt(j) - 2 * 'a') % 26 + 'a'));
+ }
+ j = ++j % key.length();
+ } else {
+ result.append(c);
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * Decrypts a given message encrypted with the Vigenère Cipher using the specified key.
+ * Steps:
+ * 1. Iterate over each character in the message.
+ * 2. If the character is a letter, shift it back by the corresponding character in the key.
+ * 3. Preserve the case of the letter.
+ * 4. Preserve non-alphabetic characters.
+ * 5. Move to the next character in the key (cyclic).
+ * 6. Return the decrypted message.
+ *
+ * @param message The encrypted message to decrypt.
+ * @param key The keyword used for decryption.
+ * @throws IllegalArgumentException if the key is empty.
+ * @return The decrypted plaintext message.
+ */
+ public String decrypt(final String message, final String key) {
+ if (key.isEmpty()) {
+ throw new IllegalArgumentException("Key cannot be empty.");
+ }
+
+ StringBuilder result = new StringBuilder();
+ int j = 0;
+ for (int i = 0; i < message.length(); i++) {
+ char c = message.charAt(i);
+ if (Character.isLetter(c)) {
+ if (Character.isUpperCase(c)) {
+ result.append((char) ('Z' - (25 - (c - key.toUpperCase().charAt(j))) % 26));
+ } else {
+ result.append((char) ('z' - (25 - (c - key.toLowerCase().charAt(j))) % 26));
+ }
+ j = ++j % key.length();
+ } else {
+ result.append(c);
+ }
+ }
+ return result.toString();
+ }
+}
diff --git a/src/main/java/com/thealgorithms/ciphers/XORCipher.java b/src/main/java/com/thealgorithms/ciphers/XORCipher.java
new file mode 100644
index 000000000000..a612ccfbcdef
--- /dev/null
+++ b/src/main/java/com/thealgorithms/ciphers/XORCipher.java
@@ -0,0 +1,95 @@
+package com.thealgorithms.ciphers;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.HexFormat;
+
+/**
+ * A simple implementation of the XOR cipher that allows both encryption and decryption
+ * using a given key. This cipher works by applying the XOR bitwise operation between
+ * the bytes of the input text and the corresponding bytes of the key (repeating the key
+ * if necessary).
+ *
+ * Usage:
+ * - Encryption: Converts plaintext into a hexadecimal-encoded ciphertext.
+ * - Decryption: Converts the hexadecimal ciphertext back into plaintext.
+ *
+ * Characteristics:
+ * - Symmetric: The same key is used for both encryption and decryption.
+ * - Simple but vulnerable: XOR encryption is insecure for real-world cryptography,
+ * especially when the same key is reused.
+ *
+ * Example:
+ * Plaintext: "Hello!"
+ * Key: "key"
+ * Encrypted: "27090c03120b"
+ * Decrypted: "Hello!"
+ *
+ * Reference: XOR Cipher - Wikipedia
+ *
+ * @author lcsjunior
+ */
+public final class XORCipher {
+
+ // Default character encoding for string conversion
+ private static final Charset CS_DEFAULT = StandardCharsets.UTF_8;
+
+ private XORCipher() {
+ }
+
+ /**
+ * Applies the XOR operation between the input bytes and the key bytes.
+ * If the key is shorter than the input, it wraps around (cyclically).
+ *
+ * @param inputBytes The input byte array (plaintext or ciphertext).
+ * @param keyBytes The key byte array used for XOR operation.
+ * @return A new byte array containing the XOR result.
+ */
+ public static byte[] xor(final byte[] inputBytes, final byte[] keyBytes) {
+ byte[] outputBytes = new byte[inputBytes.length];
+ for (int i = 0; i < inputBytes.length; ++i) {
+ outputBytes[i] = (byte) (inputBytes[i] ^ keyBytes[i % keyBytes.length]);
+ }
+ return outputBytes;
+ }
+
+ /**
+ * Encrypts the given plaintext using the XOR cipher with the specified key.
+ * The result is a hexadecimal-encoded string representing the ciphertext.
+ *
+ * @param plainText The input plaintext to encrypt.
+ * @param key The encryption key.
+ * @throws IllegalArgumentException if the key is empty.
+ * @return A hexadecimal string representing the encrypted text.
+ */
+ public static String encrypt(final String plainText, final String key) {
+ if (key.isEmpty()) {
+ throw new IllegalArgumentException("Key must not be empty");
+ }
+
+ byte[] plainTextBytes = plainText.getBytes(CS_DEFAULT);
+ byte[] keyBytes = key.getBytes(CS_DEFAULT);
+ byte[] xorResult = xor(plainTextBytes, keyBytes);
+ return HexFormat.of().formatHex(xorResult);
+ }
+
+ /**
+ * Decrypts the given ciphertext (in hexadecimal format) using the XOR cipher
+ * with the specified key. The result is the original plaintext.
+ *
+ * @param cipherText The hexadecimal string representing the encrypted text.
+ * @param key The decryption key (must be the same as the encryption key).
+ * @throws IllegalArgumentException if the key is empty.
+ * @return The decrypted plaintext.
+ */
+ public static String decrypt(final String cipherText, final String key) {
+ if (key.isEmpty()) {
+ throw new IllegalArgumentException("Key must not be empty");
+ }
+
+ byte[] cipherBytes = HexFormat.of().parseHex(cipherText);
+ byte[] keyBytes = key.getBytes(CS_DEFAULT);
+ byte[] xorResult = xor(cipherBytes, keyBytes);
+ return new String(xorResult, CS_DEFAULT);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/ciphers/a5/A5Cipher.java b/src/main/java/com/thealgorithms/ciphers/a5/A5Cipher.java
new file mode 100644
index 000000000000..cc2e9105229a
--- /dev/null
+++ b/src/main/java/com/thealgorithms/ciphers/a5/A5Cipher.java
@@ -0,0 +1,63 @@
+package com.thealgorithms.ciphers.a5;
+
+import java.util.BitSet;
+
+/**
+ * The A5Cipher class implements the A5/1 stream cipher, which is a widely used
+ * encryption algorithm, particularly in mobile communications.
+ *
+ * This implementation uses a key stream generator to produce a stream of bits
+ * that are XORed with the plaintext bits to produce the ciphertext.
+ *
+ *
+ * For more details about the A5/1 algorithm, refer to
+ * Wikipedia.
+ *
+ */
+public class A5Cipher {
+
+ private final A5KeyStreamGenerator keyStreamGenerator;
+ private static final int KEY_STREAM_LENGTH = 228; // Length of the key stream in bits (28.5 bytes)
+
+ /**
+ * Constructs an A5Cipher instance with the specified session key and frame counter.
+ *
+ * @param sessionKey a BitSet representing the session key used for encryption.
+ * @param frameCounter a BitSet representing the frame counter that helps in key stream generation.
+ */
+ public A5Cipher(BitSet sessionKey, BitSet frameCounter) {
+ keyStreamGenerator = new A5KeyStreamGenerator();
+ keyStreamGenerator.initialize(sessionKey, frameCounter);
+ }
+
+ /**
+ * Encrypts the given plaintext bits using the A5/1 cipher algorithm.
+ *
+ * This method generates a key stream and XORs it with the provided plaintext
+ * bits to produce the ciphertext.
+ *
+ * @param plainTextBits a BitSet representing the plaintext bits to be encrypted.
+ * @return a BitSet containing the encrypted ciphertext bits.
+ */
+ public BitSet encrypt(BitSet plainTextBits) {
+ // create a copy
+ var result = new BitSet(KEY_STREAM_LENGTH);
+ result.xor(plainTextBits);
+
+ var key = keyStreamGenerator.getNextKeyStream();
+ result.xor(key);
+
+ return result;
+ }
+
+ /**
+ * Resets the internal counter of the key stream generator.
+ *
+ * This method can be called to re-initialize the state of the key stream
+ * generator, allowing for new key streams to be generated for subsequent
+ * encryptions.
+ */
+ public void resetCounter() {
+ keyStreamGenerator.reInitialize();
+ }
+}
diff --git a/src/main/java/com/thealgorithms/ciphers/a5/A5KeyStreamGenerator.java b/src/main/java/com/thealgorithms/ciphers/a5/A5KeyStreamGenerator.java
new file mode 100644
index 000000000000..ee837ef4241a
--- /dev/null
+++ b/src/main/java/com/thealgorithms/ciphers/a5/A5KeyStreamGenerator.java
@@ -0,0 +1,121 @@
+package com.thealgorithms.ciphers.a5;
+
+import java.util.BitSet;
+
+/**
+ * The A5KeyStreamGenerator class is responsible for generating key streams
+ * for the A5/1 encryption algorithm using a combination of Linear Feedback Shift Registers (LFSRs).
+ *
+ *
+ * This class extends the CompositeLFSR and initializes a set of LFSRs with
+ * a session key and a frame counter to produce a pseudo-random key stream.
+ *
+ *
+ *
+ * Note: Proper exception handling for invalid usage is to be implemented.
+ *
+ */
+public class A5KeyStreamGenerator extends CompositeLFSR {
+
+ private BitSet initialFrameCounter;
+ private BitSet frameCounter;
+ private BitSet sessionKey;
+ private static final int INITIAL_CLOCKING_CYCLES = 100;
+ private static final int KEY_STREAM_LENGTH = 228;
+
+ /**
+ * Initializes the A5KeyStreamGenerator with the specified session key and frame counter.
+ *
+ *
+ * This method sets up the internal state of the LFSRs using the provided
+ * session key and frame counter. It creates three LFSRs with specific
+ * configurations and initializes them.
+ *
+ *
+ * @param sessionKey a BitSet representing the session key used for key stream generation.
+ * @param frameCounter a BitSet representing the frame counter that influences the key stream.
+ */
+ @Override
+ public void initialize(BitSet sessionKey, BitSet frameCounter) {
+ this.sessionKey = sessionKey;
+ this.frameCounter = (BitSet) frameCounter.clone();
+ this.initialFrameCounter = (BitSet) frameCounter.clone();
+ registers.clear();
+ LFSR lfsr1 = new LFSR(19, 8, new int[] {13, 16, 17, 18});
+ LFSR lfsr2 = new LFSR(22, 10, new int[] {20, 21});
+ LFSR lfsr3 = new LFSR(23, 10, new int[] {7, 20, 21, 22});
+ registers.add(lfsr1);
+ registers.add(lfsr2);
+ registers.add(lfsr3);
+ registers.forEach(lfsr -> lfsr.initialize(sessionKey, frameCounter));
+ }
+
+ /**
+ * Re-initializes the key stream generator with the original session key
+ * and frame counter. This method restores the generator to its initial
+ * state.
+ */
+ public void reInitialize() {
+ this.initialize(sessionKey, initialFrameCounter);
+ }
+
+ /**
+ * Generates the next key stream of bits.
+ *
+ *
+ * This method performs an initial set of clocking cycles and then retrieves
+ * a key stream of the specified length. After generation, it re-initializes
+ * the internal registers.
+ *
+ *
+ * @return a BitSet containing the generated key stream bits.
+ */
+ public BitSet getNextKeyStream() {
+ for (int cycle = 1; cycle <= INITIAL_CLOCKING_CYCLES; ++cycle) {
+ this.clock();
+ }
+
+ BitSet result = new BitSet(KEY_STREAM_LENGTH);
+ for (int cycle = 1; cycle <= KEY_STREAM_LENGTH; ++cycle) {
+ boolean outputBit = this.clock();
+ result.set(cycle - 1, outputBit);
+ }
+
+ reInitializeRegisters();
+ return result;
+ }
+
+ /**
+ * Re-initializes the registers for the LFSRs.
+ *
+ *
+ * This method increments the frame counter and re-initializes each LFSR
+ * with the current session key and frame counter.
+ *
+ * This method uses a utility function to increment the frame counter,
+ * which influences the key stream generation process.
+ *
+ */
+ private void incrementFrameCounter() {
+ Utils.increment(frameCounter, FRAME_COUNTER_LENGTH);
+ }
+
+ /**
+ * Retrieves the current frame counter.
+ *
+ * @return a BitSet representing the current state of the frame counter.
+ */
+ public BitSet getFrameCounter() {
+ return frameCounter;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/ciphers/a5/BaseLFSR.java b/src/main/java/com/thealgorithms/ciphers/a5/BaseLFSR.java
new file mode 100644
index 000000000000..18ad913784dc
--- /dev/null
+++ b/src/main/java/com/thealgorithms/ciphers/a5/BaseLFSR.java
@@ -0,0 +1,10 @@
+package com.thealgorithms.ciphers.a5;
+
+import java.util.BitSet;
+
+public interface BaseLFSR {
+ void initialize(BitSet sessionKey, BitSet frameCounter);
+ boolean clock();
+ int SESSION_KEY_LENGTH = 64;
+ int FRAME_COUNTER_LENGTH = 22;
+}
diff --git a/src/main/java/com/thealgorithms/ciphers/a5/CompositeLFSR.java b/src/main/java/com/thealgorithms/ciphers/a5/CompositeLFSR.java
new file mode 100644
index 000000000000..029a93848c28
--- /dev/null
+++ b/src/main/java/com/thealgorithms/ciphers/a5/CompositeLFSR.java
@@ -0,0 +1,69 @@
+package com.thealgorithms.ciphers.a5;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * The CompositeLFSR class represents a composite implementation of
+ * Linear Feedback Shift Registers (LFSRs) for cryptographic purposes.
+ *
+ *
+ * This abstract class manages a collection of LFSR instances and
+ * provides a mechanism for irregular clocking based on the
+ * majority bit among the registers. It implements the BaseLFSR
+ * interface, requiring subclasses to define specific LFSR behaviors.
+ *
+ */
+public abstract class CompositeLFSR implements BaseLFSR {
+
+ protected final List registers = new ArrayList<>();
+
+ /**
+ * Performs a clocking operation on the composite LFSR.
+ *
+ *
+ * This method determines the majority bit across all registers and
+ * clocks each register based on its clock bit. If a register's
+ * clock bit matches the majority bit, it is clocked (shifted).
+ * The method also computes and returns the XOR of the last bits
+ * of all registers.
+ *
+ *
+ * @return the XOR value of the last bits of all registers.
+ */
+ @Override
+ public boolean clock() {
+ boolean majorityBit = getMajorityBit();
+ boolean result = false;
+ for (var register : registers) {
+ result ^= register.getLastBit();
+ if (register.getClockBit() == majorityBit) {
+ register.clock();
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Calculates the majority bit among all registers.
+ *
+ *
+ * This private method counts the number of true and false clock bits
+ * across all LFSR registers. It returns true if the count of true
+ * bits is greater than or equal to the count of false bits; otherwise,
+ * it returns false.
+ *
+ *
+ * @return true if the majority clock bits are true; false otherwise.
+ */
+ private boolean getMajorityBit() {
+ Map bitCount = new TreeMap<>();
+ bitCount.put(Boolean.FALSE, 0);
+ bitCount.put(Boolean.TRUE, 0);
+
+ registers.forEach(lfsr -> bitCount.put(lfsr.getClockBit(), bitCount.get(lfsr.getClockBit()) + 1));
+ return bitCount.get(Boolean.FALSE) <= bitCount.get(Boolean.TRUE);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/ciphers/a5/LFSR.java b/src/main/java/com/thealgorithms/ciphers/a5/LFSR.java
new file mode 100644
index 000000000000..dc42ae0a7a5e
--- /dev/null
+++ b/src/main/java/com/thealgorithms/ciphers/a5/LFSR.java
@@ -0,0 +1,79 @@
+package com.thealgorithms.ciphers.a5;
+
+import java.util.BitSet;
+
+public class LFSR implements BaseLFSR {
+
+ private final BitSet register;
+ private final int length;
+ private final int clockBitIndex;
+ private final int[] tappingBitsIndices;
+
+ public LFSR(int length, int clockBitIndex, int[] tappingBitsIndices) {
+ this.length = length;
+ this.clockBitIndex = clockBitIndex;
+ this.tappingBitsIndices = tappingBitsIndices;
+ register = new BitSet(length);
+ }
+
+ @Override
+ public void initialize(BitSet sessionKey, BitSet frameCounter) {
+ register.clear();
+ clock(sessionKey, SESSION_KEY_LENGTH);
+ clock(frameCounter, FRAME_COUNTER_LENGTH);
+ }
+
+ private void clock(BitSet key, int keyLength) {
+ // We start from reverse because LFSR 0 index is the left most bit
+ // while key 0 index is right most bit, so we reverse it
+ for (int i = keyLength - 1; i >= 0; --i) {
+ var newBit = key.get(i) ^ xorTappingBits();
+ pushBit(newBit);
+ }
+ }
+
+ @Override
+ public boolean clock() {
+ return pushBit(xorTappingBits());
+ }
+
+ public boolean getClockBit() {
+ return register.get(clockBitIndex);
+ }
+
+ public boolean get(int bitIndex) {
+ return register.get(bitIndex);
+ }
+
+ public boolean getLastBit() {
+ return register.get(length - 1);
+ }
+
+ private boolean xorTappingBits() {
+ boolean result = false;
+ for (int i : tappingBitsIndices) {
+ result ^= register.get(i);
+ }
+ return result;
+ }
+
+ private boolean pushBit(boolean bit) {
+ boolean discardedBit = rightShift();
+ register.set(0, bit);
+ return discardedBit;
+ }
+
+ private boolean rightShift() {
+ boolean discardedBit = get(length - 1);
+ for (int i = length - 1; i > 0; --i) {
+ register.set(i, get(i - 1));
+ }
+ register.set(0, false);
+ return discardedBit;
+ }
+
+ @Override
+ public String toString() {
+ return register.toString();
+ }
+}
diff --git a/src/main/java/com/thealgorithms/ciphers/a5/Utils.java b/src/main/java/com/thealgorithms/ciphers/a5/Utils.java
new file mode 100644
index 000000000000..b4addf18dd9d
--- /dev/null
+++ b/src/main/java/com/thealgorithms/ciphers/a5/Utils.java
@@ -0,0 +1,25 @@
+package com.thealgorithms.ciphers.a5;
+
+// Source
+// http://www.java2s.com/example/java-utility-method/bitset/increment-bitset-bits-int-size-9fd84.html
+// package com.java2s;
+// License from project: Open Source License
+
+import java.util.BitSet;
+
+public final class Utils {
+ private Utils() {
+ }
+
+ public static boolean increment(BitSet bits, int size) {
+ int i = size - 1;
+ while (i >= 0 && bits.get(i)) {
+ bits.set(i--, false); /*from w w w . j a v a 2s .c o m*/
+ }
+ if (i < 0) {
+ return false;
+ }
+ bits.set(i, true);
+ return true;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/AffineConverter.java b/src/main/java/com/thealgorithms/conversions/AffineConverter.java
new file mode 100644
index 000000000000..199a6dd517d5
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/AffineConverter.java
@@ -0,0 +1,64 @@
+package com.thealgorithms.conversions;
+
+/**
+ * A utility class to perform affine transformations of the form:
+ * y = slope * x + intercept.
+ *
+ * This class supports inversion and composition of affine transformations.
+ * It is immutable, meaning each instance represents a fixed transformation.
+ */
+public final class AffineConverter {
+ private final double slope;
+ private final double intercept;
+
+ /**
+ * Constructs an AffineConverter with the given slope and intercept.
+ *
+ * @param inSlope The slope of the affine transformation.
+ * @param inIntercept The intercept (constant term) of the affine transformation.
+ * @throws IllegalArgumentException if either parameter is NaN.
+ */
+ public AffineConverter(final double inSlope, final double inIntercept) {
+ if (Double.isNaN(inSlope) || Double.isNaN(inIntercept)) {
+ throw new IllegalArgumentException("Slope and intercept must be valid numbers.");
+ }
+ slope = inSlope;
+ intercept = inIntercept;
+ }
+
+ /**
+ * Converts the given input value using the affine transformation:
+ * result = slope * inValue + intercept.
+ *
+ * @param inValue The input value to convert.
+ * @return The transformed value.
+ */
+ public double convert(final double inValue) {
+ return slope * inValue + intercept;
+ }
+
+ /**
+ * Returns a new AffineConverter representing the inverse of the current transformation.
+ * The inverse of y = slope * x + intercept is x = (y - intercept) / slope.
+ *
+ * @return A new AffineConverter representing the inverse transformation.
+ * @throws AssertionError if the slope is zero, as the inverse would be undefined.
+ */
+ public AffineConverter invert() {
+ assert slope != 0.0 : "Slope cannot be zero for inversion.";
+ return new AffineConverter(1.0 / slope, -intercept / slope);
+ }
+
+ /**
+ * Composes this affine transformation with another, returning a new AffineConverter.
+ * If this transformation is f(x) and the other is g(x), the result is f(g(x)).
+ *
+ * @param other Another AffineConverter to compose with.
+ * @return A new AffineConverter representing the composition of the two transformations.
+ */
+ public AffineConverter compose(final AffineConverter other) {
+ double newSlope = slope * other.slope;
+ double newIntercept = slope * other.intercept + intercept;
+ return new AffineConverter(newSlope, newIntercept);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/AnyBaseToAnyBase.java b/src/main/java/com/thealgorithms/conversions/AnyBaseToAnyBase.java
new file mode 100644
index 000000000000..7a9448fd8fe7
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/AnyBaseToAnyBase.java
@@ -0,0 +1,181 @@
+package com.thealgorithms.conversions;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.InputMismatchException;
+import java.util.Scanner;
+
+/**
+ * Class for converting from "any" base to "any" other base, when "any" means
+ * from 2-36. Works by going from base 1 to decimal to base 2. Includes
+ * auxiliary method for determining whether a number is valid for a given base.
+ *
+ * @author Michael Rolland
+ * @version 2017.10.10
+ */
+public final class AnyBaseToAnyBase {
+ private AnyBaseToAnyBase() {
+ }
+
+ /**
+ * Smallest and largest base you want to accept as valid input
+ */
+ static final int MINIMUM_BASE = 2;
+
+ static final int MAXIMUM_BASE = 36;
+
+ public static void main(String[] args) {
+ Scanner in = new Scanner(System.in);
+ String n;
+ int b1;
+ int b2;
+ while (true) {
+ try {
+ System.out.print("Enter number: ");
+ n = in.next();
+ System.out.print("Enter beginning base (between " + MINIMUM_BASE + " and " + MAXIMUM_BASE + "): ");
+ b1 = in.nextInt();
+ if (b1 > MAXIMUM_BASE || b1 < MINIMUM_BASE) {
+ System.out.println("Invalid base!");
+ continue;
+ }
+ if (!validForBase(n, b1)) {
+ System.out.println("The number is invalid for this base!");
+ continue;
+ }
+ System.out.print("Enter end base (between " + MINIMUM_BASE + " and " + MAXIMUM_BASE + "): ");
+ b2 = in.nextInt();
+ if (b2 > MAXIMUM_BASE || b2 < MINIMUM_BASE) {
+ System.out.println("Invalid base!");
+ continue;
+ }
+ break;
+ } catch (InputMismatchException e) {
+ System.out.println("Invalid input.");
+ in.next();
+ }
+ }
+ System.out.println(base2base(n, b1, b2));
+ in.close();
+ }
+
+ /**
+ * Checks if a number (as a String) is valid for a given base.
+ */
+ public static boolean validForBase(String n, int base) {
+ char[] validDigits = {
+ '0',
+ '1',
+ '2',
+ '3',
+ '4',
+ '5',
+ '6',
+ '7',
+ '8',
+ '9',
+ 'A',
+ 'B',
+ 'C',
+ 'D',
+ 'E',
+ 'F',
+ 'G',
+ 'H',
+ 'I',
+ 'J',
+ 'K',
+ 'L',
+ 'M',
+ 'N',
+ 'O',
+ 'P',
+ 'Q',
+ 'R',
+ 'S',
+ 'T',
+ 'U',
+ 'V',
+ 'W',
+ 'X',
+ 'Y',
+ 'Z',
+ };
+ // digitsForBase contains all the valid digits for the base given
+ char[] digitsForBase = Arrays.copyOfRange(validDigits, 0, base);
+
+ // Convert character array into set for convenience of contains() method
+ HashSet digitsList = new HashSet<>();
+ for (int i = 0; i < digitsForBase.length; i++) {
+ digitsList.add(digitsForBase[i]);
+ }
+
+ // Check that every digit in n is within the list of valid digits for that base.
+ for (char c : n.toCharArray()) {
+ if (!digitsList.contains(c)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Method to convert any integer from base b1 to base b2. Works by
+ * converting from b1 to decimal, then decimal to b2.
+ *
+ * @param n The integer to be converted.
+ * @param b1 Beginning base.
+ * @param b2 End base.
+ * @return n in base b2.
+ */
+ public static String base2base(String n, int b1, int b2) {
+ // Declare variables: decimal value of n,
+ // character of base b1, character of base b2,
+ // and the string that will be returned.
+ int decimalValue = 0;
+ int charB2;
+ char charB1;
+ StringBuilder output = new StringBuilder();
+ // Go through every character of n
+ for (int i = 0; i < n.length(); i++) {
+ // store the character in charB1
+ charB1 = n.charAt(i);
+ // if it is a non-number, convert it to a decimal value >9 and store it in charB2
+ if (charB1 >= 'A' && charB1 <= 'Z') {
+ charB2 = 10 + (charB1 - 'A');
+ } // Else, store the integer value in charB2
+ else {
+ charB2 = charB1 - '0';
+ }
+ // Convert the digit to decimal and add it to the
+ // decimalValue of n
+ decimalValue = decimalValue * b1 + charB2;
+ }
+
+ // Converting the decimal value to base b2:
+ // A number is converted from decimal to another base
+ // by continuously dividing by the base and recording
+ // the remainder until the quotient is zero. The number in the
+ // new base is the remainders, with the last remainder
+ // being the left-most digit.
+ if (0 == decimalValue) {
+ return "0";
+ }
+ // While the quotient is NOT zero:
+ while (decimalValue != 0) {
+ // If the remainder is a digit < 10, simply add it to
+ // the left side of the new number.
+ if (decimalValue % b2 < 10) {
+ output.insert(0, decimalValue % b2);
+ } // If the remainder is >= 10, add a character with the
+ // corresponding value to the new number. (A = 10, B = 11, C = 12, ...)
+ else {
+ output.insert(0, (char) ((decimalValue % b2) + 55));
+ }
+ // Divide by the new base again
+ decimalValue /= b2;
+ }
+ return output.toString();
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/AnyBaseToDecimal.java b/src/main/java/com/thealgorithms/conversions/AnyBaseToDecimal.java
new file mode 100644
index 000000000000..cdab98c7c28a
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/AnyBaseToDecimal.java
@@ -0,0 +1,52 @@
+package com.thealgorithms.conversions;
+
+/**
+ * @author Varun Upadhyay (...)
+ */
+public final class AnyBaseToDecimal {
+ private static final int CHAR_OFFSET_FOR_DIGIT = '0';
+ private static final int CHAR_OFFSET_FOR_UPPERCASE = 'A' - 10;
+
+ private AnyBaseToDecimal() {
+ }
+
+ /**
+ * Convert any radix to a decimal number.
+ *
+ * @param input the string to be converted
+ * @param radix the radix (base) of the input string
+ * @return the decimal equivalent of the input string
+ * @throws NumberFormatException if the input string or radix is invalid
+ */
+ public static int convertToDecimal(String input, int radix) {
+ int result = 0;
+ int power = 1;
+
+ for (int i = input.length() - 1; i >= 0; i--) {
+ int digit = valOfChar(input.charAt(i));
+ if (digit >= radix) {
+ throw new NumberFormatException("For input string: " + input);
+ }
+ result += digit * power;
+ power *= radix;
+ }
+ return result;
+ }
+
+ /**
+ * Convert a character to its integer value.
+ *
+ * @param character the character to be converted
+ * @return the integer value represented by the character
+ * @throws NumberFormatException if the character is not an uppercase letter or a digit
+ */
+ private static int valOfChar(char character) {
+ if (Character.isDigit(character)) {
+ return character - CHAR_OFFSET_FOR_DIGIT;
+ } else if (Character.isUpperCase(character)) {
+ return character - CHAR_OFFSET_FOR_UPPERCASE;
+ } else {
+ throw new NumberFormatException("invalid character:" + character);
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/AnytoAny.java b/src/main/java/com/thealgorithms/conversions/AnytoAny.java
new file mode 100644
index 000000000000..e7bdbc2b79c4
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/AnytoAny.java
@@ -0,0 +1,68 @@
+package com.thealgorithms.conversions;
+
+/**
+ * A utility class for converting numbers from any base to any other base.
+ *
+ * This class provides a method to convert a source number from a given base
+ * to a destination number in another base. Valid bases range from 2 to 10.
+ */
+public final class AnytoAny {
+ private AnytoAny() {
+ }
+
+ /**
+ * Converts a number from a source base to a destination base.
+ *
+ * @param sourceNumber The number in the source base (as an integer).
+ * @param sourceBase The base of the source number (between 2 and 10).
+ * @param destBase The base to which the number should be converted (between 2 and 10).
+ * @throws IllegalArgumentException if the bases are not between 2 and 10.
+ * @return The converted number in the destination base (as an integer).
+ */
+ public static int convertBase(int sourceNumber, int sourceBase, int destBase) {
+ if (sourceBase < 2 || sourceBase > 10 || destBase < 2 || destBase > 10) {
+ throw new IllegalArgumentException("Bases must be between 2 and 10.");
+ }
+
+ int decimalValue = toDecimal(sourceNumber, sourceBase);
+ return fromDecimal(decimalValue, destBase);
+ }
+
+ /**
+ * Converts a number from a given base to its decimal representation (base 10).
+ *
+ * @param number The number in the original base.
+ * @param base The base of the given number.
+ * @return The decimal representation of the number.
+ */
+ private static int toDecimal(int number, int base) {
+ int decimalValue = 0;
+ int multiplier = 1;
+
+ while (number != 0) {
+ decimalValue += (number % 10) * multiplier;
+ multiplier *= base;
+ number /= 10;
+ }
+ return decimalValue;
+ }
+
+ /**
+ * Converts a decimal (base 10) number to a specified base.
+ *
+ * @param decimal The decimal number to convert.
+ * @param base The destination base for conversion.
+ * @return The number in the specified base.
+ */
+ private static int fromDecimal(int decimal, int base) {
+ int result = 0;
+ int multiplier = 1;
+
+ while (decimal != 0) {
+ result += (decimal % base) * multiplier;
+ multiplier *= 10;
+ decimal /= base;
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/BinaryToDecimal.java b/src/main/java/com/thealgorithms/conversions/BinaryToDecimal.java
new file mode 100644
index 000000000000..36c0790e565f
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/BinaryToDecimal.java
@@ -0,0 +1,33 @@
+package com.thealgorithms.conversions;
+
+/**
+ * This class converts a Binary number to a Decimal number
+ */
+final class BinaryToDecimal {
+ private static final int BINARY_BASE = 2;
+
+ private BinaryToDecimal() {
+ }
+
+ /**
+ * Converts a binary number to its decimal equivalent.
+ *
+ * @param binaryNumber The binary number to convert.
+ * @return The decimal equivalent of the binary number.
+ * @throws IllegalArgumentException If the binary number contains digits other than 0 and 1.
+ */
+ public static long binaryToDecimal(long binaryNumber) {
+ long decimalValue = 0;
+ long power = 0;
+
+ while (binaryNumber != 0) {
+ long digit = binaryNumber % 10;
+ if (digit > 1) {
+ throw new IllegalArgumentException("Incorrect binary digit: " + digit);
+ }
+ decimalValue += (long) (digit * Math.pow(BINARY_BASE, power++));
+ binaryNumber /= 10;
+ }
+ return decimalValue;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/BinaryToHexadecimal.java b/src/main/java/com/thealgorithms/conversions/BinaryToHexadecimal.java
new file mode 100644
index 000000000000..9ff2f593fe1f
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/BinaryToHexadecimal.java
@@ -0,0 +1,63 @@
+package com.thealgorithms.conversions;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Converts any Binary Number to a Hexadecimal Number
+ *
+ * @author Nishita Aggarwal
+ */
+public final class BinaryToHexadecimal {
+ private static final int BITS_IN_HEX_DIGIT = 4;
+ private static final int BASE_BINARY = 2;
+ private static final int BASE_DECIMAL = 10;
+ private static final int HEX_START_DECIMAL = 10;
+ private static final int HEX_END_DECIMAL = 15;
+
+ private BinaryToHexadecimal() {
+ }
+
+ /**
+ * Converts a binary number to a hexadecimal number.
+ *
+ * @param binary The binary number to convert.
+ * @return The hexadecimal representation of the binary number.
+ * @throws IllegalArgumentException If the binary number contains digits other than 0 and 1.
+ */
+ public static String binToHex(int binary) {
+ Map hexMap = initializeHexMap();
+ StringBuilder hex = new StringBuilder();
+
+ while (binary != 0) {
+ int decimalValue = 0;
+ for (int i = 0; i < BITS_IN_HEX_DIGIT; i++) {
+ int currentBit = binary % BASE_DECIMAL;
+ if (currentBit > 1) {
+ throw new IllegalArgumentException("Incorrect binary digit: " + currentBit);
+ }
+ binary /= BASE_DECIMAL;
+ decimalValue += (int) (currentBit * Math.pow(BASE_BINARY, i));
+ }
+ hex.insert(0, hexMap.get(decimalValue));
+ }
+
+ return !hex.isEmpty() ? hex.toString() : "0";
+ }
+
+ /**
+ * Initializes the hexadecimal map with decimal to hexadecimal mappings.
+ *
+ * @return The initialized map containing mappings from decimal numbers to hexadecimal digits.
+ */
+ private static Map initializeHexMap() {
+ Map hexMap = new HashMap<>();
+ for (int i = 0; i < BASE_DECIMAL; i++) {
+ hexMap.put(i, String.valueOf(i));
+ }
+ for (int i = HEX_START_DECIMAL; i <= HEX_END_DECIMAL; i++) {
+ hexMap.put(i, String.valueOf((char) ('A' + i - HEX_START_DECIMAL)));
+ }
+ return hexMap;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/BinaryToOctal.java b/src/main/java/com/thealgorithms/conversions/BinaryToOctal.java
new file mode 100644
index 000000000000..5407c8525a23
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/BinaryToOctal.java
@@ -0,0 +1,45 @@
+package com.thealgorithms.conversions;
+
+public final class BinaryToOctal {
+ private static final int BITS_PER_OCTAL_DIGIT = 3;
+ private static final int BINARY_BASE = 2;
+ private static final int DECIMAL_BASE = 10;
+
+ private BinaryToOctal() {
+ }
+
+ /**
+ * This method converts a binary number to an octal number.
+ *
+ * @param binary The binary number
+ * @return The octal number
+ * @throws IllegalArgumentException if the input is not a valid binary number
+ */
+ public static String convertBinaryToOctal(int binary) {
+ if (binary == 0) {
+ return "0";
+ }
+
+ if (!String.valueOf(binary).matches("[01]+")) {
+ throw new IllegalArgumentException("Input is not a valid binary number.");
+ }
+
+ StringBuilder octal = new StringBuilder();
+ int currentBit;
+ int bitValueMultiplier = 1;
+
+ while (binary != 0) {
+ int octalDigit = 0;
+ for (int i = 0; i < BITS_PER_OCTAL_DIGIT && binary != 0; i++) {
+ currentBit = binary % DECIMAL_BASE;
+ binary /= DECIMAL_BASE;
+ octalDigit += currentBit * bitValueMultiplier;
+ bitValueMultiplier *= BINARY_BASE;
+ }
+ octal.insert(0, octalDigit);
+ bitValueMultiplier = 1; // Reset multiplier for the next group
+ }
+
+ return octal.toString();
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/DecimalToAnyBase.java b/src/main/java/com/thealgorithms/conversions/DecimalToAnyBase.java
new file mode 100644
index 000000000000..a5615dc002f5
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/DecimalToAnyBase.java
@@ -0,0 +1,69 @@
+package com.thealgorithms.conversions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Class that provides methods to convert a decimal number to a string representation
+ * in any specified base between 2 and 36.
+ *
+ * @author Varun Upadhyay (...)
+ */
+public final class DecimalToAnyBase {
+ private static final int MIN_BASE = 2;
+ private static final int MAX_BASE = 36;
+ private static final char ZERO_CHAR = '0';
+ private static final char A_CHAR = 'A';
+ private static final int DIGIT_OFFSET = 10;
+
+ private DecimalToAnyBase() {
+ }
+
+ /**
+ * Converts a decimal number to a string representation in the specified base.
+ * For example, converting the decimal number 10 to base 2 would return "1010".
+ *
+ * @param decimal the decimal number to convert
+ * @param base the base to convert to (must be between {@value #MIN_BASE} and {@value #MAX_BASE})
+ * @return the string representation of the number in the specified base
+ * @throws IllegalArgumentException if the base is out of the supported range
+ */
+ public static String convertToAnyBase(int decimal, int base) {
+ if (base < MIN_BASE || base > MAX_BASE) {
+ throw new IllegalArgumentException("Base must be between " + MIN_BASE + " and " + MAX_BASE);
+ }
+
+ if (decimal == 0) {
+ return String.valueOf(ZERO_CHAR);
+ }
+
+ List digits = new ArrayList<>();
+ while (decimal > 0) {
+ digits.add(convertToChar(decimal % base));
+ decimal /= base;
+ }
+
+ StringBuilder result = new StringBuilder(digits.size());
+ for (int i = digits.size() - 1; i >= 0; i--) {
+ result.append(digits.get(i));
+ }
+
+ return result.toString();
+ }
+
+ /**
+ * Converts an integer value to its corresponding character in the specified base.
+ * This method is used to convert values from 0 to 35 into their appropriate character representation.
+ * For example, 0-9 are represented as '0'-'9', and 10-35 are represented as 'A'-'Z'.
+ *
+ * @param value the integer value to convert (should be less than the base value)
+ * @return the character representing the value in the specified base
+ */
+ private static char convertToChar(int value) {
+ if (value >= 0 && value <= 9) {
+ return (char) (ZERO_CHAR + value);
+ } else {
+ return (char) (A_CHAR + value - DIGIT_OFFSET);
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/DecimalToBinary.java b/src/main/java/com/thealgorithms/conversions/DecimalToBinary.java
new file mode 100644
index 000000000000..e8d033e0093c
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/DecimalToBinary.java
@@ -0,0 +1,49 @@
+package com.thealgorithms.conversions;
+
+/**
+ * This class provides methods to convert a decimal number to a binary number.
+ */
+final class DecimalToBinary {
+ private static final int BINARY_BASE = 2;
+ private static final int DECIMAL_MULTIPLIER = 10;
+
+ private DecimalToBinary() {
+ }
+
+ /**
+ * Converts a decimal number to a binary number using a conventional algorithm.
+ * @param decimalNumber the decimal number to convert
+ * @return the binary representation of the decimal number
+ */
+ public static int convertUsingConventionalAlgorithm(int decimalNumber) {
+ int binaryNumber = 0;
+ int position = 1;
+
+ while (decimalNumber > 0) {
+ int remainder = decimalNumber % BINARY_BASE;
+ binaryNumber += remainder * position;
+ position *= DECIMAL_MULTIPLIER;
+ decimalNumber /= BINARY_BASE;
+ }
+
+ return binaryNumber;
+ }
+
+ /**
+ * Converts a decimal number to a binary number using a bitwise algorithm.
+ * @param decimalNumber the decimal number to convert
+ * @return the binary representation of the decimal number
+ */
+ public static int convertUsingBitwiseAlgorithm(int decimalNumber) {
+ int binaryNumber = 0;
+ int position = 1;
+
+ while (decimalNumber > 0) {
+ int leastSignificantBit = decimalNumber & 1;
+ binaryNumber += leastSignificantBit * position;
+ position *= DECIMAL_MULTIPLIER;
+ decimalNumber >>= 1;
+ }
+ return binaryNumber;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/DecimalToHexadecimal.java b/src/main/java/com/thealgorithms/conversions/DecimalToHexadecimal.java
new file mode 100644
index 000000000000..47a1e36b27e3
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/DecimalToHexadecimal.java
@@ -0,0 +1,42 @@
+package com.thealgorithms.conversions;
+
+/**
+ * This class provides a method to convert a decimal number to a hexadecimal string.
+ */
+final class DecimalToHexadecimal {
+ private static final int SIZE_OF_INT_IN_HALF_BYTES = 8;
+ private static final int NUMBER_OF_BITS_IN_HALF_BYTE = 4;
+ private static final int HALF_BYTE_MASK = 0x0F;
+ private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+ private DecimalToHexadecimal() {
+ }
+
+ /**
+ * Converts a decimal number to a hexadecimal string.
+ * @param decimal the decimal number to convert
+ * @return the hexadecimal representation of the decimal number
+ */
+ public static String decToHex(int decimal) {
+ StringBuilder hexBuilder = new StringBuilder(SIZE_OF_INT_IN_HALF_BYTES);
+ for (int i = SIZE_OF_INT_IN_HALF_BYTES - 1; i >= 0; --i) {
+ int currentHalfByte = decimal & HALF_BYTE_MASK;
+ hexBuilder.insert(0, HEX_DIGITS[currentHalfByte]);
+ decimal >>= NUMBER_OF_BITS_IN_HALF_BYTE;
+ }
+ return removeLeadingZeros(hexBuilder.toString().toLowerCase());
+ }
+
+ private static String removeLeadingZeros(String str) {
+ if (str == null || str.isEmpty()) {
+ return str;
+ }
+
+ int i = 0;
+ while (i < str.length() && str.charAt(i) == '0') {
+ i++;
+ }
+
+ return i == str.length() ? "0" : str.substring(i);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/DecimalToOctal.java b/src/main/java/com/thealgorithms/conversions/DecimalToOctal.java
new file mode 100644
index 000000000000..75687fc589ae
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/DecimalToOctal.java
@@ -0,0 +1,38 @@
+package com.thealgorithms.conversions;
+
+/**
+ * This class converts Decimal numbers to Octal Numbers
+ */
+public final class DecimalToOctal {
+ private static final int OCTAL_BASE = 8;
+ private static final int INITIAL_OCTAL_VALUE = 0;
+ private static final int INITIAL_PLACE_VALUE = 1;
+
+ private DecimalToOctal() {
+ }
+
+ /**
+ * Converts a decimal number to its octal equivalent.
+ *
+ * @param decimal The decimal number to convert.
+ * @return The octal equivalent as an integer.
+ * @throws IllegalArgumentException if the decimal number is negative.
+ */
+ public static int convertToOctal(int decimal) {
+ if (decimal < 0) {
+ throw new IllegalArgumentException("Decimal number cannot be negative.");
+ }
+
+ int octal = INITIAL_OCTAL_VALUE;
+ int placeValue = INITIAL_PLACE_VALUE;
+
+ while (decimal != 0) {
+ int remainder = decimal % OCTAL_BASE;
+ octal += remainder * placeValue;
+ decimal /= OCTAL_BASE;
+ placeValue *= 10;
+ }
+
+ return octal;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/EndianConverter.java b/src/main/java/com/thealgorithms/conversions/EndianConverter.java
new file mode 100644
index 000000000000..0d69098e8255
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/EndianConverter.java
@@ -0,0 +1,47 @@
+package com.thealgorithms.conversions;
+
+/**
+ * Utility class for converting integers between big-endian and little-endian formats.
+ *
+ * Endianness defines how byte sequences represent multi-byte data types:
+ *
+ *
Big-endian: The most significant byte (MSB) comes first.
+ *
Little-endian: The least significant byte (LSB) comes first.
+ *
+ *
+ * Example conversion:
+ *
+ *
Big-endian to little-endian: {@code 0x12345678} → {@code 0x78563412}
+ *
Little-endian to big-endian: {@code 0x78563412} → {@code 0x12345678}
+ *
+ *
+ *
Note: Both conversions in this utility are equivalent since reversing the bytes is symmetric.
+ *
+ *
This class only supports 32-bit integers.
+ *
+ * @author Hardvan
+ */
+public final class EndianConverter {
+ private EndianConverter() {
+ }
+
+ /**
+ * Converts a 32-bit integer from big-endian to little-endian.
+ *
+ * @param value the integer in big-endian format
+ * @return the integer in little-endian format
+ */
+ public static int bigToLittleEndian(int value) {
+ return Integer.reverseBytes(value);
+ }
+
+ /**
+ * Converts a 32-bit integer from little-endian to big-endian.
+ *
+ * @param value the integer in little-endian format
+ * @return the integer in big-endian format
+ */
+ public static int littleToBigEndian(int value) {
+ return Integer.reverseBytes(value);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/HexToOct.java b/src/main/java/com/thealgorithms/conversions/HexToOct.java
new file mode 100644
index 000000000000..d3a672d37424
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/HexToOct.java
@@ -0,0 +1,62 @@
+package com.thealgorithms.conversions;
+
+/**
+ * Converts any Hexadecimal Number to Octal
+ *
+ * @author Tanmay Joshi
+ */
+public final class HexToOct {
+ private HexToOct() {
+ }
+
+ /**
+ * Converts a Hexadecimal number to a Decimal number.
+ *
+ * @param hex The Hexadecimal number as a String.
+ * @return The Decimal equivalent as an integer.
+ */
+ public static int hexToDecimal(String hex) {
+ String hexDigits = "0123456789ABCDEF";
+ hex = hex.toUpperCase();
+ int decimalValue = 0;
+
+ for (int i = 0; i < hex.length(); i++) {
+ char hexChar = hex.charAt(i);
+ int digitValue = hexDigits.indexOf(hexChar);
+ decimalValue = 16 * decimalValue + digitValue;
+ }
+
+ return decimalValue;
+ }
+
+ /**
+ * Converts a Decimal number to an Octal number.
+ *
+ * @param decimal The Decimal number as an integer.
+ * @return The Octal equivalent as an integer.
+ */
+ public static int decimalToOctal(int decimal) {
+ int octalValue = 0;
+ int placeValue = 1;
+
+ while (decimal > 0) {
+ int remainder = decimal % 8;
+ octalValue += remainder * placeValue;
+ decimal /= 8;
+ placeValue *= 10;
+ }
+
+ return octalValue;
+ }
+
+ /**
+ * Converts a Hexadecimal number to an Octal number.
+ *
+ * @param hex The Hexadecimal number as a String.
+ * @return The Octal equivalent as an integer.
+ */
+ public static int hexToOctal(String hex) {
+ int decimalValue = hexToDecimal(hex);
+ return decimalToOctal(decimalValue);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/HexaDecimalToBinary.java b/src/main/java/com/thealgorithms/conversions/HexaDecimalToBinary.java
new file mode 100644
index 000000000000..c0eb9a01ba17
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/HexaDecimalToBinary.java
@@ -0,0 +1,62 @@
+package com.thealgorithms.conversions;
+
+/**
+ * Utility class for converting hexadecimal numbers to binary representation.
+ *
+ * A hexadecimal number consists of digits from {@code [0-9]} and {@code [A-F]} (case-insensitive),
+ * while binary representation uses only {@code [0, 1]}.
+ *
+ * This class provides methods to:
+ *
+ *
Convert a hexadecimal string to its binary string equivalent.
+ *
Ensure the binary output is padded to 8 bits (1 byte).
+ *
+ *
+ * Example:
+ *
+ *
{@code "A1"} → {@code "10100001"}
+ *
{@code "1"} → {@code "00000001"}
+ *
+ *
+ *
This class assumes that the input hexadecimal string is valid.
+ */
+public class HexaDecimalToBinary {
+
+ /**
+ * Converts a hexadecimal string to its binary string equivalent.
+ * The binary output is padded to a minimum of 8 bits (1 byte).
+ * Steps:
+ *
+ *
Convert the hexadecimal string to an integer.
+ *
Convert the integer to a binary string.
+ *
Pad the binary string to ensure it is at least 8 bits long.
+ *
Return the padded binary string.
+ *
+ *
+ * @param numHex the hexadecimal string (e.g., "A1", "7F")
+ * @throws NumberFormatException if the input string is not a valid hexadecimal number
+ * @return the binary string representation, padded to 8 bits (e.g., "10100001")
+ */
+ public String convert(String numHex) {
+ int conHex = Integer.parseInt(numHex, 16);
+ String binary = Integer.toBinaryString(conHex);
+ return completeDigits(binary);
+ }
+
+ /**
+ * Pads the binary string to ensure it is at least 8 bits long.
+ * If the binary string is shorter than 8 bits, it adds leading zeros.
+ *
+ * @param binNum the binary string to pad
+ * @return the padded binary string with a minimum length of 8
+ */
+ public String completeDigits(String binNum) {
+ final int byteSize = 8;
+ StringBuilder binNumBuilder = new StringBuilder(binNum);
+ while (binNumBuilder.length() < byteSize) {
+ binNumBuilder.insert(0, "0");
+ }
+ binNum = binNumBuilder.toString();
+ return binNum;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/HexaDecimalToDecimal.java b/src/main/java/com/thealgorithms/conversions/HexaDecimalToDecimal.java
new file mode 100644
index 000000000000..2cf6024d90a3
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/HexaDecimalToDecimal.java
@@ -0,0 +1,45 @@
+package com.thealgorithms.conversions;
+
+/**
+ * Utility class for converting a hexadecimal string to its decimal representation.
+ *
+ * A hexadecimal number uses the base-16 numeral system, with the following characters:
+ *
+ *
Digits: 0-9
+ *
Letters: A-F (case-insensitive)
+ *
+ * Each character represents a power of 16. For example:
+ *
This class provides a method to perform the conversion without using built-in Java utilities.
+ */
+public final class HexaDecimalToDecimal {
+ private HexaDecimalToDecimal() {
+ }
+
+ /**
+ * Converts a hexadecimal string to its decimal integer equivalent.
+ *
The input string is case-insensitive, and must contain valid hexadecimal characters [0-9, A-F].
+ *
+ * @param hex the hexadecimal string to convert
+ * @return the decimal integer representation of the input hexadecimal string
+ * @throws IllegalArgumentException if the input string contains invalid characters
+ */
+ public static int getHexaToDec(String hex) {
+ String digits = "0123456789ABCDEF";
+ hex = hex.toUpperCase();
+ int val = 0;
+
+ for (int i = 0; i < hex.length(); i++) {
+ int d = digits.indexOf(hex.charAt(i));
+ if (d == -1) {
+ throw new IllegalArgumentException("Invalid hexadecimal character: " + hex.charAt(i));
+ }
+ val = 16 * val + d;
+ }
+
+ return val;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/IPConverter.java b/src/main/java/com/thealgorithms/conversions/IPConverter.java
new file mode 100644
index 000000000000..765cb0201dd5
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/IPConverter.java
@@ -0,0 +1,58 @@
+package com.thealgorithms.conversions;
+
+/**
+ * Converts an IPv4 address to its binary equivalent and vice-versa.
+ * IP to Binary: Converts an IPv4 address to its binary equivalent.
+ * Example: 127.3.4.5 -> 01111111.00000011.00000100.00000101
+ *
+ * Binary to IP: Converts a binary equivalent to an IPv4 address.
+ * Example: 01111111.00000011.00000100.00000101 -> 127.3.4.5
+ *
+ * @author Hardvan
+ */
+public final class IPConverter {
+ private IPConverter() {
+ }
+
+ /**
+ * Converts an IPv4 address to its binary equivalent.
+ * @param ip The IPv4 address to convert.
+ * @return The binary equivalent of the IPv4 address.
+ */
+ public static String ipToBinary(String ip) {
+ StringBuilder binary = new StringBuilder();
+ for (String octet : ip.split("\\.")) {
+ binary.append(octetToBinary(Integer.parseInt(octet))).append(".");
+ }
+ return binary.substring(0, binary.length() - 1);
+ }
+
+ /**
+ * Converts a single octet to its 8-bit binary representation.
+ * @param octet The octet to convert (0-255).
+ * @return The 8-bit binary representation as a String.
+ */
+ private static String octetToBinary(int octet) {
+ char[] binary = {'0', '0', '0', '0', '0', '0', '0', '0'};
+ for (int i = 7; i >= 0; i--) {
+ if ((octet & 1) == 1) {
+ binary[i] = '1';
+ }
+ octet >>>= 1;
+ }
+ return new String(binary);
+ }
+
+ /**
+ * Converts a binary equivalent to an IPv4 address.
+ * @param binary The binary equivalent to convert.
+ * @return The IPv4 address of the binary equivalent.
+ */
+ public static String binaryToIP(String binary) {
+ StringBuilder ip = new StringBuilder();
+ for (String octet : binary.split("\\.")) {
+ ip.append(Integer.parseInt(octet, 2)).append(".");
+ }
+ return ip.substring(0, ip.length() - 1);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/IPv6Converter.java b/src/main/java/com/thealgorithms/conversions/IPv6Converter.java
new file mode 100644
index 000000000000..d42ffd027514
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/IPv6Converter.java
@@ -0,0 +1,98 @@
+package com.thealgorithms.conversions;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+
+/**
+ * A utility class for converting between IPv6 and IPv4 addresses.
+ *
+ * - Converts IPv4 to IPv6-mapped IPv6 address.
+ * - Extracts IPv4 address from IPv6-mapped IPv6.
+ * - Handles exceptions for invalid inputs.
+ *
+ * @author Hardvan
+ */
+public final class IPv6Converter {
+ private IPv6Converter() {
+ }
+
+ /**
+ * Converts an IPv4 address (e.g., "192.0.2.128") to an IPv6-mapped IPv6 address.
+ * Example: IPv4 "192.0.2.128" -> IPv6 "::ffff:192.0.2.128"
+ *
+ * @param ipv4Address The IPv4 address in string format.
+ * @return The corresponding IPv6-mapped IPv6 address.
+ * @throws UnknownHostException If the IPv4 address is invalid.
+ * @throws IllegalArgumentException If the IPv6 address is not a mapped IPv4 address.
+ */
+ public static String ipv4ToIpv6(String ipv4Address) throws UnknownHostException {
+ if (ipv4Address == null || ipv4Address.isEmpty()) {
+ throw new UnknownHostException("IPv4 address is empty.");
+ }
+
+ InetAddress ipv4 = InetAddress.getByName(ipv4Address);
+ byte[] ipv4Bytes = ipv4.getAddress();
+
+ // Create IPv6-mapped IPv6 address (starts with ::ffff:)
+ byte[] ipv6Bytes = new byte[16];
+ ipv6Bytes[10] = (byte) 0xff;
+ ipv6Bytes[11] = (byte) 0xff;
+ System.arraycopy(ipv4Bytes, 0, ipv6Bytes, 12, 4);
+
+ // Manually format to "::ffff:x.x.x.x" format
+ StringBuilder ipv6String = new StringBuilder("::ffff:");
+ for (int i = 12; i < 16; i++) {
+ ipv6String.append(ipv6Bytes[i] & 0xFF);
+ if (i < 15) {
+ ipv6String.append('.');
+ }
+ }
+ return ipv6String.toString();
+ }
+
+ /**
+ * Extracts the IPv4 address from an IPv6-mapped IPv6 address.
+ * Example: IPv6 "::ffff:192.0.2.128" -> IPv4 "192.0.2.128"
+ *
+ * @param ipv6Address The IPv6 address in string format.
+ * @return The extracted IPv4 address.
+ * @throws UnknownHostException If the IPv6 address is invalid or not a mapped IPv4 address.
+ */
+ public static String ipv6ToIpv4(String ipv6Address) throws UnknownHostException {
+ InetAddress ipv6 = InetAddress.getByName(ipv6Address);
+ byte[] ipv6Bytes = ipv6.getAddress();
+
+ // Check if the address is an IPv6-mapped IPv4 address
+ if (isValidIpv6MappedIpv4(ipv6Bytes)) {
+ byte[] ipv4Bytes = Arrays.copyOfRange(ipv6Bytes, 12, 16);
+ InetAddress ipv4 = InetAddress.getByAddress(ipv4Bytes);
+ return ipv4.getHostAddress();
+ } else {
+ throw new IllegalArgumentException("Not a valid IPv6-mapped IPv4 address.");
+ }
+ }
+
+ /**
+ * Helper function to check if the given byte array represents
+ * an IPv6-mapped IPv4 address (prefix 0:0:0:0:0:ffff).
+ *
+ * @param ipv6Bytes Byte array representation of the IPv6 address.
+ * @return True if the address is IPv6-mapped IPv4, otherwise false.
+ */
+ private static boolean isValidIpv6MappedIpv4(byte[] ipv6Bytes) {
+ // IPv6-mapped IPv4 addresses are 16 bytes long, with the first 10 bytes set to 0,
+ // followed by 0xff, 0xff, and the last 4 bytes representing the IPv4 address.
+ if (ipv6Bytes.length != 16) {
+ return false;
+ }
+
+ for (int i = 0; i < 10; i++) {
+ if (ipv6Bytes[i] != 0) {
+ return false;
+ }
+ }
+
+ return ipv6Bytes[10] == (byte) 0xff && ipv6Bytes[11] == (byte) 0xff;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/IntegerToEnglish.java b/src/main/java/com/thealgorithms/conversions/IntegerToEnglish.java
new file mode 100644
index 000000000000..e85c608af5d0
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/IntegerToEnglish.java
@@ -0,0 +1,108 @@
+package com.thealgorithms.conversions;
+
+import java.util.Map;
+
+/**
+ * A utility class to convert integers to their English word representation.
+ *
+ *
The class supports conversion of numbers from 0 to 2,147,483,647
+ * (the maximum value of a 32-bit signed integer). It divides the number
+ * into groups of three digits (thousands, millions, billions, etc.) and
+ * translates each group into words.
BASE_NUMBERS_MAP: Holds English words for numbers 0-20, multiples of 10 up to 90, and 100.
+ *
THOUSAND_POWER_MAP: Maps powers of 1000 (e.g., Thousand, Million, Billion).
+ *
+ */
+public final class IntegerToEnglish {
+
+ private static final Map BASE_NUMBERS_MAP = Map.ofEntries(Map.entry(0, ""), Map.entry(1, "One"), Map.entry(2, "Two"), Map.entry(3, "Three"), Map.entry(4, "Four"), Map.entry(5, "Five"), Map.entry(6, "Six"), Map.entry(7, "Seven"), Map.entry(8, "Eight"), Map.entry(9, "Nine"),
+ Map.entry(10, "Ten"), Map.entry(11, "Eleven"), Map.entry(12, "Twelve"), Map.entry(13, "Thirteen"), Map.entry(14, "Fourteen"), Map.entry(15, "Fifteen"), Map.entry(16, "Sixteen"), Map.entry(17, "Seventeen"), Map.entry(18, "Eighteen"), Map.entry(19, "Nineteen"), Map.entry(20, "Twenty"),
+ Map.entry(30, "Thirty"), Map.entry(40, "Forty"), Map.entry(50, "Fifty"), Map.entry(60, "Sixty"), Map.entry(70, "Seventy"), Map.entry(80, "Eighty"), Map.entry(90, "Ninety"), Map.entry(100, "Hundred"));
+
+ private static final Map THOUSAND_POWER_MAP = Map.ofEntries(Map.entry(1, "Thousand"), Map.entry(2, "Million"), Map.entry(3, "Billion"));
+
+ private IntegerToEnglish() {
+ }
+
+ /**
+ * Converts numbers less than 1000 into English words.
+ *
+ * @param number the integer value (0-999) to convert
+ * @return the English word representation of the input number
+ */
+ private static String convertToWords(int number) {
+ int remainder = number % 100;
+ StringBuilder result = new StringBuilder();
+
+ if (remainder <= 20) {
+ result.append(BASE_NUMBERS_MAP.get(remainder));
+ } else if (BASE_NUMBERS_MAP.containsKey(remainder)) {
+ result.append(BASE_NUMBERS_MAP.get(remainder));
+ } else {
+ int tensDigit = remainder / 10;
+ int onesDigit = remainder % 10;
+ String tens = BASE_NUMBERS_MAP.getOrDefault(tensDigit * 10, "");
+ String ones = BASE_NUMBERS_MAP.getOrDefault(onesDigit, "");
+ result.append(tens);
+ if (ones != null && !ones.isEmpty()) {
+ result.append(" ").append(ones);
+ }
+ }
+
+ int hundredsDigit = number / 100;
+ if (hundredsDigit > 0) {
+ if (result.length() > 0) {
+ result.insert(0, " ");
+ }
+ result.insert(0, String.format("%s Hundred", BASE_NUMBERS_MAP.get(hundredsDigit)));
+ }
+
+ return result.toString().trim();
+ }
+
+ /**
+ * Converts a non-negative integer to its English word representation.
+ *
+ * @param number the integer to convert (0-2,147,483,647)
+ * @return the English word representation of the input number
+ */
+ public static String integerToEnglishWords(int number) {
+ if (number == 0) {
+ return "Zero";
+ }
+
+ StringBuilder result = new StringBuilder();
+ int index = 0;
+
+ while (number > 0) {
+ int remainder = number % 1000;
+ number /= 1000;
+
+ if (remainder > 0) {
+ String subResult = convertToWords(remainder);
+ if (!subResult.isEmpty()) {
+ if (index > 0) {
+ subResult += " " + THOUSAND_POWER_MAP.get(index);
+ }
+ if (result.length() > 0) {
+ result.insert(0, " ");
+ }
+ result.insert(0, subResult);
+ }
+ }
+
+ index++;
+ }
+
+ return result.toString().trim();
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/IntegerToRoman.java b/src/main/java/com/thealgorithms/conversions/IntegerToRoman.java
new file mode 100644
index 000000000000..fec437668fe6
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/IntegerToRoman.java
@@ -0,0 +1,68 @@
+package com.thealgorithms.conversions;
+
+/**
+ * A utility class to convert integers into Roman numerals.
+ *
+ *
Roman numerals follow these rules:
+ *
+ *
I = 1
+ *
IV = 4
+ *
V = 5
+ *
IX = 9
+ *
X = 10
+ *
XL = 40
+ *
L = 50
+ *
XC = 90
+ *
C = 100
+ *
D = 500
+ *
M = 1000
+ *
+ *
+ *
Conversion is based on repeatedly subtracting the largest possible Roman numeral value
+ * from the input number until it reaches zero. For example, 1994 is converted as:
+ *
+ * 1994 -> MCMXCIV (1000 + 900 + 90 + 4)
+ *
+ */
+public final class IntegerToRoman {
+
+ // Array of Roman numeral values in descending order
+ private static final int[] ALL_ROMAN_NUMBERS_IN_ARABIC = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
+
+ // Corresponding Roman numeral symbols
+ private static final String[] ALL_ROMAN_NUMBERS = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
+
+ private IntegerToRoman() {
+ }
+
+ /**
+ * Converts an integer to its Roman numeral representation.
+ * Steps:
+ *
+ *
Iterate over the Roman numeral values in descending order
+ *
Calculate how many times a numeral fits
+ *
Append the corresponding symbol
+ *
Subtract the value from the number
+ *
Repeat until the number is zero
+ *
Return the Roman numeral representation
+ *
+ *
+ * @param num the integer value to convert (must be greater than 0)
+ * @return the Roman numeral representation of the input integer
+ * or an empty string if the input is non-positive
+ */
+ public static String integerToRoman(int num) {
+ if (num <= 0) {
+ return "";
+ }
+
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < ALL_ROMAN_NUMBERS_IN_ARABIC.length; i++) {
+ int times = num / ALL_ROMAN_NUMBERS_IN_ARABIC[i];
+ builder.append(ALL_ROMAN_NUMBERS[i].repeat(Math.max(0, times)));
+ num -= times * ALL_ROMAN_NUMBERS_IN_ARABIC[i];
+ }
+
+ return builder.toString();
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/MorseCodeConverter.java b/src/main/java/com/thealgorithms/conversions/MorseCodeConverter.java
new file mode 100644
index 000000000000..a3973da0c586
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/MorseCodeConverter.java
@@ -0,0 +1,98 @@
+package com.thealgorithms.conversions;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Converts text to Morse code and vice-versa.
+ * Text to Morse code: Each letter is separated by a space and each word is separated by a pipe (|).
+ * Example: "HELLO WORLD" -> ".... . .-.. .-.. --- | .-- --- .-. .-.. -.."
+ *
+ * Morse code to text: Each letter is separated by a space and each word is separated by a pipe (|).
+ * Example: ".... . .-.. .-.. --- | .-- --- .-. .-.. -.." -> "HELLO WORLD"
+ *
+ * Applications: Used in radio communications and algorithmic challenges.
+ *
+ * @author Hardvan
+ */
+public final class MorseCodeConverter {
+ private MorseCodeConverter() {
+ }
+
+ private static final Map MORSE_MAP = new HashMap<>();
+ private static final Map REVERSE_MAP = new HashMap<>();
+
+ static {
+ MORSE_MAP.put('A', ".-");
+ MORSE_MAP.put('B', "-...");
+ MORSE_MAP.put('C', "-.-.");
+ MORSE_MAP.put('D', "-..");
+ MORSE_MAP.put('E', ".");
+ MORSE_MAP.put('F', "..-.");
+ MORSE_MAP.put('G', "--.");
+ MORSE_MAP.put('H', "....");
+ MORSE_MAP.put('I', "..");
+ MORSE_MAP.put('J', ".---");
+ MORSE_MAP.put('K', "-.-");
+ MORSE_MAP.put('L', ".-..");
+ MORSE_MAP.put('M', "--");
+ MORSE_MAP.put('N', "-.");
+ MORSE_MAP.put('O', "---");
+ MORSE_MAP.put('P', ".--.");
+ MORSE_MAP.put('Q', "--.-");
+ MORSE_MAP.put('R', ".-.");
+ MORSE_MAP.put('S', "...");
+ MORSE_MAP.put('T', "-");
+ MORSE_MAP.put('U', "..-");
+ MORSE_MAP.put('V', "...-");
+ MORSE_MAP.put('W', ".--");
+ MORSE_MAP.put('X', "-..-");
+ MORSE_MAP.put('Y', "-.--");
+ MORSE_MAP.put('Z', "--..");
+
+ // Build reverse map for decoding
+ MORSE_MAP.forEach((k, v) -> REVERSE_MAP.put(v, k));
+ }
+
+ /**
+ * Converts text to Morse code.
+ * Each letter is separated by a space and each word is separated by a pipe (|).
+ *
+ * @param text The text to convert to Morse code.
+ * @return The Morse code representation of the text.
+ */
+ public static String textToMorse(String text) {
+ StringBuilder morse = new StringBuilder();
+ String[] words = text.toUpperCase().split(" ");
+ for (int i = 0; i < words.length; i++) {
+ for (char c : words[i].toCharArray()) {
+ morse.append(MORSE_MAP.getOrDefault(c, "")).append(" ");
+ }
+ if (i < words.length - 1) {
+ morse.append("| ");
+ }
+ }
+ return morse.toString().trim();
+ }
+
+ /**
+ * Converts Morse code to text.
+ * Each letter is separated by a space and each word is separated by a pipe (|).
+ *
+ * @param morse The Morse code to convert to text.
+ * @return The text representation of the Morse code.
+ */
+ public static String morseToText(String morse) {
+ StringBuilder text = new StringBuilder();
+ String[] words = morse.split(" \\| ");
+ for (int i = 0; i < words.length; i++) {
+ for (String code : words[i].split(" ")) {
+ text.append(REVERSE_MAP.getOrDefault(code, '?'));
+ }
+ if (i < words.length - 1) {
+ text.append(" ");
+ }
+ }
+ return text.toString();
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/NumberToWords.java b/src/main/java/com/thealgorithms/conversions/NumberToWords.java
new file mode 100644
index 000000000000..e39c5b2dea86
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/NumberToWords.java
@@ -0,0 +1,100 @@
+package com.thealgorithms.conversions;
+
+import java.math.BigDecimal;
+
+/**
+ A Java-based utility for converting numeric values into their English word
+ representations. Whether you need to convert a small number, a large number
+ with millions and billions, or even a number with decimal places, this utility
+ has you covered.
+ *
+ */
+public final class NumberToWords {
+
+ private NumberToWords() {
+ }
+
+ private static final String[] UNITS = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
+
+ private static final String[] TENS = {"", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
+
+ private static final String[] POWERS = {"", "Thousand", "Million", "Billion", "Trillion"};
+
+ private static final String ZERO = "Zero";
+ private static final String POINT = " Point";
+ private static final String NEGATIVE = "Negative ";
+
+ public static String convert(BigDecimal number) {
+ if (number == null) {
+ return "Invalid Input";
+ }
+
+ // Check for negative sign
+ boolean isNegative = number.signum() < 0;
+
+ // Split the number into whole and fractional parts
+ BigDecimal[] parts = number.abs().divideAndRemainder(BigDecimal.ONE);
+ BigDecimal wholePart = parts[0]; // Keep whole part as BigDecimal
+ String fractionalPartStr = parts[1].compareTo(BigDecimal.ZERO) > 0 ? parts[1].toPlainString().substring(2) : ""; // Get fractional part only if it exists
+
+ // Convert whole part to words
+ StringBuilder result = new StringBuilder();
+ if (isNegative) {
+ result.append(NEGATIVE);
+ }
+ result.append(convertWholeNumberToWords(wholePart));
+
+ // Convert fractional part to words
+ if (!fractionalPartStr.isEmpty()) {
+ result.append(POINT);
+ for (char digit : fractionalPartStr.toCharArray()) {
+ int digitValue = Character.getNumericValue(digit);
+ result.append(" ").append(digitValue == 0 ? ZERO : UNITS[digitValue]);
+ }
+ }
+
+ return result.toString().trim();
+ }
+
+ private static String convertWholeNumberToWords(BigDecimal number) {
+ if (number.compareTo(BigDecimal.ZERO) == 0) {
+ return ZERO;
+ }
+
+ StringBuilder words = new StringBuilder();
+ int power = 0;
+
+ while (number.compareTo(BigDecimal.ZERO) > 0) {
+ // Get the last three digits
+ BigDecimal[] divisionResult = number.divideAndRemainder(BigDecimal.valueOf(1000));
+ int chunk = divisionResult[1].intValue();
+
+ if (chunk > 0) {
+ String chunkWords = convertChunk(chunk);
+ if (power > 0) {
+ words.insert(0, POWERS[power] + " ");
+ }
+ words.insert(0, chunkWords + " ");
+ }
+
+ number = divisionResult[0]; // Continue with the remaining part
+ power++;
+ }
+
+ return words.toString().trim();
+ }
+
+ private static String convertChunk(int number) {
+ String chunkWords;
+
+ if (number < 20) {
+ chunkWords = UNITS[number];
+ } else if (number < 100) {
+ chunkWords = TENS[number / 10] + (number % 10 > 0 ? " " + UNITS[number % 10] : "");
+ } else {
+ chunkWords = UNITS[number / 100] + " Hundred" + (number % 100 > 0 ? " " + convertChunk(number % 100) : "");
+ }
+
+ return chunkWords;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/OctalToBinary.java b/src/main/java/com/thealgorithms/conversions/OctalToBinary.java
new file mode 100644
index 000000000000..a66db97633b4
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/OctalToBinary.java
@@ -0,0 +1,82 @@
+package com.thealgorithms.conversions;
+
+/**
+ * A utility class to convert an octal (base-8) number into its binary (base-2) representation.
+ *
+ *
This class provides methods to:
+ *
+ *
Convert an octal number to its binary equivalent
+ *
Convert individual octal digits to binary
+ *
+ *
+ *
Octal to Binary Conversion:
+ *
An octal number is converted to binary by converting each octal digit to its 3-bit binary equivalent.
+ * The result is a long representing the full binary equivalent of the octal number.
+ *
+ *
Example Usage
+ *
+ * long binary = OctalToBinary.convertOctalToBinary(52); // Output: 101010 (52 in octal is 101010 in binary)
+ *
+ *
+ * @author Bama Charan Chhandogi
+ * @see Octal Number System
+ * @see Binary Number System
+ */
+public final class OctalToBinary {
+ private OctalToBinary() {
+ }
+
+ /**
+ * Converts an octal number to its binary representation.
+ *
+ *
Each octal digit is individually converted to its 3-bit binary equivalent, and the binary
+ * digits are concatenated to form the final binary number.
+ *
+ * @param octalNumber the octal number to convert (non-negative integer)
+ * @return the binary equivalent as a long
+ */
+ public static long convertOctalToBinary(int octalNumber) {
+ long binaryNumber = 0;
+ int digitPosition = 1;
+
+ while (octalNumber != 0) {
+ int octalDigit = octalNumber % 10;
+ long binaryDigit = convertOctalDigitToBinary(octalDigit);
+
+ binaryNumber += binaryDigit * digitPosition;
+
+ octalNumber /= 10;
+ digitPosition *= 1000;
+ }
+
+ return binaryNumber;
+ }
+
+ /**
+ * Converts a single octal digit (0-7) to its binary equivalent.
+ *
+ *
For example:
+ *
+ *
Octal digit 7 is converted to binary 111
+ *
Octal digit 3 is converted to binary 011
+ *
+ *
+ *
+ * @param octalDigit a single octal digit (0-7)
+ * @return the binary equivalent as a long
+ */
+ public static long convertOctalDigitToBinary(int octalDigit) {
+ long binaryDigit = 0;
+ int binaryMultiplier = 1;
+
+ while (octalDigit != 0) {
+ int octalDigitRemainder = octalDigit % 2;
+ binaryDigit += octalDigitRemainder * binaryMultiplier;
+
+ octalDigit /= 2;
+ binaryMultiplier *= 10;
+ }
+
+ return binaryDigit;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/OctalToDecimal.java b/src/main/java/com/thealgorithms/conversions/OctalToDecimal.java
new file mode 100644
index 000000000000..d91ce6eb3634
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/OctalToDecimal.java
@@ -0,0 +1,42 @@
+package com.thealgorithms.conversions;
+
+/**
+ * Class for converting an octal number to a decimal number. Octal numbers are based on 8, using digits from 0 to 7.
+ *
+ */
+public final class OctalToDecimal {
+ private static final int OCTAL_BASE = 8;
+
+ private OctalToDecimal() {
+ }
+
+ /**
+ * Converts a given octal number (as a string) to its decimal representation.
+ * If the input is not a valid octal number (i.e., contains characters other than 0-7),
+ * the method throws an IllegalArgumentException.
+ *
+ * @param inputOctal The octal number as a string
+ * @return The decimal equivalent of the octal number
+ * @throws IllegalArgumentException if the input is not a valid octal number
+ */
+ public static int convertOctalToDecimal(String inputOctal) {
+ if (inputOctal == null || inputOctal.isEmpty()) {
+ throw new IllegalArgumentException("Input cannot be null or empty");
+ }
+
+ int decimalValue = 0;
+
+ for (int i = 0; i < inputOctal.length(); i++) {
+ char currentChar = inputOctal.charAt(i);
+
+ if (currentChar < '0' || currentChar > '7') {
+ throw new IllegalArgumentException("Incorrect input: Expecting an octal number (digits 0-7)");
+ }
+
+ int currentDigit = currentChar - '0';
+ decimalValue = decimalValue * OCTAL_BASE + currentDigit;
+ }
+
+ return decimalValue;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/OctalToHexadecimal.java b/src/main/java/com/thealgorithms/conversions/OctalToHexadecimal.java
new file mode 100644
index 000000000000..bac56dc2e221
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/OctalToHexadecimal.java
@@ -0,0 +1,61 @@
+package com.thealgorithms.conversions;
+
+/**
+ * Class for converting an Octal number to its Hexadecimal equivalent.
+ *
+ * @author Tanmay Joshi
+ */
+public final class OctalToHexadecimal {
+ private static final int OCTAL_BASE = 8;
+ private static final int HEX_BASE = 16;
+ private static final String HEX_DIGITS = "0123456789ABCDEF";
+
+ private OctalToHexadecimal() {
+ }
+
+ /**
+ * Converts an Octal number (as a string) to its Decimal equivalent.
+ *
+ * @param octalNumber The Octal number as a string
+ * @return The Decimal equivalent of the Octal number
+ * @throws IllegalArgumentException if the input contains invalid octal digits
+ */
+ public static int octalToDecimal(String octalNumber) {
+ if (octalNumber == null || octalNumber.isEmpty()) {
+ throw new IllegalArgumentException("Input cannot be null or empty");
+ }
+
+ int decimalValue = 0;
+ for (int i = 0; i < octalNumber.length(); i++) {
+ char currentChar = octalNumber.charAt(i);
+ if (currentChar < '0' || currentChar > '7') {
+ throw new IllegalArgumentException("Incorrect octal digit: " + currentChar);
+ }
+ int currentDigit = currentChar - '0';
+ decimalValue = decimalValue * OCTAL_BASE + currentDigit;
+ }
+
+ return decimalValue;
+ }
+
+ /**
+ * Converts a Decimal number to its Hexadecimal equivalent.
+ *
+ * @param decimalNumber The Decimal number
+ * @return The Hexadecimal equivalent of the Decimal number
+ */
+ public static String decimalToHexadecimal(int decimalNumber) {
+ if (decimalNumber == 0) {
+ return "0";
+ }
+
+ StringBuilder hexValue = new StringBuilder();
+ while (decimalNumber > 0) {
+ int digit = decimalNumber % HEX_BASE;
+ hexValue.insert(0, HEX_DIGITS.charAt(digit));
+ decimalNumber /= HEX_BASE;
+ }
+
+ return hexValue.toString();
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/PhoneticAlphabetConverter.java b/src/main/java/com/thealgorithms/conversions/PhoneticAlphabetConverter.java
new file mode 100644
index 000000000000..730ce2214e2d
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/PhoneticAlphabetConverter.java
@@ -0,0 +1,84 @@
+package com.thealgorithms.conversions;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Converts text to the NATO phonetic alphabet.
+ * Examples:
+ * "ABC" -> "Alpha Bravo Charlie"
+ * "Hello" -> "Hotel Echo Lima Lima Oscar"
+ * "123" -> "One Two Three"
+ * "A1B2C3" -> "Alpha One Bravo Two Charlie Three"
+ *
+ * @author Hardvan
+ */
+public final class PhoneticAlphabetConverter {
+ private PhoneticAlphabetConverter() {
+ }
+
+ private static final Map PHONETIC_MAP = new HashMap<>();
+
+ static {
+ PHONETIC_MAP.put('A', "Alpha");
+ PHONETIC_MAP.put('B', "Bravo");
+ PHONETIC_MAP.put('C', "Charlie");
+ PHONETIC_MAP.put('D', "Delta");
+ PHONETIC_MAP.put('E', "Echo");
+ PHONETIC_MAP.put('F', "Foxtrot");
+ PHONETIC_MAP.put('G', "Golf");
+ PHONETIC_MAP.put('H', "Hotel");
+ PHONETIC_MAP.put('I', "India");
+ PHONETIC_MAP.put('J', "Juliett");
+ PHONETIC_MAP.put('K', "Kilo");
+ PHONETIC_MAP.put('L', "Lima");
+ PHONETIC_MAP.put('M', "Mike");
+ PHONETIC_MAP.put('N', "November");
+ PHONETIC_MAP.put('O', "Oscar");
+ PHONETIC_MAP.put('P', "Papa");
+ PHONETIC_MAP.put('Q', "Quebec");
+ PHONETIC_MAP.put('R', "Romeo");
+ PHONETIC_MAP.put('S', "Sierra");
+ PHONETIC_MAP.put('T', "Tango");
+ PHONETIC_MAP.put('U', "Uniform");
+ PHONETIC_MAP.put('V', "Victor");
+ PHONETIC_MAP.put('W', "Whiskey");
+ PHONETIC_MAP.put('X', "X-ray");
+ PHONETIC_MAP.put('Y', "Yankee");
+ PHONETIC_MAP.put('Z', "Zulu");
+ PHONETIC_MAP.put('0', "Zero");
+ PHONETIC_MAP.put('1', "One");
+ PHONETIC_MAP.put('2', "Two");
+ PHONETIC_MAP.put('3', "Three");
+ PHONETIC_MAP.put('4', "Four");
+ PHONETIC_MAP.put('5', "Five");
+ PHONETIC_MAP.put('6', "Six");
+ PHONETIC_MAP.put('7', "Seven");
+ PHONETIC_MAP.put('8', "Eight");
+ PHONETIC_MAP.put('9', "Nine");
+ }
+
+ /**
+ * Converts text to the NATO phonetic alphabet.
+ * Steps:
+ * 1. Convert the text to uppercase.
+ * 2. Iterate over each character in the text.
+ * 3. Get the phonetic equivalent of the character from the map.
+ * 4. Append the phonetic equivalent to the result.
+ * 5. Append a space to separate the phonetic equivalents.
+ * 6. Return the result.
+ *
+ * @param text the text to convert
+ * @return the NATO phonetic alphabet
+ */
+ public static String textToPhonetic(String text) {
+ StringBuilder phonetic = new StringBuilder();
+ for (char c : text.toUpperCase().toCharArray()) {
+ if (Character.isWhitespace(c)) {
+ continue;
+ }
+ phonetic.append(PHONETIC_MAP.getOrDefault(c, String.valueOf(c))).append(" ");
+ }
+ return phonetic.toString().trim();
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/RgbHsvConversion.java b/src/main/java/com/thealgorithms/conversions/RgbHsvConversion.java
new file mode 100644
index 000000000000..84cbff09db6b
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/RgbHsvConversion.java
@@ -0,0 +1,168 @@
+package com.thealgorithms.conversions;
+
+import java.util.Arrays;
+
+/**
+ * The RGB color model is an additive color model in which red, green, and blue
+ * light are added together in various ways to reproduce a broad array of
+ * colors. The name of the model comes from the initials of the three additive
+ * primary colors, red, green, and blue. Meanwhile, the HSV representation
+ * models how colors appear under light. In it, colors are represented using
+ * three components: hue, saturation and (brightness-)value. This class provides
+ * methods for converting colors from one representation to the other.
+ * (description adapted from [1] and
+ * [2]).
+ */
+public final class RgbHsvConversion {
+ private RgbHsvConversion() {
+ }
+
+ public static void main(String[] args) {
+ // Expected RGB-values taken from https://www.rapidtables.com/convert/color/hsv-to-rgb.html
+
+ // Test hsvToRgb-method
+ assert Arrays.equals(hsvToRgb(0, 0, 0), new int[] {0, 0, 0});
+ assert Arrays.equals(hsvToRgb(0, 0, 1), new int[] {255, 255, 255});
+ assert Arrays.equals(hsvToRgb(0, 1, 1), new int[] {255, 0, 0});
+ assert Arrays.equals(hsvToRgb(60, 1, 1), new int[] {255, 255, 0});
+ assert Arrays.equals(hsvToRgb(120, 1, 1), new int[] {0, 255, 0});
+ assert Arrays.equals(hsvToRgb(240, 1, 1), new int[] {0, 0, 255});
+ assert Arrays.equals(hsvToRgb(300, 1, 1), new int[] {255, 0, 255});
+ assert Arrays.equals(hsvToRgb(180, 0.5, 0.5), new int[] {64, 128, 128});
+ assert Arrays.equals(hsvToRgb(234, 0.14, 0.88), new int[] {193, 196, 224});
+ assert Arrays.equals(hsvToRgb(330, 0.75, 0.5), new int[] {128, 32, 80});
+
+ // Test rgbToHsv-method
+ // approximate-assertions needed because of small deviations due to converting between
+ // int-values and double-values.
+ assert approximatelyEqualHsv(rgbToHsv(0, 0, 0), new double[] {0, 0, 0});
+ assert approximatelyEqualHsv(rgbToHsv(255, 255, 255), new double[] {0, 0, 1});
+ assert approximatelyEqualHsv(rgbToHsv(255, 0, 0), new double[] {0, 1, 1});
+ assert approximatelyEqualHsv(rgbToHsv(255, 255, 0), new double[] {60, 1, 1});
+ assert approximatelyEqualHsv(rgbToHsv(0, 255, 0), new double[] {120, 1, 1});
+ assert approximatelyEqualHsv(rgbToHsv(0, 0, 255), new double[] {240, 1, 1});
+ assert approximatelyEqualHsv(rgbToHsv(255, 0, 255), new double[] {300, 1, 1});
+ assert approximatelyEqualHsv(rgbToHsv(64, 128, 128), new double[] {180, 0.5, 0.5});
+ assert approximatelyEqualHsv(rgbToHsv(193, 196, 224), new double[] {234, 0.14, 0.88});
+ assert approximatelyEqualHsv(rgbToHsv(128, 32, 80), new double[] {330, 0.75, 0.5});
+ }
+
+ /**
+ * Conversion from the HSV-representation to the RGB-representation.
+ *
+ * @param hue Hue of the color.
+ * @param saturation Saturation of the color.
+ * @param value Brightness-value of the color.
+ * @return The tuple of RGB-components.
+ */
+ public static int[] hsvToRgb(double hue, double saturation, double value) {
+ if (hue < 0 || hue > 360) {
+ throw new IllegalArgumentException("hue should be between 0 and 360");
+ }
+
+ if (saturation < 0 || saturation > 1) {
+ throw new IllegalArgumentException("saturation should be between 0 and 1");
+ }
+
+ if (value < 0 || value > 1) {
+ throw new IllegalArgumentException("value should be between 0 and 1");
+ }
+
+ double chroma = value * saturation;
+ double hueSection = hue / 60;
+ double secondLargestComponent = chroma * (1 - Math.abs(hueSection % 2 - 1));
+ double matchValue = value - chroma;
+
+ return getRgbBySection(hueSection, chroma, matchValue, secondLargestComponent);
+ }
+
+ /**
+ * Conversion from the RGB-representation to the HSV-representation.
+ *
+ * @param red Red-component of the color.
+ * @param green Green-component of the color.
+ * @param blue Blue-component of the color.
+ * @return The tuple of HSV-components.
+ */
+ public static double[] rgbToHsv(int red, int green, int blue) {
+ if (red < 0 || red > 255) {
+ throw new IllegalArgumentException("red should be between 0 and 255");
+ }
+
+ if (green < 0 || green > 255) {
+ throw new IllegalArgumentException("green should be between 0 and 255");
+ }
+
+ if (blue < 0 || blue > 255) {
+ throw new IllegalArgumentException("blue should be between 0 and 255");
+ }
+
+ double dRed = (double) red / 255;
+ double dGreen = (double) green / 255;
+ double dBlue = (double) blue / 255;
+ double value = Math.max(Math.max(dRed, dGreen), dBlue);
+ double chroma = value - Math.min(Math.min(dRed, dGreen), dBlue);
+ double saturation = value == 0 ? 0 : chroma / value;
+ double hue;
+
+ if (chroma == 0) {
+ hue = 0;
+ } else if (value == dRed) {
+ hue = 60 * (0 + (dGreen - dBlue) / chroma);
+ } else if (value == dGreen) {
+ hue = 60 * (2 + (dBlue - dRed) / chroma);
+ } else {
+ hue = 60 * (4 + (dRed - dGreen) / chroma);
+ }
+
+ hue = (hue + 360) % 360;
+
+ return new double[] {hue, saturation, value};
+ }
+
+ private static boolean approximatelyEqualHsv(double[] hsv1, double[] hsv2) {
+ boolean bHue = Math.abs(hsv1[0] - hsv2[0]) < 0.2;
+ boolean bSaturation = Math.abs(hsv1[1] - hsv2[1]) < 0.002;
+ boolean bValue = Math.abs(hsv1[2] - hsv2[2]) < 0.002;
+
+ return bHue && bSaturation && bValue;
+ }
+
+ private static int[] getRgbBySection(double hueSection, double chroma, double matchValue, double secondLargestComponent) {
+ int red;
+ int green;
+ int blue;
+
+ if (hueSection >= 0 && hueSection <= 1) {
+ red = convertToInt(chroma + matchValue);
+ green = convertToInt(secondLargestComponent + matchValue);
+ blue = convertToInt(matchValue);
+ } else if (hueSection > 1 && hueSection <= 2) {
+ red = convertToInt(secondLargestComponent + matchValue);
+ green = convertToInt(chroma + matchValue);
+ blue = convertToInt(matchValue);
+ } else if (hueSection > 2 && hueSection <= 3) {
+ red = convertToInt(matchValue);
+ green = convertToInt(chroma + matchValue);
+ blue = convertToInt(secondLargestComponent + matchValue);
+ } else if (hueSection > 3 && hueSection <= 4) {
+ red = convertToInt(matchValue);
+ green = convertToInt(secondLargestComponent + matchValue);
+ blue = convertToInt(chroma + matchValue);
+ } else if (hueSection > 4 && hueSection <= 5) {
+ red = convertToInt(secondLargestComponent + matchValue);
+ green = convertToInt(matchValue);
+ blue = convertToInt(chroma + matchValue);
+ } else {
+ red = convertToInt(chroma + matchValue);
+ green = convertToInt(matchValue);
+ blue = convertToInt(secondLargestComponent + matchValue);
+ }
+
+ return new int[] {red, green, blue};
+ }
+
+ private static int convertToInt(double input) {
+ return (int) Math.round(255 * input);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/RomanToInteger.java b/src/main/java/com/thealgorithms/conversions/RomanToInteger.java
new file mode 100644
index 000000000000..a634c720326f
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/RomanToInteger.java
@@ -0,0 +1,91 @@
+package com.thealgorithms.conversions;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A utility class to convert Roman numerals into integers.
+ *
+ *
Roman numerals are based on seven symbols given below:
+ *
+ *
I = 1
+ *
V = 5
+ *
X = 10
+ *
L = 50
+ *
C = 100
+ *
D = 500
+ *
M = 1000
+ *
+ *
+ *
If a smaller numeral appears before a larger numeral, it is subtracted.
+ * Otherwise, it is added. For example:
+ *
+ */
+public final class RomanToInteger {
+
+ private static final Map ROMAN_TO_INT = new HashMap<>() {
+ {
+ put('I', 1);
+ put('V', 5);
+ put('X', 10);
+ put('L', 50);
+ put('C', 100);
+ put('D', 500);
+ put('M', 1000);
+ }
+ };
+
+ private RomanToInteger() {
+ }
+
+ /**
+ * Converts a single Roman numeral character to its integer value.
+ *
+ * @param symbol the Roman numeral character
+ * @return the corresponding integer value
+ * @throws IllegalArgumentException if the symbol is not a valid Roman numeral
+ */
+ private static int romanSymbolToInt(final char symbol) {
+ return ROMAN_TO_INT.computeIfAbsent(symbol, c -> { throw new IllegalArgumentException("Unknown Roman symbol: " + c); });
+ }
+
+ /**
+ * Converts a Roman numeral string to its integer equivalent.
+ * Steps:
+ *
+ *
Iterate over the string from right to left.
+ *
For each character, convert it to an integer value.
+ *
If the current value is greater than or equal to the max previous value, add it.
+ *
Otherwise, subtract it from the sum.
+ *
Update the max previous value.
+ *
Return the sum.
+ *
+ *
+ * @param roman the Roman numeral string
+ * @return the integer value of the Roman numeral
+ * @throws IllegalArgumentException if the input contains invalid Roman characters
+ * @throws NullPointerException if the input is {@code null}
+ */
+ public static int romanToInt(String roman) {
+ if (roman == null) {
+ throw new NullPointerException("Input cannot be null");
+ }
+
+ roman = roman.toUpperCase();
+ int sum = 0;
+ int maxPrevValue = 0;
+ for (int i = roman.length() - 1; i >= 0; i--) {
+ int currentValue = romanSymbolToInt(roman.charAt(i));
+ if (currentValue >= maxPrevValue) {
+ sum += currentValue;
+ maxPrevValue = currentValue;
+ } else {
+ sum -= currentValue;
+ }
+ }
+
+ return sum;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/TurkishToLatinConversion.java b/src/main/java/com/thealgorithms/conversions/TurkishToLatinConversion.java
new file mode 100644
index 000000000000..30030de6c1bd
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/TurkishToLatinConversion.java
@@ -0,0 +1,56 @@
+package com.thealgorithms.conversions;
+
+/**
+ * Converts turkish character to latin character
+ *
+ * @author Özgün Gökşenli
+ */
+public final class TurkishToLatinConversion {
+ private TurkishToLatinConversion() {
+ }
+
+ /**
+ * This method converts a turkish character to latin character.
+ * Steps:
+ * 1. Define turkish characters and their corresponding latin characters
+ * 2. Replace all turkish characters with their corresponding latin characters
+ * 3. Return the converted string
+ *
+ * @param param String paramter
+ * @return String
+ */
+ public static String convertTurkishToLatin(String param) {
+ char[] turkishChars = new char[] {
+ 0x131,
+ 0x130,
+ 0xFC,
+ 0xDC,
+ 0xF6,
+ 0xD6,
+ 0x15F,
+ 0x15E,
+ 0xE7,
+ 0xC7,
+ 0x11F,
+ 0x11E,
+ };
+ char[] latinChars = new char[] {
+ 'i',
+ 'I',
+ 'u',
+ 'U',
+ 'o',
+ 'O',
+ 's',
+ 'S',
+ 'c',
+ 'C',
+ 'g',
+ 'G',
+ };
+ for (int i = 0; i < turkishChars.length; i++) {
+ param = param.replaceAll(String.valueOf(turkishChars[i]), String.valueOf(latinChars[i]));
+ }
+ return param;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/UnitConversions.java b/src/main/java/com/thealgorithms/conversions/UnitConversions.java
new file mode 100644
index 000000000000..15f74a21a17e
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/UnitConversions.java
@@ -0,0 +1,51 @@
+package com.thealgorithms.conversions;
+
+import static java.util.Map.entry;
+
+import java.util.Map;
+import org.apache.commons.lang3.tuple.Pair;
+
+/**
+ * A utility class to perform unit conversions between different measurement systems.
+ *
+ *
Currently, the class supports temperature conversions between several scales:
+ * Celsius, Fahrenheit, Kelvin, Réaumur, Delisle, and Rankine.
+ *
+ *
Example Usage
+ *
+ * double result = UnitConversions.TEMPERATURE.convert("Celsius", "Fahrenheit", 100.0);
+ * // Output: 212.0 (Celsius to Fahrenheit conversion of 100°C)
+ *
+ *
+ *
This class makes use of an {@link UnitsConverter} that handles the conversion logic
+ * based on predefined affine transformations. These transformations include scaling factors
+ * and offsets for temperature conversions.
+ *
+ *
Temperature Scales Supported
+ *
+ *
Celsius
+ *
Fahrenheit
+ *
Kelvin
+ *
Réaumur
+ *
Delisle
+ *
Rankine
+ *
+ */
+public final class UnitConversions {
+ private UnitConversions() {
+ }
+
+ /**
+ * A preconfigured instance of {@link UnitsConverter} for temperature conversions.
+ * The converter handles conversions between the following temperature units:
+ *
+ *
Kelvin to Celsius
+ *
Celsius to Fahrenheit
+ *
Réaumur to Celsius
+ *
Delisle to Celsius
+ *
Rankine to Kelvin
+ *
+ */
+ public static final UnitsConverter TEMPERATURE = new UnitsConverter(Map.ofEntries(entry(Pair.of("Kelvin", "Celsius"), new AffineConverter(1.0, -273.15)), entry(Pair.of("Celsius", "Fahrenheit"), new AffineConverter(9.0 / 5.0, 32.0)),
+ entry(Pair.of("Réaumur", "Celsius"), new AffineConverter(5.0 / 4.0, 0.0)), entry(Pair.of("Delisle", "Celsius"), new AffineConverter(-2.0 / 3.0, 100.0)), entry(Pair.of("Rankine", "Kelvin"), new AffineConverter(5.0 / 9.0, 0.0))));
+}
diff --git a/src/main/java/com/thealgorithms/conversions/UnitsConverter.java b/src/main/java/com/thealgorithms/conversions/UnitsConverter.java
new file mode 100644
index 000000000000..00690b2c0f9b
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/UnitsConverter.java
@@ -0,0 +1,147 @@
+package com.thealgorithms.conversions;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import org.apache.commons.lang3.tuple.Pair;
+
+/**
+ * A class that handles unit conversions using affine transformations.
+ *
+ *
The {@code UnitsConverter} allows converting values between different units using
+ * pre-defined affine conversion formulas. Each conversion is represented by an
+ * {@link AffineConverter} that defines the scaling and offset for the conversion.
+ *
+ *
For each unit, both direct conversions (e.g., Celsius to Fahrenheit) and inverse
+ * conversions (e.g., Fahrenheit to Celsius) are generated automatically. It also computes
+ * transitive conversions (e.g., Celsius to Kelvin via Fahrenheit if both conversions exist).
+ *
+ *
Key features include:
+ *
+ *
Automatic handling of inverse conversions (e.g., Fahrenheit to Celsius).
+ *
Compositional conversions, meaning if conversions between A -> B and B -> C exist,
+ * it can automatically generate A -> C conversion.
+ *
Supports multiple unit systems as long as conversions are provided in pairs.
+ *
+ *
+ *
Example Usage
+ *
+ * Map<Pair<String, String>, AffineConverter> basicConversions = Map.ofEntries(
+ * entry(Pair.of("Celsius", "Fahrenheit"), new AffineConverter(9.0 / 5.0, 32.0)),
+ * entry(Pair.of("Kelvin", "Celsius"), new AffineConverter(1.0, -273.15))
+ * );
+ *
+ * UnitsConverter converter = new UnitsConverter(basicConversions);
+ * double result = converter.convert("Celsius", "Fahrenheit", 100.0);
+ * // Output: 212.0 (Celsius to Fahrenheit conversion of 100°C)
+ *
+ *
+ *
Exception Handling
+ *
+ *
If the input unit and output unit are the same, an {@link IllegalArgumentException} is thrown.
+ *
If a conversion between the requested units does not exist, a {@link NoSuchElementException} is thrown.
+ *
+ */
+public final class UnitsConverter {
+ private final Map, AffineConverter> conversions;
+ private final Set units;
+
+ private static void putIfNeeded(Map, AffineConverter> conversions, final String inputUnit, final String outputUnit, final AffineConverter converter) {
+ if (!inputUnit.equals(outputUnit)) {
+ final var key = Pair.of(inputUnit, outputUnit);
+ conversions.putIfAbsent(key, converter);
+ }
+ }
+
+ private static Map, AffineConverter> addInversions(final Map, AffineConverter> knownConversions) {
+ Map, AffineConverter> res = new HashMap, AffineConverter>();
+ for (final var curConversion : knownConversions.entrySet()) {
+ final var inputUnit = curConversion.getKey().getKey();
+ final var outputUnit = curConversion.getKey().getValue();
+ putIfNeeded(res, inputUnit, outputUnit, curConversion.getValue());
+ putIfNeeded(res, outputUnit, inputUnit, curConversion.getValue().invert());
+ }
+ return res;
+ }
+
+ private static Map, AffineConverter> addCompositions(final Map, AffineConverter> knownConversions) {
+ Map, AffineConverter> res = new HashMap, AffineConverter>();
+ for (final var first : knownConversions.entrySet()) {
+ final var firstKey = first.getKey();
+ putIfNeeded(res, firstKey.getKey(), firstKey.getValue(), first.getValue());
+ for (final var second : knownConversions.entrySet()) {
+ final var secondKey = second.getKey();
+ if (firstKey.getValue().equals(secondKey.getKey())) {
+ final var newConversion = second.getValue().compose(first.getValue());
+ putIfNeeded(res, firstKey.getKey(), secondKey.getValue(), newConversion);
+ }
+ }
+ }
+ return res;
+ }
+
+ private static Map, AffineConverter> addAll(final Map, AffineConverter> knownConversions) {
+ final var res = addInversions(knownConversions);
+ return addCompositions(res);
+ }
+
+ private static Map, AffineConverter> computeAllConversions(final Map, AffineConverter> basicConversions) {
+ var tmp = basicConversions;
+ var res = addAll(tmp);
+ while (res.size() != tmp.size()) {
+ tmp = res;
+ res = addAll(tmp);
+ }
+ return res;
+ }
+
+ private static Set extractUnits(final Map, AffineConverter> conversions) {
+ Set res = new HashSet<>();
+ for (final var conversion : conversions.entrySet()) {
+ res.add(conversion.getKey().getKey());
+ }
+ return res;
+ }
+
+ /**
+ * Constructor for {@code UnitsConverter}.
+ *
+ *
Accepts a map of basic conversions and automatically generates inverse and
+ * transitive conversions.
+ *
+ * @param basicConversions the initial set of unit conversions to add.
+ */
+ public UnitsConverter(final Map, AffineConverter> basicConversions) {
+ conversions = computeAllConversions(basicConversions);
+ units = extractUnits(conversions);
+ }
+
+ /**
+ * Converts a value from one unit to another.
+ *
+ * @param inputUnit the unit of the input value.
+ * @param outputUnit the unit to convert the value into.
+ * @param value the value to convert.
+ * @return the converted value in the target unit.
+ * @throws IllegalArgumentException if inputUnit equals outputUnit.
+ * @throws NoSuchElementException if no conversion exists between the units.
+ */
+ public double convert(final String inputUnit, final String outputUnit, final double value) {
+ if (inputUnit.equals(outputUnit)) {
+ throw new IllegalArgumentException("inputUnit must be different from outputUnit.");
+ }
+ final var conversionKey = Pair.of(inputUnit, outputUnit);
+ return conversions.computeIfAbsent(conversionKey, k -> { throw new NoSuchElementException("No converter for: " + k); }).convert(value);
+ }
+
+ /**
+ * Retrieves the set of all units supported by this converter.
+ *
+ * @return a set of available units.
+ */
+ public Set availableUnits() {
+ return units;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/WordsToNumber.java b/src/main/java/com/thealgorithms/conversions/WordsToNumber.java
new file mode 100644
index 000000000000..e2b81a0f4b47
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/WordsToNumber.java
@@ -0,0 +1,343 @@
+package com.thealgorithms.conversions;
+
+import java.io.Serial;
+import java.math.BigDecimal;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ A Java-based utility for converting English word representations of numbers
+ into their numeric form. This utility supports whole numbers, decimals,
+ large values up to trillions, and even scientific notation where applicable.
+ It ensures accurate parsing while handling edge cases like negative numbers,
+ improper word placements, and ambiguous inputs.
+ *
+ */
+
+public final class WordsToNumber {
+
+ private WordsToNumber() {
+ }
+
+ private enum NumberWord {
+ ZERO("zero", 0),
+ ONE("one", 1),
+ TWO("two", 2),
+ THREE("three", 3),
+ FOUR("four", 4),
+ FIVE("five", 5),
+ SIX("six", 6),
+ SEVEN("seven", 7),
+ EIGHT("eight", 8),
+ NINE("nine", 9),
+ TEN("ten", 10),
+ ELEVEN("eleven", 11),
+ TWELVE("twelve", 12),
+ THIRTEEN("thirteen", 13),
+ FOURTEEN("fourteen", 14),
+ FIFTEEN("fifteen", 15),
+ SIXTEEN("sixteen", 16),
+ SEVENTEEN("seventeen", 17),
+ EIGHTEEN("eighteen", 18),
+ NINETEEN("nineteen", 19),
+ TWENTY("twenty", 20),
+ THIRTY("thirty", 30),
+ FORTY("forty", 40),
+ FIFTY("fifty", 50),
+ SIXTY("sixty", 60),
+ SEVENTY("seventy", 70),
+ EIGHTY("eighty", 80),
+ NINETY("ninety", 90);
+
+ private final String word;
+ private final int value;
+
+ NumberWord(String word, int value) {
+ this.word = word;
+ this.value = value;
+ }
+
+ public static Integer getValue(String word) {
+ for (NumberWord num : values()) {
+ if (word.equals(num.word)) {
+ return num.value;
+ }
+ }
+ return null;
+ }
+ }
+
+ private enum PowerOfTen {
+ THOUSAND("thousand", new BigDecimal("1000")),
+ MILLION("million", new BigDecimal("1000000")),
+ BILLION("billion", new BigDecimal("1000000000")),
+ TRILLION("trillion", new BigDecimal("1000000000000"));
+
+ private final String word;
+ private final BigDecimal value;
+
+ PowerOfTen(String word, BigDecimal value) {
+ this.word = word;
+ this.value = value;
+ }
+
+ public static BigDecimal getValue(String word) {
+ for (PowerOfTen power : values()) {
+ if (word.equals(power.word)) {
+ return power.value;
+ }
+ }
+ return null;
+ }
+ }
+
+ public static String convert(String numberInWords) {
+ if (numberInWords == null) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.NULL_INPUT, "");
+ }
+
+ ArrayDeque wordDeque = preprocessWords(numberInWords);
+ BigDecimal completeNumber = convertWordQueueToBigDecimal(wordDeque);
+
+ return completeNumber.toString();
+ }
+
+ public static BigDecimal convertToBigDecimal(String numberInWords) {
+ String conversionResult = convert(numberInWords);
+ return new BigDecimal(conversionResult);
+ }
+
+ private static ArrayDeque preprocessWords(String numberInWords) {
+ String[] wordSplitArray = numberInWords.trim().split("[ ,-]");
+ ArrayDeque wordDeque = new ArrayDeque<>();
+ for (String word : wordSplitArray) {
+ if (word.isEmpty()) {
+ continue;
+ }
+ wordDeque.add(word.toLowerCase());
+ }
+ if (wordDeque.isEmpty()) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.NULL_INPUT, "");
+ }
+ return wordDeque;
+ }
+
+ private static void handleConjunction(boolean prevNumWasHundred, boolean prevNumWasPowerOfTen, ArrayDeque wordDeque) {
+ if (wordDeque.isEmpty()) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.INVALID_CONJUNCTION, "");
+ }
+
+ String nextWord = wordDeque.pollFirst();
+ String afterNextWord = wordDeque.peekFirst();
+
+ wordDeque.addFirst(nextWord);
+
+ Integer number = NumberWord.getValue(nextWord);
+
+ boolean isPrevWordValid = prevNumWasHundred || prevNumWasPowerOfTen;
+ boolean isNextWordValid = number != null && (number >= 10 || afterNextWord == null || "point".equals(afterNextWord));
+
+ if (!isPrevWordValid || !isNextWordValid) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.INVALID_CONJUNCTION, "");
+ }
+ }
+
+ private static BigDecimal handleHundred(BigDecimal currentChunk, String word, boolean prevNumWasPowerOfTen) {
+ boolean currentChunkIsZero = currentChunk.compareTo(BigDecimal.ZERO) == 0;
+ if (currentChunk.compareTo(BigDecimal.TEN) >= 0 || prevNumWasPowerOfTen) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.UNEXPECTED_WORD, word);
+ }
+ if (currentChunkIsZero) {
+ currentChunk = currentChunk.add(BigDecimal.ONE);
+ }
+ return currentChunk.multiply(BigDecimal.valueOf(100));
+ }
+
+ private static void handlePowerOfTen(List chunks, BigDecimal currentChunk, BigDecimal powerOfTen, String word, boolean prevNumWasPowerOfTen) {
+ boolean currentChunkIsZero = currentChunk.compareTo(BigDecimal.ZERO) == 0;
+ if (currentChunkIsZero || prevNumWasPowerOfTen) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.UNEXPECTED_WORD, word);
+ }
+ BigDecimal nextChunk = currentChunk.multiply(powerOfTen);
+
+ if (!(chunks.isEmpty() || isAdditionSafe(chunks.getLast(), nextChunk))) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.UNEXPECTED_WORD, word);
+ }
+ chunks.add(nextChunk);
+ }
+
+ private static BigDecimal handleNumber(Collection chunks, BigDecimal currentChunk, String word, Integer number) {
+ boolean currentChunkIsZero = currentChunk.compareTo(BigDecimal.ZERO) == 0;
+ if (number == 0 && !(currentChunkIsZero && chunks.isEmpty())) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.UNEXPECTED_WORD, word);
+ }
+ BigDecimal bigDecimalNumber = BigDecimal.valueOf(number);
+
+ if (!currentChunkIsZero && !isAdditionSafe(currentChunk, bigDecimalNumber)) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.UNEXPECTED_WORD, word);
+ }
+ return currentChunk.add(bigDecimalNumber);
+ }
+
+ private static void handlePoint(Collection chunks, BigDecimal currentChunk, ArrayDeque wordDeque) {
+ boolean currentChunkIsZero = currentChunk.compareTo(BigDecimal.ZERO) == 0;
+ if (!currentChunkIsZero) {
+ chunks.add(currentChunk);
+ }
+
+ String decimalPart = convertDecimalPart(wordDeque);
+ chunks.add(new BigDecimal(decimalPart));
+ }
+
+ private static void handleNegative(boolean isNegative) {
+ if (isNegative) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.MULTIPLE_NEGATIVES, "");
+ }
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.INVALID_NEGATIVE, "");
+ }
+
+ private static BigDecimal convertWordQueueToBigDecimal(ArrayDeque wordDeque) {
+ BigDecimal currentChunk = BigDecimal.ZERO;
+ List chunks = new ArrayList<>();
+
+ boolean isNegative = "negative".equals(wordDeque.peek());
+ if (isNegative) {
+ wordDeque.poll();
+ }
+
+ boolean prevNumWasHundred = false;
+ boolean prevNumWasPowerOfTen = false;
+
+ while (!wordDeque.isEmpty()) {
+ String word = wordDeque.poll();
+
+ switch (word) {
+ case "and" -> {
+ handleConjunction(prevNumWasHundred, prevNumWasPowerOfTen, wordDeque);
+ continue;
+ }
+ case "hundred" -> {
+ currentChunk = handleHundred(currentChunk, word, prevNumWasPowerOfTen);
+ prevNumWasHundred = true;
+ continue;
+ }
+ default -> {
+
+ }
+ }
+ prevNumWasHundred = false;
+
+ BigDecimal powerOfTen = PowerOfTen.getValue(word);
+ if (powerOfTen != null) {
+ handlePowerOfTen(chunks, currentChunk, powerOfTen, word, prevNumWasPowerOfTen);
+ currentChunk = BigDecimal.ZERO;
+ prevNumWasPowerOfTen = true;
+ continue;
+ }
+ prevNumWasPowerOfTen = false;
+
+ Integer number = NumberWord.getValue(word);
+ if (number != null) {
+ currentChunk = handleNumber(chunks, currentChunk, word, number);
+ continue;
+ }
+
+ switch (word) {
+ case "point" -> {
+ handlePoint(chunks, currentChunk, wordDeque);
+ currentChunk = BigDecimal.ZERO;
+ continue;
+ }
+ case "negative" -> {
+ handleNegative(isNegative);
+ }
+ default -> {
+
+ }
+ }
+
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.UNKNOWN_WORD, word);
+ }
+
+ if (currentChunk.compareTo(BigDecimal.ZERO) != 0) {
+ chunks.add(currentChunk);
+ }
+
+ BigDecimal completeNumber = combineChunks(chunks);
+ return isNegative ? completeNumber.multiply(BigDecimal.valueOf(-1))
+ :
+ completeNumber;
+ }
+
+ private static boolean isAdditionSafe(BigDecimal currentChunk, BigDecimal number) {
+ int chunkDigitCount = currentChunk.toString().length();
+ int numberDigitCount = number.toString().length();
+ return chunkDigitCount > numberDigitCount;
+ }
+
+ private static String convertDecimalPart(ArrayDeque wordDeque) {
+ StringBuilder decimalPart = new StringBuilder(".");
+
+ while (!wordDeque.isEmpty()) {
+ String word = wordDeque.poll();
+ Integer number = NumberWord.getValue(word);
+ if (number == null) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.UNEXPECTED_WORD_AFTER_POINT, word);
+ }
+ decimalPart.append(number);
+ }
+
+ boolean missingNumbers = decimalPart.length() == 1;
+ if (missingNumbers) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.MISSING_DECIMAL_NUMBERS, "");
+ }
+ return decimalPart.toString();
+ }
+
+ private static BigDecimal combineChunks(List chunks) {
+ BigDecimal completeNumber = BigDecimal.ZERO;
+ for (BigDecimal chunk : chunks) {
+ completeNumber = completeNumber.add(chunk);
+ }
+ return completeNumber;
+ }
+ }
+
+ class WordsToNumberException extends RuntimeException {
+
+ @Serial private static final long serialVersionUID = 1L;
+
+ enum ErrorType {
+ NULL_INPUT("'null' or empty input provided"),
+ UNKNOWN_WORD("Unknown Word: "),
+ UNEXPECTED_WORD("Unexpected Word: "),
+ UNEXPECTED_WORD_AFTER_POINT("Unexpected Word (after Point): "),
+ MISSING_DECIMAL_NUMBERS("Decimal part is missing numbers."),
+ MULTIPLE_NEGATIVES("Multiple 'Negative's detected."),
+ INVALID_NEGATIVE("Incorrect 'negative' placement"),
+ INVALID_CONJUNCTION("Incorrect 'and' placement");
+
+ private final String message;
+
+ ErrorType(String message) {
+ this.message = message;
+ }
+
+ public String formatMessage(String details) {
+ return "Invalid Input. " + message + (details.isEmpty() ? "" : details);
+ }
+ }
+
+ public final ErrorType errorType;
+
+ WordsToNumberException(ErrorType errorType, String details) {
+ super(errorType.formatMessage(details));
+ this.errorType = errorType;
+ }
+
+ public ErrorType getErrorType() {
+ return errorType;
+ }
+ }
diff --git a/src/main/java/com/thealgorithms/datastructures/Node.java b/src/main/java/com/thealgorithms/datastructures/Node.java
new file mode 100644
index 000000000000..c8d0e6cb4f7d
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/Node.java
@@ -0,0 +1,32 @@
+package com.thealgorithms.datastructures;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Node {
+
+ private final T value;
+ private final List> children;
+
+ public Node(final T value) {
+ this.value = value;
+ this.children = new ArrayList<>();
+ }
+
+ public Node(final T value, final List> children) {
+ this.value = value;
+ this.children = children;
+ }
+
+ public T getValue() {
+ return value;
+ }
+
+ public void addChild(Node child) {
+ children.add(child);
+ }
+
+ public List> getChildren() {
+ return children;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/datastructures/bags/Bag.java b/src/main/java/com/thealgorithms/datastructures/bags/Bag.java
new file mode 100644
index 000000000000..afc3bbe40cce
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/bags/Bag.java
@@ -0,0 +1,138 @@
+package com.thealgorithms.datastructures.bags;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * A generic collection that allows adding and iterating over elements but does not support
+ * element removal. This class implements a simple bag data structure, which can hold duplicate
+ * elements and provides operations to check for membership and the size of the collection.
+ *
+ *
Bag is not thread-safe and should not be accessed by multiple threads concurrently.
+ *
+ * @param the type of elements in this bag
+ */
+public class Bag implements Iterable {
+
+ private Node firstElement; // Reference to the first element in the bag
+ private int size; // Count of elements in the bag
+
+ // Node class representing each element in the bag
+ private static final class Node {
+ private E content;
+ private Node nextElement;
+ }
+
+ /**
+ * Constructs an empty bag.
+ *
This initializes the bag with zero elements.
+ */
+ public Bag() {
+ firstElement = null;
+ size = 0;
+ }
+
+ /**
+ * Checks if the bag is empty.
+ *
+ * @return {@code true} if the bag contains no elements; {@code false} otherwise
+ */
+ public boolean isEmpty() {
+ return size == 0;
+ }
+
+ /**
+ * Returns the number of elements in the bag.
+ *
+ * @return the number of elements currently in the bag
+ */
+ public int size() {
+ return size;
+ }
+
+ /**
+ * Adds an element to the bag.
+ *
+ *
This method adds the specified element to the bag. Duplicates are allowed, and the
+ * bag will maintain the order in which elements are added.
+ *
+ * @param element the element to add; must not be {@code null}
+ */
+ public void add(E element) {
+ Node newNode = new Node<>();
+ newNode.content = element;
+ newNode.nextElement = firstElement;
+ firstElement = newNode;
+ size++;
+ }
+
+ /**
+ * Checks if the bag contains a specific element.
+ *
+ *
This method uses the {@code equals} method of the element to determine membership.
+ *
+ * @param element the element to check for; must not be {@code null}
+ * @return {@code true} if the bag contains the specified element; {@code false} otherwise
+ */
+ public boolean contains(E element) {
+ for (E value : this) {
+ if (value.equals(element)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns an iterator over the elements in this bag.
+ *
+ *
The iterator provides a way to traverse the elements in the order they were added.
+ *
+ * @return an iterator that iterates over the elements in the bag
+ */
+ @Override
+ public Iterator iterator() {
+ return new ListIterator<>(firstElement);
+ }
+
+ // Private class for iterating over elements
+ private static class ListIterator implements Iterator {
+
+ private Node currentElement;
+
+ /**
+ * Constructs a ListIterator starting from the given first element.
+ *
+ * @param firstElement the first element of the bag to iterate over
+ */
+ ListIterator(Node firstElement) {
+ this.currentElement = firstElement;
+ }
+
+ /**
+ * Checks if there are more elements to iterate over.
+ *
+ * @return {@code true} if there are more elements; {@code false} otherwise
+ */
+ @Override
+ public boolean hasNext() {
+ return currentElement != null;
+ }
+
+ /**
+ * Returns the next element in the iteration.
+ *
+ * @return the next element in the bag
+ * @throws NoSuchElementException if there are no more elements to return
+ */
+ @Override
+ public E next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException("No more elements in the bag.");
+ }
+ E element = currentElement.content;
+ currentElement = currentElement.nextElement;
+ return element;
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java b/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java
new file mode 100644
index 000000000000..d60b95110fc2
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java
@@ -0,0 +1,139 @@
+package com.thealgorithms.datastructures.bloomfilter;
+
+import java.util.BitSet;
+
+/**
+ * A generic BloomFilter implementation for probabilistic membership checking.
+ *
+ * Bloom filters are space-efficient data structures that provide a fast way to test whether an
+ * element is a member of a set. They may produce false positives, indicating an element is
+ * in the set when it is not, but they will never produce false negatives.
+ *
+ *
+ * @param The type of elements to be stored in the Bloom filter.
+ */
+@SuppressWarnings("rawtypes")
+public class BloomFilter {
+
+ private final int numberOfHashFunctions;
+ private final BitSet bitArray;
+ private final Hash[] hashFunctions;
+
+ /**
+ * Constructs a BloomFilter with a specified number of hash functions and bit array size.
+ *
+ * @param numberOfHashFunctions the number of hash functions to use
+ * @param bitArraySize the size of the bit array, which determines the capacity of the filter
+ * @throws IllegalArgumentException if numberOfHashFunctions or bitArraySize is less than 1
+ */
+ @SuppressWarnings("unchecked")
+ public BloomFilter(int numberOfHashFunctions, int bitArraySize) {
+ if (numberOfHashFunctions < 1 || bitArraySize < 1) {
+ throw new IllegalArgumentException("Number of hash functions and bit array size must be greater than 0");
+ }
+ this.numberOfHashFunctions = numberOfHashFunctions;
+ this.bitArray = new BitSet(bitArraySize);
+ this.hashFunctions = new Hash[numberOfHashFunctions];
+ initializeHashFunctions();
+ }
+
+ /**
+ * Initializes the hash functions with unique indices to ensure different hashing.
+ */
+ private void initializeHashFunctions() {
+ for (int i = 0; i < numberOfHashFunctions; i++) {
+ hashFunctions[i] = new Hash<>(i);
+ }
+ }
+
+ /**
+ * Inserts an element into the Bloom filter.
+ *
+ * This method hashes the element using all defined hash functions and sets the corresponding
+ * bits in the bit array.
+ *
+ *
+ * @param key the element to insert into the Bloom filter
+ */
+ public void insert(T key) {
+ for (Hash hash : hashFunctions) {
+ int position = Math.abs(hash.compute(key) % bitArray.size());
+ bitArray.set(position);
+ }
+ }
+
+ /**
+ * Checks if an element might be in the Bloom filter.
+ *
+ * This method checks the bits at the positions computed by each hash function. If any of these
+ * bits are not set, the element is definitely not in the filter. If all bits are set, the element
+ * might be in the filter.
+ *
+ *
+ * @param key the element to check for membership in the Bloom filter
+ * @return {@code true} if the element might be in the Bloom filter, {@code false} if it is definitely not
+ */
+ public boolean contains(T key) {
+ for (Hash hash : hashFunctions) {
+ int position = Math.abs(hash.compute(key) % bitArray.size());
+ if (!bitArray.get(position)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Inner class representing a hash function used by the Bloom filter.
+ *
+ * Each instance of this class represents a different hash function based on its index.
+ *
+ *
+ * @param The type of elements to be hashed.
+ */
+ private static class Hash {
+
+ private final int index;
+
+ /**
+ * Constructs a Hash function with a specified index.
+ *
+ * @param index the index of this hash function, used to create a unique hash
+ */
+ Hash(int index) {
+ this.index = index;
+ }
+
+ /**
+ * Computes the hash of the given key.
+ *
+ * The hash value is calculated by multiplying the index of the hash function
+ * with the ASCII sum of the string representation of the key.
+ *
+ *
+ * @param key the element to hash
+ * @return the computed hash value
+ */
+ public int compute(T key) {
+ return index * asciiString(String.valueOf(key));
+ }
+
+ /**
+ * Computes the ASCII value sum of the characters in a string.
+ *
+ * This method iterates through each character of the string and accumulates
+ * their ASCII values to produce a single integer value.
+ *
+ *
+ * @param word the string to compute
+ * @return the sum of ASCII values of the characters in the string
+ */
+ private int asciiString(String word) {
+ int sum = 0;
+ for (char c : word.toCharArray()) {
+ sum += c;
+ }
+ return sum;
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/datastructures/buffers/CircularBuffer.java b/src/main/java/com/thealgorithms/datastructures/buffers/CircularBuffer.java
new file mode 100644
index 000000000000..3b89c2119ae0
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/buffers/CircularBuffer.java
@@ -0,0 +1,133 @@
+package com.thealgorithms.datastructures.buffers;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * The {@code CircularBuffer} class implements a generic circular (or ring) buffer.
+ * A circular buffer is a fixed-size data structure that operates in a FIFO (First In, First Out) manner.
+ * The buffer allows you to overwrite old data when the buffer is full and efficiently use limited memory.
+ * When the buffer is full, adding a new item will overwrite the oldest data.
+ *
+ * @param The type of elements stored in the circular buffer.
+ */
+@SuppressWarnings("unchecked")
+public class CircularBuffer {
+ private final Item[] buffer;
+ private final CircularPointer putPointer;
+ private final CircularPointer getPointer;
+ private final AtomicInteger size = new AtomicInteger(0);
+
+ /**
+ * Constructor to initialize the circular buffer with a specified size.
+ *
+ * @param size The size of the circular buffer.
+ * @throws IllegalArgumentException if the size is zero or negative.
+ */
+ public CircularBuffer(int size) {
+ if (size <= 0) {
+ throw new IllegalArgumentException("Buffer size must be positive");
+ }
+ // noinspection unchecked
+ this.buffer = (Item[]) new Object[size];
+ this.putPointer = new CircularPointer(0, size);
+ this.getPointer = new CircularPointer(0, size);
+ }
+
+ /**
+ * Checks if the circular buffer is empty.
+ * This method is based on the current size of the buffer.
+ *
+ * @return {@code true} if the buffer is empty, {@code false} otherwise.
+ */
+ public boolean isEmpty() {
+ return size.get() == 0;
+ }
+
+ /**
+ * Checks if the circular buffer is full.
+ * The buffer is considered full when its size equals its capacity.
+ *
+ * @return {@code true} if the buffer is full, {@code false} otherwise.
+ */
+ public boolean isFull() {
+ return size.get() == buffer.length;
+ }
+
+ /**
+ * Retrieves and removes the item at the front of the buffer (FIFO).
+ * This operation will move the {@code getPointer} forward.
+ *
+ * @return The item at the front of the buffer, or {@code null} if the buffer is empty.
+ */
+ public Item get() {
+ if (isEmpty()) {
+ return null;
+ }
+
+ Item item = buffer[getPointer.getAndIncrement()];
+ size.decrementAndGet();
+ return item;
+ }
+
+ /**
+ * Adds an item to the end of the buffer (FIFO).
+ * If the buffer is full, this operation will overwrite the oldest data.
+ *
+ * @param item The item to be added.
+ * @throws IllegalArgumentException if the item is null.
+ * @return {@code true} if the item was successfully added, {@code false} if the buffer was full and the item overwrote existing data.
+ */
+ public boolean put(Item item) {
+ if (item == null) {
+ throw new IllegalArgumentException("Null items are not allowed");
+ }
+
+ boolean wasEmpty = isEmpty();
+ if (isFull()) {
+ getPointer.getAndIncrement(); // Move get pointer to discard oldest item
+ } else {
+ size.incrementAndGet();
+ }
+
+ buffer[putPointer.getAndIncrement()] = item;
+ return wasEmpty;
+ }
+
+ /**
+ * The {@code CircularPointer} class is a helper class used to track the current index (pointer)
+ * in the circular buffer.
+ * The max value represents the capacity of the buffer.
+ * The `CircularPointer` class ensures that the pointer automatically wraps around to 0
+ * when it reaches the maximum index.
+ * This is achieved in the `getAndIncrement` method, where the pointer
+ * is incremented and then taken modulo the maximum value (`max`).
+ * This operation ensures that the pointer always stays within the bounds of the buffer.
+ */
+ private static class CircularPointer {
+ private int pointer;
+ private final int max;
+
+ /**
+ * Constructor to initialize the circular pointer.
+ *
+ * @param pointer The initial position of the pointer.
+ * @param max The maximum size (capacity) of the circular buffer.
+ */
+ CircularPointer(int pointer, int max) {
+ this.pointer = pointer;
+ this.max = max;
+ }
+
+ /**
+ * Increments the pointer by 1 and wraps it around to 0 if it reaches the maximum value.
+ * This ensures the pointer always stays within the buffer's bounds.
+ *
+ * @return The current pointer value before incrementing.
+ */
+ public int getAndIncrement() {
+ int tmp = pointer;
+ pointer = (pointer + 1) % max;
+ return tmp;
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/datastructures/caches/FIFOCache.java b/src/main/java/com/thealgorithms/datastructures/caches/FIFOCache.java
new file mode 100644
index 000000000000..fa048434a187
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/caches/FIFOCache.java
@@ -0,0 +1,549 @@
+package com.thealgorithms.datastructures.caches;
+
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.BiConsumer;
+
+/**
+ * A thread-safe generic cache implementation using the First-In-First-Out eviction policy.
+ *
+ * The cache holds a fixed number of entries, defined by its capacity. When the cache is full and a
+ * new entry is added, the oldest entry in the cache is selected and evicted to make space.
+ *
+ * Optionally, entries can have a time-to-live (TTL) in milliseconds. If a TTL is set, entries will
+ * automatically expire and be removed upon access or insertion attempts.
+ *
+ * Features:
+ *
+ *
Removes oldest entry when capacity is exceeded
+ *
Optional TTL (time-to-live in milliseconds) per entry or default TTL for all entries
+ *
Thread-safe access using locking
+ *
Hit and miss counters for cache statistics
+ *
Eviction listener callback support
+ *
+ *
+ * @param the type of keys maintained by this cache
+ * @param the type of mapped values
+ * See FIFO
+ * @author Kevin Babu (GitHub)
+ */
+public final class FIFOCache {
+
+ private final int capacity;
+ private final long defaultTTL;
+ private final Map> cache;
+ private final Lock lock;
+
+ private long hits = 0;
+ private long misses = 0;
+ private final BiConsumer evictionListener;
+ private final EvictionStrategy evictionStrategy;
+
+ /**
+ * Internal structure to store value + expiry timestamp.
+ *
+ * @param the type of the value being cached
+ */
+ private static class CacheEntry {
+ V value;
+ long expiryTime;
+
+ /**
+ * Constructs a new {@code CacheEntry} with the specified value and time-to-live (TTL).
+ * If TTL is 0, the entry is kept indefinitely, that is, unless it is the first value,
+ * then it will be removed according to the FIFO principle
+ *
+ * @param value the value to cache
+ * @param ttlMillis the time-to-live in milliseconds
+ */
+ CacheEntry(V value, long ttlMillis) {
+ this.value = value;
+ if (ttlMillis == 0) {
+ this.expiryTime = Long.MAX_VALUE;
+ } else {
+ this.expiryTime = System.currentTimeMillis() + ttlMillis;
+ }
+ }
+
+ /**
+ * Checks if the cache entry has expired.
+ *
+ * @return {@code true} if the current time is past the expiration time; {@code false} otherwise
+ */
+ boolean isExpired() {
+ return System.currentTimeMillis() > expiryTime;
+ }
+ }
+
+ /**
+ * Constructs a new {@code FIFOCache} instance using the provided {@link Builder}.
+ *
+ *
This constructor initializes the cache with the specified capacity and default TTL,
+ * sets up internal data structures (a {@code LinkedHashMap} for cache entries and configures eviction.
+ *
+ * @param builder the {@code Builder} object containing configuration parameters
+ */
+ private FIFOCache(Builder builder) {
+ this.capacity = builder.capacity;
+ this.defaultTTL = builder.defaultTTL;
+ this.cache = new LinkedHashMap<>();
+ this.lock = new ReentrantLock();
+ this.evictionListener = builder.evictionListener;
+ this.evictionStrategy = builder.evictionStrategy;
+ }
+
+ /**
+ * Retrieves the value associated with the specified key from the cache.
+ *
+ *
If the key is not present or the corresponding entry has expired, this method
+ * returns {@code null}. If an expired entry is found, it will be removed and the
+ * eviction listener (if any) will be notified. Cache hit-and-miss statistics are
+ * also updated accordingly.
+ *
+ * @param key the key whose associated value is to be returned; must not be {@code null}
+ * @return the cached value associated with the key, or {@code null} if not present or expired
+ * @throws IllegalArgumentException if {@code key} is {@code null}
+ */
+ public V get(K key) {
+ if (key == null) {
+ throw new IllegalArgumentException("Key must not be null");
+ }
+
+ lock.lock();
+ try {
+ evictionStrategy.onAccess(this);
+
+ CacheEntry entry = cache.get(key);
+ if (entry == null || entry.isExpired()) {
+ if (entry != null) {
+ cache.remove(key);
+ notifyEviction(key, entry.value);
+ }
+ misses++;
+ return null;
+ }
+ hits++;
+ return entry.value;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Adds a key-value pair to the cache using the default time-to-live (TTL).
+ *
+ *
The key may overwrite an existing entry. The actual insertion is delegated
+ * to the overloaded {@link #put(K, V, long)} method.
+ *
+ * @param key the key to cache the value under
+ * @param value the value to be cached
+ */
+ public void put(K key, V value) {
+ put(key, value, defaultTTL);
+ }
+
+ /**
+ * Adds a key-value pair to the cache with a specified time-to-live (TTL).
+ *
+ *
If the key already exists, its value is removed, re-inserted at tail and its TTL is reset.
+ * If the key does not exist and the cache is full, the oldest entry is evicted to make space.
+ * Expired entries are also cleaned up prior to any eviction. The eviction listener
+ * is notified when an entry gets evicted.
+ *
+ * @param key the key to associate with the cached value; must not be {@code null}
+ * @param value the value to be cached; must not be {@code null}
+ * @param ttlMillis the time-to-live for this entry in milliseconds; must be >= 0
+ * @throws IllegalArgumentException if {@code key} or {@code value} is {@code null}, or if {@code ttlMillis} is negative
+ */
+ public void put(K key, V value, long ttlMillis) {
+ if (key == null || value == null) {
+ throw new IllegalArgumentException("Key and value must not be null");
+ }
+ if (ttlMillis < 0) {
+ throw new IllegalArgumentException("TTL must be >= 0");
+ }
+
+ lock.lock();
+ try {
+ // If key already exists, remove it
+ CacheEntry oldEntry = cache.remove(key);
+ if (oldEntry != null && !oldEntry.isExpired()) {
+ notifyEviction(key, oldEntry.value);
+ }
+
+ // Evict expired entries to make space for new entry
+ evictExpired();
+
+ // If no expired entry was removed, remove the oldest
+ if (cache.size() >= capacity) {
+ Iterator>> it = cache.entrySet().iterator();
+ if (it.hasNext()) {
+ Map.Entry> eldest = it.next();
+ it.remove();
+ notifyEviction(eldest.getKey(), eldest.getValue().value);
+ }
+ }
+
+ // Insert new entry at tail
+ cache.put(key, new CacheEntry<>(value, ttlMillis));
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Removes all expired entries from the cache.
+ *
+ *
This method iterates through the list of cached keys and checks each associated
+ * entry for expiration. Expired entries are removed the cache map. For each eviction,
+ * the eviction listener is notified.
+ */
+ private int evictExpired() {
+ int count = 0;
+ Iterator>> it = cache.entrySet().iterator();
+
+ while (it.hasNext()) {
+ Map.Entry> entry = it.next();
+ if (entry != null && entry.getValue().isExpired()) {
+ it.remove();
+ notifyEviction(entry.getKey(), entry.getValue().value);
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+ /**
+ * Removes the specified key and its associated entry from the cache.
+ *
+ * @param key the key to remove from the cache;
+ * @return the value associated with the key; or {@code null} if no such key exists
+ */
+ public V removeKey(K key) {
+ if (key == null) {
+ throw new IllegalArgumentException("Key cannot be null");
+ }
+ CacheEntry entry = cache.remove(key);
+
+ // No such key in cache
+ if (entry == null) {
+ return null;
+ }
+
+ notifyEviction(key, entry.value);
+ return entry.value;
+ }
+
+ /**
+ * Notifies the eviction listener, if one is registered, that a key-value pair has been evicted.
+ *
+ *
If the {@code evictionListener} is not {@code null}, it is invoked with the provided key
+ * and value. Any exceptions thrown by the listener are caught and logged to standard error,
+ * preventing them from disrupting cache operations.
+ *
+ * @param key the key that was evicted
+ * @param value the value that was associated with the evicted key
+ */
+ private void notifyEviction(K key, V value) {
+ if (evictionListener != null) {
+ try {
+ evictionListener.accept(key, value);
+ } catch (Exception e) {
+ System.err.println("Eviction listener failed: " + e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Returns the number of successful cache lookups (hits).
+ *
+ * @return the number of cache hits
+ */
+ public long getHits() {
+ lock.lock();
+ try {
+ return hits;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns the number of failed cache lookups (misses), including expired entries.
+ *
+ * @return the number of cache misses
+ */
+ public long getMisses() {
+ lock.lock();
+ try {
+ return misses;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns the current number of entries in the cache, excluding expired ones.
+ *
+ * @return the current cache size
+ */
+ public int size() {
+ lock.lock();
+ try {
+ evictionStrategy.onAccess(this);
+
+ int count = 0;
+ for (CacheEntry entry : cache.values()) {
+ if (!entry.isExpired()) {
+ ++count;
+ }
+ }
+ return count;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Removes all entries from the cache, regardless of their expiration status.
+ *
+ *
This method clears the internal cache map entirely, resets the hit-and-miss counters,
+ * and notifies the eviction listener (if any) for each removed entry.
+ * Note that expired entries are treated the same as active ones for the purpose of clearing.
+ *
+ *
This operation acquires the internal lock to ensure thread safety.
+ */
+ public void clear() {
+ lock.lock();
+ try {
+ for (Map.Entry> entry : cache.entrySet()) {
+ notifyEviction(entry.getKey(), entry.getValue().value);
+ }
+ cache.clear();
+ hits = 0;
+ misses = 0;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns a set of all keys currently stored in the cache that have not expired.
+ *
+ *
This method iterates through the cache and collects the keys of all non-expired entries.
+ * Expired entries are ignored but not removed. If you want to ensure expired entries are cleaned up,
+ * consider invoking {@link EvictionStrategy#onAccess(FIFOCache)} or calling {@link #evictExpired()} manually.
+ *
+ *
This operation acquires the internal lock to ensure thread safety.
+ *
+ * @return a set containing all non-expired keys currently in the cache
+ */
+ public Set getAllKeys() {
+ lock.lock();
+ try {
+ Set keys = new LinkedHashSet<>();
+
+ for (Map.Entry> entry : cache.entrySet()) {
+ if (!entry.getValue().isExpired()) {
+ keys.add(entry.getKey());
+ }
+ }
+
+ return keys;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns the current {@link EvictionStrategy} used by this cache instance.
+
+ * @return the eviction strategy currently assigned to this cache
+ */
+ public EvictionStrategy getEvictionStrategy() {
+ return evictionStrategy;
+ }
+
+ /**
+ * Returns a string representation of the cache, including metadata and current non-expired entries.
+ *
+ *
The returned string includes the cache's capacity, current size (excluding expired entries),
+ * hit-and-miss counts, and a map of all non-expired key-value pairs. This method acquires a lock
+ * to ensure thread-safe access.
+ *
+ * @return a string summarizing the state of the cache
+ */
+ @Override
+ public String toString() {
+ lock.lock();
+ try {
+ Map visible = new LinkedHashMap<>();
+ for (Map.Entry> entry : cache.entrySet()) {
+ if (!entry.getValue().isExpired()) {
+ visible.put(entry.getKey(), entry.getValue().value);
+ }
+ }
+ return String.format("Cache(capacity=%d, size=%d, hits=%d, misses=%d, entries=%s)", capacity, visible.size(), hits, misses, visible);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * A strategy interface for controlling when expired entries are evicted from the cache.
+ *
+ *
Implementations decide whether and when to trigger {@link FIFOCache#evictExpired()} based
+ * on cache usage patterns. This allows for flexible eviction behaviour such as periodic cleanup,
+ * or no automatic cleanup.
+ *
+ * @param the type of keys maintained by the cache
+ * @param the type of cached values
+ */
+ public interface EvictionStrategy {
+ /**
+ * Called on each cache access (e.g., {@link FIFOCache#get(Object)}) to optionally trigger eviction.
+ *
+ * @param cache the cache instance on which this strategy is applied
+ * @return the number of expired entries evicted during this access
+ */
+ int onAccess(FIFOCache cache);
+ }
+
+ /**
+ * An eviction strategy that performs eviction of expired entries on each call.
+ *
+ * @param the type of keys
+ * @param the type of values
+ */
+ public static class ImmediateEvictionStrategy implements EvictionStrategy {
+ @Override
+ public int onAccess(FIFOCache cache) {
+ return cache.evictExpired();
+ }
+ }
+
+ /**
+ * An eviction strategy that triggers eviction on every fixed number of accesses.
+ *
+ *
This deterministic strategy ensures cleanup occurs at predictable intervals,
+ * ideal for moderately active caches where memory usage is a concern.
+ *
+ * @param the type of keys
+ * @param the type of values
+ */
+ public static class PeriodicEvictionStrategy implements EvictionStrategy {
+ private final int interval;
+ private final AtomicInteger counter = new AtomicInteger();
+
+ /**
+ * Constructs a periodic eviction strategy.
+ *
+ * @param interval the number of accesses between evictions; must be > 0
+ * @throws IllegalArgumentException if {@code interval} is less than or equal to 0
+ */
+ public PeriodicEvictionStrategy(int interval) {
+ if (interval <= 0) {
+ throw new IllegalArgumentException("Interval must be > 0");
+ }
+ this.interval = interval;
+ }
+
+ @Override
+ public int onAccess(FIFOCache cache) {
+ if (counter.incrementAndGet() % interval == 0) {
+ return cache.evictExpired();
+ }
+
+ return 0;
+ }
+ }
+
+ /**
+ * A builder for constructing a {@link FIFOCache} instance with customizable settings.
+ *
+ *
Allows configuring capacity, default TTL, eviction listener, and a pluggable eviction
+ * strategy. Call {@link #build()} to create the configured cache instance.
+ *
+ * @param the type of keys maintained by the cache
+ * @param the type of values stored in the cache
+ */
+ public static class Builder {
+ private final int capacity;
+ private long defaultTTL = 0;
+ private BiConsumer evictionListener;
+ private EvictionStrategy evictionStrategy = new FIFOCache.ImmediateEvictionStrategy<>();
+ /**
+ * Creates a new {@code Builder} with the specified cache capacity.
+ *
+ * @param capacity the maximum number of entries the cache can hold; must be > 0
+ * @throws IllegalArgumentException if {@code capacity} is less than or equal to 0
+ */
+ public Builder(int capacity) {
+ if (capacity <= 0) {
+ throw new IllegalArgumentException("Capacity must be > 0");
+ }
+ this.capacity = capacity;
+ }
+
+ /**
+ * Sets the default time-to-live (TTL) in milliseconds for cache entries.
+ *
+ * @param ttlMillis the TTL duration in milliseconds; must be >= 0
+ * @return this builder instance for chaining
+ * @throws IllegalArgumentException if {@code ttlMillis} is negative
+ */
+ public Builder defaultTTL(long ttlMillis) {
+ if (ttlMillis < 0) {
+ throw new IllegalArgumentException("Default TTL must be >= 0");
+ }
+ this.defaultTTL = ttlMillis;
+ return this;
+ }
+
+ /**
+ * Sets an eviction listener to be notified when entries are evicted from the cache.
+ *
+ * @param listener a {@link BiConsumer} that accepts evicted keys and values; must not be {@code null}
+ * @return this builder instance for chaining
+ * @throws IllegalArgumentException if {@code listener} is {@code null}
+ */
+ public Builder evictionListener(BiConsumer listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("Listener must not be null");
+ }
+ this.evictionListener = listener;
+ return this;
+ }
+
+ /**
+ * Builds and returns a new {@link FIFOCache} instance with the configured parameters.
+ *
+ * @return a fully configured {@code FIFOCache} instance
+ */
+ public FIFOCache build() {
+ return new FIFOCache<>(this);
+ }
+
+ /**
+ * Sets the eviction strategy used to determine when to clean up expired entries.
+ *
+ * @param strategy an {@link EvictionStrategy} implementation; must not be {@code null}
+ * @return this builder instance
+ * @throws IllegalArgumentException if {@code strategy} is {@code null}
+ */
+ public Builder evictionStrategy(EvictionStrategy strategy) {
+ if (strategy == null) {
+ throw new IllegalArgumentException("Eviction strategy must not be null");
+ }
+ this.evictionStrategy = strategy;
+ return this;
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/datastructures/caches/LFUCache.java b/src/main/java/com/thealgorithms/datastructures/caches/LFUCache.java
new file mode 100644
index 000000000000..f0d8ea8f7ff3
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/caches/LFUCache.java
@@ -0,0 +1,185 @@
+package com.thealgorithms.datastructures.caches;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The {@code LFUCache} class implements a Least Frequently Used (LFU) cache.
+ * An LFU cache evicts the least frequently used item when the cache reaches its capacity.
+ * It maintains a mapping of keys to nodes, where each node contains the key, its associated value,
+ * and a frequency count that tracks how many times the item has been accessed. A doubly linked list
+ * is used to efficiently manage the ordering of items based on their usage frequency.
+ *
+ *
This implementation is designed to provide O(1) time complexity for both the {@code get} and
+ * {@code put} operations, which is achieved through the use of a hashmap for quick access and a
+ * doubly linked list for maintaining the order of item frequencies.
+ *
+ * @param The type of keys maintained by this cache.
+ * @param The type of mapped values.
+ *
+ * @author Akshay Dubey (https://github.com/itsAkshayDubey)
+ */
+public class LFUCache {
+
+ /**
+ * The {@code Node} class represents an element in the LFU cache.
+ * Each node contains a key, a value, and a frequency count.
+ * It also has pointers to the previous and next nodes in the doubly linked list.
+ */
+ private class Node {
+ private final K key;
+ private V value;
+ private int frequency;
+ private Node previous;
+ private Node next;
+
+ /**
+ * Constructs a new {@code Node} with the specified key, value, and frequency.
+ *
+ * @param key The key associated with this node.
+ * @param value The value stored in this node.
+ * @param frequency The frequency of usage of this node.
+ */
+ Node(K key, V value, int frequency) {
+ this.key = key;
+ this.value = value;
+ this.frequency = frequency;
+ }
+ }
+
+ private Node head;
+ private Node tail;
+ private final Map cache;
+ private final int capacity;
+ private static final int DEFAULT_CAPACITY = 100;
+
+ /**
+ * Constructs an LFU cache with the default capacity.
+ */
+ public LFUCache() {
+ this(DEFAULT_CAPACITY);
+ }
+
+ /**
+ * Constructs an LFU cache with the specified capacity.
+ *
+ * @param capacity The maximum number of items that the cache can hold.
+ * @throws IllegalArgumentException if the specified capacity is less than or equal to zero.
+ */
+ public LFUCache(int capacity) {
+ if (capacity <= 0) {
+ throw new IllegalArgumentException("Capacity must be greater than zero.");
+ }
+ this.capacity = capacity;
+ this.cache = new HashMap<>();
+ }
+
+ /**
+ * Retrieves the value associated with the given key from the cache.
+ * If the key exists, the node's frequency is incremented, and the node is repositioned
+ * in the linked list based on its updated frequency.
+ *
+ * @param key The key whose associated value is to be returned.
+ * @return The value associated with the key, or {@code null} if the key is not present in the cache.
+ */
+ public V get(K key) {
+ Node node = cache.get(key);
+ if (node == null) {
+ return null;
+ }
+ removeNode(node);
+ node.frequency += 1;
+ addNodeWithUpdatedFrequency(node);
+ return node.value;
+ }
+
+ /**
+ * Inserts or updates a key-value pair in the cache.
+ * If the key already exists, the value is updated and its frequency is incremented.
+ * If the cache is full, the least frequently used item is removed before inserting the new item.
+ *
+ * @param key The key associated with the value to be inserted or updated.
+ * @param value The value to be inserted or updated.
+ */
+ public void put(K key, V value) {
+ if (cache.containsKey(key)) {
+ Node node = cache.get(key);
+ node.value = value;
+ node.frequency += 1;
+ removeNode(node);
+ addNodeWithUpdatedFrequency(node);
+ } else {
+ if (cache.size() >= capacity) {
+ cache.remove(this.head.key); // Evict least frequently used item
+ removeNode(head);
+ }
+ Node node = new Node(key, value, 1);
+ addNodeWithUpdatedFrequency(node);
+ cache.put(key, node);
+ }
+ }
+
+ /**
+ * Adds a node to the linked list in the correct position based on its frequency.
+ * The linked list is ordered by frequency, with the least frequently used node at the head.
+ *
+ * @param node The node to be inserted into the list.
+ */
+ private void addNodeWithUpdatedFrequency(Node node) {
+ if (tail != null && head != null) {
+ Node temp = this.head;
+ while (temp != null) {
+ if (temp.frequency > node.frequency) {
+ if (temp == head) {
+ node.next = temp;
+ temp.previous = node;
+ this.head = node;
+ break;
+ } else {
+ node.next = temp;
+ node.previous = temp.previous;
+ temp.previous.next = node;
+ temp.previous = node;
+ break;
+ }
+ } else {
+ temp = temp.next;
+ if (temp == null) {
+ tail.next = node;
+ node.previous = tail;
+ node.next = null;
+ tail = node;
+ break;
+ }
+ }
+ }
+ } else {
+ tail = node;
+ head = tail;
+ }
+ }
+
+ /**
+ * Removes a node from the doubly linked list.
+ * This method ensures that the pointers of neighboring nodes are properly updated.
+ *
+ * @param node The node to be removed from the list.
+ */
+ private void removeNode(Node node) {
+ if (node.previous != null) {
+ node.previous.next = node.next;
+ } else {
+ this.head = node.next;
+ }
+
+ if (node.next != null) {
+ node.next.previous = node.previous;
+ } else {
+ this.tail = node.previous;
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/datastructures/caches/LRUCache.java b/src/main/java/com/thealgorithms/datastructures/caches/LRUCache.java
new file mode 100644
index 000000000000..ec39d2a6ed28
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/caches/LRUCache.java
@@ -0,0 +1,235 @@
+package com.thealgorithms.datastructures.caches;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A Least Recently Used (LRU) Cache implementation.
+ *
+ *
An LRU cache is a fixed-size cache that maintains items in order of use. When the cache reaches
+ * its capacity and a new item needs to be added, it removes the least recently used item first.
+ * This implementation provides O(1) time complexity for both get and put operations.
+ *
+ *
Features:
+ *
+ *
Fixed-size cache with configurable capacity
+ *
Constant time O(1) operations for get and put
+ *
Thread-unsafe - should be externally synchronized if used in concurrent environments
+ *
Supports null values but not null keys
+ *
+ *
+ *
Implementation Details:
+ *
+ *
Uses a HashMap for O(1) key-value lookups
+ *
Maintains a doubly-linked list for tracking access order
+ *
The head of the list contains the least recently used item
+ *
The tail of the list contains the most recently used item
+ *
+ * @param the type of keys maintained by this cache
+ * @param the type of mapped values
+ */
+public class LRUCache {
+
+ private final Map> data = new HashMap<>();
+ private Entry head;
+ private Entry tail;
+ private int cap;
+ private static final int DEFAULT_CAP = 100;
+
+ public LRUCache() {
+ setCapacity(DEFAULT_CAP);
+ }
+
+ public LRUCache(int cap) {
+ setCapacity(cap);
+ }
+
+ /**
+ * Returns the current capacity of the cache.
+ *
+ * @param newCapacity the new capacity of the cache
+ */
+ private void setCapacity(int newCapacity) {
+ checkCapacity(newCapacity);
+ for (int i = data.size(); i > newCapacity; i--) {
+ Entry evicted = evict();
+ data.remove(evicted.getKey());
+ }
+ this.cap = newCapacity;
+ }
+
+ /**
+ * Evicts the least recently used item from the cache.
+ *
+ * @return the evicted entry
+ */
+ private Entry evict() {
+ if (head == null) {
+ throw new RuntimeException("cache cannot be empty!");
+ }
+ Entry evicted = head;
+ head = evicted.getNextEntry();
+ head.setPreEntry(null);
+ evicted.setNextEntry(null);
+ return evicted;
+ }
+
+ /**
+ * Checks if the capacity is valid.
+ *
+ * @param capacity the capacity to check
+ */
+ private void checkCapacity(int capacity) {
+ if (capacity <= 0) {
+ throw new RuntimeException("capacity must greater than 0!");
+ }
+ }
+
+ /**
+ * Returns the value to which the specified key is mapped, or null if this cache contains no
+ * mapping for the key.
+ *
+ * @param key the key whose associated value is to be returned
+ * @return the value to which the specified key is mapped, or null if this cache contains no
+ * mapping for the key
+ */
+ public V get(K key) {
+ if (!data.containsKey(key)) {
+ return null;
+ }
+ final Entry entry = data.get(key);
+ moveNodeToLast(entry);
+ return entry.getValue();
+ }
+
+ /**
+ * Moves the specified entry to the end of the list.
+ *
+ * @param entry the entry to move
+ */
+ private void moveNodeToLast(Entry entry) {
+ if (tail == entry) {
+ return;
+ }
+ final Entry preEntry = entry.getPreEntry();
+ final Entry nextEntry = entry.getNextEntry();
+ if (preEntry != null) {
+ preEntry.setNextEntry(nextEntry);
+ }
+ if (nextEntry != null) {
+ nextEntry.setPreEntry(preEntry);
+ }
+ if (head == entry) {
+ head = nextEntry;
+ }
+ tail.setNextEntry(entry);
+ entry.setPreEntry(tail);
+ entry.setNextEntry(null);
+ tail = entry;
+ }
+
+ /**
+ * Associates the specified value with the specified key in this cache.
+ *
+ * @param key the key with which the specified value is to be associated
+ * @param value the value to be associated with the specified key
+ */
+ public void put(K key, V value) {
+ if (data.containsKey(key)) {
+ final Entry existingEntry = data.get(key);
+ existingEntry.setValue(value);
+ moveNodeToLast(existingEntry);
+ return;
+ }
+ Entry newEntry;
+ if (data.size() == cap) {
+ newEntry = evict();
+ data.remove(newEntry.getKey());
+ } else {
+ newEntry = new Entry<>();
+ }
+
+ newEntry.setKey(key);
+ newEntry.setValue(value);
+ addNewEntry(newEntry);
+ data.put(key, newEntry);
+ }
+
+ /**
+ * Adds a new entry to the end of the list.
+ *
+ * @param newEntry the entry to add
+ */
+ private void addNewEntry(Entry newEntry) {
+ if (data.isEmpty()) {
+ head = newEntry;
+ tail = newEntry;
+ return;
+ }
+ tail.setNextEntry(newEntry);
+ newEntry.setPreEntry(tail);
+ newEntry.setNextEntry(null);
+ tail = newEntry;
+ }
+
+ static final class Entry {
+
+ private Entry preEntry;
+ private Entry nextEntry;
+ private I key;
+ private J value;
+
+ Entry() {
+ }
+
+ Entry(Entry preEntry, Entry nextEntry, I key, J value) {
+ this.preEntry = preEntry;
+ this.nextEntry = nextEntry;
+ this.key = key;
+ this.value = value;
+ }
+
+ public Entry getPreEntry() {
+ return preEntry;
+ }
+
+ public void setPreEntry(Entry