diff --git a/.cargo/config b/.cargo/config deleted file mode 100644 index b05dfbcf..00000000 --- a/.cargo/config +++ /dev/null @@ -1,2 +0,0 @@ -[build] -rustflags = ["-A", "unused"] diff --git a/.env b/.env new file mode 100644 index 00000000..74a701ae --- /dev/null +++ b/.env @@ -0,0 +1 @@ +LEETCODE_COOKIE= \ No newline at end of file diff --git a/.github/codecov.yml b/.github/codecov.yml new file mode 100644 index 00000000..a2b3d8ad --- /dev/null +++ b/.github/codecov.yml @@ -0,0 +1,21 @@ +# ref: https://docs.codecov.com/docs/codecovyml-reference +coverage: + # Hold ourselves to a high bar + range: 77..100 + round: down + precision: 1 + status: + # ref: https://docs.codecov.com/docs/commit-status + project: + default: + # Avoid false negatives + threshold: 1% + +# Test files aren't important for coverage +ignore: + - "tests" + +# Make comments less noisy +comment: + layout: "files" + require_changes: yes diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..8139a93a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,17 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily + - package-ecosystem: cargo + directory: / + schedule: + interval: daily + ignore: + - dependency-name: "*" + # patch and minor updates don't matter for libraries + # remove this ignore rule if your package has binaries + update-types: + - "version-update:semver-patch" + - "version-update:semver-minor" diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 00000000..c70a3774 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,84 @@ +permissions: + contents: read +on: + push: + branches: [main, master] + pull_request: + merge_group: + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +env: + CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse + RUST_TOOLCHAIN: nightly-2025-02-01 + +name: Check +jobs: + fmt: + runs-on: ubuntu-latest + strategy: + fail-fast: false + name: fmt + permissions: + # Give the default GITHUB_TOKEN write permission to commit and push the + # added or changed files to the repository. + contents: write + steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + submodules: true + - name: Install rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUST_TOOLCHAIN }} + components: rustfmt + - run: cargo fmt --check + + clippy: + runs-on: ubuntu-latest + name: clippy + permissions: + contents: read + checks: write + strategy: + fail-fast: false + steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + submodules: true + - name: Install ${{ env.RUST_TOOLCHAIN }} + uses: dtolnay/rust-toolchain@master # master + with: + toolchain: ${{ env.RUST_TOOLCHAIN }} + components: clippy + - name: Rust Cache + uses: Swatinem/rust-cache@v2 + - run: cargo clippy --workspace --all-features --all-targets -- -D warnings + + typos: + runs-on: ubuntu-latest + name: typos + permissions: + contents: read + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Check spelling + uses: crate-ci/typos@master + + \ No newline at end of file diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 00000000..5bb02ad0 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,30 @@ +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, +# surfacing known-vulnerable versions of the packages declared or updated in the PR. +# Once installed, if the workflow run is marked as required, +# PRs introducing known-vulnerable packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + disable-sudo: true + egress-policy: block + allowed-endpoints: > + api.github.com:443 + github.com:443 + - name: 'Checkout Repository' + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: 'Dependency Review' + uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0 diff --git a/.github/workflows/safety.yml b/.github/workflows/safety.yml new file mode 100644 index 00000000..9368ca37 --- /dev/null +++ b/.github/workflows/safety.yml @@ -0,0 +1,83 @@ +permissions: + contents: read +on: + push: + branches: [main, master] + pull_request: +name: Safety +jobs: + sanitizers: + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + submodules: true + - name: Install nightly + uses: dtolnay/rust-toolchain@655bc29a221a62ee6edb6a0fa9d9530cf424d31d # nightly + - run: | + # to get the symbolizer for debug symbol resolution + sudo apt install llvm + # to fix buggy leak analyzer: + # https://github.com/japaric/rust-san#unrealiable-leaksanitizer + sed -i '/\[features\]/i [profile.dev]' Cargo.toml + sed -i '/profile.dev/a opt-level = 1' Cargo.toml + cat Cargo.toml + name: Enable debug symbols + - name: Rust Cache + uses: Swatinem/rust-cache@v2 + - name: cargo +nightly test -Zsanitizer=address + # only --lib --tests b/c of https://github.com/rust-lang/rust/issues/53945 + run: cargo +nightly test --lib --tests --all-features --target x86_64-unknown-linux-gnu + env: + ASAN_OPTIONS: "detect_odr_violation=0:detect_leaks=0" + RUSTFLAGS: "-Z sanitizer=address" + - name: cargo test -Zsanitizer=leak + if: always() + run: cargo +nightly test --all-features --target x86_64-unknown-linux-gnu + env: + LSAN_OPTIONS: "suppressions=lsan-suppressions.txt" + RUSTFLAGS: "-Z sanitizer=leak" + miri: + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + submodules: true + - run: | + echo "NIGHTLY=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri)" >> $GITHUB_ENV + - name: Install ${{ env.NIGHTLY }} + uses: dtolnay/rust-toolchain@e12eda571dc9a5ee5d58eecf4738ec291c66f295 # master + with: + toolchain: ${{ env.NIGHTLY }} + components: miri + - name: Rust Cache + uses: Swatinem/rust-cache@v2 + - name: cargo miri test + run: MIRIFLAGS="-Zmiri-disable-isolation" cargo +${{ env.NIGHTLY }} miri test + env: + MIRIFLAGS: "" + # loom: + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + # with: + # submodules: true + # - name: Install stable + # uses: dtolnay/rust-toolchain@stable + # - name: cargo test --test loom + # run: cargo test --release --test loom + # env: + # LOOM_MAX_PREEMPTIONS: 2 + # RUSTFLAGS: "--cfg loom" diff --git a/.github/workflows/scheduled.yml b/.github/workflows/scheduled.yml new file mode 100644 index 00000000..b526087b --- /dev/null +++ b/.github/workflows/scheduled.yml @@ -0,0 +1,66 @@ +permissions: + contents: read +on: + push: + branches: [main, master] + pull_request: + schedule: + - cron: '7 7 * * *' +name: Rolling +jobs: + # https://twitter.com/mycoliza/status/1571295690063753218 + nightly: + runs-on: ubuntu-latest + name: ubuntu / nightly + steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + submodules: true + - name: Install nightly + uses: dtolnay/rust-toolchain@655bc29a221a62ee6edb6a0fa9d9530cf424d31d # nightly + - name: cargo generate-lockfile + if: hashFiles('Cargo.lock') == '' + run: cargo generate-lockfile + - name: Rust Cache + uses: Swatinem/rust-cache@v2 + - name: Install nextest + uses: taiki-e/install-action@nextest + - name: cargo nextest --locked + run: cargo +nightly nextest run --locked --all-features --all-targets + # https://twitter.com/alcuadrado/status/1571291687837732873 + update: + runs-on: ubuntu-latest + name: ubuntu / beta / updated + # There's no point running this if no Cargo.lock was checked in in the + # first place, since we'd just redo what happened in the regular test job. + # Unfortunately, hashFiles only works in if on steps, so we reepeat it. + # if: hashFiles('Cargo.lock') != '' + steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + submodules: true + - name: Install beta + if: hashFiles('Cargo.lock') != '' + uses: dtolnay/rust-toolchain@57d5ed5e6d9108d901fe23bef7d440faabb42d14 # beta + - name: cargo update + if: hashFiles('Cargo.lock') != '' + run: cargo update + - name: Rust Cache + uses: Swatinem/rust-cache@v2 + - name: Install nextest + uses: taiki-e/install-action@nextest + - name: cargo nextest + if: hashFiles('Cargo.lock') != '' + run: cargo +beta nextest run --locked --all-features --all-targets + env: + RUSTFLAGS: -D deprecated diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml new file mode 100644 index 00000000..0fb2f8d6 --- /dev/null +++ b/.github/workflows/scorecards.yml @@ -0,0 +1,76 @@ +# This workflow uses actions that are not certified by GitHub. They are provided +# by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '20 7 * * 2' + push: + branches: [main, master] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + contents: read + actions: read + + steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs + + - name: "Checkout code" + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecards on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories: + # - `publish_results` will always be set to `false`, regardless + # of the value entered here. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 + with: + sarif_file: results.sarif diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..605eb5a6 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,107 @@ +permissions: + contents: read +on: + push: + branches: [main, master] + pull_request: + merge_group: + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +env: + CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse + RUST_TOOLCHAIN: nightly-2025-02-01 + +name: Test +jobs: + required: + runs-on: ubuntu-latest + name: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + submodules: true + - name: Install ${{ env.RUST_TOOLCHAIN }} + uses: dtolnay/rust-toolchain@e12eda571dc9a5ee5d58eecf4738ec291c66f295 # master + with: + toolchain: ${{ env.RUST_TOOLCHAIN }} + - name: cargo generate-lockfile + if: hashFiles('Cargo.lock') == '' + run: cargo generate-lockfile + # https://twitter.com/jonhoo/status/1571290371124260865 + - name: Rust Cache + uses: Swatinem/rust-cache@v2 + - name: Install nextest + uses: taiki-e/install-action@nextest + - name: cargo nextest --locked + run: cargo nextest run --locked --workspace --all-features --all-targets + + os-check: + runs-on: ${{ matrix.os }} + name: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [macos-latest, windows-latest] + steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + submodules: true + - name: Install rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUST_TOOLCHAIN }} + - name: cargo generate-lockfile + if: hashFiles('Cargo.lock') == '' + run: cargo generate-lockfile + - name: Rust Cache + uses: Swatinem/rust-cache@v2 + - name: Install nextest + uses: taiki-e/install-action@nextest + - name: cargo nextest + run: cargo nextest run --locked --all-features --all-targets + coverage: + runs-on: ubuntu-latest + name: coverage + steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + submodules: true + - name: Install rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUST_TOOLCHAIN }} + components: llvm-tools-preview + - name: cargo install cargo-llvm-cov + uses: taiki-e/install-action@29ee91bbad05696171dd917a8c7a3838049b93d5 # cargo-llvm-cov + - name: cargo generate-lockfile + if: hashFiles('Cargo.lock') == '' + run: cargo generate-lockfile + - name: Rust Cache + uses: Swatinem/rust-cache@v2 + - name: Install nextest + uses: taiki-e/install-action@nextest + - name: cargo llvm-cov + run: cargo llvm-cov nextest --locked --workspace --all-features --all-targets --lcov --output-path lcov.info + - name: Upload to codecov.io + uses: codecov/codecov-action@1e68e06f1dbfde0e4cefc87efeba9e4643565303 # v5.1.2 + with: + fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} # required diff --git a/.mergify.yml b/.mergify.yml new file mode 100644 index 00000000..b03f83b4 --- /dev/null +++ b/.mergify.yml @@ -0,0 +1,14 @@ +pull_request_rules: + - name: Automatic merge on approval + conditions: + - -conflict + - check-success=fmt + - check-success=clippy + - check-success=typos + - check-success=coverage + - check-success=ubuntu-latest + - check-success=macos-latest + + actions: + merge: + method: merge diff --git a/.typos.toml b/.typos.toml new file mode 100644 index 00000000..54d8772b --- /dev/null +++ b/.typos.toml @@ -0,0 +1,11 @@ +# If there are words that you think should not be treated as typo. +# Please list here along with a comment. +[default.extend-words] +"ponter" = "ponter" +"pont" = "pont" +"fre" = "fre" +"poiinter" = "poiinter" +"fromi" = "fromi" +"toi" = "toi" + +[files] diff --git a/Cargo.lock b/Cargo.lock index a8df0eae..510085c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,27 +1,221 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] -name = "adler32" -version = "1.0.4" +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aead" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aes" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" +dependencies = [ + "aes-soft", + "aesni", + "cipher", +] + +[[package]] +name = "aes-gcm" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "aes-soft" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" +dependencies = [ + "cipher", + "opaque-debug", +] + +[[package]] +name = "aesni" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" +dependencies = [ + "cipher", + "opaque-debug", +] [[package]] name = "aho-corasick" -version = "0.7.6" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] [[package]] name = "anyhow" -version = "1.0.26" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue 2.5.0", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-compression" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd066d0b4ef8ecb03a55319dc13aa6910616d0f44008a045bb1835af830abff5" +dependencies = [ + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "async-executor" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" +checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +dependencies = [ + "async-task", + "concurrent-queue 1.2.4", + "fastrand 1.9.0", + "futures-lite", + "once_cell", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +dependencies = [ + "async-channel", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", +] + +[[package]] +name = "async-io" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" +dependencies = [ + "async-lock", + "autocfg 1.3.0", + "concurrent-queue 2.5.0", + "futures-lite", + "libc", + "log", + "parking", + "polling", + "slab", + "socket2 0.4.10", + "waker-fn", + "windows-sys 0.42.0", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-channel", + "async-global-executor", + "async-io", + "async-lock", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" @@ -31,40 +225,42 @@ checksum = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.38" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5" +checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" dependencies = [ - "backtrace-sys", - "cfg-if 0.1.10", + "addr2line", + "cc", + "cfg-if 1.0.0", "libc", + "miniz_oxide", + "object", "rustc-demangle", ] [[package]] -name = "backtrace-sys" -version = "0.1.31" +name = "base-x" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" -dependencies = [ - "cc", - "libc", -] +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" [[package]] name = "base64" -version = "0.10.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -dependencies = [ - "byteorder", -] +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" @@ -73,43 +269,65 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" [[package]] -name = "bumpalo" -version = "3.10.0" +name = "bitflags" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] -name = "byteorder" -version = "1.3.2" +name = "block-buffer" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] [[package]] -name = "bytes" -version = "0.4.12" +name = "blocking" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +checksum = "8c36a4d0d48574b3dd360b4b7d95cc651d2b6557b6402848a27d4b228a473e2a" dependencies = [ - "byteorder", - "either", - "iovec", + "async-channel", + "async-lock", + "async-task", + "fastrand 2.0.1", + "futures-io", + "futures-lite", + "piper", + "tracing", ] [[package]] -name = "c2-chacha" -version = "0.2.2" +name = "bumpalo" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" -dependencies = [ - "lazy_static", - "ppv-lite86", -] +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + +[[package]] +name = "bytes" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cache-padded" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "981520c98f422fcc584dc1a95c334e6953900b9106bc47a9839b81790009eb21" [[package]] name = "cc" -version = "1.0.45" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" [[package]] name = "cfg-if" @@ -124,152 +342,149 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cloudabi" -version = "0.0.3" +name = "cipher" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" dependencies = [ - "bitflags", + "generic-array", ] [[package]] -name = "cookie" -version = "0.12.0" +name = "cloudabi" +version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" dependencies = [ - "time", - "url 1.7.2", + "bitflags 1.2.0", ] [[package]] -name = "cookie_store" -version = "0.7.0" +name = "concurrent-queue" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" +checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" dependencies = [ - "cookie", - "failure", - "idna 0.1.5", - "log", - "publicsuffix", - "serde", - "serde_json", - "time", - "try_from", - "url 1.7.2", + "cache-padded", ] [[package]] -name = "core-foundation" -version = "0.6.4" +name = "concurrent-queue" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ - "core-foundation-sys", - "libc", + "crossbeam-utils", ] [[package]] -name = "core-foundation-sys" -version = "0.6.2" +name = "const_fn" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +checksum = "373e9fafaa20882876db20562275ff58d50e0caa2590077fe7ce7bef90211d0d" [[package]] -name = "crc32fast" -version = "1.2.0" +name = "cookie" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951" dependencies = [ - "cfg-if 0.1.10", + "aes-gcm", + "base64 0.13.1", + "hkdf", + "hmac", + "percent-encoding", + "rand 0.8.5", + "sha2", + "time", + "version_check 0.9.4", ] [[package]] -name = "crossbeam-channel" -version = "0.3.9" +name = "core-foundation" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ - "crossbeam-utils 0.6.6", + "core-foundation-sys", + "libc", ] [[package]] -name = "crossbeam-deque" -version = "0.7.4" +name = "core-foundation-sys" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20ff29ded3204c5106278a81a38f4b482636ed4fa1e6cfbeef193291beb29ed" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils 0.7.2", - "maybe-uninit", -] +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] -name = "crossbeam-epoch" -version = "0.8.2" +name = "cpufeatures" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ - "autocfg 1.1.0", - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "lazy_static", - "maybe-uninit", - "memoffset", - "scopeguard", + "libc", ] [[package]] -name = "crossbeam-queue" -version = "0.1.2" +name = "cpuid-bool" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" + +[[package]] +name = "crc32fast" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "crossbeam-utils 0.6.6", + "cfg-if 1.0.0", ] [[package]] name = "crossbeam-utils" -version = "0.6.6" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-mac" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" +checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a" dependencies = [ - "cfg-if 0.1.10", - "lazy_static", + "generic-array", + "subtle", ] [[package]] -name = "crossbeam-utils" -version = "0.7.2" +name = "ctr" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f" dependencies = [ - "autocfg 1.1.0", - "cfg-if 0.1.10", - "lazy_static", + "cipher", ] [[package]] name = "curl" -version = "0.4.25" +version = "0.4.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06aa71e9208a54def20792d877bc663d6aae0732b9852e612c4a933177c31283" +checksum = "1e2161dd6eba090ff1594084e95fd67aeccf04382ffea77999ea94ed42ec67b6" dependencies = [ "curl-sys", "libc", "openssl-probe", "openssl-sys", "schannel", - "socket2", - "winapi 0.3.8", + "socket2 0.5.7", + "windows-sys 0.52.0", ] [[package]] name = "curl-sys" -version = "0.4.25" +version = "0.4.72+curl-8.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c38ca47d60b86d0cc9d42caa90a0885669c2abc9791f871c81f58cdf39e979b" +checksum = "29cbdc8314c447d11e8fd156dcdd031d9e02a7a976163e396b548c03153bc9ea" dependencies = [ "cc", "libc", @@ -278,20 +493,29 @@ dependencies = [ "openssl-sys", "pkg-config", "vcpkg", - "winapi 0.3.8", + "windows-sys 0.52.0", ] [[package]] -name = "dtoa" -version = "0.4.4" +name = "digest" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "discard" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" [[package]] -name = "either" -version = "1.5.3" +name = "dotenv" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] name = "encoding_rs" @@ -303,49 +527,63 @@ dependencies = [ ] [[package]] -name = "error-chain" -version = "0.12.1" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" -dependencies = [ - "backtrace", - "version_check", -] +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] -name = "failure" -version = "0.1.5" +name = "errno" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "backtrace", - "failure_derive", + "libc", + "windows-sys 0.52.0", ] [[package]] -name = "failure_derive" -version = "0.1.5" +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "fastrand" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.44", - "synstructure", + "instant", ] +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + [[package]] name = "flate2" -version = "1.0.12" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad3c5233c9a940c8719031b423d7e6c16af66e031cb0420b0896f5245bf181d3" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ - "cfg-if 0.1.10", "crc32fast", - "libc", "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bebadab126f8120d410b677ed95eee4ba6eb7c6dd8e34a5ec88a08050e26132" +dependencies = [ + "futures-core", + "futures-sink", + "spinning_top", +] + [[package]] name = "fnv" version = "1.0.6" @@ -368,38 +606,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" +name = "form_urlencoded" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" dependencies = [ - "bitflags", - "fuchsia-zircon-sys", + "matches", + "percent-encoding", ] [[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - -[[package]] -name = "futures" -version = "0.1.29" +name = "fuchsia-cprng" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "futures" -version = "0.3.4" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -412,51 +638,25 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", ] -[[package]] -name = "futures-channel-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a" -dependencies = [ - "futures-core-preview", - "futures-sink-preview", -] - [[package]] name = "futures-core" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" - -[[package]] -name = "futures-core-preview" -version = "0.3.0-alpha.19" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" - -[[package]] -name = "futures-cpupool" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -dependencies = [ - "futures 0.1.29", - "num_cpus", -] +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.4" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -464,77 +664,55 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "futures-executor-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75236e88bd9fe88e5e8bfcd175b665d0528fe03ca4c5207fabc028c8f9d93e98" -dependencies = [ - "futures-core-preview", - "futures-util-preview", - "num_cpus", -] - [[package]] name = "futures-io" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" - -[[package]] -name = "futures-io-preview" -version = "0.3.0-alpha.19" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4914ae450db1921a56c91bde97a27846287d062087d4a652efc09bb3a01ebda" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] -name = "futures-macro" -version = "0.3.21" +name = "futures-lite" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.2", - "syn 1.0.96", + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", ] [[package]] -name = "futures-preview" -version = "0.3.0-alpha.19" +name = "futures-macro" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b1dce2a0267ada5c6ff75a8ba864b4e679a9e2aa44262af7a3b5516d530d76e" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ - "futures-channel-preview", - "futures-core-preview", - "futures-executor-preview", - "futures-io-preview", - "futures-sink-preview", - "futures-util-preview", + "proc-macro2", + "quote", + "syn 2.0.66", ] [[package]] name = "futures-sink" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" - -[[package]] -name = "futures-sink-preview" -version = "0.3.0-alpha.19" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f148ef6b69f75bb610d4f9a2336d4fc88c4b5b67129d1a340dd0fd362efeec" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -549,141 +727,251 @@ dependencies = [ ] [[package]] -name = "futures-util-preview" -version = "0.3.0-alpha.19" +name = "generic-array" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ - "futures 0.1.29", - "futures-channel-preview", - "futures-core-preview", - "futures-io-preview", - "futures-sink-preview", - "memchr", - "pin-utils", - "slab", - "tokio-io", + "typenum", + "version_check 0.9.4", ] [[package]] name = "getrandom" -version = "0.1.12" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", - "wasi", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "ghash" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", ] [[package]] name = "h2" -version = "0.1.26" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" dependencies = [ - "byteorder", - "bytes", + "atomic-waker", + "bytes 1.6.0", "fnv", - "futures 0.1.29", - "http", + "futures-core", + "futures-sink", + "http 1.1.0", "indexmap", - "log", "slab", - "string", - "tokio-io", + "tokio", + "tokio-util", + "tracing", ] [[package]] -name = "heck" -version = "0.3.1" +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hkdf" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f" +dependencies = [ + "digest", + "hmac", +] + +[[package]] +name = "hmac" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" dependencies = [ - "unicode-segmentation", + "crypto-mac", + "digest", ] [[package]] name = "http" -version = "0.1.21" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "bytes", + "bytes 1.6.0", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes 1.6.0", "fnv", "itoa", ] [[package]] name = "http-body" -version = "0.1.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ - "bytes", - "futures 0.1.29", - "http", - "tokio-buf", + "bytes 1.6.0", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes 1.6.0", + "futures-core", + "http 1.1.0", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "http-client" +version = "6.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1947510dc91e2bf586ea5ffb412caad7673264e14bb39fb9078da114a94ce1a5" +dependencies = [ + "async-std", + "async-trait", + "cfg-if 1.0.0", + "http-types", + "isahc", + "log", +] + +[[package]] +name = "http-types" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" +dependencies = [ + "anyhow", + "async-channel", + "async-std", + "base64 0.13.1", + "cookie", + "futures-lite", + "infer", + "pin-project-lite", + "rand 0.7.3", + "serde", + "serde_json", + "serde_qs", + "serde_urlencoded", + "url", ] [[package]] name = "httparse" -version = "1.3.4" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "hyper" -version = "0.12.36" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c843caf6296fc1f93444735205af9ed4e109a539005abb2564ae1d6fad34c52" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ - "bytes", - "futures 0.1.29", - "futures-cpupool", + "bytes 1.6.0", + "futures-channel", + "futures-util", "h2", - "http", + "http 1.1.0", "http-body", "httparse", - "iovec", "itoa", - "log", - "net2", - "rustc_version", - "time", + "pin-project-lite", + "smallvec 1.13.2", "tokio", - "tokio-buf", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "tokio-tcp", - "tokio-threadpool", - "tokio-timer", "want", ] [[package]] name = "hyper-tls" -version = "0.3.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ - "bytes", - "futures 0.1.29", + "bytes 1.6.0", + "http-body-util", "hyper", + "hyper-util", "native-tls", - "tokio-io", + "tokio", + "tokio-native-tls", + "tower-service", ] [[package]] -name = "idna" +name = "hyper-util" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", + "bytes 1.6.0", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body", + "hyper", + "pin-project-lite", + "socket2 0.5.7", + "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] @@ -698,76 +986,89 @@ dependencies = [ ] [[package]] -name = "indexmap" -version = "1.2.0" +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "infer" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a61202fbe46c4a951e9404a720a0180bcf3212c750d735cb5c4ba4dc551299f3" +checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" [[package]] -name = "iovec" -version = "0.1.3" +name = "instant" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9636900aa73ffed13cdbb199f17cd955670bb300927c8d25b517dfa136b6567" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ - "libc", + "cfg-if 1.0.0", ] +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + [[package]] name = "isahc" -version = "0.7.6" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b77027f12e53ae59a379f7074259d32eb10867e6183388020e922832d9c3fb" +checksum = "e2948a0ce43e2c2ef11d7edf6816508998d99e13badd1150be0914205df9388a" dependencies = [ - "bytes", - "crossbeam-channel", - "crossbeam-utils 0.6.6", + "bytes 0.5.6", + "crossbeam-utils", "curl", "curl-sys", - "futures-io-preview", - "futures-util-preview", - "http", - "lazy_static", + "flume", + "futures-lite", + "http 0.2.12", "log", + "once_cell", "slab", "sluice", + "tracing", + "tracing-futures", + "url", + "waker-fn", ] [[package]] name = "itoa" -version = "0.4.4" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.35" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7889c7c36282151f6bf465be4700359318aef36baa951462382eae49e9577cf9" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] [[package]] -name = "kernel32-sys" -version = "0.2.2" +name = "kv-log-macro" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "log", ] -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - [[package]] name = "leetcode-rust" version = "0.1.0" dependencies = [ - "futures 0.3.4", + "dotenv", + "futures", "rand 0.6.5", "regex", "reqwest", @@ -775,19 +1076,20 @@ dependencies = [ "serde_derive", "serde_json", "surf", + "tempfile", ] [[package]] name = "libc" -version = "0.2.126" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libnghttp2-sys" -version = "0.1.2" +version = "0.1.10+1.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02254d44f4435dd79e695f2c2b83cd06a47919adea30216ceaf0c57ca0a72463" +checksum = "959c25552127d2e1fa72f0e52548ec04fc386e827ba71a7bd01db46a447dc135" dependencies = [ "cc", "libc", @@ -795,9 +1097,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.0.25" +version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" +checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e" dependencies = [ "cc", "libc", @@ -805,22 +1107,29 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + [[package]] name = "lock_api" -version = "0.3.1" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ + "autocfg 1.3.0", "scopeguard", ] [[package]] name = "log" -version = "0.4.8" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" dependencies = [ - "cfg-if 0.1.10", + "value-bag", ] [[package]] @@ -837,30 +1146,21 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" - -[[package]] -name = "memoffset" -version = "0.5.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" -dependencies = [ - "rustc_version", -] +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mime" -version = "0.3.14" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd1d63acd1b78403cc0c325605908475dd9b9a3acbf65ed8bcab97e27014afcf" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.1" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" dependencies = [ "mime", "unicase", @@ -868,50 +1168,30 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.3.3" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "304f66c19be2afa56530fa7c39796192eef38618da8d19df725ad7c6d6b2aaae" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ - "adler32", + "adler", ] [[package]] name = "mio" -version = "0.6.19" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", "libc", - "log", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] - -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.48.0", ] [[package]] name = "native-tls" -version = "0.2.3" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -924,55 +1204,61 @@ dependencies = [ ] [[package]] -name = "net2" -version = "0.2.37" +name = "num_cpus" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" +checksum = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" dependencies = [ - "cfg-if 0.1.10", "libc", - "winapi 0.3.8", ] [[package]] -name = "nom" -version = "4.2.3" +name = "object" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" dependencies = [ "memchr", - "version_check", ] [[package]] -name = "num_cpus" -version = "1.10.1" +name = "once_cell" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" -dependencies = [ - "libc", -] +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] -name = "once_cell" -version = "1.12.0" +name = "opaque-debug" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.25" +version = "0.10.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f372b2b53ce10fb823a337aaa674e3a7d072b957c6264d0f4ff0bd86e657449" +checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" dependencies = [ - "bitflags", - "cfg-if 0.1.10", + "bitflags 2.5.0", + "cfg-if 1.0.0", "foreign-types", - "lazy_static", "libc", + "once_cell", + "openssl-macros", "openssl-sys", ] +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "openssl-probe" version = "0.1.2" @@ -981,11 +1267,10 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-sys" -version = "0.9.50" +version = "0.9.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c42dcccb832556b5926bc9ae61e8775f2a61e725ab07ab3d1e7fcf8ae62c3b6" +checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" dependencies = [ - "autocfg 0.1.6", "cc", "libc", "pkg-config", @@ -993,42 +1278,36 @@ dependencies = [ ] [[package]] -name = "parking_lot" -version = "0.9.0" +name = "parking" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -dependencies = [ - "lock_api", - "parking_lot_core", - "rustc_version", -] +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] -name = "parking_lot_core" -version = "0.6.2" +name = "percent-encoding" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -dependencies = [ - "cfg-if 0.1.10", - "cloudabi", - "libc", - "redox_syscall", - "rustc_version", - "smallvec", - "winapi 0.3.8", -] +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] -name = "percent-encoding" -version = "1.0.1" +name = "pin-project" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] [[package]] -name = "percent-encoding" -version = "2.1.0" +name = "pin-project-internal" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] [[package]] name = "pin-project-lite" @@ -1042,6 +1321,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" +dependencies = [ + "atomic-waker", + "fastrand 2.0.1", + "futures-io", +] + [[package]] name = "pkg-config" version = "0.3.16" @@ -1049,58 +1339,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea" [[package]] -name = "ppv-lite86" -version = "0.2.5" +name = "polling" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" +checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" +dependencies = [ + "autocfg 1.3.0", + "cfg-if 1.0.0", + "libc", + "log", + "wepoll-ffi", + "windows-sys 0.42.0", +] [[package]] -name = "proc-macro2" -version = "0.4.30" +name = "polyval" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +checksum = "eebcc4aa140b9abd2bc40d9c3f7ccec842679cd79045ac3a7ac698c1a064b7cd" dependencies = [ - "unicode-xid", + "cpuid-bool", + "opaque-debug", + "universal-hash", ] [[package]] -name = "proc-macro2" -version = "1.0.39" +name = "ppv-lite86" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" -dependencies = [ - "unicode-ident", -] +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] -name = "publicsuffix" -version = "1.5.3" +name = "proc-macro-hack" +version = "0.5.20+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bf259a81de2b2eb9850ec990ec78e6a25319715584fd7652b9b26f96fcb1510" -dependencies = [ - "error-chain", - "idna 0.2.0", - "lazy_static", - "regex", - "url 2.1.0", -] +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] -name = "quote" -version = "0.6.13" +name = "proc-macro2" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ - "proc-macro2 0.4.30", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.2" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ - "proc-macro2 1.0.39", + "proc-macro2", ] [[package]] @@ -1119,22 +1409,33 @@ dependencies = [ "rand_os", "rand_pcg", "rand_xorshift", - "winapi 0.3.8", + "winapi", ] [[package]] name = "rand" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom", + "getrandom 0.1.16", "libc", - "rand_chacha 0.2.1", + "rand_chacha 0.2.2", "rand_core 0.5.1", "rand_hc 0.2.0", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + [[package]] name = "rand_chacha" version = "0.1.1" @@ -1147,14 +1448,24 @@ dependencies = [ [[package]] name = "rand_chacha" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ - "c2-chacha", + "ppv-lite86", "rand_core 0.5.1", ] +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + [[package]] name = "rand_core" version = "0.3.1" @@ -1176,7 +1487,16 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom", + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.14", ] [[package]] @@ -1214,7 +1534,7 @@ checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" dependencies = [ "libc", "rand_core 0.4.2", - "winapi 0.3.8", + "winapi", ] [[package]] @@ -1228,7 +1548,7 @@ dependencies = [ "libc", "rand_core 0.4.2", "rdrand", - "winapi 0.3.8", + "winapi", ] [[package]] @@ -1261,76 +1581,80 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.56" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.2.0", +] [[package]] name = "regex" -version = "1.3.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" dependencies = [ "aho-corasick", "memchr", "regex-syntax", - "thread_local", ] [[package]] name = "regex-syntax" -version = "0.6.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b28dfe3fe9badec5dbf0a79a9cccad2cfc2ab5484bdb3e44cbd1ae8b3ba2be06" - -[[package]] -name = "remove_dir_all" -version = "0.5.2" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -dependencies = [ - "winapi 0.3.8", -] +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "reqwest" -version = "0.9.21" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b7e953e14c6f3102b7e8d1f1ee3abf5ecee80b427f5565c9389835cecae95c" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ - "base64", - "bytes", - "cookie", - "cookie_store", + "async-compression", + "base64 0.22.1", + "bytes 1.6.0", "encoding_rs", - "flate2", - "futures 0.1.29", - "http", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http 1.1.0", + "http-body", + "http-body-util", "hyper", "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", "log", "mime", - "mime_guess", "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", "serde", "serde_json", - "serde_urlencoded 0.5.5", - "time", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", "tokio", - "tokio-executor", - "tokio-io", - "tokio-threadpool", - "tokio-timer", - "url 1.7.2", - "uuid", + "tokio-native-tls", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", "winreg", ] [[package]] name = "rustc-demangle" -version = "0.1.16" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" @@ -1341,6 +1665,35 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +dependencies = [ + "base64 0.22.1", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + [[package]] name = "ryu" version = "1.0.0" @@ -1349,26 +1702,26 @@ checksum = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" [[package]] name = "schannel" -version = "0.1.16" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "lazy_static", - "winapi 0.3.8", + "windows-sys 0.52.0", ] [[package]] name = "scopeguard" -version = "1.0.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "security-framework" -version = "0.3.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -1377,11 +1730,12 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "0.3.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", + "libc", ] [[package]] @@ -1401,29 +1755,29 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.101" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.101" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.2", - "syn 1.0.96", + "proc-macro2", + "quote", + "syn 2.0.66", ] [[package]] name = "serde_json" -version = "1.0.41" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -1431,27 +1785,54 @@ dependencies = [ ] [[package]] -name = "serde_urlencoded" -version = "0.5.5" +name = "serde_qs" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" +checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" dependencies = [ - "dtoa", - "itoa", + "percent-encoding", "serde", - "url 1.7.2", + "thiserror", ] [[package]] name = "serde_urlencoded" -version = "0.6.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ - "dtoa", + "form_urlencoded", "itoa", + "ryu", "serde", - "url 2.1.0", +] + +[[package]] +name = "sha1" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer", + "cfg-if 1.0.0", + "cpufeatures", + "digest", + "opaque-debug", ] [[package]] @@ -1462,13 +1843,13 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "sluice" -version = "0.4.2" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a7d06dfb3e8743bc19e6de8a302277471d08077d68946b307280496dc5a3531" +checksum = "6d7400c0eff44aa2fcb5e31a5f24ba9716ed90138769e4977a2ba6014ae63eb5" dependencies = [ - "futures-channel-preview", - "futures-core-preview", - "futures-io-preview", + "async-channel", + "futures-core", + "futures-io", ] [[package]] @@ -1480,269 +1861,369 @@ dependencies = [ "maybe-uninit", ] +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "socket2" -version = "0.3.19" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ - "cfg-if 1.0.0", "libc", - "winapi 0.3.8", + "windows-sys 0.52.0", +] + +[[package]] +name = "spinning_top" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9eb1a2f4c41445a3a0ff9abc5221c5fcd28e1f13cd7c0397706f9ac938ddb0" +dependencies = [ + "lock_api", +] + +[[package]] +name = "standback" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" +dependencies = [ + "version_check 0.9.4", +] + +[[package]] +name = "stdweb" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" +dependencies = [ + "discard", + "rustc_version", + "stdweb-derive", + "stdweb-internal-macros", + "stdweb-internal-runtime", + "wasm-bindgen", +] + +[[package]] +name = "stdweb-derive" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "serde_derive", + "syn 1.0.96", +] + +[[package]] +name = "stdweb-internal-macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" +dependencies = [ + "base-x", + "proc-macro2", + "quote", + "serde", + "serde_derive", + "serde_json", + "sha1", + "syn 1.0.96", ] [[package]] -name = "sourcefile" -version = "0.1.4" +name = "stdweb-internal-runtime" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" +checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" [[package]] -name = "string" -version = "0.2.1" +name = "subtle" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" -dependencies = [ - "bytes", -] +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "surf" -version = "1.0.3" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "741a8008f8a833ef16f47df94a30754478fb2c2bf822b9c2e6f7f09203b97ace" +checksum = "718b1ae6b50351982dedff021db0def601677f2120938b070eadb10ba4038dd7" dependencies = [ - "futures-preview", - "http", - "isahc", - "js-sys", + "async-std", + "async-trait", + "cfg-if 1.0.0", + "encoding_rs", + "futures-util", + "getrandom 0.2.14", + "http-client", + "http-types", "log", - "mime", "mime_guess", + "once_cell", + "pin-project-lite", "serde", "serde_json", - "serde_urlencoded 0.6.1", - "url 2.1.0", - "wasm-bindgen", - "wasm-bindgen-futures", "web-sys", ] [[package]] name = "syn" -version = "0.15.44" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "unicode-xid", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] name = "syn" -version = "1.0.96" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.2", + "proc-macro2", + "quote", "unicode-ident", ] [[package]] -name = "synstructure" -version = "0.10.2" +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "system-configuration" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.44", - "unicode-xid", + "bitflags 1.2.0", + "core-foundation", + "system-configuration-sys", ] [[package]] -name = "tempfile" -version = "3.1.0" +name = "system-configuration-sys" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" dependencies = [ - "cfg-if 0.1.10", + "core-foundation-sys", "libc", - "rand 0.7.2", +] + +[[package]] +name = "tempfile" +version = "3.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +dependencies = [ + "cfg-if 1.0.0", + "fastrand 2.0.1", "redox_syscall", - "remove_dir_all", - "winapi 0.3.8", + "rustix", + "windows-sys 0.52.0", ] [[package]] -name = "thread_local" -version = "1.1.4" +name = "thiserror" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ - "once_cell", + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", ] [[package]] name = "time" -version = "0.1.42" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" dependencies = [ + "const_fn", "libc", - "redox_syscall", - "winapi 0.3.8", + "standback", + "stdweb", + "time-macros", + "version_check 0.9.4", + "winapi", ] [[package]] -name = "tokio" -version = "0.1.22" +name = "time-macros" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" +checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" dependencies = [ - "bytes", - "futures 0.1.29", - "mio", - "num_cpus", - "tokio-current-thread", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "tokio-tcp", - "tokio-threadpool", - "tokio-timer", + "proc-macro-hack", + "time-macros-impl", ] [[package]] -name = "tokio-buf" -version = "0.1.1" +name = "time-macros-impl" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" +checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" dependencies = [ - "bytes", - "either", - "futures 0.1.29", + "proc-macro-hack", + "proc-macro2", + "quote", + "standback", + "syn 1.0.96", ] [[package]] -name = "tokio-current-thread" -version = "0.1.6" +name = "tokio" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ - "futures 0.1.29", - "tokio-executor", + "autocfg 1.3.0", + "backtrace", + "bytes 1.6.0", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "socket2 0.4.10", + "windows-sys 0.48.0", ] [[package]] -name = "tokio-executor" -version = "0.1.8" +name = "tokio-native-tls" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ - "crossbeam-utils 0.6.6", - "futures 0.1.29", + "native-tls", + "tokio", ] [[package]] -name = "tokio-io" -version = "0.1.12" +name = "tokio-util" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" +checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c" dependencies = [ - "bytes", - "futures 0.1.29", - "log", + "bytes 1.6.0", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", ] [[package]] -name = "tokio-reactor" -version = "0.1.10" +name = "tower" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c56391be9805bc80163151c0b9e5164ee64f4b0200962c346fea12773158f22d" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ - "crossbeam-utils 0.6.6", - "futures 0.1.29", - "lazy_static", - "log", - "mio", - "num_cpus", - "parking_lot", - "slab", - "tokio-executor", - "tokio-io", - "tokio-sync", + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", ] [[package]] -name = "tokio-sync" -version = "0.1.6" +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2162248ff317e2bc713b261f242b69dbb838b85248ed20bb21df56d60ea4cae7" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "fnv", - "futures 0.1.29", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", ] [[package]] -name = "tokio-tcp" -version = "0.1.3" +name = "tracing-attributes" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "bytes", - "futures 0.1.29", - "iovec", - "mio", - "tokio-io", - "tokio-reactor", + "proc-macro2", + "quote", + "syn 2.0.66", ] [[package]] -name = "tokio-threadpool" -version = "0.1.16" +name = "tracing-core" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd2c6a3885302581f4401c82af70d792bb9df1700e7437b0aeb4ada94d5388c" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ - "crossbeam-deque", - "crossbeam-queue", - "crossbeam-utils 0.6.6", - "futures 0.1.29", - "lazy_static", - "log", - "num_cpus", - "slab", - "tokio-executor", + "once_cell", ] [[package]] -name = "tokio-timer" -version = "0.2.11" +name = "tracing-futures" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ - "crossbeam-utils 0.6.6", - "futures 0.1.29", - "slab", - "tokio-executor", + "pin-project", + "tracing", ] [[package]] name = "try-lock" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] -name = "try_from" -version = "0.3.2" +name = "typenum" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" -dependencies = [ - "cfg-if 0.1.10", -] +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicase" @@ -1750,7 +2231,7 @@ version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" dependencies = [ - "version_check", + "version_check 0.1.5", ] [[package]] @@ -1774,57 +2255,42 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" dependencies = [ - "smallvec", + "smallvec 0.6.14", ] [[package]] -name = "unicode-segmentation" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" - -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" - -[[package]] -name = "url" -version = "1.7.2" +name = "universal-hash" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" dependencies = [ - "idna 0.1.5", - "matches", - "percent-encoding 1.0.1", + "generic-array", + "subtle", ] [[package]] name = "url" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" +checksum = "22fe195a4f217c25b25cb5058ced57059824a678474874038dc88d211bf508d3" dependencies = [ - "idna 0.2.0", - "matches", - "percent-encoding 2.1.0", + "form_urlencoded", + "idna", + "percent-encoding", + "serde", ] [[package]] -name = "uuid" -version = "0.7.4" +name = "value-bag" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" -dependencies = [ - "rand 0.6.5", -] +checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" [[package]] name = "vcpkg" -version = "0.2.7" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" @@ -1832,153 +2298,134 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + [[package]] name = "want" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "futures 0.1.29", - "log", "try-lock", ] [[package]] name = "wasi" -version = "0.7.0" +version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.58" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.58" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11cdb95816290b525b32587d76419facd99662a07e59d3cdb560488a819d9a45" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", - "lazy_static", "log", - "proc-macro2 1.0.39", - "quote 1.0.2", - "syn 1.0.96", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.66", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.3.27" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83420b37346c311b9ed822af41ec2e82839bfe99867ec6c54e2da43b7538771c" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ - "cfg-if 0.1.10", - "futures 0.1.29", - "futures-channel-preview", - "futures-util-preview", + "cfg-if 1.0.0", "js-sys", - "lazy_static", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.58" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "574094772ce6921576fb6f2e3f7497b8a76273b6db092be18fc48a082de09dc3" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ - "quote 1.0.2", + "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.58" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e85031354f25eaebe78bb7db1c3d86140312a911a106b2e29f9cc440ce3e7668" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.2", - "syn 1.0.96", + "proc-macro2", + "quote", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e7e61fc929f4c0dddb748b102ebf9f632e2b8d739f2016542b4de2965a9601" - -[[package]] -name = "wasm-bindgen-webidl" -version = "0.2.58" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef012a0d93fc0432df126a8eaf547b2dce25a8ce9212e1d3cbeef5c11157975d" -dependencies = [ - "anyhow", - "heck", - "log", - "proc-macro2 1.0.39", - "quote 1.0.2", - "syn 1.0.96", - "wasm-bindgen-backend", - "weedle", -] +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.35" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf97caf6aa8c2b1dac90faf0db529d9d63c93846cca4911856f78a83cebf53b" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ - "anyhow", "js-sys", - "sourcefile", "wasm-bindgen", - "wasm-bindgen-webidl", ] [[package]] -name = "weedle" -version = "0.10.0" +name = "wepoll-ffi" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" dependencies = [ - "nom", + "cc", ] [[package]] name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - -[[package]] -name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -1992,20 +2439,200 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "winreg" -version = "0.6.2" +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "winapi 0.3.8", + "windows-targets 0.48.5", ] [[package]] -name = "ws2_32-sys" -version = "0.2.1" +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "cfg-if 1.0.0", + "windows-sys 0.48.0", ] diff --git a/Cargo.toml b/Cargo.toml index 9fdbe995..5d54ce18 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,19 +1,30 @@ [package] name = "leetcode-rust" version = "0.1.0" -authors = ["alei "] -edition = "2018" +authors = ["ben1009"] +edition = "2021" [dependencies] -reqwest = "0.9.8" +dotenv = "0.15.0" +futures = { version = "0.3.30", features = ["thread-pool"] } +rand = "0.6.5" +regex = "1.5.5" +reqwest = { version = "0.12", features = [ + "blocking", + "json", + "native-tls-alpn", + "gzip", +] } serde = "1.0" -serde_json = "1.0" serde_derive = "1.0" -rand = "0.6.5" -regex = "1.3.4" -futures = { version = "0.3.3", features = ["thread-pool"] } -surf = "1.0.3" +serde_json = "1.0" +surf = "2.3.2" +tempfile = "3.9.0" [lib] doctest = false test = true +# bench = false + +[package.metadata.cargo-machete] +ignored = ["openssl", "serde"] diff --git a/Makefile.toml b/Makefile.toml new file mode 100644 index 00000000..42665e0f --- /dev/null +++ b/Makefile.toml @@ -0,0 +1,139 @@ +[config] +default_to_workspace = false +# Skip loading of all core tasks which saves up a bit on toml parsing and task creation +skip_core_tasks = true +# Skips loading Git related environment variables +skip_git_env_info = true +# Skips loading rust related environment variables +skip_rust_env_info = true +# Skips loading the current crate related environment variables +skip_crate_env_info = true +min_version = "0.36.10" + +[tasks.install-nextest] +category = "Misc" +description = "install cargo-nextest" +install_crate = { crate_name = "cargo-nextest", version = "0.9.87", binary = "cargo", test_arg = [ + "nextest", + "--help", +] } + +[tasks.install-llvm-cov] +category = "Misc" +description = "install cargo-llvm-cov" +install_crate = { crate_name = "cargo-llvm-cov", version = "0.6.15", binary = "cargo", test_arg = [ + "llvm-cov", + "--help", +] } + +[tasks.clean] +category = "Dev - check" +description = "Run cargo clean" +command = "cargo" +args = ["clean"] + +[tasks.check-clippy] +category = "Dev - check" +description = "Run full cargo clippy check" +script = """ +#!/usr/bin/env bash + +cargo clippy --workspace --all-features --all-targets -- -D warnings +""" + +[tasks.check-fmt] +category = "Dev - check" +description = "Run cargo fmt check" +command = "cargo" +args = ["fmt", "--all"] + +[tasks.check-typos] +category = "Dev - check" +description = "Run cargo typos-cli check" +install_crate = { version = "1.28.4", crate_name = "typos-cli", binary = "typos", test_arg = [ + "--help", +] } +script = """ +#!/usr/bin/env bash + +if ! typos ; then + echo "Hint: use 'typos -w' to fix." +else + echo "typos check pass !" +fi +""" + +[tasks.check-hakari] +category = "Dev - check" +description = "Run cargo hakari check and attempt to fix" +install_crate = { version = "0.9.34", crate_name = "cargo-hakari", binary = "cargo", test_arg = [ + "hakari", + "--help", +] } +script = """ +#!/usr/bin/env bash + +cargo hakari generate --diff --quiet || cargo hakari generate +cargo hakari verify > /dev/null +""" + +[tasks.check-machete] +category = "Dev - check" +description = "Run cargo machete check" +install_crate = { version = "0.7.0", crate_name = "cargo-machete", binary = "cargo", test_arg = [ + "machete", + "--help", +] } +script = """ +#!/usr/bin/env bash +set -e + +cargo machete +""" + +[tasks.check-dep-sort] +category = "Dev - check" +description = "Run cargo sort check and attempt to fix" +install_crate = { version = "1.0.9", crate_name = "cargo-sort", binary = "cargo", test_arg = [ + "sort", + "--help", +] } +script = """ +#!/usr/bin/env bash + + (cargo sort -w -c > /dev/null) || cargo sort -w +""" + +[tasks.test-cov] +category = "Dev - check" +description = "Run unit tests and report coverage" +dependencies = ["install-llvm-cov", "install-nextest"] +script = """ +#!/usr/bin/env bash +set -e + +cargo llvm-cov nextest --workspace --all-features --all-targets --html +""" + +[tasks.test] +category = "Dev - check" +description = "Run unit tests" +dependencies = ["install-nextest"] +script = """ +#!/usr/bin/env bash +set -e + +cargo nextest run --workspace --all-features --all-targets +""" + +[tasks.check] +category = "Dev - check" +description = "Run all checks one by one" +dependencies = [ + "check-fmt", + "check-dep-sort", + "check-clippy", + "check-machete", + "test", + "check-typos", +] diff --git a/README.md b/README.md index 587b18a2..46130088 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,16 @@ -# My Leetcode Solution in Rust +# 🦀 Leetcode Solution in Rust, just to torture myself for fun 🤪 -Run `cargo run {id}` to initialize the template submission file of "question #id". - -Run `cargo test test_{id}` to test the solution for "question #id". +[![codecov](https://codecov.io/gh/ben1009/leetcode-rust/branch/master/graph/badge.svg)](https://codecov.io/gh/ben1009/leetcode-rust) +[![Build Status](https://github.com/ben1009/leetcode-rust/workflows/check/badge.svg)](https://github.com/ben1009/leetcode-rust/actions?query=workflow:check) -对于大部分难度为 Hard 的问题, 会有中文的思路注释 +Set `LEETCODE_COOKIE` in `.env` file or environment variable first. -Working in progress, to do: +Run `cargo run {id}` to initialize the template submission file of "question #id". -- [ ] auto generation of solution list (when 100 problems solved) +Run `cargo test test_{id}` to test the solution for "question #id". ## Usage -* Remove all the solution .rs -* Clean lib.rs file -* Start your leetcode journey in rust by typing `cargo run {question_id}` - +- Remove all the solution .rs +- Clean lib.rs file +- Start your leetcode journey in rust by typing `cargo run {question_id}` diff --git a/dev b/dev new file mode 100755 index 00000000..83e0342c --- /dev/null +++ b/dev @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +if [ -z "$(which cargo-binstall)" ]; then + echo "Installing cargo-binstall..." + curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash +fi + +if [ -z "$(which cargo-make)" ]; then + echo "Installing cargo-make..." + cargo binstall cargo-make +fi + +if [ $# -eq 0 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then + cargo make --list-all-steps --hide-uninteresting + exit 0 +fi + +cargo make "$@" \ No newline at end of file diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 00000000..bcc3629e --- /dev/null +++ b/rust-toolchain @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly-2025-02-01" \ No newline at end of file diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..3ff1f871 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,14 @@ +edition = "2021" +style_edition = "2024" +comment_width = 120 +format_code_in_doc_comments = true +format_macro_bodies = true +format_macro_matchers = true +normalize_comments = true +normalize_doc_attributes = true +imports_granularity = "Crate" +group_imports = "StdExternalCrate" +reorder_impl_items = true +reorder_imports = true +tab_spaces = 4 +wrap_comments = true diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 00000000..abb6084d Binary files /dev/null and b/src/.DS_Store differ diff --git a/src/fetcher.rs b/src/fetcher.rs index c356dee8..ac893d5c 100644 --- a/src/fetcher.rs +++ b/src/fetcher.rs @@ -1,9 +1,10 @@ extern crate reqwest; extern crate serde_json; -use serde_json::Value; use std::fmt::{Display, Error, Formatter}; +use serde_json::Value; + const PROBLEMS_URL: &str = "https://leetcode.com/api/problems/algorithms/"; const GRAPHQL_URL: &str = "https://leetcode.com/graphql"; const QUESTION_QUERY_STRING: &str = r#" @@ -25,8 +26,8 @@ pub fn get_problem(frontend_question_id: u32) -> Option { if problem.paid_only { return None; } - - let client = reqwest::Client::new(); + println!("getting problem ..."); + let client = reqwest::blocking::Client::new(); let resp: RawProblem = client .post(GRAPHQL_URL) .json(&Query::question_query( @@ -46,7 +47,7 @@ pub fn get_problem(frontend_question_id: u32) -> Option { question_id: problem.stat.frontend_question_id, return_type: { let v: Value = serde_json::from_str(&resp.data.question.meta_data).unwrap(); - v["return"]["type"].to_string().replace("\"", "") + v["return"]["type"].to_string().replace('\"', "") }, }); } @@ -81,7 +82,8 @@ pub async fn get_problem_async(problem_stat: StatWithStatus) -> Option return None; } let resp: RawProblem = resp.unwrap(); - return Some(Problem { + + Some(Problem { title: problem_stat.stat.question_title.clone().unwrap(), title_slug: problem_stat.stat.question_title_slug.clone().unwrap(), code_definition: serde_json::from_str(&resp.data.question.code_definition).unwrap(), @@ -91,13 +93,86 @@ pub async fn get_problem_async(problem_stat: StatWithStatus) -> Option question_id: problem_stat.stat.frontend_question_id, return_type: { let v: Value = serde_json::from_str(&resp.data.question.meta_data).unwrap(); - v["return"]["type"].to_string().replace("\"", "") + v["return"]["type"].to_string().replace('\"', "") }, - }); + }) } pub fn get_problems() -> Option { - reqwest::get(PROBLEMS_URL).unwrap().json().unwrap() + println!("getting all problems ..."); + let headers = { + let mut h = reqwest::header::HeaderMap::new(); + h.insert( + "Accept", + reqwest::header::HeaderValue::from_static( + "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", + ), + ); + h.insert( + "Accept-Encoding", + reqwest::header::HeaderValue::from_static("gzip, deflate, br"), + ); + h.insert( + "Accept-Language", + reqwest::header::HeaderValue::from_static("zh-CN,en-US;q=0.7,en;q=0.3"), + ); + h.insert( + "Connection", + reqwest::header::HeaderValue::from_static("keep-alive"), + ); + h.insert( + "User-Agent", + reqwest::header::HeaderValue::from_static( + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0", + ), + ); + h.insert( + "Sec-Fetch-Dest", + reqwest::header::HeaderValue::from_static("document"), + ); + h.insert( + "Sec-Fetch-Mode", + reqwest::header::HeaderValue::from_static("navigate"), + ); + h.insert( + "Sec-Fetch-Site", + reqwest::header::HeaderValue::from_static("none"), + ); + h.insert( + "Sec-Fetch-User", + reqwest::header::HeaderValue::from_static("?1"), + ); + h.insert( + "Upgrade-Insecure-Requests", + reqwest::header::HeaderValue::from_static("1"), + ); + + h.insert( + "Host", + reqwest::header::HeaderValue::from_static("leetcode.com"), + ); + h.insert( + "Cookie", + reqwest::header::HeaderValue::from_str( + &std::env::var("LEETCODE_COOKIE") + .expect("Please set LEETCODE_COOKIE in .env file or environment"), + ) + .unwrap(), + ); + h + }; + let client = reqwest::blocking::Client::builder() + .connection_verbose(true) + .http2_prior_knowledge() + .gzip(true) + .build() + .unwrap(); + let get = client.get(PROBLEMS_URL).headers(headers); + // println!("Get: {:?}", get); + let response = get.send().unwrap(); + // println!("Response: {:?}", response); + let result = response.json(); + result.unwrap() } #[derive(Serialize, Deserialize)] diff --git a/src/lib.rs b/src/lib.rs index 55b0298f..74b04f1d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,7 @@ +#![feature(test)] + #[macro_use] pub mod util; -pub mod solution; +// pub mod solution; pub mod problem; diff --git a/src/main.rs b/src/main.rs index 6fecf106..10e6a172 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,29 +2,39 @@ extern crate serde_derive; #[macro_use] extern crate serde_json; +extern crate dotenv; mod fetcher; -use crate::fetcher::{CodeDefinition, Problem}; +use std::{ + fs, + fs::File, + io, + io::{BufRead, Write}, + path::Path, + sync::{Arc, Mutex}, +}; + +use dotenv::dotenv; +use futures::{ + executor::{ThreadPool, block_on}, + future::join_all, + task::SpawnExt, +}; use regex::Regex; -use std::env; -use std::fs; -use std::fs::File; -use std::io; -use std::io::{BufRead, Write}; -use std::path::Path; -use futures::executor::block_on; -use futures::executor::ThreadPool; -use futures::future::join_all; -use futures::stream::StreamExt; -use futures::task::SpawnExt; -use std::sync::{Arc, Mutex}; +use crate::fetcher::{CodeDefinition, Problem}; /// main() helps to generate the submission template .rs fn main() { println!("Welcome to leetcode-rust system.\n"); - let mut initialized_ids = get_initialized_ids(); + dotenv().unwrap(); + + let mut initialized_ids = get_initialized_ids("./src/problem/mod.rs"); + let random_pattern = Regex::new(r"^random$").unwrap(); + let solving_pattern = Regex::new(r"^solve (\d+)$").unwrap(); + let all_pattern = Regex::new(r"^all$").unwrap(); + loop { println!( "Please enter a frontend problem id, \n\ @@ -32,29 +42,25 @@ fn main() { or \"solve $i\" to move problem to solution/, \n\ or \"all\" to initialize all problems \n" ); - let mut is_random = false; - let mut is_solving = false; - let mut id: u32 = 0; + let mut _is_random = false; + let mut _is_solving = false; + let mut _id: u32 = 0; let mut id_arg = String::new(); io::stdin() .read_line(&mut id_arg) .expect("Failed to read line"); let id_arg = id_arg.trim(); - let random_pattern = Regex::new(r"^random$").unwrap(); - let solving_pattern = Regex::new(r"^solve (\d+)$").unwrap(); - let all_pattern = Regex::new(r"^all$").unwrap(); - if random_pattern.is_match(id_arg) { println!("You select random mode."); - id = generate_random_id(&initialized_ids); - is_random = true; - println!("Generate random problem: {}", &id); + _id = generate_random_id(&initialized_ids); + _is_random = true; + println!("Generate random problem: {}", &_id); } else if solving_pattern.is_match(id_arg) { // solve a problem // move it from problem/ to solution/ - is_solving = true; - id = solving_pattern + _is_solving = true; + _id = solving_pattern .captures(id_arg) .unwrap() .get(1) @@ -62,14 +68,14 @@ fn main() { .as_str() .parse() .unwrap(); - deal_solving(&id); + deal_solving(&_id); break; } else if all_pattern.is_match(id_arg) { // deal all problems let pool = ThreadPool::new().unwrap(); let mut tasks = vec![]; let problems = fetcher::get_problems().unwrap(); - let mut mod_file_addon = Arc::new(Mutex::new(vec![])); + let mod_file_addon = Arc::new(Mutex::new(vec![])); for problem_stat in problems.stat_status_pairs { if initialized_ids.contains(&problem_stat.stat.frontend_question_id) { continue; @@ -82,10 +88,7 @@ fn main() { return; } let problem = problem.unwrap(); - let code = problem - .code_definition - .iter() - .find(|&d| d.value == "rust".to_string()); + let code = problem.code_definition.iter().find(|&d| d.value == *"rust"); if code.is_none() { println!("Problem {} has no rust version.", problem.question_id); return; @@ -95,61 +98,58 @@ fn main() { mod_file_addon.lock().unwrap().push(format!( "mod p{:04}_{};", problem.question_id, - problem.title_slug.replace("-", "_") + problem.title_slug.replace('-', "_") )); } .await; let code = code.unwrap(); // not sure this can be async // maybe should use async-std io - async { deal_problem(&problem, &code, false) }.await + async { deal_problem(&problem, code, false) }.await }) .unwrap(), ); } block_on(join_all(tasks)); let mut lib_file = fs::OpenOptions::new() - .write(true) .append(true) .open("./src/problem/mod.rs") .unwrap(); - writeln!(lib_file, "{}", mod_file_addon.lock().unwrap().join("\n")); + let _ = writeln!(lib_file, "{}", mod_file_addon.lock().unwrap().join("\n")); break; } else { - id = id_arg + _id = id_arg .parse::() .unwrap_or_else(|_| panic!("not a number: {}", id_arg)); - if initialized_ids.contains(&id) { + if initialized_ids.contains(&_id) { println!("The problem you chose has been initialized in problem/"); continue; } } - let problem = fetcher::get_problem(id).unwrap_or_else(|| { + let problem = fetcher::get_problem(_id).unwrap_or_else(|| { panic!( "Error: failed to get problem #{} \ (The problem may be paid-only or may not be exist).", - id + _id ) }); - let code = problem - .code_definition - .iter() - .find(|&d| d.value == "rust".to_string()); + let code = problem.code_definition.iter().find(|&d| d.value == *"rust"); if code.is_none() { - println!("Problem {} has no rust version.", &id); + println!("Problem {} has no rust version.", &_id); initialized_ids.push(problem.question_id); continue; } let code = code.unwrap(); - deal_problem(&problem, &code, true); + deal_problem(&problem, code, true); break; } + println!("Done, Thanks for using leetcode-rust system.\n"); } fn generate_random_id(except_ids: &[u32]) -> u32 { use rand::Rng; - use std::fs; + let mut rng = rand::thread_rng(); loop { let res: u32 = rng.gen_range(1, 1106); @@ -164,13 +164,20 @@ fn generate_random_id(except_ids: &[u32]) -> u32 { } } -fn get_initialized_ids() -> Vec { - let content = fs::read_to_string("./src/problem/mod.rs").unwrap(); +fn get_initialized_ids(path: &str) -> Vec { + let content = fs::read_to_string(path).unwrap(); let id_pattern = Regex::new(r"p(\d{4})_").unwrap(); - id_pattern - .captures_iter(&content) - .map(|x| x.get(1).unwrap().as_str().parse().unwrap()) - .collect() + + let mut ret = vec![]; + for l in content.lines() { + if !l.trim().starts_with("//") { + if let Some(id) = id_pattern.captures(l) { + ret.push(id.get(1).unwrap().as_str().parse::().unwrap()); + } + } + } + + ret } fn parse_extra_use(code: &str) -> String { @@ -203,37 +210,38 @@ fn insert_return_in_code(return_type: &str, code: &str) -> String { let re = Regex::new(r"\{[ \n]+}").unwrap(); match return_type { "ListNode" => re - .replace(&code, "{\n Some(Box::new(ListNode::new(0)))\n }") + .replace(code, "{\n Some(Box::new(ListNode::new(0)))\n }") .to_string(), - "ListNode[]" => re.replace(&code, "{\n vec![]\n }").to_string(), + "ListNode[]" => re.replace(code, "{\n vec![]\n }").to_string(), "TreeNode" => re .replace( - &code, + code, "{\n Some(Rc::new(RefCell::new(TreeNode::new(0))))\n }", ) .to_string(), - "boolean" => re.replace(&code, "{\n false\n }").to_string(), - "character" => re.replace(&code, "{\n '0'\n }").to_string(), - "character[][]" => re.replace(&code, "{\n vec![]\n }").to_string(), - "double" => re.replace(&code, "{\n 0f64\n }").to_string(), - "double[]" => re.replace(&code, "{\n vec![]\n }").to_string(), - "int[]" => re.replace(&code, "{\n vec![]\n }").to_string(), - "integer" => re.replace(&code, "{\n 0\n }").to_string(), - "integer[]" => re.replace(&code, "{\n vec![]\n }").to_string(), - "integer[][]" => re.replace(&code, "{\n vec![]\n }").to_string(), - "list" => re.replace(&code, "{\n vec![]\n }").to_string(), - "list" => re.replace(&code, "{\n vec![]\n }").to_string(), - "list" => re.replace(&code, "{\n vec![]\n }").to_string(), - "list" => re.replace(&code, "{\n vec![]\n }").to_string(), - "list" => re.replace(&code, "{\n vec![]\n }").to_string(), - "list>" => re.replace(&code, "{\n vec![]\n }").to_string(), - "list>" => re.replace(&code, "{\n vec![]\n }").to_string(), - "list" => re.replace(&code, "{\n vec![]\n }").to_string(), + "boolean" => re.replace(code, "{\n false\n }").to_string(), + "character" => re.replace(code, "{\n '0'\n }").to_string(), + "character[][]" => re.replace(code, "{\n vec![]\n }").to_string(), + "double" => re.replace(code, "{\n 0f64\n }").to_string(), + "double[]" => re.replace(code, "{\n vec![]\n }").to_string(), + "int[]" => re.replace(code, "{\n vec![]\n }").to_string(), + + "integer" => re.replace(code, "{\n 0\n }").to_string(), + "integer[]" => re.replace(code, "{\n vec![]\n }").to_string(), + "integer[][]" => re.replace(code, "{\n vec![]\n }").to_string(), + "list" => re.replace(code, "{\n vec![]\n }").to_string(), + "list" => re.replace(code, "{\n vec![]\n }").to_string(), + "list" => re.replace(code, "{\n vec![]\n }").to_string(), + "list" => re.replace(code, "{\n vec![]\n }").to_string(), + "list" => re.replace(code, "{\n vec![]\n }").to_string(), + "list>" => re.replace(code, "{\n vec![]\n }").to_string(), + "list>" => re.replace(code, "{\n vec![]\n }").to_string(), + "list" => re.replace(code, "{\n vec![]\n }").to_string(), "null" => code.to_string(), "string" => re - .replace(&code, "{\n String::new()\n }") + .replace(code, "{\n String::new()\n }") .to_string(), - "string[]" => re.replace(&code, "{\n vec![]\n }").to_string(), + "string[]" => re.replace(code, "{\n vec![]\n }").to_string(), "void" => code.to_string(), "NestedInteger" => code.to_string(), "Node" => code.to_string(), @@ -273,7 +281,7 @@ fn build_desc(content: &str) -> String { .replace("−", "-") .replace("'", "'") .replace("\n\n", "\n") - .replace("\n", "\n * ") + .replace('\n', "\n * ") } fn deal_solving(id: &u32) { @@ -281,7 +289,7 @@ fn deal_solving(id: &u32) { let file_name = format!( "p{:04}_{}", problem.question_id, - problem.title_slug.replace("-", "_") + problem.title_slug.replace('-', "_") ); let file_path = Path::new("./src/problem").join(format!("{}.rs", file_name)); // check problem/ existence @@ -292,7 +300,7 @@ fn deal_solving(id: &u32) { let solution_name = format!( "s{:04}_{}", problem.question_id, - problem.title_slug.replace("-", "_") + problem.title_slug.replace('-', "_") ); let solution_path = Path::new("./src/solution").join(format!("{}.rs", solution_name)); if solution_path.exists() { @@ -308,25 +316,22 @@ fn deal_solving(id: &u32) { .map(|x| x.unwrap()) .filter(|x| *x != target_line) .collect(); - fs::write(mod_file, lines.join("\n")); + let _ = fs::write(mod_file, lines.join("\n")); // insert into solution/mod.rs let mut lib_file = fs::OpenOptions::new() .append(true) .open("./src/solution/mod.rs") .unwrap(); - writeln!(lib_file, "mod {};", solution_name); + let _ = writeln!(lib_file, "mod {};", solution_name); } fn deal_problem(problem: &Problem, code: &CodeDefinition, write_mod_file: bool) { let file_name = format!( "p{:04}_{}", problem.question_id, - problem.title_slug.replace("-", "_") + problem.title_slug.replace('-', "_") ); let file_path = Path::new("./src/problem").join(format!("{}.rs", file_name)); - if file_path.exists() { - panic!("problem already initialized"); - } let template = fs::read_to_string("./template.rs").unwrap(); let source = template @@ -345,7 +350,7 @@ fn deal_problem(problem: &Problem, code: &CodeDefinition, write_mod_file: bool) .write(true) .create(true) .truncate(true) - .open(&file_path) + .open(file_path) .unwrap(); file.write_all(source.as_bytes()).unwrap(); @@ -353,10 +358,31 @@ fn deal_problem(problem: &Problem, code: &CodeDefinition, write_mod_file: bool) if write_mod_file { let mut lib_file = fs::OpenOptions::new() - .write(true) .append(true) .open("./src/problem/mod.rs") .unwrap(); - writeln!(lib_file, "mod {};", file_name); + let _ = writeln!(lib_file, "pub mod {};", file_name); + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_get_initialized_ids() { + let dir = tempfile::TempDir::new().unwrap(); + let path = dir.path().join("test_get_initialized_ids"); + let mut file = fs::File::create(path.clone()).unwrap(); + let content = r#" + // pub mod p0001_two_sum; + pub mod p0002_add_two_numbers; + pub mod p0003_longest_substring_without_repeating_characters;"#; + writeln!(file, "{}", content).unwrap(); + let ids = get_initialized_ids(path.to_str().unwrap()); + println!("{:?}", ids); + assert!(ids.len() == 2); + assert!(ids[0] == 2); + assert!(ids[1] == 3); } } diff --git a/src/problem/mod.rs b/src/problem/mod.rs index e69de29b..dd268e06 100644 --- a/src/problem/mod.rs +++ b/src/problem/mod.rs @@ -0,0 +1,83 @@ +pub mod p0001_two_sum; +pub mod p0002_add_two_numbers; +pub mod p0003_longest_substring_without_repeating_characters; +pub mod p0005_longest_palindromic_substring; +pub mod p0007_reverse_integer; +pub mod p0010_regular_expression_matching; +pub mod p0011_container_with_most_water; +pub mod p0014_longest_common_prefix; +pub mod p0017_letter_combinations_of_a_phone_number; +pub mod p0019_remove_nth_node_from_end_of_list; +pub mod p0020_valid_parentheses; +pub mod p0022_generate_parentheses; +pub mod p0023_merge_k_sorted_lists; +pub mod p0027_remove_element; +pub mod p0029_divide_two_integers; +pub mod p0041_first_missing_positive; +pub mod p0042_trapping_rain_water; +pub mod p0043_multiply_strings; +pub mod p0056_merge_intervals; +pub mod p0064_minimum_path_sum; +pub mod p0070_climbing_stairs; +pub mod p0088_merge_sorted_array; +pub mod p0091_decode_ways; +pub mod p0094_binary_tree_inorder_traversal; +pub mod p0095_unique_binary_search_trees_ii; +pub mod p0096_unique_binary_search_trees; +pub mod p0101_symmetric_tree; +pub mod p0109_convert_sorted_list_to_binary_search_tree; +pub mod p0111_minimum_depth_of_binary_tree; +pub mod p0114_flatten_binary_tree_to_linked_list; +pub mod p0128_longest_consecutive_sequence; +pub mod p0133_clone_graph; +pub mod p0144_binary_tree_preorder_traversal; +pub mod p0145_binary_tree_postorder_traversal; +pub mod p0148_sort_list; +pub mod p0152_maximum_product_subarray; +pub mod p0153_find_minimum_in_rotated_sorted_array; +pub mod p0155_min_stack; +pub mod p0165_compare_version_numbers; +pub mod p0202_happy_number; +pub mod p0205_isomorphic_strings; +pub mod p0243_shortest_word_distance; +pub mod p0345_reverse_vowels_of_a_string; +pub mod p0416_partition_equal_subset_sum; +pub mod p0494_target_sum; +pub mod p0496_next_greater_element_i; +pub mod p0503_next_greater_element_ii; +pub mod p0521_longest_uncommon_subsequence; +pub mod p0543_diameter_of_binary_tree; +pub mod p0551_student_attendance_record_i; +pub mod p0560_subarray_sum_equals_k; +pub mod p0581_shortest_unsorted_continuous_subarray; +pub mod p0617_merge_two_binary_trees; +pub mod p0682_baseball_game; +pub mod p0705_design_hashset; +pub mod p0724_find_pivot_index; +pub mod p0739_daily_temperatures; +pub mod p0912_sort_an_array; +pub mod p0926_flip_string_to_monotone_increasing; +pub mod p1004_max_consecutive_ones_iii; +pub mod p1016_binary_string_with_substrings_representing_1_to_n; +pub mod p1054_distant_barcodes; +pub mod p1186_maximum_subarray_sum_with_one_deletion; +pub mod p1376_time_needed_to_inform_all_employees; +pub mod p2437_number_of_valid_clock_times; +pub mod p2671_frequency_tracker; +pub mod p2708_maximum_strength_of_a_group; +pub mod p2710_remove_trailing_zeros_from_a_string; +pub mod p2766_relocate_marbles; +pub mod p2810_faulty_keyboard; +pub mod p2923_find_champion_i; +pub mod p2924_find_champion_ii; +pub mod p2938_separate_black_and_white_balls; +pub mod p2956_find_common_elements_between_two_arrays; +pub mod p2974_minimum_number_game; +pub mod p3033_modify_the_matrix; +pub mod p3142_check_if_grid_satisfies_conditions; +pub mod p3151_special_array_i; +pub mod p3152_special_array_ii; +pub mod p3153_sum_of_digit_differences_of_all_pairs; +pub mod p3174_clear_digits; +pub mod p3226_number_of_bit_changes_to_make_two_integers_equal; +pub mod p3259_maximum_energy_boost_from_two_drinks; diff --git a/src/problem/p0001_two_sum.rs b/src/problem/p0001_two_sum.rs new file mode 100644 index 00000000..22eaf2cb --- /dev/null +++ b/src/problem/p0001_two_sum.rs @@ -0,0 +1,69 @@ +use std::collections::HashMap; + +/// [1] Two Sum +/// +/// Given an array of integers nums and an integer target, return indices of the two numbers such +/// that they add up to target. You may assume that each input would have exactly one solution, and +/// you may not use the same element twice. You can return the answer in any order. +/// +/// Example 1: +/// +/// Input: nums = [2,7,11,15], target = 9 +/// Output: [0,1] +/// Explanation: Because nums[0] + nums[1] == 9, we return [0, 1]. +/// +/// Example 2: +/// +/// Input: nums = [3,2,4], target = 6 +/// Output: [1,2] +/// +/// Example 3: +/// +/// Input: nums = [3,3], target = 6 +/// Output: [0,1] +/// +/// +/// Constraints: +/// +/// 2 <= nums.length <= 10^4 +/// -10^9 <= nums[i] <= 10^9 +/// -10^9 <= target <= 10^9 +/// Only one valid answer exists. +/// +/// +/// Follow-up: Can you come up with an algorithm that is less than O(n^2) +/// time complexity? +pub struct Solution {} + +// problem: https://leetcode.com/problems/two-sum/ +// discuss: https://leetcode.com/problems/two-sum/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn two_sum(nums: Vec, target: i32) -> Vec { + let mut map = HashMap::new(); + for (i, &n) in nums.iter().enumerate() { + if let Some(&j) = map.get(&(target - n)) { + return vec![j, i as i32]; + } + map.insert(n, i as i32); + } + + vec![] + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1() { + assert!(Solution::two_sum(vec![2, 7, 11, 15], 9) == vec![0, 1]); + assert!(Solution::two_sum(vec![3, 2, 4], 6) == vec![1, 2]); + assert!(Solution::two_sum(vec![3, 3], 6) == vec![0, 1]); + } +} diff --git a/src/problem/p0002_add_two_numbers.rs b/src/problem/p0002_add_two_numbers.rs new file mode 100644 index 00000000..7da77a43 --- /dev/null +++ b/src/problem/p0002_add_two_numbers.rs @@ -0,0 +1,117 @@ +/// [2] Add Two Numbers +/// +/// You are given two non-empty linked lists representing two non-negative integers. The digits are +/// stored in reverse order, and each of their nodes contains a single digit. Add the two numbers +/// and return the sum as a linked list. You may assume the two numbers do not contain any leading +/// zero, except the number 0 itself. +/// Example 1: +/// +/// Input: l1 = [2,4,3], l2 = [5,6,4] +/// Output: [7,0,8] +/// Explanation: 342 + 465 = 807. +/// +/// Example 2: +/// +/// Input: l1 = [0], l2 = [0] +/// Output: [0] +/// +/// Example 3: +/// +/// Input: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9] +/// Output: [8,9,9,9,0,0,0,1] +/// +/// +/// Constraints: +/// +/// The number of nodes in each linked list is in the range [1, 100]. +/// 0 <= Node.val <= 9 +/// It is guaranteed that the list represents a number that does not have leading zeros. +pub struct Solution {} + +use crate::util::linked_list::ListNode; + +// problem: https://leetcode.com/problems/add-two-numbers/ +// discuss: https://leetcode.com/problems/add-two-numbers/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +// Definition for singly-linked list. +// #[derive(PartialEq, Eq, Clone, Debug)] +// pub struct ListNode { +// pub val: i32, +// pub next: Option> +// } +// +// impl ListNode { +// #[inline] +// fn new(val: i32) -> Self { +// ListNode { +// next: None, +// val +// } +// } +// } + +impl Solution { + pub fn add_two_numbers( + l1: Option>, + l2: Option>, + ) -> Option> { + if l1.is_none() { + return l2; + } + if l2.is_none() { + return l1; + } + + let mut root_pointer = ListNode::new(0); + let mut current = &mut root_pointer; + let mut carry = 0; + let mut l1 = l1; + let mut l2 = l2; + while l1.is_some() || l2.is_some() || carry != 0 { + let mut v1 = 0; + let mut v2 = 0; + if let Some(mut n1) = l1 { + v1 = n1.val; + l1 = n1.next.take(); + } + if let Some(mut n2) = l2 { + v2 = n2.val; + l2 = n2.next.take(); + } + let v = (v1 + v2 + carry) % 10; + carry = (v1 + v2 + carry) / 10; + current.next = Some(Box::new(ListNode::new(v))); + current = current.next.as_mut().unwrap(); + } + + root_pointer.next + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + use crate::util::linked_list::to_list; + + #[test] + fn test_2() { + assert_eq!( + Solution::add_two_numbers(to_list(vec![2, 4, 3]), to_list(vec![5, 6, 4])), + to_list(vec![7, 0, 8]) + ); + + assert_eq!( + Solution::add_two_numbers(to_list(vec![9, 9, 9, 9]), to_list(vec![9, 9, 9, 9, 9, 9])), + to_list(vec![8, 9, 9, 9, 0, 0, 1]) + ); + + assert_eq!( + Solution::add_two_numbers(to_list(vec![0]), to_list(vec![0])), + to_list(vec![0]) + ) + } +} diff --git a/src/problem/p0003_longest_substring_without_repeating_characters.rs b/src/problem/p0003_longest_substring_without_repeating_characters.rs new file mode 100644 index 00000000..7c843eb5 --- /dev/null +++ b/src/problem/p0003_longest_substring_without_repeating_characters.rs @@ -0,0 +1,77 @@ +use std::collections::HashMap; + +/// [3] Longest Substring Without Repeating Characters +/// +/// Given a string s, find the length of the longest substring without repeating characters. +/// Example 1: +/// +/// Input: s = "abcabcbb" +/// Output: 3 +/// Explanation: The answer is "abc", with the length of 3. +/// +/// Example 2: +/// +/// Input: s = "bbbbb" +/// Output: 1 +/// Explanation: The answer is "b", with the length of 1. +/// +/// Example 3: +/// +/// Input: s = "pwwkew" +/// Output: 3 +/// Explanation: The answer is "wke", with the length of 3. +/// Notice that the answer must be a substring, "pwke" is a subsequence and not a substring. +/// +/// +/// Constraints: +/// +/// 0 <= s.length <= 5 * 10^4 +/// s consists of English letters, digits, symbols and spaces. +pub struct Solution {} + +// problem: https://leetcode.com/problems/longest-substring-without-repeating-characters/ +// discuss: https://leetcode.com/problems/longest-substring-without-repeating-characters/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn length_of_longest_substring(s: String) -> i32 { + if s.len() <= 1 { + return s.len() as i32; + } + + let mut map = HashMap::new(); + let mut ret = 0; + let mut pre = 0; + for (i, c) in s.bytes().enumerate() { + match map.entry(c) { + std::collections::hash_map::Entry::Occupied(o) => { + if o.get() >= &pre { + pre = o.get() + 1; + } + } + std::collections::hash_map::Entry::Vacant(_) => {} + } + ret = ret.max(i - pre + 1); + map.insert(c, i); + } + + ret as i32 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_3() { + assert_eq!(Solution::length_of_longest_substring("abcda".into()), 4); + assert_eq!(Solution::length_of_longest_substring("abcd".into()), 4); + assert_eq!(Solution::length_of_longest_substring("".into()), 0); + assert!(Solution::length_of_longest_substring("tmmzuxt".into()) == 5); + } +} diff --git a/src/problem/p0005_longest_palindromic_substring.rs b/src/problem/p0005_longest_palindromic_substring.rs new file mode 100644 index 00000000..76e4908b --- /dev/null +++ b/src/problem/p0005_longest_palindromic_substring.rs @@ -0,0 +1,71 @@ +/// [5] Longest Palindromic Substring +/// +/// Given a string s, return the longest palindromic +/// substring in s. +/// Example 1: +/// +/// Input: s = "babad" +/// Output: "bab" +/// Explanation: "aba" is also a valid answer. +/// +/// Example 2: +/// +/// Input: s = "cbbd" +/// Output: "bb" +/// +/// +/// Constraints: +/// +/// 1 <= s.length <= 1000 +/// s consist of only digits and English letters. +pub struct Solution {} + +// problem: https://leetcode.com/problems/longest-palindromic-substring/ +// discuss: https://leetcode.com/problems/longest-palindromic-substring/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn longest_palindrome(s: String) -> String { + if s.len() == 1 { + return s; + } + + let s = s.as_bytes(); + let mut ret: &[u8] = &[]; + for i in 0..s.len() - 1 { + let s1 = Solution::pali(s, i as i32, i); + let s2 = Solution::pali(s, i as i32, i + 1); + if s1.len() > ret.len() { + ret = s1; + } + if s2.len() > ret.len() { + ret = s2; + } + } + + String::from_utf8_lossy(ret).to_string() + } + + fn pali(s: &[u8], mut l: i32, mut r: usize) -> &[u8] { + while l >= 0 && r < s.len() && s[l as usize] == s[r] { + l -= 1; + r += 1; + } + + &s[(l + 1) as usize..r] + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_5() { + assert_eq!("a", Solution::longest_palindrome("ab".into())); + assert_eq!("bab", Solution::longest_palindrome("babad".into())); + } +} diff --git a/src/problem/p0007_reverse_integer.rs b/src/problem/p0007_reverse_integer.rs new file mode 100644 index 00000000..bc216d26 --- /dev/null +++ b/src/problem/p0007_reverse_integer.rs @@ -0,0 +1,65 @@ +/// [7] Reverse Integer +/// +/// Given a signed 32-bit integer x, return x with its digits reversed. If reversing x causes the +/// value to go outside the signed 32-bit integer range [-2^31, 2^31 - 1], then return 0. Assume the +/// environment does not allow you to store 64-bit integers (signed or unsigned). +/// Example 1: +/// +/// Input: x = 123 +/// Output: 321 +/// +/// Example 2: +/// +/// Input: x = -123 +/// Output: -321 +/// +/// Example 3: +/// +/// Input: x = 120 +/// Output: 21 +/// +/// +/// Constraints: +/// +/// -2^31 <= x <= 2^31 - 1 +pub struct Solution {} + +// problem: https://leetcode.com/problems/reverse-integer/ +// discuss: https://leetcode.com/problems/reverse-integer/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn reverse(x: i32) -> i32 { + if x == 0 { + return x; + } + + let mut ret: i64 = 0; + let mut x = x; + while x != 0 { + ret = x as i64 % 10 + ret * 10; + if ret > i32::MAX as i64 || ret < i32::MIN as i64 { + return 0; + } + x /= 10; + } + + ret as i32 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_7() { + assert_eq!(Solution::reverse(123), 321); + assert_eq!(Solution::reverse(1), 1); + assert_eq!(Solution::reverse(12300), 321); + assert_eq!(Solution::reverse(-123), -321); + } +} diff --git a/src/problem/p0010_regular_expression_matching.rs b/src/problem/p0010_regular_expression_matching.rs new file mode 100644 index 00000000..bb221499 --- /dev/null +++ b/src/problem/p0010_regular_expression_matching.rs @@ -0,0 +1,59 @@ +/// [10] Regular Expression Matching +/// +/// Given an input string s and a pattern p, implement regular expression matching with support for +/// '.' and '*' where: +/// +/// '.' Matches any single character.​​​​ +/// '*' Matches zero or more of the preceding element. +/// +/// The matching should cover the entire input string (not partial). +/// +/// Example 1: +/// +/// Input: s = "aa", p = "a" +/// Output: false +/// Explanation: "a" does not match the entire string "aa". +/// +/// Example 2: +/// +/// Input: s = "aa", p = "a*" +/// Output: true +/// Explanation: '*' means zero or more of the preceding element, 'a'. Therefore, by repeating 'a' +/// once, it becomes "aa". +/// +/// Example 3: +/// +/// Input: s = "ab", p = ".*" +/// Output: true +/// Explanation: ".*" means "zero or more (*) of any character (.)". +/// +/// +/// Constraints: +/// +/// 1 <= s.length <= 20 +/// 1 <= p.length <= 20 +/// p contains only lowercase English letters, '.', and '*'. +/// s contains only lowercase English letters. +/// It is guaranteed for each appearance of the character '*', there will be a previous valid +/// character to match. +pub struct Solution {} + +// problem: https://leetcode.com/problems/regular-expression-matching/ +// discuss: https://leetcode.com/problems/regular-expression-matching/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn is_match(_s: String, _p: String) -> bool { + false + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + + #[test] + fn test_10() {} +} diff --git a/src/problem/p0011_container_with_most_water.rs b/src/problem/p0011_container_with_most_water.rs new file mode 100644 index 00000000..6a9c70f0 --- /dev/null +++ b/src/problem/p0011_container_with_most_water.rs @@ -0,0 +1,66 @@ +/// [11] Container With Most Water +/// +/// You are given an integer array height of length n. There are n vertical lines drawn such that +/// the two endpoints of the i^th line are (i, 0) and (i, height[i]). Find two lines that together +/// with the x-axis form a container, such that the container contains the most water. Return the +/// maximum amount of water a container can store. Notice that you may not slant the container. +/// +/// Example 1: +/// +/// Input: height = [1,8,6,2,5,4,8,3,7] +/// Output: 49 +/// Explanation: The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this +/// case, the max area of water (blue section) the container can contain is 49. +/// +/// Example 2: +/// +/// Input: height = [1,1] +/// Output: 1 +/// +/// +/// Constraints: +/// +/// n == height.length +/// 2 <= n <= 10^5 +/// 0 <= height[i] <= 10^4 +pub struct Solution {} + +// problem: https://leetcode.com/problems/container-with-most-water/ +// discuss: https://leetcode.com/problems/container-with-most-water/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn max_area(height: Vec) -> i32 { + let mut ret = 0; + let mut i = 0; + let mut j = height.len() - 1; + let mut t; + while i != j { + t = (j - i) as i32; + if height[i] < height[j] { + t *= height[i]; + i += 1; + } else { + t *= height[j]; + j -= 1; + } + ret = ret.max(t); + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_11() { + assert_eq!(Solution::max_area(vec![1, 8, 6, 2, 5, 4, 8, 3, 7]), 49); + assert_eq!(Solution::max_area(vec![1, 11]), 1); + } +} diff --git a/src/problem/p0014_longest_common_prefix.rs b/src/problem/p0014_longest_common_prefix.rs new file mode 100644 index 00000000..a5ae638f --- /dev/null +++ b/src/problem/p0014_longest_common_prefix.rs @@ -0,0 +1,76 @@ +use std::cmp; + +/// [14] Longest Common Prefix +/// +/// Write a function to find the longest common prefix string amongst an array of strings. +/// If there is no common prefix, return an empty string "". +/// +/// Example 1: +/// +/// Input: strs = ["flower","flow","flight"] +/// Output: "fl" +/// +/// Example 2: +/// +/// Input: strs = ["dog","racecar","car"] +/// Output: "" +/// Explanation: There is no common prefix among the input strings. +/// +/// +/// Constraints: +/// +/// 1 <= strs.length <= 200 +/// 0 <= strs[i].length <= 200 +/// strs[i] consists of only lowercase English letters. +pub struct Solution {} + +// problem: https://leetcode.com/problems/longest-common-prefix/ +// discuss: https://leetcode.com/problems/longest-common-prefix/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn longest_common_prefix(strs: Vec) -> String { + if strs.len() == 1 { + return strs[0].clone(); + } + + let mut ret = strs[0].as_bytes(); + for str in strs.iter().skip(1) { + let t = str.as_bytes(); + let mut j = 0; + while j < cmp::min(ret.len(), t.len()) { + if ret[j] != t[j] { + break; + } + j += 1; + } + ret = &ret[0..j]; + } + + String::from_utf8_lossy(ret).to_string() + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_14() { + assert_eq!( + Solution::longest_common_prefix(vec_string!("dog", "racecar", "car")), + String::from("") + ); + assert_eq!( + Solution::longest_common_prefix(vec_string!("flower", "flow", "flight")), + String::from("fl") + ); + assert_eq!( + Solution::longest_common_prefix(vec_string!("ab", "a")), + String::from("a") + ); + } +} diff --git a/src/problem/p0017_letter_combinations_of_a_phone_number.rs b/src/problem/p0017_letter_combinations_of_a_phone_number.rs new file mode 100644 index 00000000..216b755d --- /dev/null +++ b/src/problem/p0017_letter_combinations_of_a_phone_number.rs @@ -0,0 +1,100 @@ +use std::collections::HashMap; + +/// [17] Letter Combinations of a Phone Number +/// +/// Given a string containing digits from 2-9 inclusive, return all possible letter combinations +/// that the number could represent. Return the answer in any order. A mapping of digits to letters +/// (just like on the telephone buttons) is given below. Note that 1 does not map to any letters. +/// +/// Example 1: +/// +/// Input: digits = "23" +/// Output: ["ad","ae","af","bd","be","bf","cd","ce","cf"] +/// +/// Example 2: +/// +/// Input: digits = "" +/// Output: [] +/// +/// Example 3: +/// +/// Input: digits = "2" +/// Output: ["a","b","c"] +/// +/// +/// Constraints: +/// +/// 0 <= digits.length <= 4 +/// digits[i] is a digit in the range ['2', '9']. +pub struct Solution {} + +// problem: https://leetcode.com/problems/letter-combinations-of-a-phone-number/ +// discuss: https://leetcode.com/problems/letter-combinations-of-a-phone-number/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn letter_combinations(digits: String) -> Vec { + if digits.is_empty() { + return Vec::new(); + } + + let dic = HashMap::from([ + (b'2', "abc"), + (b'3', "def"), + (b'4', "ghi"), + (b'5', "jkl"), + (b'6', "mno"), + (b'7', "pqrs"), + (b'8', "tuv"), + (b'9', "wxyz"), + ]); + + let mut ret = vec![]; + Self::dfs(digits.as_bytes(), 0, &dic, &mut vec![], &mut ret); + + ret + } + + fn dfs( + digits: &[u8], + idx: usize, + dic: &HashMap, + tmp: &mut Vec, + ret: &mut Vec, + ) { + if tmp.len() == digits.len() { + ret.push(String::from_utf8(tmp.clone()).unwrap()); + return; + } + + for c in dic[&digits[idx]].as_bytes() { + tmp.push(*c); + Self::dfs(digits, idx + 1, dic, tmp, ret); + tmp.pop(); + } + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_17() { + assert_eq!( + Solution::letter_combinations("23".to_owned()), + vec!["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"] + ); + assert_eq!( + Solution::letter_combinations("2".to_owned()), + vec!["a", "b", "c"] + ); + assert_eq!( + Solution::letter_combinations("".to_owned()), + Vec::::new() + ); + } +} diff --git a/src/problem/p0019_remove_nth_node_from_end_of_list.rs b/src/problem/p0019_remove_nth_node_from_end_of_list.rs new file mode 100644 index 00000000..48304363 --- /dev/null +++ b/src/problem/p0019_remove_nth_node_from_end_of_list.rs @@ -0,0 +1,89 @@ +/// [19] Remove Nth Node From End of List +/// +/// Given the head of a linked list, remove the n^th node from the end of the list and return its +/// head. +/// Example 1: +/// +/// Input: head = [1,2,3,4,5], n = 2 +/// Output: [1,2,3,5] +/// +/// Example 2: +/// +/// Input: head = [1], n = 1 +/// Output: [] +/// +/// Example 3: +/// +/// Input: head = [1,2], n = 1 +/// Output: [1] +/// +/// +/// Constraints: +/// +/// The number of nodes in the list is sz. +/// 1 <= sz <= 30 +/// 0 <= Node.val <= 100 +/// 1 <= n <= sz +/// +/// +/// Follow up: Could you do this in one pass? +pub struct Solution {} + +use crate::util::linked_list::ListNode; + +// problem: https://leetcode.com/problems/remove-nth-node-from-end-of-list/ +// discuss: https://leetcode.com/problems/remove-nth-node-from-end-of-list/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +// Definition for singly-linked list. +// #[derive(PartialEq, Eq, Clone, Debug)] +// pub struct ListNode { +// pub val: i32, +// pub next: Option> +// } +// +// impl ListNode { +// #[inline] +// fn new(val: i32) -> Self { +// ListNode { +// next: None, +// val +// } +// } +// } +impl Solution { + pub fn remove_nth_from_end(head: Option>, n: i32) -> Option> { + let mut root_pointer = ListNode { val: 0, next: head }; + let mut pre = &mut root_pointer; + let mut current = &pre.clone(); + for _i in 0..n { + current = current.next.as_ref().unwrap(); + } + + while let Some(ref n) = current.next { + current = n; + pre = pre.next.as_mut().unwrap(); + } + pre.next = pre.next.as_mut().unwrap().next.take(); + + root_pointer.next + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + use crate::util::linked_list::to_list; + + #[test] + fn test_19() { + assert_eq!( + Solution::remove_nth_from_end(to_list(vec![1, 2, 3, 4, 5]), 2), + list!(1, 2, 3, 5) + ); + assert_eq!(Solution::remove_nth_from_end(list!(1), 1), None); + } +} diff --git a/src/problem/p0020_valid_parentheses.rs b/src/problem/p0020_valid_parentheses.rs new file mode 100644 index 00000000..a60f5dd5 --- /dev/null +++ b/src/problem/p0020_valid_parentheses.rs @@ -0,0 +1,78 @@ +use std::collections::HashMap; + +/// [20] Valid Parentheses +/// +/// Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if +/// the input string is valid. An input string is valid if: +///
    +/// Open brackets must be closed by the same type of brackets. +/// Open brackets must be closed in the correct order. +/// Every close bracket has a corresponding open bracket of the same type. +///
+/// +/// Example 1: +/// +/// Input: s = "()" +/// Output: true +/// +/// Example 2: +/// +/// Input: s = "()[]{}" +/// Output: true +/// +/// Example 3: +/// +/// Input: s = "(]" +/// Output: false +/// +/// +/// Constraints: +/// +/// 1 <= s.length <= 10^4 +/// s consists of parentheses only '()[]{}'. +pub struct Solution {} + +// problem: https://leetcode.com/problems/valid-parentheses/ +// discuss: https://leetcode.com/problems/valid-parentheses/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn is_valid(s: String) -> bool { + if s.len() == 1 { + return false; + } + + let mut stack = vec![]; + let s = s.as_bytes(); + let map = HashMap::from([(b'}', b'{'), (b')', b'('), (b']', b'[')]); + for v in s { + if let Some(t) = stack.last() { + if let Some(p) = map.get(v) { + if p == t { + stack.pop(); + continue; + } + } + } + + stack.push(*v); + } + + stack.is_empty() + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_20() { + assert!(Solution::is_valid("()".into())); + assert!(Solution::is_valid("()[]{}".into())); + assert!(!Solution::is_valid("()[{}".into())); + } +} diff --git a/src/problem/p0022_generate_parentheses.rs b/src/problem/p0022_generate_parentheses.rs new file mode 100644 index 00000000..433a339d --- /dev/null +++ b/src/problem/p0022_generate_parentheses.rs @@ -0,0 +1,64 @@ +/// [22] Generate Parentheses +/// +/// Given n pairs of parentheses, write a function to generate all combinations of well-formed +/// parentheses. +/// Example 1: +/// Input: n = 3 +/// Output: ["((()))","(()())","(())()","()(())","()()()"] +/// Example 2: +/// Input: n = 1 +/// Output: ["()"] +/// +/// Constraints: +/// +/// 1 <= n <= 8 +pub struct Solution {} + +// problem: https://leetcode.com/problems/generate-parentheses/ +// discuss: https://leetcode.com/problems/generate-parentheses/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn generate_parenthesis(n: i32) -> Vec { + let mut ret = vec![]; + Self::gen(n, 0, 0, &mut vec![], &mut ret); + + ret + } + + fn gen(n: i32, l: i32, r: i32, tmp: &mut Vec, ret: &mut Vec) { + if tmp.len() == n as usize * 2 { + ret.push(String::from_utf8(tmp.clone()).unwrap()); + return; + } + + if l < n { + tmp.push(b'('); + Self::gen(n, l + 1, r, tmp, ret); + tmp.pop(); + } + if r < l { + tmp.push(b')'); + Self::gen(n, l, r + 1, tmp, ret); + tmp.pop(); + } + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_22() { + assert_eq!( + Solution::generate_parenthesis(3), + vec!["((()))", "(()())", "(())()", "()(())", "()()()"] + ); + assert_eq!(Solution::generate_parenthesis(1), vec!["()"]); + assert_eq!(Solution::generate_parenthesis(2), vec!["(())", "()()"]); + } +} diff --git a/src/problem/p0023_merge_k_sorted_lists.rs b/src/problem/p0023_merge_k_sorted_lists.rs new file mode 100644 index 00000000..ab9e11a9 --- /dev/null +++ b/src/problem/p0023_merge_k_sorted_lists.rs @@ -0,0 +1,121 @@ +/// [23] Merge k Sorted Lists +/// +/// You are given an array of k linked-lists lists, each linked-list is sorted in ascending order. +/// Merge all the linked-lists into one sorted linked-list and return it. +/// +/// Example 1: +/// +/// Input: lists = [[1,4,5],[1,3,4],[2,6]] +/// Output: [1,1,2,3,4,4,5,6] +/// Explanation: The linked-lists are: +/// [ +/// 1->4->5, +/// 1->3->4, +/// 2->6 +/// ] +/// merging them into one sorted list: +/// 1->1->2->3->4->4->5->6 +/// +/// Example 2: +/// +/// Input: lists = [] +/// Output: [] +/// +/// Example 3: +/// +/// Input: lists = [[]] +/// Output: [] +/// +/// +/// Constraints: +/// +/// k == lists.length +/// 0 <= k <= 10^4 +/// 0 <= lists[i].length <= 500 +/// -10^4 <= lists[i][j] <= 10^4 +/// lists[i] is sorted in ascending order. +/// The sum of lists[i].length will not exceed 10^4. +pub struct Solution {} +use std::collections::BinaryHeap; + +use crate::util::linked_list::ListNode; + +// problem: https://leetcode.com/problems/merge-k-sorted-lists/ +// discuss: https://leetcode.com/problems/merge-k-sorted-lists/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +// Definition for singly-linked list. +// #[derive(PartialEq, Eq, Clone, Debug)] +// pub struct ListNode { +// pub val: i32, +// pub next: Option> +// } +// +// impl ListNode { +// #[inline] +// fn new(val: i32) -> Self { +// ListNode { +// next: None, +// val +// } +// } +// } +impl Solution { + pub fn merge_k_lists(lists: Vec>>) -> Option> { + if lists.is_empty() { + return None; + } + + let mut ret = ListNode::new(0); + let mut current = &mut ret; + let mut heap = BinaryHeap::new(); + + for list in lists.into_iter().flatten() { + heap.push(std::cmp::Reverse(list)); + } + + while let Some(std::cmp::Reverse(l)) = heap.pop() { + current.next = Some(Box::new(ListNode { + val: l.val, + next: None, + })); + current = current.next.as_mut().unwrap(); + if let Some(l) = l.next { + heap.push(std::cmp::Reverse(l)); + } + } + + ret.next + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_23() { + assert_eq!( + Solution::merge_k_lists(vec![list!(1, 4), list!(2, 3)]), + Some(Box::new(ListNode { + val: 1, + next: Some(Box::new(ListNode { + val: 2, + next: Some(Box::new(ListNode { + val: 3, + next: Some(Box::new(ListNode { val: 4, next: None })) + })) + })) + })) + ); + assert_eq!(Solution::merge_k_lists(vec![]), None); + assert_eq!(Solution::merge_k_lists(vec![None]), None); + assert_eq!( + Solution::merge_k_lists(vec![list!(1)]), + Some(Box::new(ListNode { val: 1, next: None })) + ); + } +} diff --git a/src/problem/p0027_remove_element.rs b/src/problem/p0027_remove_element.rs new file mode 100644 index 00000000..79c98db2 --- /dev/null +++ b/src/problem/p0027_remove_element.rs @@ -0,0 +1,125 @@ +/// [27] Remove Element +/// +/// Given an integer array nums and an integer val, remove all occurrences of val in nums in-place. The order of the elements may be changed. Then return the number of elements in nums which are not equal to val. +/// Consider the number of elements in nums which are not equal to val be k, to get accepted, you +/// need to do the following things: +/// +/// Change the array nums such that the first k elements of nums contain the elements which are +/// not equal to val. The remaining elements of nums are not important as well as the size of nums. +/// Return k. +/// +/// Custom Judge: +/// The judge will test your solution with the following code: +/// +/// int[] nums = [...]; // Input array +/// int val = ...; // Value to remove +/// int[] expectedNums = [...]; // The expected answer with correct length. +/// // It is sorted with no values equaling val. +/// int k = removeElement(nums, val); // Calls your implementation +/// assert k == expectedNums.length; +/// sort(nums, 0, k); // Sort the first k elements of nums +/// for (int i = 0; i < actualLength; i++) { +/// assert nums[i] == expectedNums[i]; +/// } +/// +/// If all assertions pass, then your solution will be accepted. +/// +/// Example 1: +/// +/// Input: nums = [3,2,2,3], val = 3 +/// Output: 2, nums = [2,2,_,_] +/// Explanation: Your function should return k = 2, with the first two elements of nums being 2. +/// It does not matter what you leave beyond the returned k (hence they are underscores). +/// +/// Example 2: +/// +/// Input: nums = [0,1,2,2,3,0,4,2], val = 2 +/// Output: 5, nums = [0,1,4,0,3,_,_,_] +/// Explanation: Your function should return k = 5, with the first five elements of nums containing +/// 0, 0, 1, 3, and 4. Note that the five elements can be returned in any order. +/// It does not matter what you leave beyond the returned k (hence they are underscores). +/// +/// +/// Constraints: +/// +/// 0 <= nums.length <= 100 +/// 0 <= nums[i] <= 50 +/// 0 <= val <= 100 +pub struct Solution {} + +// problem: https://leetcode.com/problems/remove-element/ +// discuss: https://leetcode.com/problems/remove-element/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + // same order + pub fn remove_element(nums: &mut [i32], val: i32) -> i32 { + if nums.is_empty() { + return 0; + } + + let mut lo = 0; + for i in 0..nums.len() { + if nums[i] != val { + nums[lo] = nums[i]; + lo += 1; + } + } + + lo as i32 + } + + // any order + pub fn remove_element1(nums: &mut [i32], val: i32) -> i32 { + if nums.is_empty() { + return 0; + } + + let mut hi = nums.len() as i32 - 1; + let mut lo = 0; + while lo as i32 <= hi { + if nums[lo] == val { + nums[lo] = nums[hi as usize]; + hi -= 1; + continue; + } + + lo += 1; + } + + hi + 1 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_27() { + assert_eq!(Solution::remove_element(&mut [3, 2, 2, 3], 3), 2); + assert_eq!( + Solution::remove_element(&mut [0, 1, 2, 2, 3, 0, 4, 2], 2), + 5 + ); + assert_eq!( + Solution::remove_element(&mut [0, 1, 2, 2, 3, 0, 4, 2], 0), + 6 + ); + + assert_eq!(Solution::remove_element1(&mut [3, 2, 2, 3], 3), 2); + assert_eq!( + Solution::remove_element1(&mut [0, 1, 2, 2, 3, 0, 4, 2], 2), + 5 + ); + assert_eq!( + Solution::remove_element1(&mut [0, 1, 2, 2, 3, 0, 4, 2], 0), + 6 + ); + assert_eq!(Solution::remove_element(&mut [1], 1), 0); + assert_eq!(Solution::remove_element1(&mut [1], 1), 0); + } +} diff --git a/src/problem/p0029_divide_two_integers.rs b/src/problem/p0029_divide_two_integers.rs new file mode 100644 index 00000000..6e8f1a3e --- /dev/null +++ b/src/problem/p0029_divide_two_integers.rs @@ -0,0 +1,102 @@ +/// [29] Divide Two Integers +/// +/// Given two integers dividend and divisor, divide two integers without using multiplication, +/// division, and mod operator. The integer division should truncate toward zero, which means losing +/// its fractional part. For example, 8.345 would be truncated to 8, and -2.7335 would be truncated +/// to -2. Return the quotient after dividing dividend by divisor. +/// Note: Assume we are dealing with an environment that could only store integers within the 32-bit +/// signed integer range: [-2^31, 2^31 - 1]. For this problem, if the quotient is strictly greater +/// than 2^31 - 1, then return 2^31 - 1, and if the quotient is strictly less than -2^31, then +/// return -2^31. +/// Example 1: +/// +/// Input: dividend = 10, divisor = 3 +/// Output: 3 +/// Explanation: 10/3 = 3.33333.. which is truncated to 3. +/// +/// Example 2: +/// +/// Input: dividend = 7, divisor = -3 +/// Output: -2 +/// Explanation: 7/-3 = -2.33333.. which is truncated to -2. +/// +/// +/// Constraints: +/// +/// -2^31 <= dividend, divisor <= 2^31 - 1 +/// divisor != 0 +pub struct Solution {} + +// problem: https://leetcode.com/problems/divide-two-integers/ +// discuss: https://leetcode.com/problems/divide-two-integers/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn divide(dividend: i32, divisor: i32) -> i32 { + let mut dd: i64 = dividend as i64; + let mut di: i64 = divisor as i64; + let mut ret: i64 = 0; + let mut sign = 1; + if dd * di < 0 { + sign = -1; + } + dd = dd.abs(); + di = di.abs(); + + let mut i = 0; + while dd >= di { + di <<= 1; + i += 1; + } + + while i >= 0 { + if dd >= di { + dd -= di; + ret += 1 << i; + } + di >>= 1; + i -= 1; + } + + ret *= sign; + if ret > i32::MAX as i64 { + return i32::MAX; + } + if ret < i32::MIN as i64 { + return i32::MIN; + } + + ret as i32 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_29() { + assert_eq!(Solution::divide(10, 2), 5); + assert_eq!(Solution::divide(10, 3), 3); + assert_eq!(Solution::divide(7, -3), -2); + assert_eq!( + Solution::divide(-2147483648, 1), + -2147483648, + "-2147483648, 1" + ); + assert_eq!( + Solution::divide(-2147483648, -1), + 2147483647, + "-2147483648, -1" + ); + assert_eq!(Solution::divide(2147483647, 1), 2147483647, "2147483647, 1"); + assert_eq!( + Solution::divide(2147483647, -1), + -2147483647, + "2147483647, -1" + ); + } +} diff --git a/src/problem/p0041_first_missing_positive.rs b/src/problem/p0041_first_missing_positive.rs new file mode 100644 index 00000000..2aa9da9a --- /dev/null +++ b/src/problem/p0041_first_missing_positive.rs @@ -0,0 +1,75 @@ +/// [41] First Missing Positive +/// +/// Given an unsorted integer array nums, return the smallest missing positive integer. +/// You must implement an algorithm that runs in O(n) time and uses constant extra space. +/// +/// Example 1: +/// +/// Input: nums = [1,2,0] +/// Output: 3 +/// Explanation: The numbers in the range [1,2] are all in the array. +/// +/// Example 2: +/// +/// Input: nums = [3,4,-1,1] +/// Output: 2 +/// Explanation: 1 is in the array but 2 is missing. +/// +/// Example 3: +/// +/// Input: nums = [7,8,9,11,12] +/// Output: 1 +/// Explanation: The smallest positive integer 1 is missing. +/// +/// +/// Constraints: +/// +/// 1 <= nums.length <= 10^5 +/// -2^31 <= nums[i] <= 2^31 - 1 +pub struct Solution {} + +// problem: https://leetcode.com/problems/first-missing-positive/ +// discuss: https://leetcode.com/problems/first-missing-positive/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn first_missing_positive(nums: Vec) -> i32 { + let mut nums = nums; + let mut i = 0; + while i < nums.len() { + if nums[i] <= 0 + || nums[i] >= nums.len() as i32 + || nums[i] == nums[nums[i] as usize] + || nums[i] == i as i32 + 1 + { + i += 1; + continue; + } + let t = nums[i]; + nums.swap(t as usize, i); + } + + for (i, item) in nums.iter().enumerate() { + if *item != i as i32 + 1 { + return i as i32 + 1; + } + } + nums.len() as i32 + 1 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_41() { + assert_eq!(Solution::first_missing_positive(vec![1, 1]), 2); + assert_eq!(Solution::first_missing_positive(vec![1, 2, 0]), 3); + assert_eq!(Solution::first_missing_positive(vec![3, 4, -1, 1]), 2); + assert_eq!(Solution::first_missing_positive(vec![7, 8, 9, 11, 12]), 1); + } +} diff --git a/src/problem/p0042_trapping_rain_water.rs b/src/problem/p0042_trapping_rain_water.rs new file mode 100644 index 00000000..090f15b0 --- /dev/null +++ b/src/problem/p0042_trapping_rain_water.rs @@ -0,0 +1,68 @@ +// 42. Trapping Rain Water + +// Given n non-negative integers representing an elevation map where the width of each bar is 1, +// compute how much water it can trap after raining. + +// Example 1: + +// Input: height = [0,1,0,2,1,0,1,3,2,1,2,1] +// Output: 6 +// Explanation: The above elevation map (black section) is represented by array +// [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. +// Example 2: + +// Input: height = [4,2,0,3,2,5] +// Output: 9 + +// Constraints: + +// n == height.length +// 1 <= n <= 2 * 104 +// 0 <= height[i] <= 105 +pub struct Solution {} + +// problem: https://leetcode.com/problems/trapping-rain-water/ +// discuss: https://leetcode.com/problems/trapping-rain-water/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn trap(height: Vec) -> i32 { + if height.len() <= 2 { + return 0; + } + + let mut ret = 0; + let mut l = vec![0; height.len()]; + l[0] = height[0]; + for i in 1..height.len() { + l[i] = std::cmp::max(l[i - 1], height[i]); + } + + let mut r = vec![0; height.len()]; + r[height.len() - 1] = height[height.len() - 1]; + for i in (0..=height.len() - 2).rev() { + r[i] = std::cmp::max(r[i + 1], height[i]); + } + + for i in 1..height.len() - 1 { + ret += std::cmp::max(0, std::cmp::min(l[i - 1], r[i + 1]) - height[i]); + } + + ret + } +} +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_42() { + assert_eq!(Solution::trap(vec![0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]), 6); + assert_eq!(Solution::trap(vec![4, 2, 0, 3, 2, 5]), 9); + assert_eq!(Solution::trap(vec![5, 2, 1, 2, 1, 5]), 14); + assert_eq!(Solution::trap(vec![5, 1]), 0); + } +} diff --git a/src/problem/p0043_multiply_strings.rs b/src/problem/p0043_multiply_strings.rs new file mode 100644 index 00000000..1985b3bc --- /dev/null +++ b/src/problem/p0043_multiply_strings.rs @@ -0,0 +1,104 @@ +/// [43] Multiply Strings +/// +/// Given two non-negative integers num1 and num2 represented as strings, return the product of num1 +/// and num2, also represented as a string. Note: You must not use any built-in BigInteger library +/// or convert the inputs to integer directly. +/// Example 1: +/// Input: num1 = "2", num2 = "3" +/// Output: "6" +/// Example 2: +/// Input: num1 = "123", num2 = "456" +/// Output: "56088" +/// +/// Constraints: +/// +/// 1 <= num1.length, num2.length <= 200 +/// num1 and num2 consist of digits only. +/// Both num1 and num2 do not contain any leading zero, except the number 0 itself. +pub struct Solution {} + +// problem: https://leetcode.com/problems/multiply-strings/ +// discuss: https://leetcode.com/problems/multiply-strings/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn multiply(num1: String, num2: String) -> String { + if num1 == "0" || num2 == "0" { + return "0".to_string(); + } + + let num1 = num1.as_bytes(); + let num2 = num2.as_bytes(); + let mut tmp = vec![]; + for i in (0..num1.len()).rev() { + let mut s = vec![0; num1.len() - 1 - i]; + let mut _num = 0; + let mut carry = 0; + for j in (0..num2.len()).rev() { + _num = (num1[i] - b'0') * (num2[j] - b'0') + carry; + carry = _num / 10; + _num %= 10; + s.push(_num); + } + if carry != 0 { + s.push(carry); + } + s.reverse(); + tmp.push(s); + } + + let mut ret = vec![]; + for item in &tmp { + ret = Self::add(&ret, item); + } + + ret.iter().map(|x| x.to_string()).collect::() + } + + fn add(a: &[u8], b: &[u8]) -> Vec { + let mut ret = vec![]; + let mut carry = 0; + let mut i = a.len() as i32 - 1; + let mut j = b.len() as i32 - 1; + let mut _num = 0; + while i >= 0 || j >= 0 { + _num = carry; + if i >= 0 { + _num += a[i as usize]; + } + if j >= 0 { + _num += b[j as usize]; + } + ret.push(_num % 10); + carry = _num / 10; + i -= 1; + j -= 1; + } + if carry != 0 { + ret.push(carry); + } + ret.reverse(); + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_43() { + assert_eq!( + Solution::multiply("2".to_string(), "3".to_string()), + "6".to_string() + ); + assert_eq!( + Solution::multiply("123".to_string(), "456".to_string()), + "56088".to_string() + ); + } +} diff --git a/src/problem/p0056_merge_intervals.rs b/src/problem/p0056_merge_intervals.rs new file mode 100644 index 00000000..d2cf0453 --- /dev/null +++ b/src/problem/p0056_merge_intervals.rs @@ -0,0 +1,73 @@ +/// [56] Merge Intervals +/// +/// Given an array of intervals where intervals[i] = [starti, endi], merge all overlapping +/// intervals, and return an array of the non-overlapping intervals that cover all the intervals in +/// the input. +/// Example 1: +/// +/// Input: intervals = [[1,3],[2,6],[8,10],[15,18]] +/// Output: [[1,6],[8,10],[15,18]] +/// Explanation: Since intervals [1,3] and [2,6] overlap, merge them into [1,6]. +/// +/// Example 2: +/// +/// Input: intervals = [[1,4],[4,5]] +/// Output: [[1,5]] +/// Explanation: Intervals [1,4] and [4,5] are considered overlapping. +/// +/// +/// Constraints: +/// +/// 1 <= intervals.length <= 10^4 +/// intervals[i].length == 2 +/// 0 <= starti <= endi <= 10^4 +pub struct Solution {} + +// problem: https://leetcode.com/problems/merge-intervals/ +// discuss: https://leetcode.com/problems/merge-intervals/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn merge(intervals: Vec>) -> Vec> { + if intervals.len() == 1 { + return intervals; + } + + let mut intervals = intervals; + intervals.sort_by(|a, b| a[0].cmp(&b[0])); + let mut ret = vec![intervals[0].clone()]; + + for item in &intervals[1..] { + let t = ret.last_mut().unwrap(); + if t[1] < item[0] { + ret.push(item.to_vec()); + continue; + } + if t[1] >= item[0] && t[1] <= item[1] { + t[1] = item[1]; + } + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_56() { + assert_eq!( + Solution::merge(vec![vec![2, 6], vec![1, 3], vec![8, 10], vec![15, 18]]), + vec![vec![1, 6], vec![8, 10], vec![15, 18]] + ); + assert_eq!( + Solution::merge(vec![vec![1, 4], vec![4, 5]]), + vec![vec![1, 5]] + ); + } +} diff --git a/src/problem/p0064_minimum_path_sum.rs b/src/problem/p0064_minimum_path_sum.rs new file mode 100644 index 00000000..25c1dd62 --- /dev/null +++ b/src/problem/p0064_minimum_path_sum.rs @@ -0,0 +1,77 @@ +use std::vec; + +/// [64] Minimum Path Sum +/// +/// Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right, +/// which minimizes the sum of all numbers along its path. Note: You can only move either down or +/// right at any point in time. +/// Example 1: +/// +/// Input: grid = [[1,3,1],[1,5,1],[4,2,1]] +/// Output: 7 +/// Explanation: Because the path 1 → 3 → 1 → 1 → 1 minimizes the sum. +/// +/// Example 2: +/// +/// Input: grid = [[1,2,3],[4,5,6]] +/// Output: 12 +/// +/// +/// Constraints: +/// +/// m == grid.length +/// n == grid[i].length +/// 1 <= m, n <= 200 +/// 0 <= grid[i][j] <= 100 +pub struct Solution {} + +// problem: https://leetcode.com/problems/minimum-path-sum/ +// discuss: https://leetcode.com/problems/minimum-path-sum/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn min_path_sum(grid: Vec>) -> i32 { + let (m, n) = (grid.len(), grid[0].len()); + if m == 1 && n == 1 { + return grid[0][0]; + } + + let mut dp = vec![vec![0; n]; m]; + dp[0][0] = grid[0][0]; + for i in 1..m { + dp[i][0] = dp[i - 1][0] + grid[i][0]; + } + + for j in 1..n { + dp[0][j] = dp[0][j - 1] + grid[0][j]; + } + + for i in 1..m { + for j in 1..n { + dp[i][j] = std::cmp::min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j]; + } + } + + dp[m - 1][n - 1] + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_64() { + assert_eq!( + Solution::min_path_sum(vec![vec![1, 3, 1], vec![1, 5, 1], vec![4, 2, 1]]), + 7 + ); + assert_eq!( + Solution::min_path_sum(vec![vec![1, 2, 3], vec![4, 5, 6]]), + 12 + ); + } +} diff --git a/src/problem/p0070_climbing_stairs.rs b/src/problem/p0070_climbing_stairs.rs new file mode 100644 index 00000000..57eb2fbd --- /dev/null +++ b/src/problem/p0070_climbing_stairs.rs @@ -0,0 +1,63 @@ +/// [70] Climbing Stairs +/// +/// You are climbing a staircase. It takes n steps to reach the top. +/// Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? +/// +/// Example 1: +/// +/// Input: n = 2 +/// Output: 2 +/// Explanation: There are two ways to climb to the top. +/// 1. 1 step + 1 step +/// 2. 2 steps +/// +/// Example 2: +/// +/// Input: n = 3 +/// Output: 3 +/// Explanation: There are three ways to climb to the top. +/// 1. 1 step + 1 step + 1 step +/// 2. 1 step + 2 steps +/// 3. 2 steps + 1 step +/// +/// +/// Constraints: +/// +/// 1 <= n <= 45 +pub struct Solution {} + +// problem: https://leetcode.com/problems/climbing-stairs/ +// discuss: https://leetcode.com/problems/climbing-stairs/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn climb_stairs(n: i32) -> i32 { + if n == 1 { + return 1; + } + let n = n as usize; + let mut dp = vec![1; n + 1]; + dp[1] = 1; + for i in 2..=n { + dp[i] = dp[i - 1] + dp[i - 2]; + } + + dp[n] + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_70() { + assert_eq!(Solution::climb_stairs(1), 1); + assert_eq!(Solution::climb_stairs(2), 2); + assert_eq!(Solution::climb_stairs(3), 3); + assert_eq!(Solution::climb_stairs(4), 5); + } +} diff --git a/src/problem/p0088_merge_sorted_array.rs b/src/problem/p0088_merge_sorted_array.rs new file mode 100644 index 00000000..2f14cfa9 --- /dev/null +++ b/src/problem/p0088_merge_sorted_array.rs @@ -0,0 +1,91 @@ +/// [88] Merge Sorted Array +/// +/// You are given two integer arrays nums1 and nums2, sorted in non-decreasing order, and two +/// integers m and n, representing the number of elements in nums1 and nums2 respectively. +/// Merge nums1 and nums2 into a single array sorted in non-decreasing order. +/// The final sorted array should not be returned by the function, but instead be stored inside the +/// array nums1. To accommodate this, nums1 has a length of m + n, where the first m elements denote +/// the elements that should be merged, and the last n elements are set to 0 and should be ignored. +/// nums2 has a length of n. +/// Example 1: +/// +/// Input: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3 +/// Output: [1,2,2,3,5,6] +/// Explanation: The arrays we are merging are [1,2,3] and [2,5,6]. +/// The result of the merge is [1,2,2,3,5,6] with the underlined elements +/// coming from nums1. +/// +/// Example 2: +/// +/// Input: nums1 = [1], m = 1, nums2 = [], n = 0 +/// Output: [1] +/// Explanation: The arrays we are merging are [1] and []. +/// The result of the merge is [1]. +/// +/// Example 3: +/// +/// Input: nums1 = [0], m = 0, nums2 = [1], n = 1 +/// Output: [1] +/// Explanation: The arrays we are merging are [] and [1]. +/// The result of the merge is [1]. +/// Note that because m = 0, there are no elements in nums1. The 0 is only there to ensure the merge +/// result can fit in nums1. +/// +/// +/// Constraints: +/// +/// nums1.length == m + n +/// nums2.length == n +/// 0 <= m, n <= 200 +/// 1 <= m + n <= 200 +/// -10^9 <= nums1[i], nums2[j] <= 10^9 +/// +/// +/// Follow up: Can you come up with an algorithm that runs in O(m + n) time? +pub struct Solution {} + +// problem: https://leetcode.com/problems/merge-sorted-array/ +// discuss: https://leetcode.com/problems/merge-sorted-array/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + #[allow(clippy::ptr_arg)] + pub fn merge(nums1: &mut Vec, m: i32, nums2: &Vec, n: i32) { + if nums2.is_empty() { + return; + } + + let mut i = m - 1; + let mut j = n - 1; + let mut k = m + n - 1; + while j >= 0 { + if i >= 0 && nums1[i as usize] > nums2[j as usize] { + nums1[k as usize] = nums1[i as usize]; + i -= 1; + } else { + nums1[k as usize] = nums2[j as usize]; + j -= 1; + } + k -= 1; + } + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_88() { + let mut num1 = vec![1, 2, 3, 0, 0, 0]; + Solution::merge(&mut num1, 3, &vec![2, 5, 6], 3); + assert_eq!(vec![1, 2, 2, 3, 5, 6], num1); + + let mut num1 = vec![1, 2, 3, 0, 0, 0]; + Solution::merge(&mut num1, 3, &vec![], 0); + assert_eq!(vec![1, 2, 3, 0, 0, 0], num1) + } +} diff --git a/src/problem/p0091_decode_ways.rs b/src/problem/p0091_decode_ways.rs new file mode 100644 index 00000000..46b843e4 --- /dev/null +++ b/src/problem/p0091_decode_ways.rs @@ -0,0 +1,99 @@ +/// [91] Decode Ways +/// +/// A message containing letters from A-Z can be encoded into numbers using the following mapping: +/// +/// 'A' -> "1" +/// 'B' -> "2" +/// ... +/// 'Z' -> "26" +/// +/// To decode an encoded message, all the digits must be grouped then mapped back into letters using +/// the reverse of the mapping above (there may be multiple ways). For example, "11106" can be +/// mapped into: +/// +/// "AAJF" with the grouping (1 1 10 6) +/// "KJF" with the grouping (11 10 6) +/// +/// Note that the grouping (1 11 06) is invalid because "06" cannot be mapped into 'F' since "6" is +/// different from "06". Given a string s containing only digits, return the number of ways to +/// decode it. The test cases are generated so that the answer fits in a 32-bit integer. +/// +/// Example 1: +/// +/// Input: s = "12" +/// Output: 2 +/// Explanation: "12" could be decoded as "AB" (1 2) or "L" (12). +/// +/// Example 2: +/// +/// Input: s = "226" +/// Output: 3 +/// Explanation: "226" could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6). +/// +/// Example 3: +/// +/// Input: s = "06" +/// Output: 0 +/// Explanation: "06" cannot be mapped to "F" because of the leading zero ("6" is different from +/// "06"). +/// +/// +/// Constraints: +/// +/// 1 <= s.length <= 100 +/// s contains only digits and may contain leading zero(s). +pub struct Solution {} + +// problem: https://leetcode.com/problems/decode-ways/ +// discuss: https://leetcode.com/problems/decode-ways/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn num_decodings(s: String) -> i32 { + if s.starts_with('0') { + return 0; + } + + let mut dp = vec![0; s.len() + 1]; + dp[0] = 1; + dp[1] = 1; + for i in 2..=s.len() { + if Self::is_valid(&s[i - 1..i]) { + dp[i] += dp[i - 1]; + } + if Self::is_valid(&s[i - 2..i]) { + dp[i] += dp[i - 2]; + } + } + + dp[s.len()] + } + + fn is_valid(s: &str) -> bool { + if s.starts_with('0') { + return false; + } + + let n = s.parse::().unwrap(); + if n > 26 { + return false; + } + + true + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_91() { + assert_eq!(Solution::num_decodings("12".to_string()), 2); + assert_eq!(Solution::num_decodings("226".to_string()), 3); + assert_eq!(Solution::num_decodings("06".to_string()), 0); + } +} diff --git a/src/problem/p0094_binary_tree_inorder_traversal.rs b/src/problem/p0094_binary_tree_inorder_traversal.rs new file mode 100644 index 00000000..dce67a84 --- /dev/null +++ b/src/problem/p0094_binary_tree_inorder_traversal.rs @@ -0,0 +1,98 @@ +/// [94] Binary Tree Inorder Traversal +/// +/// Given the root of a binary tree, return the inorder traversal of its nodes' values. +/// +/// Example 1: +/// +/// Input: root = [1,null,2,3] +/// Output: [1,3,2] +/// +/// Example 2: +/// +/// Input: root = [] +/// Output: [] +/// +/// Example 3: +/// +/// Input: root = [1] +/// Output: [1] +/// +/// +/// Constraints: +/// +/// The number of nodes in the tree is in the range [0, 100]. +/// -100 <= Node.val <= 100 +/// +/// +/// Follow up: Recursive solution is trivial, could you do it iteratively? +pub struct Solution {} +use std::cell::RefCell; +// problem: https://leetcode.com/problems/binary-tree-inorder-traversal/ +// discuss: https://leetcode.com/problems/binary-tree-inorder-traversal/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::rc::Rc; + +use crate::util::tree::TreeNode; +impl Solution { + pub fn inorder_traversal(root: Option>>) -> Vec { + if root.is_none() { + return vec![]; + } + + let mut stack = vec![]; + let mut root = root; + let mut ret = vec![]; + while root.is_some() || !stack.is_empty() { + if root.is_some() { + stack.push(root.clone()); + let t = root.as_ref().unwrap().borrow().left.clone(); + root = t; + continue; + } + root = stack.pop().unwrap(); + ret.push(root.as_ref().unwrap().borrow().val); + let t = root.as_ref().unwrap().borrow().right.clone(); + root = t; + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + use crate::util::tree::to_tree; + + #[test] + fn test_94() { + assert_eq!( + Solution::inorder_traversal(tree![1, null, 2, 3]), + vec![1, 3, 2] + ); + assert_eq!(Solution::inorder_traversal(tree![1]), vec![1]); + assert_eq!(Solution::inorder_traversal(tree![]), vec![]); + } +} diff --git a/src/problem/p0095_unique_binary_search_trees_ii.rs b/src/problem/p0095_unique_binary_search_trees_ii.rs new file mode 100644 index 00000000..e3541e10 --- /dev/null +++ b/src/problem/p0095_unique_binary_search_trees_ii.rs @@ -0,0 +1,94 @@ +/// [95] Unique Binary Search Trees II +/// +/// Given an integer n, return all the structurally unique BST's (binary search trees), which has +/// exactly n nodes of unique values from 1 to n. Return the answer in any order. +/// Example 1: +/// +/// Input: n = 3 +/// Output: [[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,null,2],[3,2,null,1]] +/// +/// Example 2: +/// +/// Input: n = 1 +/// Output: [[1]] +/// +/// +/// Constraints: +/// +/// 1 <= n <= 8 +pub struct Solution {} +// problem: https://leetcode.com/problems/unique-binary-search-trees-ii/ +// discuss: https://leetcode.com/problems/unique-binary-search-trees-ii/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::{cell::RefCell, rc::Rc, vec}; + +use crate::util::tree::TreeNode; +impl Solution { + pub fn generate_trees(n: i32) -> Vec>>> { + Self::gen(1, n) + } + + fn gen(i: i32, j: i32) -> Vec>>> { + if i > j { + return vec![None]; + } + + let mut ret = vec![]; + for k in i..=j { + let left = Self::gen(i, k - 1); + let right = Self::gen(k + 1, j); + for l in &left { + for r in &right { + let mut node = TreeNode::new(k); + node.left.clone_from(l); + node.right.clone_from(r); + ret.push(Some(Rc::new(RefCell::new(node)))); + } + } + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + use crate::util::tree::to_tree; + + #[test] + fn test_95() { + assert_eq!( + Solution::generate_trees(3), + vec![ + tree![1, null, 2, null, 3], + tree![1, null, 3, 2], + tree![2, 1, 3], + tree![3, 1, null, null, 2], + tree![3, 2, null, 1] + ] + ); + } +} diff --git a/src/problem/p0096_unique_binary_search_trees.rs b/src/problem/p0096_unique_binary_search_trees.rs new file mode 100644 index 00000000..2891ff5d --- /dev/null +++ b/src/problem/p0096_unique_binary_search_trees.rs @@ -0,0 +1,59 @@ +/// [96] Unique Binary Search Trees +/// +/// Given an integer n, return the number of structurally unique BST's (binary search trees) which +/// has exactly n nodes of unique values from 1 to n. +/// Example 1: +/// +/// Input: n = 3 +/// Output: 5 +/// +/// Example 2: +/// +/// Input: n = 1 +/// Output: 1 +/// +/// +/// Constraints: +/// +/// 1 <= n <= 19 +pub struct Solution {} + +// problem: https://leetcode.com/problems/unique-binary-search-trees/ +// discuss: https://leetcode.com/problems/unique-binary-search-trees/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn num_trees(n: i32) -> i32 { + if n == 1 { + return 1; + } + + let n = n as usize; + let mut dp = vec![0; n + 1]; + dp[0] = 1; + dp[1] = 1; + for i in 2..=n { + for j in 0..i { + dp[i] += dp[j] * dp[i - j - 1]; + } + } + + dp[n] + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_96() { + assert_eq!(Solution::num_trees(3), 5); + assert_eq!(Solution::num_trees(1), 1); + assert_eq!(Solution::num_trees(2), 2); + assert_eq!(Solution::num_trees(4), 14); + } +} diff --git a/src/problem/p0101_symmetric_tree.rs b/src/problem/p0101_symmetric_tree.rs new file mode 100644 index 00000000..fc499858 --- /dev/null +++ b/src/problem/p0101_symmetric_tree.rs @@ -0,0 +1,103 @@ +/// [101] Symmetric Tree +/// +/// Given the root of a binary tree, check whether it is a mirror of itself (i.e., symmetric around +/// its center). +/// Example 1: +/// +/// Input: root = [1,2,2,3,4,4,3] +/// Output: true +/// +/// Example 2: +/// +/// Input: root = [1,2,2,null,3,null,3] +/// Output: false +/// +/// +/// Constraints: +/// +/// The number of nodes in the tree is in the range [1, 1000]. +/// -100 <= Node.val <= 100 +/// +/// +/// Follow up: Could you solve it both recursively and iteratively? +pub struct Solution {} +// problem: https://leetcode.com/problems/symmetric-tree/ +// discuss: https://leetcode.com/problems/symmetric-tree/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::{cell::RefCell, rc::Rc}; + +use crate::util::tree::TreeNode; +impl Solution { + pub fn is_symmetric(root: Option>>) -> bool { + if root.is_none() { + return true; + } + + Self::is_sym( + root.as_ref().unwrap().borrow().left.clone(), + root.as_ref().unwrap().borrow().right.clone(), + ) + } + + fn is_sym(r: Option>>, l: Option>>) -> bool { + if r.is_none() && l.is_none() { + return true; + } + if r.is_none() || l.is_none() { + return false; + } + if r.as_ref().unwrap().borrow().val != l.as_ref().unwrap().borrow().val { + return false; + } + + Self::is_sym( + r.as_ref().unwrap().borrow().left.clone(), + l.as_ref().unwrap().borrow().right.clone(), + ) && Self::is_sym( + r.as_ref().unwrap().borrow().right.clone(), + l.as_ref().unwrap().borrow().left.clone(), + ) + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + use crate::util::tree::to_tree; + + #[test] + fn test_101() { + assert!(Solution::is_symmetric(to_tree(vec![ + Some(1), + Some(2), + Some(2), + Some(3), + Some(4), + Some(4), + Some(3) + ]))); + assert!(!Solution::is_symmetric(tree![1, 2, 2, null, 3, null, 3])); + } +} diff --git a/src/problem/p0109_convert_sorted_list_to_binary_search_tree.rs b/src/problem/p0109_convert_sorted_list_to_binary_search_tree.rs new file mode 100644 index 00000000..3578ff71 --- /dev/null +++ b/src/problem/p0109_convert_sorted_list_to_binary_search_tree.rs @@ -0,0 +1,120 @@ +/// [109] Convert Sorted List to Binary Search Tree +/// +/// Given the head of a singly linked list where elements are sorted in ascending order, convert it +/// to a height-balanced binary search tree. +/// Example 1: +/// +/// Input: head = [-10,-3,0,5,9] +/// Output: [0,-3,9,-10,null,5] +/// Explanation: One possible answer is [0,-3,9,-10,null,5], which represents the shown height +/// balanced BST. +/// +/// Example 2: +/// +/// Input: head = [] +/// Output: [] +/// +/// +/// Constraints: +/// +/// The number of nodes in head is in the range [0, 2 * 10^4]. +/// -10^5 <= Node.val <= 10^5 +pub struct Solution {} + +// problem: https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/ +// discuss: https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +// Definition for singly-linked list. +// #[derive(PartialEq, Eq, Clone, Debug)] +// pub struct ListNode { +// pub val: i32, +// pub next: Option> +// } +// +// impl ListNode { +// #[inline] +// fn new(val: i32) -> Self { +// ListNode { +// next: None, +// val +// } +// } +// } +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::{cell::RefCell, rc::Rc}; + +use crate::util::{linked_list::ListNode, tree::TreeNode}; +impl Solution { + pub fn sorted_list_to_bst(head: Option>) -> Option>> { + head.as_ref()?; + + Self::to_bst(head, None) + } + + fn to_bst( + head: Option>, + tail: Option>, + ) -> Option>> { + if head == tail { + return None; + } + + // TODO: could push into a vec, get mid by idx, instead of traversing again and again for + // better time complexity + let mid = Self::find_mid(head.clone(), tail.clone()); + let mut n = TreeNode::new(mid.as_ref().unwrap().val); + n.left = Self::to_bst(head, mid.clone()); + n.right = Self::to_bst(mid.unwrap().next, tail); + + Some(Rc::new(RefCell::new(n))) + } + + #[allow(clippy::assigning_clones)] + fn find_mid(head: Option>, tail: Option>) -> Option> { + let mut slow = head.clone(); + let mut fast = head; + while fast != tail && fast.as_ref().unwrap().next != tail { + fast = fast.as_ref().unwrap().next.as_ref().unwrap().next.clone(); + slow = slow.as_ref().unwrap().next.clone(); + } + + slow + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + use crate::util::{linked_list::to_list, tree::to_tree}; + + #[test] + fn test_109() { + assert_eq!( + Solution::sorted_list_to_bst(linked![-10, -3, 0, 5, 9]), + tree![0, -3, 9, -10, null, 5] + ); + assert_eq!(Solution::sorted_list_to_bst(linked![]), tree![]); + assert_eq!(Solution::sorted_list_to_bst(linked![-1]), tree![-1]); + } +} diff --git a/src/problem/p0111_minimum_depth_of_binary_tree.rs b/src/problem/p0111_minimum_depth_of_binary_tree.rs new file mode 100644 index 00000000..57ad0dd2 --- /dev/null +++ b/src/problem/p0111_minimum_depth_of_binary_tree.rs @@ -0,0 +1,91 @@ +/// [111] Minimum Depth of Binary Tree +/// +/// Given a binary tree, find its minimum depth. +/// The minimum depth is the number of nodes along the shortest path from the root node down to the +/// nearest leaf node. Note: A leaf is a node with no children. +/// +/// Example 1: +/// +/// Input: root = [3,9,20,null,null,15,7] +/// Output: 2 +/// +/// Example 2: +/// +/// Input: root = [2,null,3,null,4,null,5,null,6] +/// Output: 5 +/// +/// +/// Constraints: +/// +/// The number of nodes in the tree is in the range [0, 10^5]. +/// -1000 <= Node.val <= 1000 +pub struct Solution {} +// problem: https://leetcode.com/problems/minimum-depth-of-binary-tree/ +// discuss: https://leetcode.com/problems/minimum-depth-of-binary-tree/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::{cell::RefCell, collections::VecDeque, rc::Rc}; + +use crate::util::tree::TreeNode; + +impl Solution { + pub fn min_depth(root: Option>>) -> i32 { + if root.is_none() { + return 0; + } + + let mut root = root; + let mut ret = 1; + let mut queue = VecDeque::from([(root, ret)]); + while !queue.is_empty() { + (root, ret) = queue.pop_front().unwrap(); + if root.as_ref().unwrap().borrow().left.is_none() + && root.as_ref().unwrap().borrow().right.is_none() + { + break; + } + if let l @ Some(_) = &root.as_ref().unwrap().borrow().left { + queue.push_back((l.clone(), ret + 1)); + } + if let r @ Some(_) = &root.as_ref().unwrap().borrow().right { + queue.push_back((r.clone(), ret + 1)); + } + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + use crate::util::tree::to_tree; + + #[test] + fn test_111() { + assert_eq!(Solution::min_depth(tree![3, 9, 20, null, null, 15, 7]), 2); + assert_eq!(Solution::min_depth(tree![3, 9, 20, 15, 7]), 2); + assert_eq!(Solution::min_depth(tree![1, 2]), 2); + } +} diff --git a/src/problem/p0114_flatten_binary_tree_to_linked_list.rs b/src/problem/p0114_flatten_binary_tree_to_linked_list.rs new file mode 100644 index 00000000..d85c4c5b --- /dev/null +++ b/src/problem/p0114_flatten_binary_tree_to_linked_list.rs @@ -0,0 +1,113 @@ +/// [114] Flatten Binary Tree to Linked List +/// +/// Given the root of a binary tree, flatten the tree into a "linked list": +/// +/// The "linked list" should use the same TreeNode class where the right child pointer points to +/// the next node in the list and the left child pointer is always null. The "linked list" should be in the same order as a pre-order traversal of the binary tree. +/// +/// +/// Example 1: +/// +/// Input: root = [1,2,5,3,4,null,6] +/// Output: [1,null,2,null,3,null,4,null,5,null,6] +/// +/// Example 2: +/// +/// Input: root = [] +/// Output: [] +/// +/// Example 3: +/// +/// Input: root = [0] +/// Output: [0] +/// +/// +/// Constraints: +/// +/// The number of nodes in the tree is in the range [0, 2000]. +/// -100 <= Node.val <= 100 +/// +/// +/// Follow up: Can you flatten the tree in-place (with O(1) extra space)? +pub struct Solution {} +// problem: https://leetcode.com/problems/flatten-binary-tree-to-linked-list/ +// discuss: https://leetcode.com/problems/flatten-binary-tree-to-linked-list/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::{cell::RefCell, rc::Rc}; + +use crate::util::tree::TreeNode; +impl Solution { + #[allow(clippy::assigning_clones)] + pub fn flatten(root: &Option>>) { + if root.is_none() { + return; + } + + let mut root = root.as_ref().unwrap().borrow_mut(); + Self::flatten(&root.left.clone()); + Self::flatten(&root.right.clone()); + + if root.left.is_none() { + return; + } + let n = Self::find_right_last(root.left.clone()); + n.as_ref() + .unwrap() + .borrow_mut() + .right + .clone_from(&root.right); + // n.as_ref().unwrap().borrow_mut().right = root.right.clone(); + root.right = root.left.clone(); + root.left = None + } + + fn find_right_last(mut root: Option>>) -> Option>> { + loop { + let n = root.as_ref().unwrap().borrow_mut().right.clone(); + match n { + n @ Some(_) => root = n, + None => break, + } + } + + root + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + use crate::util::tree::to_tree; + + #[test] + fn test_114() { + let tree_node = tree!(1, 2, 5, 3, 4, null, 6); + Solution::flatten(&tree_node); + assert_eq!( + tree_node, + tree![1, null, 2, null, 3, null, 4, null, 5, null, 6] + ); + } +} diff --git a/src/problem/p0128_longest_consecutive_sequence.rs b/src/problem/p0128_longest_consecutive_sequence.rs new file mode 100644 index 00000000..0655fb1d --- /dev/null +++ b/src/problem/p0128_longest_consecutive_sequence.rs @@ -0,0 +1,72 @@ +use std::collections::HashSet; + +/// [128] Longest Consecutive Sequence +/// +/// Given an unsorted array of integers nums, return the length of the longest consecutive elements +/// sequence. You must write an algorithm that runs in O(n) time. +/// +/// Example 1: +/// +/// Input: nums = [100,4,200,1,3,2] +/// Output: 4 +/// Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is +/// 4. +/// +/// Example 2: +/// +/// Input: nums = [0,3,7,2,5,8,4,6,0,1] +/// Output: 9 +/// +/// +/// Constraints: +/// +/// 0 <= nums.length <= 10^5 +/// -10^9 <= nums[i] <= 10^9 +pub struct Solution {} + +// problem: https://leetcode.com/problems/longest-consecutive-sequence/ +// discuss: https://leetcode.com/problems/longest-consecutive-sequence/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +// TODO: use union-find, kind of showoff ? +impl Solution { + pub fn longest_consecutive(nums: Vec) -> i32 { + if nums.len() < 2 { + return nums.len() as i32; + } + + let mut dic = nums.iter().collect::>(); + let mut ret = 0; + for k in &nums { + let mut k1 = *k; + while dic.remove(&(k1 - 1)) { + k1 -= 1; + } + let mut k2 = *k; + while dic.remove(&(k2 + 1)) { + k2 += 1; + } + + ret = ret.max(k2 - k1 + 1); + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_128() { + assert_eq!(Solution::longest_consecutive(vec![100, 4, 200, 1, 3, 2]), 4); + assert_eq!( + Solution::longest_consecutive(vec![0, 3, 7, 2, 5, 8, 4, 6, 0, 1]), + 9 + ); + } +} diff --git a/src/problem/p0133_clone_graph.rs b/src/problem/p0133_clone_graph.rs new file mode 100644 index 00000000..faabc3c6 --- /dev/null +++ b/src/problem/p0133_clone_graph.rs @@ -0,0 +1,157 @@ +/// [133] Clone Graph +/// +/// Given a reference of a node in a connected undirected graph. +/// +/// Return a deep copy (clone) of the graph. +/// +/// Each node in the graph contains a value (int) and a list (List[Node]) of its neighbors. +/// +/// class Node { +/// public int val; +/// public List neighbors; +/// } +/// +/// Test case format: +/// +/// For simplicity, each node's value is the same as the node's index (1-indexed). For example, the +/// first node with val == 1, the second node with val == 2, and so on. The graph is represented in +/// the test case using an adjacency list. +/// +/// An adjacency list is a collection of unordered lists used to represent a finite graph. Each list +/// describes the set of neighbors of a node in the graph. +/// +/// The given node will always be the first node with val = 1. You must return the copy of the given +/// node as a reference to the cloned graph. +/// +/// Example 1: +/// +/// Input: adjList = [[2,4],[1,3],[2,4],[1,3]] +/// Output: [[2,4],[1,3],[2,4],[1,3]] +/// Explanation: There are 4 nodes in the graph. +/// 1st node (val = 1)'s neighbors are 2nd node (val = 2) and 4th node (val = 4). +/// 2nd node (val = 2)'s neighbors are 1st node (val = 1) and 3rd node (val = 3). +/// 3rd node (val = 3)'s neighbors are 2nd node (val = 2) and 4th node (val = 4). +/// 4th node (val = 4)'s neighbors are 1st node (val = 1) and 3rd node (val = 3). +/// Example 2: +/// +/// Input: adjList = [[]] +/// Output: [[]] +/// Explanation: Note that the input contains one empty list. The graph consists of only one node +/// with val = 1 and it does not have any neighbors. Example 3: +/// +/// Input: adjList = [] +/// Output: [] +/// Explanation: This an empty graph, it does not have any nodes. +/// +/// Constraints: +/// +/// The number of nodes in the graph is in the range [0, 100]. +/// 1 <= Node.val <= 100 +/// Node.val is unique for each node. +/// There are no repeated edges and no self-loops in the graph. +/// The Graph is connected and all nodes can be visited starting from the given node. +pub struct Solution {} + +use std::{cell::RefCell, collections::HashMap, rc::Rc}; + +#[derive(Debug, PartialEq, Eq)] +pub struct GraphNode { + val: i32, + neighbors: Vec>>, +} + +impl GraphNode { + pub fn new(val: i32) -> Self { + Self { + val, + neighbors: vec![], + } + } +} + +impl Solution { + pub fn clone_graph(node: Option>>) -> Option>> { + node.as_ref()?; + + let mut map = HashMap::new(); + Self::bfs(node?, &mut map); + + Some(map.get(&1)?.clone()) + } + + fn bfs( + node: Rc>, + map: &mut HashMap>>, + ) -> Option<()> { + let mut stack = vec![node.clone()]; + map.insert( + node.borrow().val, + Rc::new(RefCell::new(GraphNode::new(node.borrow().val))), + ); + + while let Some(node) = stack.pop() { + for n in &node.borrow().neighbors { + let mut c_node = Rc::new(RefCell::new(GraphNode::new(n.borrow().val))); + match map.entry(n.borrow().val) { + std::collections::hash_map::Entry::Occupied(m) => { + c_node = m.get().clone(); + } + std::collections::hash_map::Entry::Vacant(m) => { + m.insert(c_node.clone()); + stack.push(n.clone()); + } + } + + map.get(&node.borrow().val)? + .borrow_mut() + .neighbors + .push(c_node); + } + } + + None + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_133() { + assert_eq!( + Solution::clone_graph(Some(Rc::new(RefCell::new(GraphNode::new(1))))), + Some(Rc::new(RefCell::new(GraphNode::new(1)))) + ); + + let n1 = Some(Rc::new(RefCell::new(GraphNode::new(1)))); + let n2 = Some(Rc::new(RefCell::new(GraphNode::new(2)))); + n1.as_ref() + .unwrap() + .borrow_mut() + .neighbors + .push(n2.as_ref().unwrap().clone()); + n2.as_ref() + .unwrap() + .borrow_mut() + .neighbors + .push(Rc::new(RefCell::new(GraphNode::new(3)))); + + // TODO: should checked by is_same_graph instead of eq + assert_eq!( + Solution::clone_graph(n1.clone()), + n1, + "clone_graph test fail" + ); + assert_ne!( + Solution::clone_graph(n1.clone()).unwrap().as_ptr(), + n1.clone().unwrap().as_ptr(), + "clone_graph test fail" + ); + assert_eq!( + n1.clone().unwrap().as_ptr(), + n1.clone().unwrap().as_ptr(), + "clone_graph test fail" + ); + } +} diff --git a/src/problem/p0144_binary_tree_preorder_traversal.rs b/src/problem/p0144_binary_tree_preorder_traversal.rs new file mode 100644 index 00000000..38091521 --- /dev/null +++ b/src/problem/p0144_binary_tree_preorder_traversal.rs @@ -0,0 +1,99 @@ +/// [144] Binary Tree Preorder Traversal +/// +/// Given the root of a binary tree, return the preorder traversal of its nodes' values. +/// +/// Example 1: +/// +/// Input: root = [1,null,2,3] +/// Output: [1,2,3] +/// +/// Example 2: +/// +/// Input: root = [] +/// Output: [] +/// +/// Example 3: +/// +/// Input: root = [1] +/// Output: [1] +/// +/// +/// Constraints: +/// +/// The number of nodes in the tree is in the range [0, 100]. +/// -100 <= Node.val <= 100 +/// +/// +/// Follow up: Recursive solution is trivial, could you do it iteratively? +pub struct Solution {} +use std::cell::RefCell; +// problem: https://leetcode.com/problems/binary-tree-preorder-traversal/ +// discuss: https://leetcode.com/problems/binary-tree-preorder-traversal/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::rc::Rc; + +use crate::util::tree::TreeNode; + +impl Solution { + pub fn preorder_traversal(root: Option>>) -> Vec { + if root.is_none() { + return vec![]; + } + + let mut stack = vec![]; + let mut root = root; + let mut ret = vec![]; + while root.is_some() || !stack.is_empty() { + if root.is_some() { + stack.push(root.clone()); + ret.push(root.as_ref().unwrap().borrow().val); + let t = root.as_ref().unwrap().borrow().left.clone(); + root = t; + continue; + } + root = stack.pop().unwrap(); + let t = root.as_ref().unwrap().borrow().right.clone(); + root = t; + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + use crate::util::tree::to_tree; + + #[test] + fn test_144() { + assert_eq!( + Solution::preorder_traversal(tree![1, null, 2, 3]), + vec![1, 2, 3] + ); + assert_eq!(Solution::preorder_traversal(tree![1]), vec![1]); + assert_eq!(Solution::preorder_traversal(tree![]), vec![]); + } +} diff --git a/src/problem/p0145_binary_tree_postorder_traversal.rs b/src/problem/p0145_binary_tree_postorder_traversal.rs new file mode 100644 index 00000000..9054a25b --- /dev/null +++ b/src/problem/p0145_binary_tree_postorder_traversal.rs @@ -0,0 +1,108 @@ +/// [145] Binary Tree Postorder Traversal +/// +/// Given the root of a binary tree, return the postorder traversal of its nodes' values. +/// +/// Example 1: +/// +/// Input: root = [1,null,2,3] +/// Output: [3,2,1] +/// +/// Example 2: +/// +/// Input: root = [] +/// Output: [] +/// +/// Example 3: +/// +/// Input: root = [1] +/// Output: [1] +/// +/// +/// Constraints: +/// +/// The number of the nodes in the tree is in the range [0, 100]. +/// -100 <= Node.val <= 100 +/// +/// +/// Follow up: Recursive solution is trivial, could you do it iteratively? +pub struct Solution {} +// problem: https://leetcode.com/problems/binary-tree-postorder-traversal/ +// discuss: https://leetcode.com/problems/binary-tree-postorder-traversal/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::{cell::RefCell, rc::Rc}; + +use crate::util::tree::TreeNode; +impl Solution { + pub fn postorder_traversal(root: Option>>) -> Vec { + if root.is_none() { + return vec![]; + } + + let mut stack = vec![]; + let mut root = root; + let mut ret = vec![]; + let mut pre = Some(Rc::new(RefCell::new(TreeNode::new(0)))); + while root.is_some() || !stack.is_empty() { + if root.is_some() { + stack.push(root.clone()); + let n = root.as_ref().unwrap().borrow().left.clone(); + root = n; + continue; + } + + root.clone_from(stack.last().unwrap()); + // root = stack.last().unwrap().clone(); + if root.as_ref().unwrap().borrow().right.is_none() + || root.as_ref().unwrap().borrow().right == pre + { + stack.pop(); + ret.push(root.as_ref().unwrap().borrow().val); + pre = root; + root = None; + } else { + let n = root.as_ref().unwrap().borrow().right.clone(); + root = n; + } + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + use crate::util::tree::to_tree; + + #[test] + fn test_145() { + assert_eq!( + Solution::postorder_traversal(tree![1, null, 2, 3]), + vec![3, 2, 1] + ); + assert_eq!(Solution::postorder_traversal(tree![1]), vec![1]); + assert_eq!(Solution::postorder_traversal(tree![1, 2]), vec![2, 1]); + } +} diff --git a/src/problem/p0148_sort_list.rs b/src/problem/p0148_sort_list.rs new file mode 100644 index 00000000..da5cfd7e --- /dev/null +++ b/src/problem/p0148_sort_list.rs @@ -0,0 +1,330 @@ +// Given the head of a linked list, return the list after sorting it in ascending order. + +// Example 1: + +// Input: head = [4,2,1,3] +// Output: [1,2,3,4] +// Example 2: + +// Input: head = [-1,5,3,4,0] +// Output: [-1,0,3,4,5] +// Example 3: + +// Input: head = [] +// Output: [] + +// Constraints: + +// The number of nodes in the list is in the range [0, 5 * 104]. +// -105 <= Node.val <= 105 + +// Follow up: Can you sort the linked list in O(n logn) time and O(1) memory (i.e. constant space)? + +// https://leetcode.com/problems/sort-list/ + +use crate::util::linked_list::ListNode; + +// Definition for singly-linked list. +// #[derive(PartialEq, Eq, Clone, Debug)] +// pub struct ListNode { +// pub val: i32, +// pub next: Option> +// } +// +// impl ListNode { +// #[inline] +// fn new(val: i32) -> Self { +// ListNode { +// next: None, +// val +// } +// } +// } +pub struct Solution; + +impl Solution { + // need randomize pivot, optimize for == povit, three way quick sort, + // e.g. [1,1,1,,1,1,4,4,4,6,5,7,8,9], bla, bla + pub fn sort_list_with_quick_sort(head: Option>) -> Option> { + if head.is_none() || head.as_ref().unwrap().next.is_none() { + return head; + } + + let povit = head.as_ref().unwrap().val; + let mut less = None; + let mut great = None; + let mut current = head; + while let Some(mut n) = current { + current = n.next.take(); + if n.val < povit { + n.next = less; + less = Some(n); + } else { + n.next = great; + great = Some(n); + } + } + + let less = Solution::sort_list_with_quick_sort(less); + let great = Solution::sort_list_with_quick_sort(great); + + let mut less_head_pointer = ListNode::new(0); + less_head_pointer.next = less; + let mut less_tail = &mut less_head_pointer; + while let Some(ref mut n) = less_tail.next { + less_tail = n; + } + + less_tail.next = great; + + less_head_pointer.next + } + + pub fn sort_list_with_vec(head: Option>) -> Option> { + if head.is_none() || head.as_ref().unwrap().next.is_none() { + return head; + } + + let mut t = vec![]; + let mut head = head; + while let Some(mut n) = head { + head = n.next.take(); + t.push(n); + } + + t.sort(); + + let mut head = None; + while let Some(mut item) = t.pop() { + item.next = head; + head = Some(item); + } + + head + } + + pub fn sort_list_half_cut(head: Option>) -> Option> { + if head.is_none() || head.as_ref().unwrap().next.is_none() { + return head; + } + + let (h1, h2) = Solution::half_cut(head); + let h1 = Solution::sort_list_half_cut(h1); + let h2 = Solution::sort_list_half_cut(h2); + + Solution::merge(h1, h2) + } + + pub fn sort_list_half_cut_len(head: Option>) -> Option> { + if head.is_none() || head.as_ref().unwrap().next.is_none() { + return head; + } + + let (h1, h2) = Solution::half_cut_len(head); + let h1 = Solution::sort_list_half_cut_len(h1); + let h2 = Solution::sort_list_half_cut_len(h2); + + Solution::merge(h1, h2) + } + + fn merge( + mut h1: Option>, + mut h2: Option>, + ) -> Option> { + if h1.is_none() { + return h2; + } + if h2.is_none() { + return h1; + } + + let mut head_pointer = ListNode::new(0); + let mut pre = &mut head_pointer; + while h1.is_some() || h2.is_some() { + if h1.is_none() { + pre.next = h2.take(); + break; + } + if h2.is_none() { + pre.next = h1.take(); + break; + } + + if h1.as_ref().unwrap().val < h2.as_ref().unwrap().val { + let n = h1.as_mut().unwrap().next.take(); + pre.next = h1.take(); + h1 = n; + } else { + let n = h2.as_mut().unwrap().next.take(); + pre.next = h2.take(); + h2 = n; + } + pre = pre.next.as_deref_mut().unwrap(); + } + + head_pointer.next + } + + fn half_cut_len( + mut head: Option>, + ) -> (Option>, Option>) { + if head.is_none() || head.as_ref().unwrap().next.is_none() { + return (head, None); + } + + let len = Solution::len(&mut head); + let mid = len / 2; + + let mut head_pointer = ListNode::new(0); + head_pointer.next = head; + let mut head2 = &mut head_pointer; + for _i in 0..mid { + head2 = head2.next.as_mut().unwrap(); + } + let head2 = head2.next.take(); + + (head_pointer.next, head2) + } + + fn len(head: &mut Option>) -> i32 { + let mut len = 0; + let mut head = head; + while let Some(ref mut n) = head { + head = &mut n.next; + len += 1; + } + + len + } + + fn half_cut(head: Option>) -> (Option>, Option>) { + if head.is_none() || head.as_ref().unwrap().next.is_none() { + return (head, None); + } + + let mut head = head; + let mut head_pointer = ListNode::new(0); + head_pointer.next = head.take(); + + let mut slow = &mut head_pointer; + let mut fast = Some(Box::new(slow.clone())); // clone() kind of slow down the algorithm + while fast.is_some() && fast.as_ref().unwrap().next.is_some() { + slow = slow.next.as_mut().unwrap(); + fast = fast.as_mut().unwrap().next.as_mut().unwrap().next.take(); + } + let head2 = slow.next.take(); + // slow.next = None; + + (head_pointer.next, head2) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::util::linked_list; + + #[test] + fn test_148() { + // sort_list_with_quick_sort + assert_eq!( + Solution::sort_list_with_quick_sort(linked_list::to_list(vec![4, 2, 1, 3])), + linked_list::to_list(vec![1, 2, 3, 4]) + ); + assert_eq!( + Solution::sort_list_with_quick_sort(linked_list::to_list(vec![-1, 5, 3, 4, 0])), + linked_list::to_list(vec![-1, 0, 3, 4, 5]) + ); + assert_eq!( + Solution::sort_list_with_quick_sort(linked_list::to_list(vec![])), + linked_list::to_list(vec![]) + ); + + // sort_list_half_cut + assert_eq!( + Solution::sort_list_half_cut(linked_list::to_list(vec![4, 2, 1, 3])), + linked_list::to_list(vec![1, 2, 3, 4]) + ); + assert_eq!( + Solution::sort_list_half_cut(linked_list::to_list(vec![-1, 5, 3, 4, 0])), + linked_list::to_list(vec![-1, 0, 3, 4, 5]) + ); + assert_eq!( + Solution::sort_list_half_cut(linked_list::to_list(vec![])), + linked_list::to_list(vec![]) + ); + + // sort_list_half_cut_len + assert_eq!( + Solution::sort_list_half_cut_len(linked_list::to_list(vec![4, 2, 1, 3])), + linked_list::to_list(vec![1, 2, 3, 4]) + ); + assert_eq!( + Solution::sort_list_half_cut_len(linked_list::to_list(vec![-1, 5, 3, 4, 0])), + linked_list::to_list(vec![-1, 0, 3, 4, 5]) + ); + assert_eq!( + Solution::sort_list_half_cut_len(linked_list::to_list(vec![])), + linked_list::to_list(vec![]) + ); + + // sort_list_with_vec + assert_eq!( + Solution::sort_list_with_vec(linked_list::to_list(vec![4, 2, 1, 3])), + linked_list::to_list(vec![1, 2, 3, 4]) + ); + assert_eq!( + Solution::sort_list_with_vec(linked_list::to_list(vec![])), + linked_list::to_list(vec![]) + ); + assert_eq!( + Solution::sort_list_with_vec(linked_list::to_list(vec![-1, 5, 3, 4, 0])), + linked_list::to_list(vec![-1, 0, 3, 4, 5]) + ); + } + + extern crate test; + use test::{Bencher, black_box}; + + #[rustfmt::skip] + // test problem::p0148_sort_list::tests::bench_sort_list_half_cut ... bench: 8,389.08 ns/iter (+/- 243.06) + // test problem::p0148_sort_list::tests::bench_sort_list_half_cut_len ... bench: 1,913.11 ns/iter (+/- 57.90) + // test problem::p0148_sort_list::tests::bench_sort_list_with_quick ... bench: 16,013.85 ns/iter (+/- 116.08) + // test problem::p0148_sort_list::tests::bench_sort_list_with_vec ... bench: 1,142.24 ns/iter (+/- 35.95) + + #[bench] + fn bench_sort_list_with_quick(b: &mut Bencher) { + b.iter(|| { + black_box(Solution::sort_list_with_quick_sort(linked_list::to_list( + (1..=100).rev().collect(), + ))) + }); + } + + #[bench] + fn bench_sort_list_half_cut(b: &mut Bencher) { + b.iter(|| { + black_box(Solution::sort_list_half_cut(linked_list::to_list( + (1..=100).rev().collect(), + ))) + }); + } + + #[bench] + fn bench_sort_list_half_cut_len(b: &mut Bencher) { + b.iter(|| { + black_box(Solution::sort_list_half_cut_len(linked_list::to_list( + (1..=100).rev().collect(), + ))) + }); + } + + #[bench] + fn bench_sort_list_with_vec(b: &mut Bencher) { + b.iter(|| { + black_box(Solution::sort_list_with_vec(linked_list::to_list( + (1..=100).rev().collect(), + ))) + }); + } +} diff --git a/src/problem/p0152_maximum_product_subarray.rs b/src/problem/p0152_maximum_product_subarray.rs new file mode 100644 index 00000000..230f61fb --- /dev/null +++ b/src/problem/p0152_maximum_product_subarray.rs @@ -0,0 +1,67 @@ +use std::cmp::{self}; + +/// [152] Maximum Product Subarray +/// +/// Given an integer array nums, find a subarray that +/// has the largest product, and return the product. The test cases are generated so that the answer +/// will fit in a 32-bit integer. +/// Example 1: +/// +/// Input: nums = [2,3,-2,4] +/// Output: 6 +/// Explanation: [2,3] has the largest product 6. +/// +/// Example 2: +/// +/// Input: nums = [-2,0,-1] +/// Output: 0 +/// Explanation: The result cannot be 2, because [-2,-1] is not a subarray. +/// +/// +/// Constraints: +/// +/// 1 <= nums.length <= 2 * 10^4 +/// -10 <= nums[i] <= 10 +/// The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer. +pub struct Solution {} + +// problem: https://leetcode.com/problems/maximum-product-subarray/ +// discuss: https://leetcode.com/problems/maximum-product-subarray/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn max_product(nums: Vec) -> i32 { + if nums.len() == 1 { + return nums[0]; + } + + let mut ret = nums[0]; + let mut pre_min = ret; + let mut pre_max = ret; + for n in nums.iter().skip(1) { + let t_min = pre_min; + pre_min = cmp::min(cmp::min(pre_min * n, pre_max * n), *n); + pre_max = cmp::max(cmp::max(t_min * n, pre_max * n), *n); + + ret = cmp::max(ret, pre_max); + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_152() { + assert_eq!(6, Solution::max_product(vec![2, 3, -2, 4])); + assert_eq!(0, Solution::max_product(vec![-2, 0, -1])); + assert_eq!(0, Solution::max_product(vec![-2, 0])); + assert_eq!(1, Solution::max_product(vec![1])); + } +} diff --git a/src/problem/p0153_find_minimum_in_rotated_sorted_array.rs b/src/problem/p0153_find_minimum_in_rotated_sorted_array.rs new file mode 100644 index 00000000..2cde24d7 --- /dev/null +++ b/src/problem/p0153_find_minimum_in_rotated_sorted_array.rs @@ -0,0 +1,77 @@ +/// [153] Find Minimum in Rotated Sorted Array +/// +/// Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For +/// example, the array nums = [0,1,2,4,5,6,7] might become: +/// +/// [4,5,6,7,0,1,2] if it was rotated 4 times. +/// [0,1,2,4,5,6,7] if it was rotated 7 times. +/// +/// Notice that rotating an array [a[0], a[1], a[2], ..., a[n-1]] 1 time results in the array +/// [a[n-1], a[0], a[1], a[2], ..., a[n-2]]. Given the sorted rotated array nums of unique elements, +/// return the minimum element of this array. You must write an algorithm that runs in O(log n) +/// time. +/// Example 1: +/// +/// Input: nums = [3,4,5,1,2] +/// Output: 1 +/// Explanation: The original array was [1,2,3,4,5] rotated 3 times. +/// +/// Example 2: +/// +/// Input: nums = [4,5,6,7,0,1,2] +/// Output: 0 +/// Explanation: The original array was [0,1,2,4,5,6,7] and it was rotated 4 times. +/// +/// Example 3: +/// +/// Input: nums = [11,13,15,17] +/// Output: 11 +/// Explanation: The original array was [11,13,15,17] and it was rotated 4 times. +/// +/// +/// Constraints: +/// +/// n == nums.length +/// 1 <= n <= 5000 +/// -5000 <= nums[i] <= 5000 +/// All the integers of nums are unique. +/// nums is sorted and rotated between 1 and n times. +pub struct Solution {} + +// problem: https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/ +// discuss: https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn find_min(nums: Vec) -> i32 { + if nums.len() == 1 { + return nums[0]; + } + + let (mut lo, mut hi) = (0, nums.len() - 1); + while lo < hi { + let mid = lo + (hi - lo) / 2; + if nums[mid] > nums[hi] { + lo = mid + 1; + } else { + hi = mid; + } + } + + nums[lo] + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_153() { + assert_eq!(Solution::find_min(vec![3, 4, 5, 1, 2]), 1); + assert_eq!(Solution::find_min(vec![4, 5, 6, 7, 0, 1, 2]), 0); + } +} diff --git a/src/problem/p0155_min_stack.rs b/src/problem/p0155_min_stack.rs new file mode 100644 index 00000000..ea2ba44a --- /dev/null +++ b/src/problem/p0155_min_stack.rs @@ -0,0 +1,107 @@ +use std::cmp; + +/// [155] Min Stack +/// +/// Design a stack that supports push, pop, top, and retrieving the minimum element in constant +/// time. Implement the MinStack class: +/// +/// MinStack() initializes the stack object. +/// void push(int val) pushes the element val onto the stack. +/// void pop() removes the element on the top of the stack. +/// int top() gets the top element of the stack. +/// int getMin() retrieves the minimum element in the stack. +/// +/// You must implement a solution with O(1) time complexity for each function. +/// +/// Example 1: +/// +/// Input +/// ["MinStack","push","push","push","getMin","pop","top","getMin"] +/// [[],[-2],[0],[-3],[],[],[],[]] +/// Output +/// [null,null,null,null,-3,null,0,-2] +/// Explanation +/// MinStack minStack = new MinStack(); +/// minStack.push(-2); +/// minStack.push(0); +/// minStack.push(-3); +/// minStack.getMin(); // return -3 +/// minStack.pop(); +/// minStack.top(); // return 0 +/// minStack.getMin(); // return -2 +/// +/// +/// Constraints: +/// +/// -2^31 <= val <= 2^31 - 1 +/// Methods pop, top and getMin operations will always be called on non-empty stacks. +/// At most 3 * 10^4 calls will be made to push, pop, top, and getMin. +pub struct Solution {} + +// problem: https://leetcode.com/problems/min-stack/ +// discuss: https://leetcode.com/problems/min-stack/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +#[allow(dead_code)] +struct MinStack { + vec: Vec<(i32, i32)>, +} + +#[allow(dead_code)] +impl MinStack { + fn new() -> Self { + Self { vec: vec![] } + } + + fn push(&mut self, val: i32) { + if self.vec.is_empty() { + self.vec.push((val, val)); + return; + } + + let min = self.vec.last().unwrap().1; + self.vec.push((val, cmp::min(val, min))); + } + + fn pop(&mut self) { + self.vec.pop(); + } + + fn top(&self) -> i32 { + self.vec.last().unwrap().0 + } + + fn get_min(&self) -> i32 { + self.vec.last().unwrap().1 + } +} + +// /// Your MinStack object will be instantiated and called as such: +// /// let obj = MinStack::new(); +// /// obj.push(val); +// /// obj.pop(); +// /// let ret_3: i32 = obj.top(); +// /// let ret_4: i32 = obj.get_min(); + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_155() { + let mut min_stack = MinStack::new(); + min_stack.push(-2); + min_stack.push(0); + min_stack.push(-3); + assert_eq!(min_stack.get_min(), -3); + min_stack.pop(); + assert_eq!(min_stack.top(), 0); + assert_eq!(min_stack.get_min(), -2); + min_stack.pop(); + assert_eq!(min_stack.top(), -2); + assert_eq!(min_stack.get_min(), -2); + } +} diff --git a/src/problem/p0165_compare_version_numbers.rs b/src/problem/p0165_compare_version_numbers.rs new file mode 100644 index 00000000..b3db9a53 --- /dev/null +++ b/src/problem/p0165_compare_version_numbers.rs @@ -0,0 +1,108 @@ +use std::cmp::{Ordering, max}; + +/// [165] Compare Version Numbers +/// +/// Given two version numbers, version1 and version2, compare them. +/// +/// +/// Version numbers consist of one or more revisions joined by a dot '.'. Each revision consists of +/// digits and may contain leading zeros. Every revision contains at least one character. Revisions +/// are 0-indexed from left to right, with the leftmost revision being revision 0, the next revision +/// being revision 1, and so on. For example 2.5.33 and 0.1 are valid version numbers. To compare +/// version numbers, compare their revisions in left-to-right order. Revisions are compared using +/// their integer value ignoring any leading zeros. This means that revisions 1 and 001 are +/// considered equal. If a version number does not specify a revision at an index, then treat the +/// revision as 0. For example, version 1.0 is less than version 1.1 because their revision 0s are +/// the same, but their revision 1s are 0 and 1 respectively, and 0 < 1. Return the following: +/// +/// If version1 < version2, return -1. +/// If version1 > version2, return 1. +/// Otherwise, return 0. +/// +/// +/// Example 1: +/// +/// Input: version1 = "1.01", version2 = "1.001" +/// Output: 0 +/// Explanation: Ignoring leading zeroes, both "01" and "001" represent the same integer "1". +/// +/// Example 2: +/// +/// Input: version1 = "1.0", version2 = "1.0.0" +/// Output: 0 +/// Explanation: version1 does not specify revision 2, which means it is treated as "0". +/// +/// Example 3: +/// +/// Input: version1 = "0.1", version2 = "1.1" +/// Output: -1 +/// Explanation: version1's revision 0 is "0", while version2's revision 0 is "1". 0 < 1, so +/// version1 < version2. +/// +/// +/// Constraints: +/// +/// 1 <= version1.length, version2.length <= 500 +/// version1 and version2 only contain digits and '.'. +/// version1 and version2 are valid version numbers. +/// All the given revisions in version1 and version2 can be stored in a 32-bit integer. +pub struct Solution {} + +// problem: https://leetcode.com/problems/compare-version-numbers/ +// discuss: https://leetcode.com/problems/compare-version-numbers/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn compare_version(version1: String, version2: String) -> i32 { + let v1 = version1 + .split('.') + .map(|s| s.parse::().unwrap()) + .collect::>(); + + let v2 = version2 + .split('.') + .map(|s| s.parse::().unwrap()) + .collect::>(); + + for i in 0..max(v1.len(), v2.len()) { + match v1.get(i).unwrap_or(&0).cmp(v2.get(i).unwrap_or(&0)) { + Ordering::Equal => (), + not_equal => return not_equal as i32, + } + } + + Ordering::Equal as i32 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_165() { + assert_eq!( + 0, + Solution::compare_version("1.01".to_string(), "1.001".to_string()) + ); + assert_eq!( + 0, + Solution::compare_version("1.0".to_string(), "1.0.0".to_string()) + ); + assert_eq!( + -1, + Solution::compare_version("0.1".to_string(), "1.1".to_string()) + ); + assert_eq!( + 0, + Solution::compare_version("1.0".to_string(), "1.0.0".to_string()) + ); + assert_eq!( + 1, + Solution::compare_version("1.0.1".to_string(), "1".to_string()) + ); + } +} diff --git a/src/problem/p0202_happy_number.rs b/src/problem/p0202_happy_number.rs new file mode 100644 index 00000000..8c0f57e9 --- /dev/null +++ b/src/problem/p0202_happy_number.rs @@ -0,0 +1,78 @@ +/// [202] Happy Number +/// +/// Write an algorithm to determine if a number n is happy. +/// A happy number is a number defined by the following process: +/// +/// Starting with any positive integer, replace the number by the sum of the squares of its +/// digits. Repeat the process until the number equals 1 (where it will stay), or it loops +/// endlessly in a cycle which does not include 1. Those numbers for which this process ends in +/// 1 are happy. +/// +/// Return true if n is a happy number, and false if not. +/// +/// Example 1: +/// +/// Input: n = 19 +/// Output: true +/// Explanation: +/// 1^2 + 9^2 = 82 +/// 8^2 + 2^2 = 68 +/// 6^2 + 8^2 = 100 +/// 1^2 + 0^2 + 0^2 = 1 +/// +/// Example 2: +/// +/// Input: n = 2 +/// Output: false +/// +/// +/// Constraints: +/// +/// 1 <= n <= 2^31 - 1 +pub struct Solution {} + +// problem: https://leetcode.com/problems/happy-number/ +// discuss: https://leetcode.com/problems/happy-number/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn is_happy(n: i32) -> bool { + if n == 1 { + return true; + } + + let mut slow = n; + let mut fast = Self::next(n); + while slow != fast { + slow = Self::next(slow); + fast = Self::next(Self::next(fast)); + } + + slow == 1 + } + + fn next(mut n: i32) -> i32 { + let mut ret = 0; + while n > 0 { + ret += (n % 10) * (n % 10); + n /= 10; + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_202() { + assert!(Solution::is_happy(19)); + assert!(!Solution::is_happy(2)); + assert!(Solution::is_happy(1)); + } +} diff --git a/src/problem/p0205_isomorphic_strings.rs b/src/problem/p0205_isomorphic_strings.rs new file mode 100644 index 00000000..9f604f48 --- /dev/null +++ b/src/problem/p0205_isomorphic_strings.rs @@ -0,0 +1,82 @@ +use std::collections::HashMap; + +/// [205] Isomorphic Strings +/// +/// Given two strings s and t, determine if they are isomorphic. +/// Two strings s and t are isomorphic if the characters in s can be replaced to get t. +/// All occurrences of a character must be replaced with another character while preserving the +/// order of characters. No two characters may map to the same character, but a character may map to +/// itself. +/// Example 1: +/// Input: s = "egg", t = "add" +/// Output: true +/// Example 2: +/// Input: s = "foo", t = "bar" +/// Output: false +/// Example 3: +/// Input: s = "paper", t = "title" +/// Output: true +/// +/// Constraints: +/// +/// 1 <= s.length <= 5 * 10^4 +/// t.length == s.length +/// s and t consist of any valid ascii character. +pub struct Solution {} + +// problem: https://leetcode.com/problems/isomorphic-strings/ +// discuss: https://leetcode.com/problems/isomorphic-strings/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn is_isomorphic(s: String, t: String) -> bool { + if s.len() == 1 { + return true; + } + + let mut ss = HashMap::new(); + let mut tt = HashMap::new(); + let s = s.as_bytes(); + let t = t.as_bytes(); + for i in 0..s.len() { + ss.insert(s[i], t[i]); + tt.insert(t[i], s[i]); + } + + for i in 0..s.len() { + if ss[&s[i]] != t[i] || tt[&t[i]] != s[i] { + return false; + } + } + + true + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_205() { + assert!(Solution::is_isomorphic( + "egg".to_string(), + "add".to_string() + )); + assert!(!Solution::is_isomorphic( + "foo".to_string(), + "bar".to_string() + )); + assert!(Solution::is_isomorphic( + "paper".to_string(), + "title".to_string() + )); + assert!(Solution::is_isomorphic( + "foo".to_string(), + "foo".to_string() + )); + } +} diff --git a/src/problem/p0243_shortest_word_distance.rs b/src/problem/p0243_shortest_word_distance.rs new file mode 100644 index 00000000..e02e4dde --- /dev/null +++ b/src/problem/p0243_shortest_word_distance.rs @@ -0,0 +1,67 @@ +/// [243] Shortest Word Distance +/// +/// Given a list of words and two words word1 and word2, return the shortest distance between these +/// two words in the list. +/// +/// Input:["practice", "makes", "perfect", "coding", "makes"], "coding","practice" +/// Output:3 +/// Explanation:index("coding") - index("practice") = 3 +/// +/// Input:["practice", "makes", "perfect", "coding", "makes"], "makes","coding" +/// Output:1 +/// Explanation:index("makes") - index("coding") = 1 +/// +/// You may assume that word1 does not equal to word2, and word1 and word2 are both in the list. +pub struct Solution {} + +impl Solution { + pub fn shortest_distance(words: Vec, word1: String, word2: String) -> i32 { + if words.len() == 2 { + return 1; + } + + let mut ret = words.len() as i32; + let mut p1 = -1; + let mut p2 = -1; + for (i, w) in words.iter().enumerate() { + if w == &word1 { + p1 = i as i32; + } + if w == &word2 { + p2 = i as i32; + } + if p1 != -1 && p2 != -1 { + ret = ret.min((p1 - p2).abs()); + } + } + + ret + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_243() { + assert_eq!( + Solution::shortest_distance( + vec_string!["practice", "makes", "perfect", "coding", "makes"], + "coding".to_string(), + "practice".to_string() + ), + 3 + ); + assert_eq!( + Solution::shortest_distance( + vec_string![ + "practice", "makes", "coding", "makes", "perfect", "coding", "practice" + ], + "coding".to_string(), + "practice".to_string() + ), + 1 + ); + } +} diff --git a/src/problem/p0345_reverse_vowels_of_a_string.rs b/src/problem/p0345_reverse_vowels_of_a_string.rs new file mode 100644 index 00000000..351903c3 --- /dev/null +++ b/src/problem/p0345_reverse_vowels_of_a_string.rs @@ -0,0 +1,83 @@ +use std::collections::HashSet; + +/// [345] Reverse Vowels of a String +/// +/// Given a string s, reverse only all the vowels in the string and return it. +/// The vowels are 'a', 'e', 'i', 'o', and 'u', and they can appear in both lower and upper cases, +/// more than once. +/// Example 1: +/// Input: s = "hello" +/// Output: "holle" +/// Example 2: +/// Input: s = "leetcode" +/// Output: "leotcede" +/// +/// Constraints: +/// +/// 1 <= s.length <= 3 * 10^5 +/// s consist of printable ASCII characters. +pub struct Solution {} + +// problem: https://leetcode.com/problems/reverse-vowels-of-a-string/ +// discuss: https://leetcode.com/problems/reverse-vowels-of-a-string/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn reverse_vowels(mut s: String) -> String { + if s.len() < 2 { + return s; + } + let set = HashSet::from([b'a', b'A', b'e', b'E', b'i', b'I', b'o', b'O', b'u', b'U']); + + let s1 = unsafe { s.as_bytes_mut() }; + let mut i = 0; + let mut j = s1.len() - 1; + while i < j { + if !set.contains(&s1[i]) { + i += 1; + continue; + } + if !set.contains(&s1[j]) { + j -= 1; + continue; + } + s1.swap(i, j); + i += 1; + j -= 1; + } + + s + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_345() { + assert_eq!( + Solution::reverse_vowels(String::from("hello")), + String::from("holle") + ); + assert_eq!( + Solution::reverse_vowels(String::from("leetcode")), + String::from("leotcede") + ); + assert_eq!( + Solution::reverse_vowels(String::from("aA")), + String::from("Aa") + ); + assert_eq!( + Solution::reverse_vowels(String::from("ar")), + String::from("ar") + ); + assert_eq!( + Solution::reverse_vowels(String::from("sfsfsf")), + String::from("sfsfsf") + ); + } +} diff --git a/src/problem/p0416_partition_equal_subset_sum.rs b/src/problem/p0416_partition_equal_subset_sum.rs new file mode 100644 index 00000000..8ac5a0da --- /dev/null +++ b/src/problem/p0416_partition_equal_subset_sum.rs @@ -0,0 +1,66 @@ +// Given an integer array nums, return true if you can partition the array into two subsets such +// that the sum of the elements in both subsets is equal or false otherwise. + +// Example 1: + +// Input: nums = [1,5,11,5] +// Output: true +// Explanation: The array can be partitioned as [1, 5, 5] and [11]. +// Example 2: + +// Input: nums = [1,2,3,5] +// Output: false +// Explanation: The array cannot be partitioned into equal sum subsets. + +// Constraints: + +// 1 <= nums.length <= 200 +// 1 <= nums[i] <= 100 + +// https://leetcode.com/problems/partition-equal-subset-sum +// https://leetcode.com/problems/partition-equal-subset-sum/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here +pub struct Solution {} + +impl Solution { + pub fn can_partition(nums: Vec) -> bool { + let sum = nums.iter().sum::(); + if sum % 2 != 0 { + return false; + } + + let n = nums.len(); + let m = sum as usize / 2; + let mut dp = vec![vec![0; m + 1]; n + 1]; + + dp[0][0] = 1; + for i in 1..n + 1 { + for j in 0..m + 1 { + dp[i][j] = dp[i - 1][j]; + if j >= nums[i - 1] as usize { + dp[i][j] = dp[i - 1][j - nums[i - 1] as usize] + dp[i - 1][j]; + } + if j == m && dp[i][j] != 0 { + return true; + } + } + } + + dp[n][m] != 0 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_0416() { + assert!(Solution::can_partition(vec![1, 5, 11, 5])); + assert!(!Solution::can_partition(vec![1, 2, 3, 5])); + assert!(!Solution::can_partition(vec![1, 2, 5])); + } +} diff --git a/src/problem/p0494_target_sum.rs b/src/problem/p0494_target_sum.rs new file mode 100644 index 00000000..3baa80c4 --- /dev/null +++ b/src/problem/p0494_target_sum.rs @@ -0,0 +1,76 @@ +// You are given an integer array nums and an integer target. + +// You want to build an expression out of nums by adding one of the symbols '+' and '-' before each +// integer in nums and then concatenate all the integers. + +// For example, if nums = [2, 1], you can add a '+' before 2 and a '-' before 1 and concatenate them +// to build the expression "+2-1". Return the number of different expressions that you can build, +// which evaluates to target. + +// Example 1: + +// Input: nums = [1,1,1,1,1], target = 3 +// Output: 5 +// Explanation: There are 5 ways to assign symbols to make the sum of nums be target 3. +// -1 + 1 + 1 + 1 + 1 = 3 +// +1 - 1 + 1 + 1 + 1 = 3 +// +1 + 1 - 1 + 1 + 1 = 3 +// +1 + 1 + 1 - 1 + 1 = 3 +// +1 + 1 + 1 + 1 - 1 = 3 +// Example 2: + +// Input: nums = [1], target = 1 +// Output: 1 + +// Constraints: + +// 1 <= nums.length <= 20 +// 0 <= nums[i] <= 1000 +// 0 <= sum(nums[i]) <= 1000 +// -1000 <= target <= 1000 + +// https://leetcode.com/problems/target-sum +// https://leetcode.com/problems/target-sum/solution + +// submission codes start here +pub struct Solution {} + +impl Solution { + pub fn find_target_sum_ways(nums: Vec, target: i32) -> i32 { + let sum = nums.iter().sum::(); + // s(p) + s(n) = target + // s(p) - s(n) = sum + // 2s(p) = target + sum + if sum + target < 0 || (target + sum) % 2 != 0 { + return 0; + } + + let n = nums.len(); + let m = ((target + sum) / 2) as usize; + let mut dp = vec![vec![0; m + 1]; n + 1]; + dp[0][0] = 1; + for i in 1..n + 1 { + for j in 0..m + 1 { + dp[i][j] = dp[i - 1][j]; + if j >= nums[i - 1] as usize { + dp[i][j] = dp[i - 1][j - nums[i - 1] as usize] + dp[i - 1][j]; + } + } + } + + dp[n][m] + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_494() { + assert_eq!(Solution::find_target_sum_ways(vec![1, 1, 1, 1, 1], 3), 5); + assert_eq!(Solution::find_target_sum_ways(vec![1], 1), 1); + } +} diff --git a/src/problem/p0496_next_greater_element_i.rs b/src/problem/p0496_next_greater_element_i.rs new file mode 100644 index 00000000..1c2ba160 --- /dev/null +++ b/src/problem/p0496_next_greater_element_i.rs @@ -0,0 +1,91 @@ +// The next greater element of some element x in an array is the first greater element that is to +// the right of x in the same array. + +// You are given two distinct 0-indexed integer arrays nums1 and nums2, where nums1 is a subset of +// nums2. + +// For each 0 <= i < nums1.length, find the index j such that nums1[i] == nums2[j] and determine the +// next greater element of nums2[j] in nums2. If there is no next greater element, then the answer +// for this query is -1. + +// Return an array ans of length nums1.length such that ans[i] is the next greater element as +// described above. + +// Example 1: + +// Input: nums1 = [4,1,2], nums2 = [1,3,4,2] +// Output: [-1,3,-1] +// Explanation: The next greater element for each value of nums1 is as follows: +// - 4 is underlined in nums2 = [1,3,4,2]. There is no next greater element, so the answer is -1. +// - 1 is underlined in nums2 = [1,3,4,2]. The next greater element is 3. +// - 2 is underlined in nums2 = [1,3,4,2]. There is no next greater element, so the answer is -1. +// Example 2: + +// Input: nums1 = [2,4], nums2 = [1,2,3,4] +// Output: [3,-1] +// Explanation: The next greater element for each value of nums1 is as follows: +// - 2 is underlined in nums2 = [1,2,3,4]. The next greater element is 3. +// - 4 is underlined in nums2 = [1,2,3,4]. There is no next greater element, so the answer is -1. + +// Constraints: + +// 1 <= nums1.length <= nums2.length <= 1000 +// 0 <= nums1[i], nums2[i] <= 104 +// All integers in nums1 and nums2 are unique. +// All the integers of nums1 also appear in nums2. + +// Follow up: Could you find an O(nums1.length + nums2.length) solution? + +use std::collections::hash_map; + +pub struct Solution {} + +// problem: https://leetcode.com/problems/next-greater-element-i/ +// discuss: https://leetcode.com/problems/next-greater-element-i/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn next_greater_element(nums1: Vec, nums2: Vec) -> Vec { + if nums2.len() == 1 { + return vec![-1]; + } + + let mut stack = vec![]; + let mut dic = hash_map::HashMap::new(); + for n in nums2 { + while !stack.is_empty() && stack[stack.len() - 1] < n { + let t = stack.pop().unwrap(); + dic.insert(t, n); + } + stack.push(n); + } + + let mut ret = vec![]; + for n in nums1 { + let t = dic.get(&n).map_or(-1, |v| *v); + ret.push(t); + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_0496() { + assert_eq!( + Solution::next_greater_element(vec![4, 1, 2], vec![1, 3, 4, 2]), + vec![-1, 3, -1] + ); + assert_eq!( + Solution::next_greater_element(vec![2, 4], vec![1, 2, 3, 4]), + vec![3, -1] + ); + } +} diff --git a/src/problem/p0503_next_greater_element_ii.rs b/src/problem/p0503_next_greater_element_ii.rs new file mode 100644 index 00000000..0432b3a5 --- /dev/null +++ b/src/problem/p0503_next_greater_element_ii.rs @@ -0,0 +1,60 @@ +// Given a circular integer array nums (i.e., the next element of nums[nums.length - 1] is nums[0]), +// return the next greater number for every element in nums. + +// The next greater number of a number x is the first greater number to its traversing-order next in +// the array, which means you could search circularly to find its next greater number. If it doesn't +// exist, return -1 for this number. + +// Example 1: + +// Input: nums = [1,2,1] +// Output: [2,-1,2] +// Explanation: The first 1's next greater number is 2; +// The number 2 can't find next greater number. +// The second 1's next greater number needs to search circularly, which is also 2. +// Example 2: + +// Input: nums = [1,2,3,4,3] +// Output: [2,3,4,-1,4] + +// Constraints: + +// 1 <= nums.length <= 104 +// -109 <= nums[i] <= 109 + +pub struct Solution {} + +impl Solution { + pub fn next_greater_elements(nums: Vec) -> Vec { + let mut ret = vec![-1; nums.len()]; + let mut stack = vec![]; + for i in 0..2 * nums.len() { + while !stack.is_empty() && nums[stack[stack.len() - 1]] < nums[i % nums.len()] { + let j = stack.pop().unwrap(); + ret[j] = nums[i % nums.len()]; + } + if i < nums.len() { + stack.push(i); + } + } + + ret + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_0503() { + assert_eq!( + Solution::next_greater_elements(vec![1, 2, 1]), + vec![2, -1, 2] + ); + assert_eq!( + Solution::next_greater_elements(vec![1, 2, 3, 4, 3]), + vec![2, 3, 4, -1, 4] + ); + } +} diff --git a/src/problem/p0521_longest_uncommon_subsequence.rs b/src/problem/p0521_longest_uncommon_subsequence.rs new file mode 100644 index 00000000..32cbd156 --- /dev/null +++ b/src/problem/p0521_longest_uncommon_subsequence.rs @@ -0,0 +1,67 @@ +// Given two strings a and b, return the length of the longest uncommon subsequence between a and b. +// If no such uncommon subsequence exists, return -1. + +// An uncommon subsequence between two strings is a string that is a +// subsequence +// of exactly one of them. + +// Example 1: + +// Input: a = "aba", b = "cdc" +// Output: 3 +// Explanation: One longest uncommon subsequence is "aba" because "aba" is a subsequence of "aba" +// but not "cdc". Note that "cdc" is also a longest uncommon subsequence. +// Example 2: + +// Input: a = "aaa", b = "bbb" +// Output: 3 +// Explanation: The longest uncommon subsequences are "aaa" and "bbb". +// Example 3: + +// Input: a = "aaa", b = "aaa" +// Output: -1 +// Explanation: Every subsequence of string a is also a subsequence of string b. Similarly, every +// subsequence of string b is also a subsequence of string a. So the answer would be -1. + +// Constraints: + +// 1 <= a.length, b.length <= 100 +// a and b consist of lower-case English letters. + +pub struct Solution {} + +impl Solution { + pub fn find_lu_slength(a: String, b: String) -> i32 { + if a == b { + return -1; + } + + a.len().max(b.len()) as i32 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_find_lu_slength() { + assert_eq!( + Solution::find_lu_slength("aba".to_string(), "cdc".to_string()), + 3 + ); + assert_eq!( + Solution::find_lu_slength("aaa".to_string(), "bbb".to_string()), + 3 + ); + assert_eq!( + Solution::find_lu_slength("aaa".to_string(), "aaa".to_string()), + -1 + ); + + assert_eq!( + Solution::find_lu_slength("a".to_string(), "a".to_string()), + -1 + ); + } +} diff --git a/src/problem/p0543_diameter_of_binary_tree.rs b/src/problem/p0543_diameter_of_binary_tree.rs new file mode 100644 index 00000000..1d4c7ecb --- /dev/null +++ b/src/problem/p0543_diameter_of_binary_tree.rs @@ -0,0 +1,94 @@ +/// [543] Diameter of Binary Tree +/// +/// Given the root of a binary tree, return the length of the diameter of the tree. +/// The diameter of a binary tree is the length of the longest path between any two nodes in a tree. +/// This path may or may not pass through the root. The length of a path between two nodes is +/// represented by the number of edges between them. +/// Example 1: +/// +/// Input: root = [1,2,3,4,5] +/// Output: 3 +/// Explanation: 3 is the length of the path [4,2,1,3] or [5,2,1,3]. +/// +/// Example 2: +/// +/// Input: root = [1,2] +/// Output: 1 +/// +/// +/// Constraints: +/// +/// The number of nodes in the tree is in the range [1, 10^4]. +/// -100 <= Node.val <= 100 +pub struct Solution {} +// problem: https://leetcode.com/problems/diameter-of-binary-tree/ +// discuss: https://leetcode.com/problems/diameter-of-binary-tree/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::{cell::RefCell, rc::Rc}; + +use crate::util::tree::TreeNode; +impl Solution { + pub fn diameter_of_binary_tree(root: Option>>) -> i32 { + let (_, ret) = Self::diameter(root, 0); + ret + } + + fn diameter(root: Option>>, ret: i32) -> (i32, i32) { + if root.is_none() { + return (0, ret); + } + if root.as_ref().unwrap().borrow().left.is_none() + && root.as_ref().unwrap().borrow().right.is_none() + { + return (0, ret); + } + + let (l, ret) = Self::diameter(root.as_ref().unwrap().borrow().left.clone(), ret); + let (r, ret) = Self::diameter(root.as_ref().unwrap().borrow().right.clone(), ret); + let m = l.max(r) + 1; + let mut t = l + r; + if root.as_ref().unwrap().borrow().left.is_some() { + t += 1; + } + if root.as_ref().unwrap().borrow().right.is_some() { + t += 1; + } + + (m, ret.max(t)) + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + use crate::util::tree::to_tree; + + #[test] + fn test_543() { + assert_eq!(Solution::diameter_of_binary_tree(tree![1, 2, 3, 4, 5]), 3); + assert_eq!(Solution::diameter_of_binary_tree(tree![1, 2]), 1); + assert_eq!(Solution::diameter_of_binary_tree(tree![1]), 0); + } +} diff --git a/src/problem/p0551_student_attendance_record_i.rs b/src/problem/p0551_student_attendance_record_i.rs new file mode 100644 index 00000000..de625449 --- /dev/null +++ b/src/problem/p0551_student_attendance_record_i.rs @@ -0,0 +1,73 @@ +// You are given a string s representing an attendance record for a student where each character +// signifies whether the student was absent, late, or present on that day. The record only contains +// the following three characters: + +// 'A': Absent. +// 'L': Late. +// 'P': Present. +// The student is eligible for an attendance award if they meet both of the following criteria: + +// The student was absent ('A') for strictly fewer than 2 days total. +// The student was never late ('L') for 3 or more consecutive days. +// Return true if the student is eligible for an attendance award, or false otherwise. + +// Example 1: + +// Input: s = "PPALLP" +// Output: true +// Explanation: The student has fewer than 2 absences and was never late 3 or more consecutive days. +// Example 2: + +// Input: s = "PPALLL" +// Output: false +// Explanation: The student was late 3 consecutive days in the last 3 days, so is not eligible for +// the award. + +// Constraints: + +// 1 <= s.length <= 1000 +// s[i] is either 'A', 'L', or 'P'. + +// https://leetcode.com/problems/student-attendance-record-i/ + +pub struct Solution {} + +impl Solution { + pub fn check_record(s: String) -> bool { + if s.len() < 2 { + return true; + } + + let mut a = 0; + let mut l = 0; + let s = s.as_bytes(); + for i in 0..s.len() { + if s[i] == b'L' { + if i == 0 || s[i - 1] != b'L' { + l = 1; + } else { + l += 1; + if l == 3 { + return false; + } + } + } else if s[i] == b'A' { + a += 1; + } + } + + a < 2 + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_0551() { + assert!(Solution::check_record("PPALLP".to_string())); + assert!(!Solution::check_record("PPALLL".to_string())); + assert!(Solution::check_record("A".to_string())); + } +} diff --git a/src/problem/p0560_subarray_sum_equals_k.rs b/src/problem/p0560_subarray_sum_equals_k.rs new file mode 100644 index 00000000..942e00e3 --- /dev/null +++ b/src/problem/p0560_subarray_sum_equals_k.rs @@ -0,0 +1,60 @@ +// Given an array of integers nums and an integer k, return the total number of subarrays whose sum +// equals to k. + +// A subarray is a contiguous non-empty sequence of elements within an array. + +// Example 1: + +// Input: nums = [1,1,1], k = 2 +// Output: 2 +// Example 2: + +// Input: nums = [1,2,3], k = 3 +// Output: 2 + +// Constraints: + +// 1 <= nums.length <= 2 * 104 +// -1000 <= nums[i] <= 1000 +// -107 <= k <= 107 + +pub struct Solution {} + +// problem: https://leetcode.com/problems/subarray-sum-equals-k/ + +// submission codes start here + +impl Solution { + pub fn subarray_sum(nums: Vec, k: i32) -> i32 { + let mut ret = 0; + let mut sum = 0; + let mut dic = std::collections::HashMap::new(); + + for item in nums { + sum += item; + if sum == k { + ret += 1; + } + if let Some(v) = dic.get(&(sum - k)) { + ret += v; + } + *dic.entry(sum).or_insert(0) += 1; + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_560() { + assert_eq!(Solution::subarray_sum(vec![1, 1, 1], 2), 2); + assert_eq!(Solution::subarray_sum(vec![1, 2, 3], 3), 2); + assert_eq!(Solution::subarray_sum(vec![1], 3), 0); + } +} diff --git a/src/problem/p0581_shortest_unsorted_continuous_subarray.rs b/src/problem/p0581_shortest_unsorted_continuous_subarray.rs new file mode 100644 index 00000000..06314702 --- /dev/null +++ b/src/problem/p0581_shortest_unsorted_continuous_subarray.rs @@ -0,0 +1,112 @@ +/// [581] Shortest Unsorted Continuous Subarray +/// +/// Given an integer array nums, you need to find one continuous subarray such that if you only sort +/// this subarray in non-decreasing order, then the whole array will be sorted in non-decreasing +/// order. Return the shortest such subarray and output its length. +/// +/// Example 1: +/// +/// Input: nums = [2,6,4,8,10,9,15] +/// Output: 5 +/// Explanation: You need to sort [6, 4, 8, 10, 9] in ascending order to make the whole array sorted +/// in ascending order. +/// +/// Example 2: +/// +/// Input: nums = [1,2,3,4] +/// Output: 0 +/// +/// Example 3: +/// +/// Input: nums = [1] +/// Output: 0 +/// +/// +/// Constraints: +/// +/// 1 <= nums.length <= 10^4 +/// -10^5 <= nums[i] <= 10^5 +/// +/// +/// Follow up: Can you solve it in O(n) time complexity? +pub struct Solution {} + +// problem: https://leetcode.com/problems/shortest-unsorted-continuous-subarray/ +// discuss: https://leetcode.com/problems/shortest-unsorted-continuous-subarray/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn find_unsorted_subarray(nums: Vec) -> i32 { + if nums.len() <= 1 { + return 0; + } + + let mut m = -1; + let mut n = -1; + for i in 1..nums.len() { + if nums[i] < nums[i - 1] { + m = i as i32 - 1; + break; + } + } + if m == -1 { + return 0; + } + + for i in (1..nums.len()).rev() { + if nums[i] < nums[i - 1] { + n = i as i32; + break; + } + } + let mut min = nums[m as usize]; + let mut max = nums[m as usize]; + for i in m..n + 1 { + if nums[i as usize] > max { + max = nums[i as usize]; + } + if nums[i as usize] < min { + min = nums[i as usize]; + } + } + let mut lo = 0; + let mut hi = nums.len() as i32 - 1; + for i in (0..m).rev() { + if nums[i as usize] <= min { + lo = i + 1; + break; + } + } + for i in n + 1..nums.len() as i32 { + if nums[i as usize] >= max { + hi = i - 1; + break; + } + } + + hi - lo + 1 + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_581() { + assert_eq!( + Solution::find_unsorted_subarray(vec![2, 6, 4, 8, 10, 9, 15]), + 5 + ); + assert_eq!( + Solution::find_unsorted_subarray(vec![2, 116, 117, 4, 8, 10, 9, 15]), + 7 + ); + assert_eq!(Solution::find_unsorted_subarray(vec![1, 2, 3, 4]), 0); + assert_eq!(Solution::find_unsorted_subarray(vec![1]), 0); + assert_eq!(Solution::find_unsorted_subarray(vec![2, 1]), 2); + } +} diff --git a/src/problem/p0617_merge_two_binary_trees.rs b/src/problem/p0617_merge_two_binary_trees.rs new file mode 100644 index 00000000..096e1f3c --- /dev/null +++ b/src/problem/p0617_merge_two_binary_trees.rs @@ -0,0 +1,94 @@ +/// [617] Merge Two Binary Trees +/// +/// You are given two binary trees root1 and root2. +/// Imagine that when you put one of them to cover the other, some nodes of the two trees are +/// overlapped while the others are not. You need to merge the two trees into a new binary tree. The +/// merge rule is that if two nodes overlap, then sum node values up as the new value of the merged +/// node. Otherwise, the NOT null node will be used as the node of the new tree. Return the merged +/// tree. Note: The merging process must start from the root nodes of both trees. +/// +/// Example 1: +/// +/// Input: root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7] +/// Output: [3,4,5,5,4,null,7] +/// +/// Example 2: +/// +/// Input: root1 = [1], root2 = [1,2] +/// Output: [2,2] +/// +/// +/// Constraints: +/// +/// The number of nodes in both trees is in the range [0, 2000]. +/// -10^4 <= Node.val <= 10^4 +pub struct Solution {} +// problem: https://leetcode.com/problems/merge-two-binary-trees/ +// discuss: https://leetcode.com/problems/merge-two-binary-trees/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::{cell::RefCell, rc::Rc}; + +use crate::util::tree::TreeNode; +impl Solution { + pub fn merge_trees( + root1: Option>>, + root2: Option>>, + ) -> Option>> { + if root1.is_none() { + return root2; + } + if root2.is_none() { + return root1; + } + + let val = root1.as_ref().unwrap().borrow().val + root2.as_ref().unwrap().borrow().val; + let root = Some(Rc::new(RefCell::new(TreeNode::new(val)))); + root.as_ref().unwrap().borrow_mut().left = Self::merge_trees( + root1.as_ref().unwrap().borrow().left.clone(), + root2.as_ref().unwrap().borrow().left.clone(), + ); + root.as_ref().unwrap().borrow_mut().right = Self::merge_trees( + root1.as_ref().unwrap().borrow().right.clone(), + root2.as_ref().unwrap().borrow().right.clone(), + ); + + root + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + use crate::util::tree::to_tree; + + #[test] + fn test_617() { + assert_eq!( + Solution::merge_trees(tree![1, 3, 2, 5], tree![2, 1, 3, null, 4, null, 7]), + tree![3, 4, 5, 5, 4, null, 7] + ); + assert_eq!(Solution::merge_trees(tree![1], tree![1, 2]), tree![2, 2]); + } +} diff --git a/src/problem/p0682_baseball_game.rs b/src/problem/p0682_baseball_game.rs new file mode 100644 index 00000000..94687968 --- /dev/null +++ b/src/problem/p0682_baseball_game.rs @@ -0,0 +1,126 @@ +// You are keeping the scores for a baseball game with strange rules. At the beginning of the game, +// you start with an empty record. + +// You are given a list of strings operations, where operations[i] is the ith operation you must +// apply to the record and is one of the following: + +// An integer x. +// Record a new score of x. +// '+'. +// Record a new score that is the sum of the previous two scores. +// 'D'. +// Record a new score that is the double of the previous score. +// 'C'. +// Invalidate the previous score, removing it from the record. +// Return the sum of all the scores on the record after applying all the operations. + +// The test cases are generated such that the answer and all intermediate calculations fit in a +// 32-bit integer and that all operations are valid. + +// Example 1: + +// Input: ops = ["5","2","C","D","+"] +// Output: 30 +// Explanation: +// "5" - Add 5 to the record, record is now [5]. +// "2" - Add 2 to the record, record is now [5, 2]. +// "C" - Invalidate and remove the previous score, record is now [5]. +// "D" - Add 2 * 5 = 10 to the record, record is now [5, 10]. +// "+" - Add 5 + 10 = 15 to the record, record is now [5, 10, 15]. +// The total sum is 5 + 10 + 15 = 30. +// Example 2: + +// Input: ops = ["5","-2","4","C","D","9","+","+"] +// Output: 27 +// Explanation: +// "5" - Add 5 to the record, record is now [5]. +// "-2" - Add -2 to the record, record is now [5, -2]. +// "4" - Add 4 to the record, record is now [5, -2, 4]. +// "C" - Invalidate and remove the previous score, record is now [5, -2]. +// "D" - Add 2 * -2 = -4 to the record, record is now [5, -2, -4]. +// "9" - Add 9 to the record, record is now [5, -2, -4, 9]. +// "+" - Add -4 + 9 = 5 to the record, record is now [5, -2, -4, 9, 5]. +// "+" - Add 9 + 5 = 14 to the record, record is now [5, -2, -4, 9, 5, 14]. +// The total sum is 5 + -2 + -4 + 9 + 5 + 14 = 27. +// Example 3: + +// Input: ops = ["1","C"] +// Output: 0 +// Explanation: +// "1" - Add 1 to the record, record is now [1]. +// "C" - Invalidate and remove the previous score, record is now []. +// Since the record is empty, the total sum is 0. + +// Constraints: + +// 1 <= operations.length <= 1000 +// operations[i] is "C", "D", "+", or a string representing an integer in the range [-3 * 104, 3 * +// 104]. For operation "+", there will always be at least two previous scores on the record. +// For operations "C" and "D", there will always be at least one previous score on the record. + +// https://leetcode.com/problems/baseball-game/ + +pub struct Solution {} + +// submission codes start here +impl Solution { + pub fn cal_points(operations: Vec) -> i32 { + let mut n = vec![]; + for i in operations { + match i.as_str() { + "C" => { + n.pop(); + } + "D" => { + n.push(n[n.len() - 1] * 2); + } + "+" => { + n.push(n[n.len() - 1] + n[n.len() - 2]); + } + _ => { + n.push(i.parse().unwrap()); + } + } + } + + n.iter().sum() + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_0682() { + assert_eq!( + Solution::cal_points(vec![ + "5".to_string(), + "2".to_string(), + "C".to_string(), + "D".to_string(), + "+".to_string() + ]), + 30 + ); + assert_eq!( + Solution::cal_points(vec![ + "5".to_string(), + "-2".to_string(), + "4".to_string(), + "C".to_string(), + "D".to_string(), + "9".to_string(), + "+".to_string(), + "+".to_string() + ]), + 27 + ); + assert_eq!( + Solution::cal_points(vec!["1".to_string(), "C".to_string()]), + 0 + ); + } +} diff --git a/src/problem/p0705_design_hashset.rs b/src/problem/p0705_design_hashset.rs new file mode 100644 index 00000000..bfdf73d5 --- /dev/null +++ b/src/problem/p0705_design_hashset.rs @@ -0,0 +1,112 @@ +// Design a HashSet without using any built-in hash table libraries. + +// Implement MyHashSet class: + +// void add(key) Inserts the value key into the HashSet. +// bool contains(key) Returns whether the value key exists in the HashSet or not. +// void remove(key) Removes the value key in the HashSet. If key does not exist in the HashSet, do +// nothing. + +// Example 1: + +// Input +// ["MyHashSet", "add", "add", "contains", "contains", "add", "contains", "remove", "contains"] +// [[], [1], [2], [1], [3], [2], [2], [2], [2]] +// Output +// [null, null, null, true, false, null, true, null, false] + +// Explanation +// MyHashSet myHashSet = new MyHashSet(); +// myHashSet.add(1); // set = [1] +// myHashSet.add(2); // set = [1, 2] +// myHashSet.contains(1); // return True +// myHashSet.contains(3); // return False, (not found) +// myHashSet.add(2); // set = [1, 2] +// myHashSet.contains(2); // return True +// myHashSet.remove(2); // set = [1] +// myHashSet.contains(2); // return False, (already removed) + +// Constraints: + +// 0 <= key <= 10^6 +// At most 10^4 calls will be made to add, remove, and contains. + +#[allow(dead_code)] +struct MyHashSet { + arr: Vec, + size: i32, +} + +/// `&self` means the method takes an immutable reference. +/// If you need a mutable reference, change it to `&mut self` instead. +#[allow(dead_code)] +impl MyHashSet { + fn new() -> Self { + let size = 100000; + + Self { + arr: vec![-1; size], + size: size as i32, + } + } + + fn add(&mut self, key: i32) { + let mut idx = (key % self.size) as usize; + while self.arr[idx] != -1 { + if self.arr[idx] == key { + return; + } + idx += 1; + } + self.arr[idx] = key; + } + + fn remove(&mut self, key: i32) { + let mut idx = (key % self.size) as usize; + while self.arr[idx] != key { + if self.arr[idx] != -1 { + return; + } + idx += 1; + if idx == self.size as usize { + return; + } + } + self.arr[idx] = -1; + } + + fn contains(&self, key: i32) -> bool { + let mut idx = (key % self.size) as usize; + while self.arr[idx] != key { + if self.arr[idx] == -1 { + return false; + } + + idx += 1; + if idx == self.size as usize { + return false; + } + } + + true + } +} +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_705() { + let mut m = MyHashSet::new(); + m.add(1); + m.add(2); + assert!(m.contains(1)); + assert!(!m.contains(3)); + m.add(2); + assert!(m.contains(2)); + m.remove(2); + assert!(!m.contains(2)); + } +} diff --git a/src/problem/p0724_find_pivot_index.rs b/src/problem/p0724_find_pivot_index.rs new file mode 100644 index 00000000..beabaaa0 --- /dev/null +++ b/src/problem/p0724_find_pivot_index.rs @@ -0,0 +1,69 @@ +// Given an array of integers nums, calculate the pivot index of this array. + +// The pivot index is the index where the sum of all the numbers strictly to the left of the index +// is equal to the sum of all the numbers strictly to the index's right. + +// If the index is on the left edge of the array, then the left sum is 0 because there are no +// elements to the left. This also applies to the right edge of the array. + +// Return the leftmost pivot index. If no such index exists, return -1. + +// Example 1: + +// Input: nums = [1,7,3,6,5,6] +// Output: 3 +// Explanation: +// The pivot index is 3. +// Left sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 +// Right sum = nums[4] + nums[5] = 5 + 6 = 11 +// Example 2: + +// Input: nums = [1,2,3] +// Output: -1 +// Explanation: +// There is no index that satisfies the conditions in the problem statement. +// Example 3: + +// Input: nums = [2,1,-1] +// Output: 0 +// Explanation: +// The pivot index is 0. +// Left sum = 0 (no elements to the left of index 0) +// Right sum = nums[1] + nums[2] = 1 + -1 = 0 + +// Constraints: + +// 1 <= nums.length <= 104 +// -1000 <= nums[i] <= 1000 + +pub struct Solution {} + +impl Solution { + pub fn pivot_index(nums: Vec) -> i32 { + let mut r = nums.iter().sum::(); + let mut l = 0; + for i in 0..nums.len() { + if i > 0 { + l += nums[i - 1]; + } + r -= nums[i]; + if l == r { + return i as i32; + } + } + + -1 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_0724() { + assert_eq!(Solution::pivot_index(vec![1, 7, 3, 6, 5, 6]), 3); + assert_eq!(Solution::pivot_index(vec![1, 2, 3]), -1); + assert_eq!(Solution::pivot_index(vec![2, 1, -1]), 0); + } +} diff --git a/src/problem/p0739_daily_temperatures.rs b/src/problem/p0739_daily_temperatures.rs new file mode 100644 index 00000000..7bf9910d --- /dev/null +++ b/src/problem/p0739_daily_temperatures.rs @@ -0,0 +1,71 @@ +// Given an array of integers temperatures represents the daily temperatures, return an array answer +// such that answer[i] is the number of days you have to wait after the ith day to get a warmer +// temperature. If there is no future day for which this is possible, keep answer[i] == 0 instead. + +// Example 1: + +// Input: temperatures = [73,74,75,71,69,72,76,73] +// Output: [1,1,4,2,1,1,0,0] +// Example 2: + +// Input: temperatures = [30,40,50,60] +// Output: [1,1,1,0] +// Example 3: + +// Input: temperatures = [30,60,90] +// Output: [1,1,0] + +// Constraints: + +// 1 <= temperatures.length <= 105 +// 30 <= temperatures[i] <= 100 + +pub struct Solution {} + +// problem: https://leetcode.com/problems/daily-temperatures/ +// discuss: https://leetcode.com/problems/daily-temperatures/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn daily_temperatures(temperatures: Vec) -> Vec { + if temperatures.len() == 1 { + return vec![0]; + } + + let mut ret = vec![0; temperatures.len()]; + let mut stack = vec![]; + for i in 0..temperatures.len() { + while !stack.is_empty() && temperatures[stack[stack.len() - 1]] < temperatures[i] { + let j = stack.pop().unwrap(); + ret[j] = (i - j) as i32; + } + stack.push(i); + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_0739() { + assert_eq!( + Solution::daily_temperatures(vec![73, 74, 75, 71, 69, 72, 76, 73]), + vec![1, 1, 4, 2, 1, 1, 0, 0] + ); + assert_eq!( + Solution::daily_temperatures(vec![30, 40, 50, 60]), + vec![1, 1, 1, 0] + ); + assert_eq!( + Solution::daily_temperatures(vec![30, 60, 90]), + vec![1, 1, 0] + ); + } +} diff --git a/src/problem/p0912_sort_an_array.rs b/src/problem/p0912_sort_an_array.rs new file mode 100644 index 00000000..77847a29 --- /dev/null +++ b/src/problem/p0912_sort_an_array.rs @@ -0,0 +1,98 @@ +/// [912] Sort an Array +/// +/// Given an array of integers nums, sort the array in ascending order and return it. +/// You must solve the problem without using any built-in functions in O(nlog(n)) time complexity +/// and with the smallest space complexity possible. +/// Example 1: +/// +/// Input: nums = [5,2,3,1] +/// Output: [1,2,3,5] +/// Explanation: After sorting the array, the positions of some numbers are not changed (for +/// example, 2 and 3), while the positions of other numbers are changed (for example, 1 and 5). +/// +/// Example 2: +/// +/// Input: nums = [5,1,1,2,0,0] +/// Output: [0,0,1,1,2,5] +/// Explanation: Note that the values of nums are not necessarily unique. +/// +/// +/// Constraints: +/// +/// 1 <= nums.length <= 5 * 10^4 +/// -5 * 10^4 <= nums[i] <= 5 * 10^4 +pub struct Solution {} + +// problem: https://leetcode.com/problems/sort-an-array/ +// discuss: https://leetcode.com/problems/sort-an-array/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn sort_array(nums: Vec) -> Vec { + if nums.len() == 1 { + return nums; + } + + let mut max = i32::MIN; + for i in &nums { + max = std::cmp::max(max, i.abs()); + } + + let mut i = 0; + let mut nums = nums; + while max >= 10_i32.pow(i) { + nums = Self::sort(&nums, i); + i += 1; + } + + nums + } + + fn sort(nums: &[i32], k: u32) -> Vec { + let mut count = [0; 21]; // [-9 - 9] + for item in nums.iter() { + let n = item / 10_i32.pow(k) % 10 + 10; + count[n as usize + 1] += 1; + } + for i in 1..count.len() { + count[i] += count[i - 1]; + } + + let mut ret = vec![0; nums.len()]; + for item in nums.iter() { + let n = item / 10_i32.pow(k) % 10 + 10; + ret[count[n as usize]] = *item; + count[n as usize] += 1; + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_912() { + assert_eq!(Solution::sort_array(vec![5, 2, 3, 1]), vec![1, 2, 3, 5]); + assert_eq!(Solution::sort_array(vec![-5, 2, 3, 1]), vec![-5, 1, 2, 3]); + assert_eq!( + Solution::sort_array(vec![511, 2, -3, 11]), + vec![-3, 2, 11, 511] + ); + assert_eq!( + Solution::sort_array(vec![5, 1, 1, 2, 0, 0]), + vec![0, 0, 1, 1, 2, 5] + ); + assert_eq!(Solution::sort_array(vec![2, 1]), vec![1, 2]); + assert_eq!(Solution::sort_array(vec![1, 1, 2]), vec![1, 1, 2]); + assert_eq!( + Solution::sort_array(vec![-1, 2, -8, -10]), + vec![-10, -8, -1, 2] + ); + } +} diff --git a/src/problem/p0926_flip_string_to_monotone_increasing.rs b/src/problem/p0926_flip_string_to_monotone_increasing.rs new file mode 100644 index 00000000..4914c2da --- /dev/null +++ b/src/problem/p0926_flip_string_to_monotone_increasing.rs @@ -0,0 +1,96 @@ +use std::cmp::min; + +/// [926] Flip String to Monotone Increasing +/// +/// A binary string is monotone increasing if it consists of some number of 0's (possibly none), +/// followed by some number of 1's (also possibly none). You are given a binary string s. You can +/// flip s[i] changing it from 0 to 1 or from 1 to 0. Return the minimum number of flips to make s +/// monotone increasing. +/// Example 1: +/// +/// Input: s = "00110" +/// Output: 1 +/// Explanation: We flip the last digit to get 00111. +/// +/// Example 2: +/// +/// Input: s = "010110" +/// Output: 2 +/// Explanation: We flip to get 011111, or alternatively 000111. +/// +/// Example 3: +/// +/// Input: s = "00011000" +/// Output: 2 +/// Explanation: We flip to get 00000000. +/// +/// +/// Constraints: +/// +/// 1 <= s.length <= 10^5 +/// s[i] is either '0' or '1'. +pub struct Solution {} + +// problem: https://leetcode.com/problems/flip-string-to-monotone-increasing/ +// discuss: https://leetcode.com/problems/flip-string-to-monotone-increasing/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn min_flips_mono_incr(s: String) -> i32 { + if s.len() == 1 { + return 0; + } + + let n = s.len(); + let mut ret = n as i32; + let mut l = vec![0; n]; + let mut r = vec![0; n]; + let s = s.as_bytes(); + + if s[0] == b'1' { + l[0] = 1; + } + for i in 1..n { + l[i] = l[i - 1]; + if s[i] == b'1' { + l[i] = l[i - 1] + 1; + } + } + + if s[n - 1] == b'0' { + r[n - 1] = 1; + } + for i in (0..n - 1).rev() { + r[i] = r[i + 1]; + if s[i] == b'0' { + r[i] = r[i + 1] + 1; + } + } + ret = min(ret, min(l[n - 1], r[0])); + for i in 1..n - 1 { + ret = min(ret, l[i - 1] + r[i + 1]); + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_926() { + assert_eq!( + Solution::min_flips_mono_incr("00110".to_string()), + 1, + "00110" + ); + assert_eq!(Solution::min_flips_mono_incr("010110".to_string()), 2); + assert_eq!(Solution::min_flips_mono_incr("00011000".to_string()), 2); + assert_eq!(Solution::min_flips_mono_incr("010110".to_string()), 2); + } +} diff --git a/src/problem/p1004_max_consecutive_ones_iii.rs b/src/problem/p1004_max_consecutive_ones_iii.rs new file mode 100644 index 00000000..425fd1c1 --- /dev/null +++ b/src/problem/p1004_max_consecutive_ones_iii.rs @@ -0,0 +1,73 @@ +// Given a binary array nums and an integer k, return the maximum number of consecutive 1's in the +// array if you can flip at most k 0's. + +// Example 1: + +// Input: nums = [1,1,1,0,0,0,1,1,1,1,0], k = 2 +// Output: 6 +// Explanation: [1,1,1,0,0,1,1,1,1,1,1] +// Bolded numbers were flipped from 0 to 1. The longest subarray is underlined. +// Example 2: + +// Input: nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], k = 3 +// Output: 10 +// Explanation: [0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1] +// Bolded numbers were flipped from 0 to 1. The longest subarray is underlined. + +// Constraints: + +// 1 <= nums.length <= 105 +// nums[i] is either 0 or 1. +// 0 <= k <= nums.length + +// problem: https://leetcode.com/problems/max-consecutive-ones-iii/ + +// submission codes start here +pub struct Solution {} + +impl Solution { + pub fn longest_ones(nums: Vec, k: i32) -> i32 { + let mut l = 0; + let mut r = 0; + let mut z = 0; + let mut ret = 0; + while r < nums.len() { + if nums[r] == 0 { + z += 1; + } + while l <= r && z > k { + if nums[l] == 0 { + z -= 1; + } + l += 1; + } + ret = std::cmp::max(ret, r as i32 - l as i32 + 1); + r += 1; + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1004() { + assert_eq!(Solution::longest_ones(vec![0, 0, 0], 0), 0); + assert_eq!( + Solution::longest_ones(vec![1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0], 2), + 6 + ); + assert_eq!( + Solution::longest_ones( + vec![0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1], + 3 + ), + 10 + ); + } +} diff --git a/src/problem/p1016_binary_string_with_substrings_representing_1_to_n.rs b/src/problem/p1016_binary_string_with_substrings_representing_1_to_n.rs new file mode 100644 index 00000000..3ad62682 --- /dev/null +++ b/src/problem/p1016_binary_string_with_substrings_representing_1_to_n.rs @@ -0,0 +1,49 @@ +/// [1016] Binary String With Substrings Representing 1 To N +/// +/// Given a binary string s and a positive integer n, return true if the binary representation of +/// all the integers in the range [1, n] are substrings of s, or false otherwise. A substring is a +/// contiguous sequence of characters within a string. +/// Example 1: +/// Input: s = "0110", n = 3 +/// Output: true +/// Example 2: +/// Input: s = "0110", n = 4 +/// Output: false +/// +/// Constraints: +/// +/// 1 <= s.length <= 1000 +/// s[i] is either '0' or '1'. +/// 1 <= n <= 10^9 +pub struct Solution {} + +// problem: https://leetcode.com/problems/binary-string-with-substrings-representing-1-to-n/ +// discuss: https://leetcode.com/problems/binary-string-with-substrings-representing-1-to-n/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn query_string(s: String, n: i32) -> bool { + for i in 1..=n { + if !s.contains(&format!("{:b}", i)) { + return false; + } + } + + true + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1016() { + assert!(Solution::query_string("0110".to_string(), 3)); + assert!(!Solution::query_string("0110".to_string(), 4)); + assert!(!Solution::query_string("0110".to_string(), 5)); + } +} diff --git a/src/problem/p1054_distant_barcodes.rs b/src/problem/p1054_distant_barcodes.rs new file mode 100644 index 00000000..0ea3c2d8 --- /dev/null +++ b/src/problem/p1054_distant_barcodes.rs @@ -0,0 +1,84 @@ +use std::collections::HashMap; + +/// [1054] Distant Barcodes +/// +/// In a warehouse, there is a row of barcodes, where the i^th barcode is barcodes[i]. +/// Rearrange the barcodes so that no two adjacent barcodes are equal. You may return any answer, +/// and it is guaranteed an answer exists. +/// Example 1: +/// Input: barcodes = [1,1,1,2,2,2] +/// Output: [2,1,2,1,2,1] +/// Example 2: +/// Input: barcodes = [1,1,1,1,2,2,3,3] +/// Output: [1,3,1,3,1,2,1,2] +/// +/// Constraints: +/// +/// 1 <= barcodes.length <= 10000 +/// 1 <= barcodes[i] <= 10000 +pub struct Solution {} + +// problem: https://leetcode.com/problems/distant-barcodes/ +// discuss: https://leetcode.com/problems/distant-barcodes/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn rearrange_barcodes(barcodes: Vec) -> Vec { + if barcodes.len() < 3 { + return barcodes; + } + + let mut map: HashMap = HashMap::new(); + let mut key = 0; + for item in &barcodes { + map.entry(*item).and_modify(|v| *v += 1).or_insert(1); + if *map.entry(key).or_default() < map[item] { + key = *item; + } + } + + let mut ret = vec![0; barcodes.len()]; + let mut i = 0; + for _c in 1..=map[&key] { + ret[i] = key; + i += 2; + } + + for (k, v) in &map { + if *k == key { + continue; + } + for _c in 1..=*v { + if i >= barcodes.len() { + i = 1; + } + ret[i] = *k; + i += 2; + } + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1054() { + let a = Solution::rearrange_barcodes(vec![1, 1, 1, 1, 2, 2, 2, 3, 3]); + assert!( + [ + vec![1, 2, 1, 2, 1, 3, 1, 3, 2], + vec![1, 3, 1, 2, 1, 2, 1, 2, 3] + ] + .contains(&a) + ); + + assert_eq!(vec![1, 2], Solution::rearrange_barcodes(vec![1, 2])); + } +} diff --git a/src/problem/p1186_maximum_subarray_sum_with_one_deletion.rs b/src/problem/p1186_maximum_subarray_sum_with_one_deletion.rs new file mode 100644 index 00000000..2807537d --- /dev/null +++ b/src/problem/p1186_maximum_subarray_sum_with_one_deletion.rs @@ -0,0 +1,63 @@ +// Given an array of integers, return the maximum sum for a non-empty subarray (contiguous elements) +// with at most one element deletion. In other words, you want to choose a subarray and optionally +// delete one element from it so that there is still at least one element left and the sum of the +// remaining elements is maximum possible. + +// Note that the subarray needs to be non-empty after deleting one element. + +// Example 1: + +// Input: arr = [1,-2,0,3] +// Output: 4 +// Explanation: Because we can choose [1, -2, 0, 3] and drop -2, thus the subarray [1, 0, 3] becomes +// the maximum value. Example 2: + +// Input: arr = [1,-2,-2,3] +// Output: 3 +// Explanation: We just choose [3] and it's the maximum sum. +// Example 3: + +// Input: arr = [-1,-1,-1,-1] +// Output: -1 +// Explanation: The final subarray needs to be non-empty. You can't choose [-1] and delete -1 from +// it, then get an empty subarray to make the sum equals to 0. + +// Constraints: + +// 1 <= arr.length <= 105 +// -104 <= arr[i] <= 104 + +// https://leetcode.com/problems/maximum-subarray-sum-with-one-deletion/ +// https://leetcode.com/problems/maximum-subarray-sum-with-one-deletion/discuss/1763358/Rust-or-Explanation-or-Implementation + +pub struct Solution {} + +impl Solution { + pub fn maximum_sum(arr: Vec) -> i32 { + if arr.len() == 1 { + return arr[0]; + } + + let mut ret = arr[0]; + let mut no_del = arr[0]; + let mut del = 0; + for item in arr.iter().skip(1) { + del = std::cmp::max(del + item, no_del); + no_del = std::cmp::max(no_del + item, *item); + ret = std::cmp::max(ret, std::cmp::max(del, no_del)); + } + + ret + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1186() { + assert_eq!(Solution::maximum_sum(vec![1, -2, 0, 3]), 4); + assert_eq!(Solution::maximum_sum(vec![1, -2, -2, 3]), 3); + } +} diff --git a/src/problem/p1376_time_needed_to_inform_all_employees.rs b/src/problem/p1376_time_needed_to_inform_all_employees.rs new file mode 100644 index 00000000..cd7cbfb7 --- /dev/null +++ b/src/problem/p1376_time_needed_to_inform_all_employees.rs @@ -0,0 +1,111 @@ +use std::collections::HashMap; + +/// [1376] Time Needed to Inform All Employees +/// +/// A company has n employees with a unique ID for each employee from 0 to n - 1. The head of the +/// company is the one with headID. Each employee has one direct manager given in the manager array +/// where manager[i] is the direct manager of the i-th employee, manager[headID] = -1. Also, it is +/// guaranteed that the subordination relationships have a tree structure. The head of the company +/// wants to inform all the company employees of an urgent piece of news. He will inform his direct +/// subordinates, and they will inform their subordinates, and so on until all employees know about +/// the urgent news. The i-th employee needs informTime[i] minutes to inform all of his direct +/// subordinates (i.e., After informTime[i] minutes, all his direct subordinates can start spreading +/// the news). Return the number of minutes needed to inform all the employees about the urgent +/// news. +/// Example 1: +/// +/// Input: n = 1, headID = 0, manager = [-1], informTime = [0] +/// Output: 0 +/// Explanation: The head of the company is the only employee in the company. +/// +/// Example 2: +/// +/// Input: n = 6, headID = 2, manager = [2,2,-1,2,2,2], informTime = [0,0,1,0,0,0] +/// Output: 1 +/// Explanation: The head of the company with id = 2 is the direct manager of all the employees in +/// the company and needs 1 minute to inform them all. The tree structure of the employees in the +/// company is shown. +/// +/// +/// Constraints: +/// +/// 1 <= n <= 10^5 +/// 0 <= headID < n +/// manager.length == n +/// 0 <= manager[i] < n +/// manager[headID] == -1 +/// informTime.length == n +/// 0 <= informTime[i] <= 1000 +/// informTime[i] == 0 if employee i has no subordinates. +/// It is guaranteed that all the employees can be informed. +pub struct Solution {} + +// problem: https://leetcode.com/problems/time-needed-to-inform-all-employees/ +// discuss: https://leetcode.com/problems/time-needed-to-inform-all-employees/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn num_of_minutes(_n: i32, head_id: i32, manager: Vec, inform_time: Vec) -> i32 { + if manager.len() < 2 { + return 0; + } + + let mut dag: HashMap> = HashMap::new(); + for (idx, v) in manager.iter().enumerate() { + dag.entry(*v).or_default().push(idx as i32); + } + + Self::dfs( + &dag, + head_id, + &inform_time, + inform_time[head_id as usize], + 0, + ) + } + + fn dfs( + dag: &HashMap>, + id: i32, + inform_time: &Vec, + time: i32, + mut ret: i32, + ) -> i32 { + let list = dag.get(&id); + if list.is_none() { + return ret.max(time); + } + + for i in list.unwrap() { + ret = Self::dfs(dag, *i, inform_time, time + inform_time[*i as usize], ret) + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_1376() { + assert_eq!(0, Solution::num_of_minutes(1, 0, vec![-1], vec![0])); + assert_eq!( + 1, + Solution::num_of_minutes(6, 2, vec![2, 2, -1, 2, 2, 2], vec![0, 0, 1, 0, 0, 0]) + ); + assert_eq!( + 3, + Solution::num_of_minutes( + 15, + 0, + vec![-1, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6], + vec![1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0] + ) + ); + } +} diff --git a/src/problem/p2437_number_of_valid_clock_times.rs b/src/problem/p2437_number_of_valid_clock_times.rs new file mode 100644 index 00000000..f35a4614 --- /dev/null +++ b/src/problem/p2437_number_of_valid_clock_times.rs @@ -0,0 +1,87 @@ +/// [2437] Number of Valid Clock Times +/// +/// You are given a string of length 5 called time, representing the current time on a digital clock +/// in the format "hh:mm". The earliest possible time is "00:00" and the latest possible time is +/// "23:59". In the string time, the digits represented by the ? symbol are unknown, and must be +/// replaced with a digit from 0 to 9. Return an integer answer, the number of valid clock times +/// that can be created by replacing every ? with a digit from 0 to 9. +/// Example 1: +/// +/// Input: time = "?5:00" +/// Output: 2 +/// Explanation: We can replace the ? with either a 0 or 1, producing "05:00" or "15:00". Note that +/// we cannot replace it with a 2, since the time "25:00" is invalid. In total, we have two choices. +/// +/// Example 2: +/// +/// Input: time = "0?:0?" +/// Output: 100 +/// Explanation: Each ? can be replaced by any digit from 0 to 9, so we have 100 total choices. +/// +/// Example 3: +/// +/// Input: time = "??:??" +/// Output: 1440 +/// Explanation: There are 24 possible choices for the hours, and 60 possible choices for the +/// minutes. In total, we have 24 * 60 = 1440 choices. +/// +/// +/// Constraints: +/// +/// time is a valid string of length 5 in the format "hh:mm". +/// "00" <= hh <= "23" +/// "00" <= mm <= "59" +/// Some of the digits might be replaced with '?' and need to be replaced with digits from 0 to +/// 9. +pub struct Solution {} + +// problem: https://leetcode.com/problems/number-of-valid-clock-times/ +// discuss: https://leetcode.com/problems/number-of-valid-clock-times/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn count_time(time: String) -> i32 { + let time = time.as_bytes(); + let mut ret = 1; + if time[4] == b'?' { + ret *= 10; + } + if time[3] == b'?' { + ret *= 6; + } + if time[0] == b'?' && time[1] == b'?' { + ret *= 24; + } + if time[0] != b'?' && time[1] == b'?' { + if time[0] - b'0' < 2 { + ret *= 10; + } else { + ret *= 4; + } + } + if time[0] == b'?' && time[1] != b'?' { + if time[1] - b'0' < 4 { + ret *= 3; + } else { + ret *= 2; + } + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2437() { + assert_eq!(Solution::count_time("?5:00".to_string()), 2); + assert_eq!(Solution::count_time("0?:0?".to_string()), 100); + assert_eq!(Solution::count_time("??:??".to_string()), 1440); + } +} diff --git a/src/problem/p2671_frequency_tracker.rs b/src/problem/p2671_frequency_tracker.rs new file mode 100644 index 00000000..7c789c37 --- /dev/null +++ b/src/problem/p2671_frequency_tracker.rs @@ -0,0 +1,141 @@ +#![allow(dead_code)] +// Design a data structure that keeps track of the values in it and answers some queries +// regarding their frequencies. + +// Implement the FrequencyTracker class. + +// FrequencyTracker(): Initializes the FrequencyTracker object with an empty array initially. +// void add(int number): Adds number to the data structure. +// void deleteOne(int number): Deletes one occurrence of number from the data structure. The +// data structure may not contain number, and in this case nothing is deleted. bool +// hasFrequency(int frequency): Returns true if there is a number in the data structure that +// occurs frequency number of times, otherwise, it returns false. + +// Example 1: + +// Input +// ["FrequencyTracker", "add", "add", "hasFrequency"] +// [[], [3], [3], [2]] +// Output +// [null, null, null, true] + +// Explanation +// FrequencyTracker frequencyTracker = new FrequencyTracker(); +// frequencyTracker.add(3); // The data structure now contains [3] +// frequencyTracker.add(3); // The data structure now contains [3, 3] +// frequencyTracker.hasFrequency(2); // Returns true, because 3 occurs twice + +// Example 2: + +// Input +// ["FrequencyTracker", "add", "deleteOne", "hasFrequency"] +// [[], [1], [1], [1]] +// Output +// [null, null, null, false] + +// Explanation +// FrequencyTracker frequencyTracker = new FrequencyTracker(); +// frequencyTracker.add(1); // The data structure now contains [1] +// frequencyTracker.deleteOne(1); // The data structure becomes empty [] +// frequencyTracker.hasFrequency(1); // Returns false, because the data structure is empty + +// Example 3: + +// Input +// ["FrequencyTracker", "hasFrequency", "add", "hasFrequency"] +// [[], [2], [3], [1]] +// Output +// [null, false, null, true] + +// Explanation +// FrequencyTracker frequencyTracker = new FrequencyTracker(); +// frequencyTracker.hasFrequency(2); // Returns false, because the data structure is empty +// frequencyTracker.add(3); // The data structure now contains [3] +// frequencyTracker.hasFrequency(1); // Returns true, because 3 occurs once + +// Constraints: + +// 1 <= number <= 105 +// 1 <= frequency <= 105 +// At most, 2 * 105 calls will be made to add, deleteOne, and hasFrequency in total. +use std::collections::{HashMap, HashSet}; + +struct FrequencyTracker { + /// frequency -> numbers + fre: HashMap>, + /// number -> frequency + num: HashMap, +} + +/// `&self` means the method takes an immutable reference. +/// If you need a mutable reference, change it to `&mut self` instead. +impl FrequencyTracker { + fn new() -> Self { + Self { + fre: HashMap::new(), + num: HashMap::new(), + } + } + + fn add(&mut self, number: i32) { + let frequency = self.num.get(&number).unwrap_or(&0) + 1; + self.num.insert(number, frequency); + self.fre.entry(frequency).or_default().insert(number); + if frequency != 1 { + self.fre.entry(frequency - 1).and_modify(|s| { + s.remove(&number); + }); + } + } + + fn delete_one(&mut self, number: i32) { + let frequency = self.num.get(&number).unwrap_or(&0) - 1; + if frequency == -1 { + return; + } + + self.num.insert(number, frequency); + self.fre.entry(frequency).or_default().insert(number); + self.fre.entry(frequency + 1).and_modify(|s| { + s.remove(&number); + }); + } + + fn has_frequency(&self, frequency: i32) -> bool { + if let Some(v) = self.fre.get(&frequency) { + !v.is_empty() + } else { + false + } + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2671() { + let mut ft = FrequencyTracker::new(); + ft.add(3); + ft.add(3); + assert!(ft.has_frequency(2)); + ft.delete_one(3); + assert!(!ft.has_frequency(2)); + + let mut ft = FrequencyTracker::new(); + ft.add(1); + assert!(ft.has_frequency(1)); + ft.delete_one(1); + assert!(!ft.has_frequency(1)); + + let mut ft = FrequencyTracker::new(); + assert!(!ft.has_frequency(2)); + ft.add(3); + assert!(ft.has_frequency(1)); + ft.delete_one(3); + assert!(!ft.has_frequency(1)); + } +} diff --git a/src/problem/p2708_maximum_strength_of_a_group.rs b/src/problem/p2708_maximum_strength_of_a_group.rs new file mode 100644 index 00000000..7c9e935d --- /dev/null +++ b/src/problem/p2708_maximum_strength_of_a_group.rs @@ -0,0 +1,79 @@ +// You are given a 0-indexed integer array nums representing the score of students in an exam. The +// teacher would like to form one non-empty group of students with maximal strength, where the +// strength of a group of students of indices i0, i1, i2, ... , ik is defined as nums[i0] * nums[i1] +// * nums[i2] * ... * nums[ik​]. + +// Return the maximum strength of a group the teacher can create. + +// Example 1: + +// Input: nums = [3,-1,-5,2,5,-9] +// Output: 1350 +// Explanation: One way to form a group of maximal strength is to group the students at indices +// [0,2,3,4,5]. Their strength is 3 * (-5) * 2 * 5 * (-9) = 1350, which we can show is optimal. +// Example 2: + +// Input: nums = [-4,-5,-4] +// Output: 20 +// Explanation: Group the students at indices [0, 1] . Then, we’ll have a resulting strength of 20. +// We cannot achieve greater strength. + +// Constraints: + +// 1 <= nums.length <= 13 +// -9 <= nums[i] <= 9 + +// problem: https://leetcode.com/problems/maximum-strength-of-a-group/ +// discuss: https://leetcode.com/problems/maximum-strength-of-a-group/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here +pub struct Solution {} + +impl Solution { + pub fn max_strength(nums: Vec) -> i64 { + if nums.len() == 1 { + return nums[0] as i64; + } + + let mut ret = 1_i64; + let mut zero = 0; + let mut neg_max = -9_i64; + for &n in &nums { + if n == 0 { + zero += 1; + continue; + } + ret *= n as i64; + if n < 0 { + neg_max = std::cmp::max(neg_max, n as i64); + } + } + + if zero == nums.len() as i32 { + return 0; + } + if ret > 0 { + return ret; + } + if zero == nums.len() as i32 - 1 { + return 0; + } + + ret / neg_max + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2708() { + assert_eq!(Solution::max_strength(vec![3, -1, -5, 2, 5, -9]), 1350); + assert_eq!(Solution::max_strength(vec![-4, -5, -4]), 20); + assert_eq!(Solution::max_strength(vec![0, 0, 0]), 0); + assert_eq!(Solution::max_strength(vec![0, 0, 0, -6]), 0); + } +} diff --git a/src/problem/p2710_remove_trailing_zeros_from_a_string.rs b/src/problem/p2710_remove_trailing_zeros_from_a_string.rs new file mode 100644 index 00000000..9a4ce43a --- /dev/null +++ b/src/problem/p2710_remove_trailing_zeros_from_a_string.rs @@ -0,0 +1,66 @@ +// Given a positive integer num represented as a string, return the integer num without trailing +// zeros as a string. + +// Example 1: + +// Input: num = "51230100" +// Output: "512301" +// Explanation: Integer "51230100" has 2 trailing zeros, we remove them and return integer "512301". +// Example 2: + +// Input: num = "123" +// Output: "123" +// Explanation: Integer "123" has no trailing zeros, we return integer "123". + +// Constraints: + +// 1 <= num.length <= 1000 +// num consists of only digits. +// num doesn't have any leading zeros. + +pub struct Solution {} + +// problem: https://leetcode.com/problems/remove-trailing-zeros-from-a-string/ +// discuss: https://leetcode.com/problems/remove-trailing-zeros-from-a-string/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn remove_trailing_zeros_1(num: String) -> String { + num.trim_end_matches('0').to_string() + } + + pub fn remove_trailing_zeros(num: String) -> String { + let mut n = num.as_bytes(); + let mut i = n.len() as i32 - 1; + while i >= 0 && n[i as usize] == b'0' { + i -= 1; + } + + n = &n[0..=i as usize]; + + String::from_utf8_lossy(n).to_string() + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2710() { + assert_eq!( + Solution::remove_trailing_zeros("51230100".to_string()), + "512301" + ); + assert_eq!(Solution::remove_trailing_zeros("123".to_string()), "123"); + + assert_eq!( + Solution::remove_trailing_zeros_1("51230100".to_string()), + "512301" + ); + assert_eq!(Solution::remove_trailing_zeros_1("123".to_string()), "123"); + } +} diff --git a/src/problem/p2766_relocate_marbles.rs b/src/problem/p2766_relocate_marbles.rs new file mode 100644 index 00000000..3076a1b2 --- /dev/null +++ b/src/problem/p2766_relocate_marbles.rs @@ -0,0 +1,92 @@ +// You are given a 0-indexed integer array nums representing the initial positions of some marbles. +// You are also given two 0-indexed integer arrays moveFrom and moveTo of equal length. + +// Throughout moveFrom.length steps, you will change the positions of the marbles. On the ith step, +// you will move all marbles at position moveFrom[i] to position moveTo[i]. + +// After completing all the steps, return the sorted list of occupied positions. + +// Notes: + +// We call a position occupied if there is at least one marble in that position. +// There may be multiple marbles in a single position. + +// Example 1: + +// Input: nums = [1,6,7,8], moveFrom = [1,7,2], moveTo = [2,9,5] +// Output: [5,6,8,9] +// Explanation: Initially, the marbles are at positions 1,6,7,8. +// At the i = 0th step, we move the marbles at position 1 to position 2. Then, positions 2,6,7,8 are +// occupied. At the i = 1st step, we move the marbles at position 7 to position 9. Then, positions +// 2,6,8,9 are occupied. At the i = 2nd step, we move the marbles at position 2 to position 5. Then, +// positions 5,6,8,9 are occupied. At the end, the final positions containing at least one marbles +// are [5,6,8,9]. Example 2: + +// Input: nums = [1,1,3,3], moveFrom = [1,3], moveTo = [2,2] +// Output: [2] +// Explanation: Initially, the marbles are at positions [1,1,3,3]. +// At the i = 0th step, we move all the marbles at position 1 to position 2. Then, the marbles are +// at positions [2,2,3,3]. At the i = 1st step, we move all the marbles at position 3 to position 2. +// Then, the marbles are at positions [2,2,2,2]. Since 2 is the only occupied position, we return +// [2]. + +// Constraints: + +// 1 <= nums.length <= 105 +// 1 <= moveFrom.length <= 105 +// moveFrom.length == moveTo.length +// 1 <= nums[i], moveFrom[i], moveTo[i] <= 109 +// The test cases are generated such that there is at least a marble in moveFrom[i] at the moment we +// want to apply the ith move. + +// https://leetcode.com/problems/relocate-marbles/ + +// submission codes start here + +pub struct Solution {} + +impl Solution { + pub fn relocate_marbles(nums: Vec, move_from: Vec, move_to: Vec) -> Vec { + let mut set: std::collections::HashSet = std::collections::HashSet::from_iter(nums); + for i in 0..move_from.len() { + set.remove(&move_from[i]); + set.insert(move_to[i]); + } + + let mut ret = set.into_iter().collect::>(); + ret.sort(); + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2766() { + assert_eq!( + Solution::relocate_marbles(vec![1], vec![1], vec![2]), + vec![2] + ); + assert_eq!( + Solution::relocate_marbles(vec![1, 6, 7, 8], vec![1, 7, 2], vec![2, 9, 5]), + vec![5, 6, 8, 9] + ); + assert_eq!( + Solution::relocate_marbles(vec![1, 1, 3, 3], vec![1, 3], vec![2, 2]), + vec![2] + ); + assert_eq!( + Solution::relocate_marbles( + vec![3, 4], + vec![4, 3, 1, 2, 2, 3, 2, 4, 1], + vec![3, 1, 2, 2, 3, 2, 4, 1, 1] + ), + vec![1] + ); + } +} diff --git a/src/problem/p2810_faulty_keyboard.rs b/src/problem/p2810_faulty_keyboard.rs new file mode 100644 index 00000000..a352d104 --- /dev/null +++ b/src/problem/p2810_faulty_keyboard.rs @@ -0,0 +1,77 @@ +// Your laptop keyboard is faulty, and whenever you type a character 'i' on it, it reverses the +// string that you have written. Typing other characters works as expected. + +// You are given a 0-indexed string s, and you type each character of s using your faulty keyboard. + +// Return the final string that will be present on your laptop screen. + +// Example 1: + +// Input: s = "string" +// Output: "rtsng" +// Explanation: +// After typing first character, the text on the screen is "s". +// After the second character, the text is "st". +// After the third character, the text is "str". +// Since the fourth character is an 'i', the text gets reversed and becomes "rts". +// After the fifth character, the text is "rtsn". +// After the sixth character, the text is "rtsng". +// Therefore, we return "rtsng". +// Example 2: + +// Input: s = "poiinter" +// Output: "ponter" +// Explanation: +// After the first character, the text on the screen is "p". +// After the second character, the text is "po". +// Since the third character you type is an 'i', the text gets reversed and becomes "op". +// Since the fourth character you type is an 'i', the text gets reversed and becomes "po". +// After the fifth character, the text is "pon". +// After the sixth character, the text is "pont". +// After the seventh character, the text is "ponte". +// After the eighth character, the text is "ponter". +// Therefore, we return "ponter". + +// Constraints: + +// 1 <= s.length <= 100 +// s consists of lowercase English letters. +// s[0] != 'i' + +pub struct Solution {} + +impl Solution { + pub fn final_string(s: String) -> String { + if s.len() == 1 { + return s; + } + + let mut arr = vec![]; + for b in s.as_bytes() { + if *b == b'i' { + arr.reverse(); + } else { + arr.push(*b); + } + } + + String::from_utf8(arr).unwrap() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2810() { + assert_eq!( + Solution::final_string("string".to_string()), + "rtsng".to_string() + ); + assert_eq!( + Solution::final_string("poiinter".to_string()), + "ponter".to_string() + ); + } +} diff --git a/src/problem/p2923_find_champion_i.rs b/src/problem/p2923_find_champion_i.rs new file mode 100644 index 00000000..04a64ea4 --- /dev/null +++ b/src/problem/p2923_find_champion_i.rs @@ -0,0 +1,69 @@ +// There are n teams numbered from 0 to n - 1 in a tournament. + +// Given a 0-indexed 2D boolean matrix grid of size n * n. For all i, j that 0 <= i, j <= n - 1 and +// i != j team i is stronger than team j if grid[i][j] == 1, otherwise, team j is stronger than team +// i. + +// Team a will be the champion of the tournament if there is no team b that is stronger than team a. + +// Return the team that will be the champion of the tournament. + +// Example 1: + +// Input: grid = [[0,1],[0,0]] +// Output: 0 +// Explanation: There are two teams in this tournament. +// grid[0][1] == 1 means that team 0 is stronger than team 1. So team 0 will be the champion. +// Example 2: + +// Input: grid = [[0,0,1],[1,0,1],[0,0,0]] +// Output: 1 +// Explanation: There are three teams in this tournament. +// grid[1][0] == 1 means that team 1 is stronger than team 0. +// grid[1][2] == 1 means that team 1 is stronger than team 2. +// So team 1 will be the champion. + +// Constraints: + +// n == grid.length +// n == grid[i].length +// 2 <= n <= 100 +// grid[i][j] is either 0 or 1. +// For all i grid[i][i] is 0. +// For all i, j that i != j, grid[i][j] != grid[j][i]. +// The input is generated such that if team a is stronger than team b and team b is stronger than +// team c, then team a is stronger than team c. + +pub struct Solution {} + +impl Solution { + #[allow(clippy::needless_range_loop)] + pub fn find_champion(grid: Vec>) -> i32 { + let n = grid.len(); + for i in 0..n { + let mut ret = 0; + for j in 0..n { + ret += grid[i][j]; + } + if ret == n as i32 - 1 { + return i as i32; + } + } + + -1 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2923() { + assert_eq!(Solution::find_champion(vec![vec![0, 1], vec![0, 0]]), 0); + assert_eq!( + Solution::find_champion(vec![vec![0, 0, 1], vec![1, 0, 1], vec![0, 0, 0]]), + 1 + ); + } +} diff --git a/src/problem/p2924_find_champion_ii.rs b/src/problem/p2924_find_champion_ii.rs new file mode 100644 index 00000000..e24ef743 --- /dev/null +++ b/src/problem/p2924_find_champion_ii.rs @@ -0,0 +1,87 @@ +// There are n teams numbered from 0 to n - 1 in a tournament; each team is also a node in a DAG. + +// You are given the integer n and a 0-indexed 2D integer array edges of length m representing the +// DAG, where edges[i] = [ui, vi] indicates that there is a directed edge from team ui to team vi in +// the graph. + +// A directed edge from a to b in the graph means that team a is stronger than team b and team b is +// weaker than team a. + +// Team a will be the champion of the tournament if there is no team b that is stronger than team a. + +// Return the team that will be the champion of the tournament if there is a unique champion, +// otherwise, return -1. + +// Notes + +// A cycle is a series of nodes a1, a2, ..., an, an+1 such that node a1 is the same node as node +// an+1, the nodes a1, a2, ..., an are distinct, and there is a directed edge from the node ai to +// node ai+1 for every i in the range [1, n]. A DAG is a directed graph that does not have any +// cycle. + +// Example 1: + +// Input: n = 3, edges = [[0,1],[1,2]] +// Output: 0 +// Explanation: Team 1 is weaker than team 0. Team 2 is weaker than team 1. So the champion is team +// 0. Example 2: + +// Input: n = 4, edges = [[0,2],[1,3],[1,2]] +// Output: -1 +// Explanation: Team 2 is weaker than team 0 and team 1. Team 3 is weaker than team 1. But team 1 +// and team 0 are not weaker than any other teams. So the answer is -1. + +// Constraints: + +// 1 <= n <= 100 +// m == edges.length +// 0 <= m <= n * (n - 1) / 2 +// edges[i].length == 2 +// 0 <= edge[i][j] <= n - 1 +// edges[i][0] != edges[i][1] +// The input is generated such that if team a is stronger than team b, team b is not stronger than +// team a. The input is generated such that if team a is stronger than team b and team b is stronger +// than team c, then team a is stronger than team c. + +use std::collections::HashSet; + +pub struct Solution {} + +impl Solution { + pub fn find_champion(n: i32, edges: Vec>) -> i32 { + if n == 1 { + return 0; + } + + let mut set = HashSet::new(); + for i in edges { + set.insert(i[1]); + } + let mut ret = vec![]; + for i in 0..n { + if !set.contains(&i) { + if !ret.is_empty() { + return -1; + } + ret.push(i); + } + } + + ret[0] + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_find_champion() { + assert_eq!(Solution::find_champion(3, vec![vec![0, 1], vec![1, 2]]), 0); + assert_eq!( + Solution::find_champion(4, vec![vec![0, 2], vec![1, 3], vec![1, 2]]), + -1 + ); + assert_eq!(Solution::find_champion(1, vec![vec![0, 0]]), 0); + } +} diff --git a/src/problem/p2938_separate_black_and_white_balls.rs b/src/problem/p2938_separate_black_and_white_balls.rs new file mode 100644 index 00000000..f44e25f4 --- /dev/null +++ b/src/problem/p2938_separate_black_and_white_balls.rs @@ -0,0 +1,80 @@ +/// [2938] Separate Black and White Balls +/// +/// There are n balls on a table, each ball has a color black or white. +/// You are given a 0-indexed binary string s of length n, where 1 and 0 represent black and white +/// balls, respectively. In each step, you can choose two adjacent balls and swap them. +/// Return the minimum number of steps to group all the black balls to the right and all the white +/// balls to the left. +/// Example 1: +/// +/// Input: s = "101" +/// Output: 1 +/// Explanation: We can group all the black balls to the right in the following way: +/// - Swap s[0] and s[1], s = "011". +/// +/// Initially, 1s are not grouped together, requiring at least 1 step to group them to the right. +/// Example 2: +/// +/// Input: s = "100" +/// Output: 2 +/// Explanation: We can group all the black balls to the right in the following way: +/// - Swap s[0] and s[1], s = "010". +/// - Swap s[1] and s[2], s = "001". +/// +/// It can be proven that the minimum number of steps needed is 2. +/// +/// Example 3: +/// +/// Input: s = "0111" +/// Output: 0 +/// Explanation: All the black balls are already grouped to the right. +/// +/// +/// Constraints: +/// +/// 1 <= n == s.length <= 10^5 +/// s[i] is either '0' or '1'. +pub struct Solution {} + +// problem: https://leetcode.com/problems/separate-black-and-white-balls/ +// discuss: https://leetcode.com/problems/separate-black-and-white-balls/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here + +impl Solution { + pub fn minimum_steps(s: String) -> i64 { + if s.len() == 1 { + return 0; + } + + let mut ret = 0; + let mut count = 0; + for b in s.as_bytes().iter().rev() { + if b == &b'0' { + count += 1; + } else { + ret += count; + } + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2938() { + assert!(Solution::minimum_steps("101".to_string()) == 1); + assert!(Solution::minimum_steps("100".to_string()) == 2); + assert!(Solution::minimum_steps("0111".to_string()) == 0); + assert!(Solution::minimum_steps("1111".to_string()) == 0); + assert!(Solution::minimum_steps("0000".to_string()) == 0); + assert!(Solution::minimum_steps("0001".to_string()) == 0); + assert!(Solution::minimum_steps("1".to_string()) == 0); + } +} diff --git a/src/problem/p2956_find_common_elements_between_two_arrays.rs b/src/problem/p2956_find_common_elements_between_two_arrays.rs new file mode 100644 index 00000000..7c79c15f --- /dev/null +++ b/src/problem/p2956_find_common_elements_between_two_arrays.rs @@ -0,0 +1,88 @@ +// You are given two integer arrays nums1 and nums2 of sizes n and m, respectively. Calculate the +// following values: + +// answer1 : the number of indices i such that nums1[i] exists in nums2. +// answer2 : the number of indices i such that nums2[i] exists in nums1. +// Return [answer1,answer2]. + +// Example 1: + +// Input: nums1 = [2,3,2], nums2 = [1,2] + +// Output: [2,1] + +// Explanation: + +// Example 2: + +// Input: nums1 = [4,3,2,3,1], nums2 = [2,2,5,2,3,6] + +// Output: [3,4] + +// Explanation: + +// The elements at indices 1, 2, and 3 in nums1 exist in nums2 as well. So answer1 is 3. + +// The elements at indices 0, 1, 3, and 4 in nums2 exist in nums1. So answer2 is 4. + +// Example 3: + +// Input: nums1 = [3,4,2,3], nums2 = [1,5] + +// Output: [0,0] + +// Explanation: + +// No numbers are common between nums1 and nums2, so answer is [0,0]. + +// Constraints: + +// n == nums1.length +// m == nums2.length +// 1 <= n, m <= 100 +// 1 <= nums1[i], nums2[i] <= 100 + +pub struct Solution {} + +impl Solution { + pub fn find_intersection_values(nums1: Vec, nums2: Vec) -> Vec { + let set1 = nums1.iter().collect::>(); + let set2 = nums2.iter().collect::>(); + let mut c1 = 0; + for n in &nums1 { + if set2.contains(&n) { + c1 += 1 + } + } + + let mut c2 = 0; + for n in &nums2 { + if set1.contains(&n) { + c2 += 1 + } + } + + vec![c1, c2] + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2956() { + assert_eq!( + Solution::find_intersection_values(vec![2, 3, 2], vec![1, 2]), + vec![2, 1] + ); + assert_eq!( + Solution::find_intersection_values(vec![4, 3, 2, 3, 1], vec![2, 2, 5, 2, 3, 6]), + vec![3, 4] + ); + assert_eq!( + Solution::find_intersection_values(vec![3, 4, 2, 3], vec![1, 5]), + vec![0, 0] + ); + } +} diff --git a/src/problem/p2974_minimum_number_game.rs b/src/problem/p2974_minimum_number_game.rs new file mode 100644 index 00000000..c3c34c83 --- /dev/null +++ b/src/problem/p2974_minimum_number_game.rs @@ -0,0 +1,58 @@ +// You are given a 0-indexed integer array nums of even length and there is also an empty array arr. +// Alice and Bob decided to play a game where in every round Alice and Bob will do one move. The +// rules of the game are as follows: + +// Every round, first Alice will remove the minimum element from nums, and then Bob does the same. +// Now, first Bob will append the removed element in the array arr, and then Alice does the same. +// The game continues until nums becomes empty. +// Return the resulting array arr. + +// Example 1: + +// Input: nums = [5,4,2,3] +// Output: [3,2,5,4] +// Explanation: In round one, first Alice removes 2 and then Bob removes 3. Then in arr firstly Bob +// appends 3 and then Alice appends 2. So arr = [3,2]. At the beginning of round two, nums = [5,4]. +// Now, first Alice removes 4 and then Bob removes 5. Then both append in arr which becomes +// [3,2,5,4]. Example 2: + +// Input: nums = [2,5] +// Output: [5,2] +// Explanation: In round one, first Alice removes 2 and then Bob removes 5. Then in arr firstly Bob +// appends and then Alice appends. So arr = [5,2]. + +// Constraints: + +// 2 <= nums.length <= 100 +// 1 <= nums[i] <= 100 +// nums.length % 2 == 0 + +use std::vec; + +pub struct Solution {} + +impl Solution { + pub fn number_game(nums: Vec) -> Vec { + let mut ret = vec![0; nums.len()]; + let mut nums = nums; + nums.sort(); + + for i in (1..nums.len()).step_by(2) { + ret[i] = nums[i - 1]; + ret[i - 1] = nums[i]; + } + + ret + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_2974() { + assert_eq!(Solution::number_game(vec![5, 4, 2, 3]), vec![3, 2, 5, 4]); + assert_eq!(Solution::number_game(vec![2, 5]), vec![5, 2]); + } +} diff --git a/src/problem/p3033_modify_the_matrix.rs b/src/problem/p3033_modify_the_matrix.rs new file mode 100644 index 00000000..692de7c4 --- /dev/null +++ b/src/problem/p3033_modify_the_matrix.rs @@ -0,0 +1,77 @@ +// Given a 0-indexed m x n integer matrix matrix, create a new 0-indexed matrix called answer. Make +// answer equal to matrix, then replace each element with the value -1 with the maximum element in +// its respective column. + +// Return the matrix answer. + +// Example 1: + +// Input: matrix = [[1,2,-1],[4,-1,6],[7,8,9]] +// Output: [[1,2,9],[4,8,6],[7,8,9]] +// Explanation: The diagram above shows the elements that are changed (in blue). +// - We replace the value in the cell [1][1] with the maximum value in the column 1, that is 8. +// - We replace the value in the cell [0][2] with the maximum value in the column 2, that is 9. +// Example 2: + +// Input: matrix = [[3,-1],[5,2]] +// Output: [[3,2],[5,2]] +// Explanation: The diagram above shows the elements that are changed (in blue). + +// Constraints: + +// m == matrix.length +// n == matrix[i].length +// 2 <= m, n <= 50 +// -1 <= matrix[i][j] <= 100 +// The input is generated such that each column contains at least one non-negative integer. + +// https://leetcode.com/problems/modify-the-matrix/ +// https://leetcode.com/problems/modify-the-matrix/discuss/?currentPage=1&orderBy=most_votes&query= + +// submission codes start here +pub struct Solution {} + +#[allow(clippy::needless_range_loop)] +impl Solution { + pub fn modified_matrix(matrix: Vec>) -> Vec> { + let m = matrix.len(); + let n = matrix[0].len(); + let mut ret = vec![vec![0; n]; m]; + let mut max = vec![0; n]; + for i in 0..m { + for j in 0..n { + ret[i][j] = matrix[i][j]; + max[j] = std::cmp::max(max[j], matrix[i][j]); + } + } + + for i in 0..m { + for j in 0..n { + if ret[i][j] == -1 { + ret[i][j] = max[j]; + } + } + } + + ret + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_3033() { + assert_eq!( + Solution::modified_matrix(vec![vec![1, 2, -1], vec![4, -1, 6], vec![7, 8, 9]]), + vec![vec![1, 2, 9], vec![4, 8, 6], vec![7, 8, 9]] + ); + assert_eq!( + Solution::modified_matrix(vec![vec![3, -1], vec![5, 2]]), + vec![vec![3, 2], vec![5, 2]] + ); + } +} diff --git a/src/problem/p3142_check_if_grid_satisfies_conditions.rs b/src/problem/p3142_check_if_grid_satisfies_conditions.rs new file mode 100644 index 00000000..b8471c40 --- /dev/null +++ b/src/problem/p3142_check_if_grid_satisfies_conditions.rs @@ -0,0 +1,90 @@ +// You are given a 2D matrix grid of size m x n. You need to check if each cell grid[i][j] is: + +// Equal to the cell below it, i.e. grid[i][j] == grid[i + 1][j] (if it exists). +// Different from the cell to its right, i.e. grid[i][j] != grid[i][j + 1] (if it exists). +// Return true if all the cells satisfy these conditions, otherwise, return false. + +// Example 1: + +// Input: grid = [[1,0,2],[1,0,2]] + +// Output: true + +// Explanation: + +// All the cells in the grid satisfy the conditions. + +// Example 2: + +// Input: grid = [[1,1,1],[0,0,0]] + +// Output: false + +// Explanation: + +// All cells in the first row are equal. + +// Example 3: + +// Input: grid = [[1],[2],[3]] + +// Output: false + +// Explanation: + +// Cells in the first column have different values. + +// Constraints: + +// 1 <= n, m <= 10 +// 0 <= grid[i][j] <= 9 + +// https://leetcode.com/problems/check-if-grid-satisfies-a-condition/ + +// problem: https://leetcode.com/problems/check-if-grid-satisfies-a-condition/ + +pub struct Solution {} + +// submission codes start here + +impl Solution { + pub fn satisfies_conditions(grid: Vec>) -> bool { + let (m, n) = (grid.len(), grid[0].len()); + for i in 0..m { + for j in 0..n { + if i + 1 < m && grid[i][j] != grid[i + 1][j] { + return false; + } + if j + 1 < n && grid[i][j] == grid[i][j + 1] { + return false; + } + } + } + + true + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_3142() { + assert!(Solution::satisfies_conditions(vec![ + vec![1, 0, 2], + vec![1, 0, 2] + ])); + assert!(!Solution::satisfies_conditions(vec![ + vec![1, 1, 1], + vec![0, 0, 0] + ])); + assert!(!Solution::satisfies_conditions(vec![ + vec![1], + vec![2], + vec![3] + ])); + } +} diff --git a/src/problem/p3151_special_array_i.rs b/src/problem/p3151_special_array_i.rs new file mode 100644 index 00000000..c3e001cc --- /dev/null +++ b/src/problem/p3151_special_array_i.rs @@ -0,0 +1,74 @@ +// An array is considered special if every pair of its adjacent elements contains two numbers with +// different parity. + +// You are given an array of integers nums. Return true if nums is a special array, otherwise, +// return false. + +// Example 1: + +// Input: nums = [1] + +// Output: true + +// Explanation: + +// There is only one element. So the answer is true. + +// Example 2: + +// Input: nums = [2,1,4] + +// Output: true + +// Explanation: + +// There is only two pairs: (2,1) and (1,4), and both of them contain numbers with different parity. +// So the answer is true. + +// Example 3: + +// Input: nums = [4,3,1,6] + +// Output: false + +// Explanation: + +// nums[1] and nums[2] are both odd. So the answer is false. + +// Constraints: + +// 1 <= nums.length <= 100 +// 1 <= nums[i] <= 100 + +// https://leetcode.com/problems/special-array-with-x-elements-greater-than-x +// https://leetcode.com/problems/special-array-with-x-elements-greater-than-x/discuss/?currentPage=1&orderBy=most_votes&query= + +pub struct Solution {} + +impl Solution { + pub fn is_array_special(nums: Vec) -> bool { + if nums.len() == 1 { + return true; + } + + for i in 1..nums.len() { + if nums[i] % 2 == nums[i - 1] % 2 { + return false; + } + } + + true + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_3151() { + assert!(Solution::is_array_special(vec![1])); + assert!(Solution::is_array_special(vec![2, 1, 4])); + assert!(!Solution::is_array_special(vec![4, 3, 1, 6])); + } +} diff --git a/src/problem/p3152_special_array_ii.rs b/src/problem/p3152_special_array_ii.rs new file mode 100644 index 00000000..227f5cd7 --- /dev/null +++ b/src/problem/p3152_special_array_ii.rs @@ -0,0 +1,83 @@ +// // An array is considered special if every pair of its adjacent elements contains two numbers +// with different parity. + +// You are given an array of integer nums and a 2D integer matrix queries, where for queries[i] = +// [fromi, toi] your task is to check that subarray +// nums[fromi..toi] is special or not. + +// Return an array of booleans answer such that answer[i] is true if nums[fromi..toi] is special. + +// Example 1: + +// Input: nums = [3,4,1,2,6], queries = [[0,4]] + +// Output: [false] + +// Explanation: + +// The subarray is [3,4,1,2,6]. 2 and 6 are both even. + +// Example 2: + +// Input: nums = [4,3,1,6], queries = [[0,2],[2,3]] + +// Output: [false,true] + +// Explanation: + +// The subarray is [4,3,1]. 3 and 1 are both odd. So the answer to this query is false. +// The subarray is [1,6]. There is only one pair: (1,6) and it contains numbers with different +// parity. So the answer to this query is true. + +// Constraints: + +// 1 <= nums.length <= 105 +// 1 <= nums[i] <= 105 +// 1 <= queries.length <= 105 +// queries[i].length == 2 +// 0 <= queries[i][0] <= queries[i][1] <= nums.length - 1 + +// problem: https://leetcode.com/problems/special-array-ii/ +// discuss: https://leetcode.com/problems/special-array-ii/discuss/?currentPage=1&orderBy=most_votes&query= + +pub struct Solution {} + +impl Solution { + pub fn is_array_special(nums: Vec, queries: Vec>) -> Vec { + let mut dic = vec![0]; + for i in 1..nums.len() { + if nums[i] % 2 != nums[i - 1] % 2 { + dic.push(0); + } else { + dic.push(1); + } + } + for i in 1..dic.len() { + dic[i] += dic[i - 1]; + } + + let mut ret = vec![]; + for q in queries { + ret.push(dic[q[1] as usize] == dic[q[0] as usize]); + } + + ret + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_3152() { + assert_eq!( + Solution::is_array_special(vec![3, 4, 1, 2, 6], vec![vec![0, 4]]), + vec![false] + ); + assert_eq!( + Solution::is_array_special(vec![4, 3, 1, 6], vec![vec![0, 2], vec![2, 3]]), + vec![false, true] + ); + } +} diff --git a/src/problem/p3153_sum_of_digit_differences_of_all_pairs.rs b/src/problem/p3153_sum_of_digit_differences_of_all_pairs.rs new file mode 100644 index 00000000..d266e227 --- /dev/null +++ b/src/problem/p3153_sum_of_digit_differences_of_all_pairs.rs @@ -0,0 +1,72 @@ +// You are given an array nums consisting of positive integers where all integers have the same +// number of digits. + +// The digit difference between two integers is the count of different digits that are in the same +// position in the two integers. + +// Return the sum of the digit differences between all pairs of integers in nums. + +// Example 1: + +// Input: nums = [13,23,12] + +// Output: 4 + +// Explanation: +// We have the following: +// - The digit difference between 13 and 23 is 1. +// - The digit difference between 13 and 12 is 1. +// - The digit difference between 23 and 12 is 2. +// So the total sum of digit differences between all pairs of integers is 1 + 1 + 2 = 4. + +// Example 2: + +// Input: nums = [10,10,10,10] + +// Output: 0 + +// Explanation: +// All the integers in the array are the same. So the total sum of digit differences between all +// pairs of integers will be 0. + +// Constraints: + +// 2 <= nums.length <= 105 +// 1 <= nums[i] < 109 +// All integers in nums have the same number of digits. + +// problem: https://leetcode.com/problems/sum-of-digit-differences-between-two-pairs/ +// solution: https://leetcode.com/problems/sum-of-digit-differences-between-two-pairs/discuss/?currentPage=1&orderBy=most_votes&query= + +pub struct Solution {} + +impl Solution { + pub fn sum_digit_differences(nums: Vec) -> i64 { + let mut ret = 0; + let m = nums[0].to_string().len(); + let mut count = vec![vec![0; 10]; m]; + for (i, &n) in nums.iter().enumerate() { + let mut k = n; + for c in count.iter_mut() { + let d = (k % 10) as usize; + ret += i - c[d]; + + c[d] += 1; + k /= 10; + } + } + + ret as i64 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_3153() { + assert_eq!(4, Solution::sum_digit_differences(vec![13, 23, 12])); + assert_eq!(0, Solution::sum_digit_differences(vec![10, 10, 10, 10])); + } +} diff --git a/src/problem/p3174_clear_digits.rs b/src/problem/p3174_clear_digits.rs new file mode 100644 index 00000000..abf3e6f6 --- /dev/null +++ b/src/problem/p3174_clear_digits.rs @@ -0,0 +1,74 @@ +// You are given a string s. + +// Your task is to remove all digits by doing this operation repeatedly: + +// Delete the first digit and the closest non-digit character to its left. +// Return the resulting string after removing all digits. + +// Example 1: + +// Input: s = "abc" + +// Output: "abc" + +// Explanation: + +// There is no digit in the string. + +// Example 2: + +// Input: s = "cb34" + +// Output: "" + +// Explanation: + +// First, we apply the operation on s[2], and s becomes "c4". + +// Then we apply the operation on s[1], and s becomes "". + +// Constraints: + +// 1 <= s.length <= 100 +// s consists only of lowercase English letters and digits. +// The input is generated such that it is possible to delete all digits. + +// problem: https://leetcode.com/problems/clear-digits/ + +// submission codes start here +pub struct Solution {} + +impl Solution { + pub fn clear_digits(s: String) -> String { + if s.len() == 1 { + return s; + } + + let mut ret = Vec::new(); + for c in s.chars() { + if c.is_alphabetic() { + ret.push(c); + } else if ret.last().unwrap_or(&'a').is_alphabetic() { + ret.pop(); + } else { + ret.push(c); + } + } + + ret.iter().collect() + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_3174() { + assert_eq!(Solution::clear_digits("abc".to_string()), "abc".to_string()); + assert_eq!(Solution::clear_digits("cb34".to_string()), "".to_string()); + assert_eq!(Solution::clear_digits("1".to_string()), "1".to_string()); + } +} diff --git a/src/problem/p3226_number_of_bit_changes_to_make_two_integers_equal.rs b/src/problem/p3226_number_of_bit_changes_to_make_two_integers_equal.rs new file mode 100644 index 00000000..4063681f --- /dev/null +++ b/src/problem/p3226_number_of_bit_changes_to_make_two_integers_equal.rs @@ -0,0 +1,63 @@ +// You are given two positive integers n and k. + +// You can choose any bit in the binary representation of n that is equal to 1 and change it to 0. + +// Return the number of changes needed to make n equal to k. If it is impossible, return -1. + +// Example 1: + +// Input: n = 13, k = 4 + +// Output: 2 + +// Explanation: +// Initially, the binary representations of n and k are n = (1101)2 and k = (0100)2. +// We can change the first and fourth bits of n. The resulting integer is n = (0100)2 = k. + +// Example 2: + +// Input: n = 21, k = 21 + +// Output: 0 + +// Explanation: +// n and k are already equal, so no changes are needed. + +// Example 3: + +// Input: n = 14, k = 13 + +// Output: -1 + +// Explanation: +// It is not possible to make n equal to k. + +// Constraints: + +// 1 <= n, k <= 106 + +// https://leetcode.com/problems/number-of-bit-changes-to-make-two-integers-equal/ +// https://leetcode.com/problems/number-of-bit-changes-to-make-two-integers-equal/discuss/?currentPage=1&orderBy=most_votes&query= +pub struct Solution {} + +impl Solution { + pub fn min_changes(n: i32, k: i32) -> i32 { + if n & k != k { + return -1; + } + + (n ^ k).count_ones() as i32 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_3226() { + assert_eq!(Solution::min_changes(13, 4), 2); + assert_eq!(Solution::min_changes(21, 21), 0); + assert_eq!(Solution::min_changes(14, 13), -1); + } +} diff --git a/src/problem/p3259_maximum_energy_boost_from_two_drinks.rs b/src/problem/p3259_maximum_energy_boost_from_two_drinks.rs new file mode 100644 index 00000000..066d53d5 --- /dev/null +++ b/src/problem/p3259_maximum_energy_boost_from_two_drinks.rs @@ -0,0 +1,75 @@ +// You are given two integer arrays energyDrinkA and energyDrinkB of the same length n by a +// futuristic sports scientist. These arrays represent the energy boosts per hour provided by two +// different energy drinks, A and B, respectively. + +// You want to maximize your total energy boost by drinking one energy drink per hour. However, if +// you want to switch from consuming one energy drink to the other, you need to wait for one hour to +// cleanse your system (meaning you won't get any energy boost in that hour). + +// Return the maximum total energy boost you can gain in the next n hours. + +// Note that you can start consuming either of the two energy drinks. + +// Example 1: + +// Input: energyDrinkA = [1,3,1], energyDrinkB = [3,1,1] + +// Output: 5 + +// Explanation: + +// To gain an energy boost of 5, drink only the energy drink A (or only B). + +// Example 2: + +// Input: energyDrinkA = [4,1,1], energyDrinkB = [1,1,3] + +// Output: 7 + +// Explanation: + +// To gain an energy boost of 7: + +// Drink the energy drink A for the first hour. +// Switch to the energy drink B and we lose the energy boost of the second hour. +// Gain the energy boost of the drink B in the third hour. + +// Constraints: + +// n == energyDrinkA.length == energyDrinkB.length +// 3 <= n <= 105 +// 1 <= energyDrinkA[i], energyDrinkB[i] <= 105 + +// https://leetcode.com/problems/maximum-energy-boost-from-two-drinks/ + +// solution: +pub struct Solution {} + +impl Solution { + pub fn max_energy_boost(energy_drink_a: Vec, energy_drink_b: Vec) -> i64 { + let n = energy_drink_a.len(); + let mut max_a = vec![0; n]; + let mut max_b = vec![0; n]; + max_a[0] = energy_drink_a[0] as i64; + max_a[1] = energy_drink_a[0] as i64 + energy_drink_a[1] as i64; + max_b[0] = energy_drink_b[0] as i64; + max_b[1] = energy_drink_b[0] as i64 + energy_drink_b[1] as i64; + for i in 2..n { + max_a[i] = std::cmp::max(max_b[i - 2], max_a[i - 1]) + energy_drink_a[i] as i64; + max_b[i] = std::cmp::max(max_a[i - 2], max_b[i - 1]) + energy_drink_b[i] as i64; + } + + std::cmp::max(max_a[n - 1], max_b[n - 1]) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_3259() { + assert_eq!(Solution::max_energy_boost(vec![1, 3, 1], vec![3, 1, 1]), 5); + assert_eq!(Solution::max_energy_boost(vec![4, 1, 1], vec![1, 1, 3]), 7); + } +} diff --git a/src/solution/mod.rs b/src/solution/mod.rs index bc982de9..d05f6ceb 100644 --- a/src/solution/mod.rs +++ b/src/solution/mod.rs @@ -235,3 +235,4 @@ mod s0704_binary_search; mod s0969_pancake_sorting; mod s1018_binary_prefix_divisible_by_5; mod s1046_last_stone_weight; +mod s0001_two_sum; diff --git a/src/solution/s0001_two_sum.rs b/src/solution/s0001_two_sum.rs deleted file mode 100644 index 4a44a732..00000000 --- a/src/solution/s0001_two_sum.rs +++ /dev/null @@ -1,53 +0,0 @@ -/** - * [1] Two Sum - * - * Given an array of integers, return indices of the two numbers such that they - * add up to a specific target. - * - * You may assume that each input would have exactly one solution, and you may - * not use the same element twice. - * - * Example: - * - * - * Given nums = [2, 7, 11, 15], target = 9, - * - * Because nums[0] + nums[1] = 2 + 7 = 9, - * return [0, 1]. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/two-sum/ -// discuss: https://leetcode.com/problems/two-sum/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::collections::HashMap; -impl Solution { - pub fn two_sum(nums: Vec, target: i32) -> Vec { - let mut map = HashMap::with_capacity(nums.len()); - for (index, num) in nums.iter().enumerate() { - match map.get(&(target - num)) { - None => { - map.insert(num, index); - } - Some(sub_index) => return vec![*sub_index as i32, index as i32], - } - } - vec![] - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_1() { - assert_eq!(vec![0, 1], Solution::two_sum(vec![2, 7, 11, 15], 9)); - assert_eq!(vec![1, 2], Solution::two_sum(vec![3, 2, 4], 6)); - } -} diff --git a/src/solution/s0002_add_two_numbers.rs b/src/solution/s0002_add_two_numbers.rs deleted file mode 100644 index d8bfc2d8..00000000 --- a/src/solution/s0002_add_two_numbers.rs +++ /dev/null @@ -1,98 +0,0 @@ -/** - * [2] Add Two Numbers - * - * You are given two non-empty linked lists representing two non-negative - * integers. The digits are stored in reverse order and each of their nodes - * contain a single digit. Add the two numbers and return it as a linked list. - * - * You may assume the two numbers do not contain any leading zero, except the - * number 0 itself. - * - * Example: - * - * - * Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) - * Output: 7 -> 0 -> 8 - * Explanation: 342 + 465 = 807. - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; - -// problem: https://leetcode.com/problems/add-two-numbers/ -// discuss: https://leetcode.com/problems/add-two-numbers/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn add_two_numbers( - l1: Option>, - l2: Option>, - ) -> Option> { - let (mut l1, mut l2) = (l1, l2); - let mut dummy_head = Some(Box::new(ListNode::new(0))); - let mut tail = &mut dummy_head; - let (mut l1_end, mut l2_end, mut overflow) = (false, false, false); - loop { - let lhs = match l1 { - Some(node) => { - l1 = node.next; - node.val - } - None => { - l1_end = true; - 0 - } - }; - let rhs = match l2 { - Some(node) => { - l2 = node.next; - node.val - } - None => { - l2_end = true; - 0 - } - }; - // if l1, l2 end and there is not overflow from previous operation, return the result - if l1_end && l2_end && !overflow { - break dummy_head.unwrap().next; - } - let sum = lhs + rhs + if overflow { 1 } else { 0 }; - let sum = if sum >= 10 { - overflow = true; - sum - 10 - } else { - overflow = false; - sum - }; - tail.as_mut().unwrap().next = Some(Box::new(ListNode::new(sum))); - tail = &mut tail.as_mut().unwrap().next - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_2() { - assert_eq!( - Solution::add_two_numbers(to_list(vec![2, 4, 3]), to_list(vec![5, 6, 4])), - to_list(vec![7, 0, 8]) - ); - - assert_eq!( - Solution::add_two_numbers(to_list(vec![9, 9, 9, 9]), to_list(vec![9, 9, 9, 9, 9, 9])), - to_list(vec![8, 9, 9, 9, 0, 0, 1]) - ); - - assert_eq!( - Solution::add_two_numbers(to_list(vec![0]), to_list(vec![0])), - to_list(vec![0]) - ) - } -} diff --git a/src/solution/s0003_longest_substring_without_repeating_characters.rs b/src/solution/s0003_longest_substring_without_repeating_characters.rs deleted file mode 100644 index 0ad6903d..00000000 --- a/src/solution/s0003_longest_substring_without_repeating_characters.rs +++ /dev/null @@ -1,61 +0,0 @@ -/** - * [3] Longest Substring Without Repeating Characters - * - * Given a string, find the length of the longest substring without repeating characters. - * - * Example: - * - * Input: "abcabcbb" - * Output: 3 - * Explanation: The answer is "abc", with the length of 3. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/longest-substring-without-repeating-characters/ -// discuss: https://leetcode.com/problems/longest-substring-without-repeating-characters/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn length_of_longest_substring(s: String) -> i32 { - let seq: Vec = s.chars().collect(); - let len = seq.len(); - let (mut start, mut end, mut max) = (0, 0, 0); - - while end < len { - for idx in start..end { - if seq[end] == seq[idx] { - start = idx + 1; - break; - } - } - let curr = end - start + 1; - if curr > max { - max = curr - } - end += 1 - } - max as i32 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_3() { - assert_eq!( - Solution::length_of_longest_substring("abcabcbb".to_string()), - 3 - ); - assert_eq!(Solution::length_of_longest_substring("bbbb".to_string()), 1); - assert_eq!( - Solution::length_of_longest_substring("pwwkew".to_string()), - 3 - ); - } -} diff --git a/src/solution/s0004_median_of_two_sorted_arrays.rs b/src/solution/s0004_median_of_two_sorted_arrays.rs deleted file mode 100644 index e3c2d014..00000000 --- a/src/solution/s0004_median_of_two_sorted_arrays.rs +++ /dev/null @@ -1,62 +0,0 @@ -/** - * [4] Median of Two Sorted Arrays - * - * There are two sorted arrays nums1 and nums2 of size m and n respectively. - * - * Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)). - * - * You may assume nums1 and nums2 cannot be both empty. - * - * Example 1: - * - * - * nums1 = [1, 3] - * nums2 = [2] - * - * The median is 2.0 - * - * - * Example 2: - * - * - * nums1 = [1, 2] - * nums2 = [3, 4] - * - * The median is (2 + 3)/2 = 2.5 - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/median-of-two-sorted-arrays/ -// discuss: https://leetcode.com/problems/median-of-two-sorted-arrays/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// TODO: nth slice -impl Solution { - pub fn find_median_sorted_arrays(nums1: Vec, nums2: Vec) -> f64 { - 1.0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - // TODO: implementation - #[test] - #[ignore] - fn test_4() { - assert_eq!( - Solution::find_median_sorted_arrays(vec![1, 3], vec![2]), - 2.0 - ); - assert_eq!( - Solution::find_median_sorted_arrays(vec![1, 2], vec![3, 4]), - 2.5 - ); - } -} diff --git a/src/solution/s0005_longest_palindromic_substring.rs b/src/solution/s0005_longest_palindromic_substring.rs deleted file mode 100644 index 675e1951..00000000 --- a/src/solution/s0005_longest_palindromic_substring.rs +++ /dev/null @@ -1,82 +0,0 @@ -/** - * [5] Longest Palindromic Substring - * - * Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000. - * - * Example 1: - * - * - * Input: "babad" - * Output: "bab" - * Note: "aba" is also a valid answer. - * - * - * Example 2: - * - * - * Input: "cbbd" - * Output: "bb" - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/longest-palindromic-substring/ -// discuss: https://leetcode.com/problems/longest-palindromic-substring/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn longest_palindrome(s: String) -> String { - let seq: Vec = s.chars().collect(); - let len = seq.len(); - if len < 1 { - return s; - } - let (mut idx, mut curr_len, mut curr_start, mut curr_end) = (0, 0, 0, 0); - while idx < len { - let (mut i, mut j) = (idx, idx); - let ch = seq[idx]; - // handle same char - while i > 0 && seq[i - 1] == ch { - i -= 1 - } - while j < len - 1 && seq[j + 1] == ch { - j += 1 - } - idx = j + 1; - while i > 0 && j < len - 1 && seq[i - 1] == seq[j + 1] { - i -= 1; - j += 1; - } - let max_len = j - i + 1; - if max_len > curr_len { - curr_len = max_len; - curr_start = i; - curr_end = j; - } - if max_len >= len - 1 { - break; - } - } - - s[curr_start..curr_end + 1].to_owned() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_5() { - assert_eq!(Solution::longest_palindrome("aaaaa".to_owned()), "aaaaa"); - assert_eq!(Solution::longest_palindrome("babab".to_owned()), "babab"); - assert_eq!(Solution::longest_palindrome("babcd".to_owned()), "bab"); - assert_eq!(Solution::longest_palindrome("cbbd".to_owned()), "bb"); - assert_eq!(Solution::longest_palindrome("bb".to_owned()), "bb"); - assert_eq!(Solution::longest_palindrome("".to_owned()), ""); - } -} diff --git a/src/solution/s0006_zigzag_conversion.rs b/src/solution/s0006_zigzag_conversion.rs deleted file mode 100644 index 51ed13a7..00000000 --- a/src/solution/s0006_zigzag_conversion.rs +++ /dev/null @@ -1,95 +0,0 @@ -/** - * [6] ZigZag Conversion - * - * The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility) - * - * - * P A H N - * A P L S I I G - * Y I R - * - * - * And then read line by line: "PAHNAPLSIIGYIR" - * - * Write the code that will take a string and make this conversion given a number of rows: - * - * - * string convert(string s, int numRows); - * - * Example 1: - * - * - * Input: s = "PAYPALISHIRING", numRows = 3 - * Output: "PAHNAPLSIIGYIR" - * - * - * Example 2: - * - * - * Input: s = "PAYPALISHIRING", numRows = 4 - * Output: "PINALSIGYAHRPI" - * Explanation: - * - * P I N - * A L S I G - * Y A H R - * P I - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/zigzag-conversion/ -// discuss: https://leetcode.com/problems/zigzag-conversion/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn convert(s: String, num_rows: i32) -> String { - if num_rows < 2 { - return s; - } - let seq: Vec = s.chars().collect(); - let len = seq.len(); - let unit: usize = (2 * num_rows - 2) as usize; - let mut sb = String::with_capacity(s.capacity()); - for row in 0..num_rows { - let mut i = row as usize; - let step1 = 2 * (num_rows - 1 - row) as usize; - let step2 = (unit - step1) as usize; - let mut trigger = false; - while i < len { - sb.push(seq[i]); - if step1 == 0 { - i += step2 - } else if step2 == 0 { - i += step1 - } else { - i += if trigger { step2 } else { step1 }; - trigger = !trigger; - } - } - } - sb - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_6() { - assert_eq!( - Solution::convert("PAYPALISHIRING".to_string(), 4), - "PINALSIGYAHRPI" - ); - assert_eq!( - Solution::convert("PAYPALISHIRING".to_string(), 3), - "PAHNAPLSIIGYIR" - ); - assert_eq!(Solution::convert("A".to_string(), 1), "A"); - assert_eq!(Solution::convert("AY".to_string(), 2), "AY"); - } -} diff --git a/src/solution/s0007_reverse_integer.rs b/src/solution/s0007_reverse_integer.rs deleted file mode 100644 index ad89eebd..00000000 --- a/src/solution/s0007_reverse_integer.rs +++ /dev/null @@ -1,73 +0,0 @@ -/** - * [7] Reverse Integer - * - * Given a 32-bit signed integer, reverse digits of an integer. - * - * Example 1: - * - * - * Input: 123 - * Output: 321 - * - * - * Example 2: - * - * - * Input: -123 - * Output: -321 - * - * - * Example 3: - * - * - * Input: 120 - * Output: 21 - * - * - * Note:
- * Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [-2^31, 2^31 - 1]. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/reverse-integer/ -// discuss: https://leetcode.com/problems/reverse-integer/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here -impl Solution { - pub fn reverse(x: i32) -> i32 { - let mut input: i64 = x as i64; - let mut result: i64 = 0; - let mut digit: i64 = 0; - let base: i64 = 2; - let upper_bound: i64 = base.pow(31) - 1; - let lower_bound: i64 = -base.pow(31); - while input != 0 { - digit = input % 10; - result = result * 10 + digit; - input = input / 10; - } - if result > upper_bound || result < lower_bound { - return 0; - } - result as i32 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_7() { - assert_eq!(Solution::reverse(123), 321); - assert_eq!(Solution::reverse(-123), -321); - assert_eq!(Solution::reverse(0), 0); - assert_eq!(Solution::reverse(-123000), -321); - let base: i64 = 2; - assert_eq!(Solution::reverse((base.pow(31) - 1) as i32), 0); - assert_eq!(Solution::reverse((-base.pow(31)) as i32), 0); - } -} diff --git a/src/solution/s0008_string_to_integer_atoi.rs b/src/solution/s0008_string_to_integer_atoi.rs deleted file mode 100644 index 9c86e17b..00000000 --- a/src/solution/s0008_string_to_integer_atoi.rs +++ /dev/null @@ -1,131 +0,0 @@ -/** - * [8] String to Integer (atoi) - * - * Implement atoi which converts a string to an integer. - * - * The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value. - * - * The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function. - * - * If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed. - * - * If no valid conversion could be performed, a zero value is returned. - * - * Note: - * - *
    - *
  • Only the space character ' ' is considered as whitespace character.
  • - *
  • Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [-2^31, 2^31 - 1]. If the numerical value is out of the range of representable values, INT_MAX (2^31 - 1) or INT_MIN (-2^31) is returned.
  • - *
- * - * Example 1: - * - * - * Input: "42" - * Output: 42 - * - * - * Example 2: - * - * - * Input: " -42" - * Output: -42 - * Explanation: The first non-whitespace character is '-', which is the minus sign. - * Then take as many numerical digits as possible, which gets 42. - * - * - * Example 3: - * - * - * Input: "4193 with words" - * Output: 4193 - * Explanation: Conversion stops at digit '3' as the next character is not a numerical digit. - * - * - * Example 4: - * - * - * Input: "words and 987" - * Output: 0 - * Explanation: The first non-whitespace character is 'w', which is not a numerical - * digit or a +/- sign. Therefore no valid conversion could be performed. - * - * Example 5: - * - * - * Input: "-91283472332" - * Output: -2147483648 - * Explanation: The number "-91283472332" is out of the range of a 32-bit signed integer. - * Thefore INT_MIN (-2^31) is returned. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/string-to-integer-atoi/ -// discuss: https://leetcode.com/problems/string-to-integer-atoi/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn my_atoi(input: String) -> i32 { - let (i32_min, i32_max) = (-2_i64.pow(31), 2_i64.pow(31) - 1); - let mut result: i64 = 0; - let mut minus = false; - // simple state machine - let mut num_matched = false; - for ch in input.chars().into_iter() { - if !num_matched { - match ch { - ' ' => {} - '0'..='9' => { - num_matched = true; - result = result * 10 + ch.to_digit(10).unwrap() as i64; - } - '-' => { - num_matched = true; - minus = true; - } - '+' => { - num_matched = true; - } - _ => return 0, - } - } else { - match ch { - '0'..='9' => { - result = result * 10 + ch.to_digit(10).unwrap() as i64; - if result > i32_max { - break; - } - } - _ => break, - } - } - } - result = if minus { -result } else { result }; - if result > i32_max { - return i32_max as i32; - } - if result < i32_min { - return i32_min as i32; - } - return result as i32; - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_8() { - assert_eq!(Solution::my_atoi("aa".to_string()), 0); - assert_eq!(Solution::my_atoi("-91283472332".to_string()), -2147483648); - assert_eq!(Solution::my_atoi("words and 987".to_string()), 0); - assert_eq!(Solution::my_atoi("4193 with words".to_string()), 4193); - assert_eq!(Solution::my_atoi("42".to_string()), 42); - assert_eq!(Solution::my_atoi("004193333".to_string()), 4193333); - } -} diff --git a/src/solution/s0009_palindrome_number.rs b/src/solution/s0009_palindrome_number.rs deleted file mode 100644 index 255eeed1..00000000 --- a/src/solution/s0009_palindrome_number.rs +++ /dev/null @@ -1,89 +0,0 @@ -/** - * [9] Palindrome Number - * - * Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same backward as forward. - * - * Example 1: - * - * - * Input: 121 - * Output: true - * - * - * Example 2: - * - * - * Input: -121 - * Output: false - * Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome. - * - * - * Example 3: - * - * - * Input: 10 - * Output: false - * Explanation: Reads 01 from right to left. Therefore it is not a palindrome. - * - * - * Follow up: - * - * Coud you solve it without converting the integer to a string? - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/palindrome-number/ -// discuss: https://leetcode.com/problems/palindrome-number/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// TODO: not optimal, we only have to revert half of the string -impl Solution { - pub fn is_palindrome(x: i32) -> bool { - if x < 0 { - return false; - } - let mut digits: Vec = Vec::new(); - let mut input = x; - while input != 0 { - digits.push(input % 10); - input = input / 10; - } - let len = digits.len(); - // handle one digit - if len < 2 { - return true; - } - // handle end with 0 - if digits[0] == 0 { - return false; - } - let mut i = 0; - while i < len / 2 { - if digits[i] != digits[len - 1 - i] { - return false; - } - i += 1; - } - true - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_9() { - assert_eq!(Solution::is_palindrome(-32), false); - assert_eq!(Solution::is_palindrome(10), false); - assert_eq!(Solution::is_palindrome(0), true); - assert_eq!(Solution::is_palindrome(9), true); - assert_eq!(Solution::is_palindrome(121), true); - assert_eq!(Solution::is_palindrome(2222), true); - assert_eq!(Solution::is_palindrome(11222211), true); - } -} diff --git a/src/solution/s0010_regular_expression_matching.rs b/src/solution/s0010_regular_expression_matching.rs deleted file mode 100644 index 13e15cb7..00000000 --- a/src/solution/s0010_regular_expression_matching.rs +++ /dev/null @@ -1,92 +0,0 @@ -/** - * [10] Regular Expression Matching - * - * Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'. - * - * - * '.' Matches any single character. - * '*' Matches zero or more of the preceding element. - * - * - * The matching should cover the entire input string (not partial). - * - * Note: - * - * - * s could be empty and contains only lowercase letters a-z. - * p could be empty and contains only lowercase letters a-z, and characters like . or *. - * - * - * Example 1: - * - * - * Input: - * s = "aa" - * p = "a" - * Output: false - * Explanation: "a" does not match the entire string "aa". - * - * - * Example 2: - * - * - * Input: - * s = "aa" - * p = "a*" - * Output: true - * Explanation: '*' means zero or more of the precedeng element, 'a'. Therefore, by repeating 'a' once, it becomes "aa". - * - * - * Example 3: - * - * - * Input: - * s = "ab" - * p = ".*" - * Output: true - * Explanation: ".*" means "zero or more (*) of any character (.)". - * - * - * Example 4: - * - * - * Input: - * s = "aab" - * p = "c*a*b" - * Output: true - * Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore it matches "aab". - * - * - * Example 5: - * - * - * Input: - * s = "mississippi" - * p = "mis*is*p*." - * Output: false - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/regular-expression-matching/ -// discuss: https://leetcode.com/problems/regular-expression-matching/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// TODO: NFA -impl Solution { - pub fn is_match(s: String, p: String) -> bool { - false - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_10() {} -} diff --git a/src/solution/s0011_container_with_most_water.rs b/src/solution/s0011_container_with_most_water.rs deleted file mode 100644 index ae818bac..00000000 --- a/src/solution/s0011_container_with_most_water.rs +++ /dev/null @@ -1,81 +0,0 @@ -/** - * [11] Container With Most Water - * - * Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water. - * - * Note: You may not slant the container and n is at least 2. - * - * - * - * - * - * The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49. - * - * - * - * Example: - * - * - * Input: [1,8,6,2,5,4,8,3,7] - * Output: 49 - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/container-with-most-water/ -// discuss: https://leetcode.com/problems/container-with-most-water/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// Brute force: O(N^2) - -// Two Pointer: a[0] -> <- a[n-1] -impl Solution { - pub fn max_area(height: Vec) -> i32 { - let (mut start, mut end) = (0_usize, (height.len() - 1)); - let mut max: i32 = (end - start) as i32 * Solution::min(height[start], height[end]); - let mut curr_area: i32 = 0; - while end - start > 1 { - // move the lower one - if height[start] < height[end] { - start += 1; - if height[start] < height[start - 1] { - continue; - } - } else { - end -= 1; - if height[end] < height[end + 1] { - continue; - } - } - curr_area = (end - start) as i32 * Solution::min(height[start], height[end]); - if curr_area > max { - max = curr_area - } - } - max - } - - #[inline(always)] - fn min(i: i32, j: i32) -> i32 { - if i > j { - j - } else { - i - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_11() { - assert_eq!(Solution::max_area(vec![1, 8, 6, 2, 5, 4, 8, 3, 7]), 49); - assert_eq!(Solution::max_area(vec![6, 9]), 6); - assert_eq!(Solution::max_area(vec![1, 1, 2, 1, 1, 1]), 5); - } -} diff --git a/src/solution/s0012_integer_to_roman.rs b/src/solution/s0012_integer_to_roman.rs deleted file mode 100644 index b32592c7..00000000 --- a/src/solution/s0012_integer_to_roman.rs +++ /dev/null @@ -1,114 +0,0 @@ -/** - * [12] Integer to Roman - * - * Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M. - * - * - * Symbol Value - * I 1 - * V 5 - * X 10 - * L 50 - * C 100 - * D 500 - * M 1000 - * - * For example, two is written as II in Roman numeral, just two one's added together. Twelve is written as, XII, which is simply X + II. The number twenty seven is written as XXVII, which is XX + V + II. - * - * Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used: - * - * - * I can be placed before V (5) and X (10) to make 4 and 9. - * X can be placed before L (50) and C (100) to make 40 and 90. - * C can be placed before D (500) and M (1000) to make 400 and 900. - * - * - * Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 to 3999. - * - * Example 1: - * - * - * Input: 3 - * Output: "III" - * - * Example 2: - * - * - * Input: 4 - * Output: "IV" - * - * Example 3: - * - * - * Input: 9 - * Output: "IX" - * - * Example 4: - * - * - * Input: 58 - * Output: "LVIII" - * Explanation: L = 50, V = 5, III = 3. - * - * - * Example 5: - * - * - * Input: 1994 - * Output: "MCMXCIV" - * Explanation: M = 1000, CM = 900, XC = 90 and IV = 4. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/integer-to-roman/ -// discuss: https://leetcode.com/problems/integer-to-roman/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn int_to_roman(num: i32) -> String { - let table: Vec<(i32, &'static str)> = vec![ - (1000, "M"), - (900, "CM"), - (500, "D"), - (400, "CD"), - (100, "C"), - (90, "XC"), - (50, "L"), - (40, "XL"), - (10, "X"), - (9, "IX"), - (5, "V"), - (4, "IV"), - (1, "I"), - ]; - - let mut num = num; - let mut sb = String::new(); - for p in table.iter() { - if num >= p.0 { - for _ in 0..(num / p.0) { - sb.push_str(p.1); - } - num = num % p.0 - } - } - sb - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_12() { - assert_eq!(Solution::int_to_roman(3), "III"); - assert_eq!(Solution::int_to_roman(4), "IV"); - assert_eq!(Solution::int_to_roman(9), "IX"); - assert_eq!(Solution::int_to_roman(1994), "MCMXCIV"); - } -} diff --git a/src/solution/s0013_roman_to_integer.rs b/src/solution/s0013_roman_to_integer.rs deleted file mode 100644 index 4f3f0ae4..00000000 --- a/src/solution/s0013_roman_to_integer.rs +++ /dev/null @@ -1,115 +0,0 @@ -/** - * [13] Roman to Integer - * - * Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M. - * - * - * Symbol Value - * I 1 - * V 5 - * X 10 - * L 50 - * C 100 - * D 500 - * M 1000 - * - * For example, two is written as II in Roman numeral, just two one's added together. Twelve is written as, XII, which is simply X + II. The number twenty seven is written as XXVII, which is XX + V + II. - * - * Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used: - * - * - * I can be placed before V (5) and X (10) to make 4 and 9. - * X can be placed before L (50) and C (100) to make 40 and 90. - * C can be placed before D (500) and M (1000) to make 400 and 900. - * - * - * Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range from 1 to 3999. - * - * Example 1: - * - * - * Input: "III" - * Output: 3 - * - * Example 2: - * - * - * Input: "IV" - * Output: 4 - * - * Example 3: - * - * - * Input: "IX" - * Output: 9 - * - * Example 4: - * - * - * Input: "LVIII" - * Output: 58 - * Explanation: L = 50, V= 5, III = 3. - * - * - * Example 5: - * - * - * Input: "MCMXCIV" - * Output: 1994 - * Explanation: M = 1000, CM = 900, XC = 90 and IV = 4. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/roman-to-integer/ -// discuss: https://leetcode.com/problems/roman-to-integer/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn roman_to_int(s: String) -> i32 { - let table: Vec<(i32, &'static str)> = vec![ - (1000, "M"), - (900, "CM"), - (500, "D"), - (400, "CD"), - (100, "C"), - (90, "XC"), - (50, "L"), - (40, "XL"), - (10, "X"), - (9, "IX"), - (5, "V"), - (4, "IV"), - (1, "I"), - ]; - let mut sum = 0; - let mut idx = 0; - for p in table.iter() { - while idx + p.1.len() <= s.len() && p.1 == &s[idx..idx + p.1.len()] { - idx += p.1.len(); - sum += p.0; - if idx >= s.len() { - return sum; - } - } - } - sum - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_13() { - assert_eq!(Solution::roman_to_int("III".to_string()), 3); - assert_eq!(Solution::roman_to_int("IV".to_string()), 4); - assert_eq!(Solution::roman_to_int("IX".to_string()), 9); - assert_eq!(Solution::roman_to_int("MCMXCIV".to_string()), 1994); - assert_eq!(Solution::roman_to_int("DCXXI".to_string()), 621); - } -} diff --git a/src/solution/s0014_longest_common_prefix.rs b/src/solution/s0014_longest_common_prefix.rs deleted file mode 100644 index 1c5fd985..00000000 --- a/src/solution/s0014_longest_common_prefix.rs +++ /dev/null @@ -1,90 +0,0 @@ -/** - * [14] Longest Common Prefix - * - * Write a function to find the longest common prefix string amongst an array of strings. - * - * If there is no common prefix, return an empty string "". - * - * Example 1: - * - * - * Input: ["flower","flow","flight"] - * Output: "fl" - * - * - * Example 2: - * - * - * Input: ["dog","racecar","car"] - * Output: "" - * Explanation: There is no common prefix among the input strings. - * - * - * Note: - * - * All given inputs are in lowercase letters a-z. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/longest-common-prefix/ -// discuss: https://leetcode.com/problems/longest-common-prefix/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::str::Chars; -impl Solution { - pub fn longest_common_prefix(strs: Vec) -> String { - let mut prefix = String::new(); - let mut iters: Vec = strs.iter().map(|s| s.chars()).collect(); - let mut curr_char: Option = None; - if strs.len() < 1 { - return prefix; - } - loop { - curr_char.take().map(|ch| prefix.push(ch)); - for iter in iters.iter_mut() { - let mut ch = iter.next(); - if ch.is_none() { - return prefix; - } - match curr_char { - None => curr_char = ch.take(), - Some(curr) => { - if curr != ch.unwrap() { - return prefix; - } - } - } - } - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_14() { - assert_eq!( - Solution::longest_common_prefix(vec![ - "".to_string(), - "racecar".to_string(), - "car".to_string() - ]), - "" - ); - assert_eq!( - Solution::longest_common_prefix(vec![ - "flower".to_string(), - "flow".to_string(), - "flight".to_string() - ]), - "fl" - ); - assert_eq!(Solution::longest_common_prefix(vec![]), ""); - } -} diff --git a/src/solution/s0015_3sum.rs b/src/solution/s0015_3sum.rs deleted file mode 100644 index 9feb3cd0..00000000 --- a/src/solution/s0015_3sum.rs +++ /dev/null @@ -1,143 +0,0 @@ -/** - * [15] 3Sum - * - * Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero. - * - * Note: - * - * The solution set must not contain duplicate triplets. - * - * Example: - * - * - * Given array nums = [-1, 0, 1, 2, -1, -4], - * - * A solution set is: - * [ - * [-1, 0, 1], - * [-1, -1, 2] - * ] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/3sum/ -// discuss: https://leetcode.com/problems/3sum/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn three_sum(nums: Vec) -> Vec> { - let len = nums.len(); - if len < 3 { - return vec![]; - } - let mut nums = nums; - nums.sort(); - let mut i = 0; - let mut result: Vec> = Vec::new(); - let mut previous = nums[0] - 1; - while i < len - 2 { - // skip same number - if nums[i] == previous { - i += 1; - continue; - } - previous = nums[i]; - let mut vec = Solution::two_sum(&nums[(i + 1)..len], 0 - nums[i]); - for t in vec.iter() { - result.push(vec![nums[i], t.0, t.1]); - } - i += 1; - } - result - } - - // 2 sum using 2 pointers: nums[0] -> <- nums[len-1] - #[inline(always)] - fn two_sum(nums: &[i32], sum: i32) -> Vec<(i32, i32)> { - let (mut i, mut j) = (0_usize, nums.len() - 1); - let mut result = Vec::new(); - while i < j { - if nums[i] + nums[j] < sum { - i += 1 - } else if nums[i] + nums[j] > sum { - j -= 1 - } else { - result.push((nums[i], nums[j])); - i = Solution::next_unique(nums, i, true); - j = Solution::next_unique(nums, j, false); - } - } - result - } - - // seek next un-repeat number - #[inline(always)] - fn next_unique(nums: &[i32], idx: usize, forward: bool) -> usize { - let curr = nums[idx]; - let mut i = idx; - while i > 0 && i < nums.len() && nums[i] == curr { - i = if forward { i + 1 } else { i - 1 } - } - i - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_15() { - assert_eq!( - Solution::three_sum(vec![-1, 0, 1, 2, -1, -4]), - vec![vec![-1, -1, 2], vec![-1, 0, 1]] - ); - assert_eq!( - Solution::three_sum(vec![ - -7, -4, -6, 6, 4, -6, -9, -10, -7, 5, 3, -1, -5, 8, -1, -2, -8, -1, 5, -3, -5, 4, - 2, -5, -4, 4, 7 - ]), - vec![ - vec![-10, 2, 8], - vec![-10, 3, 7], - vec![-10, 4, 6], - vec![-10, 5, 5], - vec![-9, 2, 7], - vec![-9, 3, 6], - vec![-9, 4, 5], - vec![-8, 2, 6], - vec![-8, 3, 5], - vec![-8, 4, 4], - vec![-7, -1, 8], - vec![-7, 2, 5], - vec![-7, 3, 4], - vec![-6, -2, 8], - vec![-6, -1, 7], - vec![-6, 2, 4], - vec![-5, -3, 8], - vec![-5, -2, 7], - vec![-5, -1, 6], - vec![-5, 2, 3], - vec![-4, -4, 8], - vec![-4, -3, 7], - vec![-4, -2, 6], - vec![-4, -1, 5], - vec![-3, -2, 5], - vec![-3, -1, 4], - vec![-2, -1, 3], - vec![-1, -1, 2] - ] - ); - assert_eq!( - Solution::three_sum(vec![2, 0, -2, -5, -5, -3, 2, -4]), - vec![vec![-4, 2, 2], vec![-2, 0, 2]] - ); - let empty_vec: Vec> = vec![]; - assert_eq!(Solution::three_sum(vec![]), empty_vec); - } -} diff --git a/src/solution/s0016_3sum_closest.rs b/src/solution/s0016_3sum_closest.rs deleted file mode 100644 index 01cf442d..00000000 --- a/src/solution/s0016_3sum_closest.rs +++ /dev/null @@ -1,76 +0,0 @@ -/** - * [16] 3Sum Closest - * - * Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution. - * - * Example: - * - * - * Given array nums = [-1, 2, 1, -4], and target = 1. - * - * The sum that is closest to the target is 2. (-1 + 2 + 1 = 2). - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/3sum-closest/ -// discuss: https://leetcode.com/problems/3sum-closest/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn three_sum_closest(nums: Vec, target: i32) -> i32 { - let mut nums = nums; - let mut min_distance: i32 = i32::max_value(); - nums.sort(); - let mut i = 0; - while i < nums.len() - 2 { - let sub_min = Solution::two_sum_closest(&nums[(i + 1)..nums.len()], target - nums[i]); - if sub_min.abs() < min_distance.abs() { - min_distance = sub_min; - if min_distance == 0 { - break; - } - } - i += 1; - } - target + min_distance - } - - pub fn two_sum_closest(nums: &[i32], target: i32) -> i32 { - let (mut i, mut j) = (0_usize, nums.len() - 1); - let mut local_min = i32::max_value(); - while i < j { - let sum = nums[i] + nums[j]; - if sum > target { - j -= 1; - } else if sum < target { - i += 1; - } else { - return 0; - } - if (sum - target).abs() < local_min.abs() { - local_min = sum - target - } - } - local_min - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_16() { - assert_eq!(Solution::three_sum_closest(vec![-1, 2, 1, -4], 1), 2); - assert_eq!(Solution::three_sum_closest(vec![1, 2, 3], 1), 6); - assert_eq!( - Solution::three_sum_closest(vec![1, 2, 4, 8, 16, 32, 64, 128], 82), - 82 - ); - } -} diff --git a/src/solution/s0017_letter_combinations_of_a_phone_number.rs b/src/solution/s0017_letter_combinations_of_a_phone_number.rs deleted file mode 100644 index 7d3245f4..00000000 --- a/src/solution/s0017_letter_combinations_of_a_phone_number.rs +++ /dev/null @@ -1,81 +0,0 @@ -/** - * [17] Letter Combinations of a Phone Number - * - * Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent. - * - * A mapping of digit to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters. - * - * - * - * Example: - * - * - * Input: "23" - * Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]. - * - * - * Note: - * - * Although the above answer is in lexicographical order, your answer could be in any order you want. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/letter-combinations-of-a-phone-number/ -// discuss: https://leetcode.com/problems/letter-combinations-of-a-phone-number/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn letter_combinations(digits: String) -> Vec { - // '0' and '1' as placeholder to avoid index shifting - let table: Vec<(char, Vec)> = vec![ - ('0', vec![]), - ('1', vec![]), - ('2', vec!['a', 'b', 'c']), - ('3', vec!['d', 'e', 'f']), - ('4', vec!['g', 'h', 'i']), - ('5', vec!['j', 'k', 'l']), - ('6', vec!['m', 'n', 'o']), - ('7', vec!['p', 'q', 'r', 's']), - ('8', vec!['t', 'u', 'v']), - ('9', vec!['w', 'x', 'y', 'z']), - ]; - if digits.len() < 1 { - return vec![]; - } - let mut combs: Vec = vec![String::with_capacity(digits.len())]; - for ch in digits.chars().into_iter() { - let chs = &table[ch.to_digit(10).unwrap() as usize].1; - let mut added: Vec = Vec::with_capacity((chs.len() - 1) * combs.len()); - for comb in combs.iter_mut() { - for (i, &alphabetic) in chs.iter().enumerate() { - if i == chs.len() - 1 { - comb.push(alphabetic); - } else { - let mut new_comb = (*comb).clone(); - new_comb.push(alphabetic); - added.push(new_comb); - } - } - } - combs.append(&mut added); - } - combs - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_17() { - assert_eq!( - Solution::letter_combinations("23".to_string()), - ["cf", "af", "bf", "cd", "ce", "ad", "ae", "bd", "be"] - ); - } -} diff --git a/src/solution/s0018_4sum.rs b/src/solution/s0018_4sum.rs deleted file mode 100644 index d832aef1..00000000 --- a/src/solution/s0018_4sum.rs +++ /dev/null @@ -1,99 +0,0 @@ -/** - * [18] 4Sum - * - * Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target. - * - * Note: - * - * The solution set must not contain duplicate quadruplets. - * - * Example: - * - * - * Given array nums = [1, 0, -1, 0, -2, 2], and target = 0. - * - * A solution set is: - * [ - * [-1, 0, 0, 1], - * [-2, -1, 1, 2], - * [-2, 0, 0, 2] - * ] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/4sum/ -// discuss: https://leetcode.com/problems/4sum/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// TODO: change to faster N^3 solution... maybe -// this is a N^2 * logN solution, but slower than N^3 solution -// iterate all combinations and the sum of 2 elements, then use one-round hash -use std::collections::BTreeMap; -use std::collections::HashSet; -impl Solution { - pub fn four_sum(nums: Vec, target: i32) -> Vec> { - if nums.len() < 4 { - return vec![]; - } - let mut set: HashSet> = HashSet::new(); - let mut map: BTreeMap> = BTreeMap::new(); - // collect two-sums in asc order, store the index to avoid single number reusing - for i in 0..(nums.len() - 1) { - for j in (i + 1)..nums.len() { - map.entry(nums[i] + nums[j]) - .or_insert(Vec::new()) - .push((i, j)); - } - } - // find results - for (&sum, pairs) in map.iter() { - // avoid duplicates - if sum > target / 2 { - break; - } - match map.get(&(target - sum)) { - None => continue, - // 2-sum + 2-sum == target, then all the possible combination - // (without index conflicts) is our answer - Some(subs) => { - for pair in pairs.iter() { - for sub in subs.iter() { - if sub.0 == pair.0 - || sub.0 == pair.1 - || sub.1 == pair.0 - || sub.1 == pair.1 - { - continue; - } - let mut vec = - vec![nums[pair.0], nums[pair.1], nums[sub.0], nums[sub.1]]; - vec.sort(); - set.insert(vec); - } - } - } - } - } - set.into_iter().collect() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - // TODO: build a macro for arbitrary match - #[test] - #[ignore] - fn test_18() { - assert_eq!( - Solution::four_sum(vec![1, 0, -1, 0, -2, 2], 0), - vec![vec![-1, 0, 0, 1], vec![-2, 0, 0, 2], vec![-2, -1, 1, 2]] - ); - } -} diff --git a/src/solution/s0019_remove_nth_node_from_end_of_list.rs b/src/solution/s0019_remove_nth_node_from_end_of_list.rs deleted file mode 100644 index c3f53a32..00000000 --- a/src/solution/s0019_remove_nth_node_from_end_of_list.rs +++ /dev/null @@ -1,71 +0,0 @@ -/** - * [19] Remove Nth Node From End of List - * - * Given a linked list, remove the n-th node from the end of list and return its head. - * - * Example: - * - * - * Given linked list: 1->2->3->4->5, and n = 2. - * - * After removing the second node from the end, the linked list becomes 1->2->3->5. - * - * - * Note: - * - * Given n will always be valid. - * - * Follow up: - * - * Could you do this in one pass? - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; - -// problem: https://leetcode.com/problems/remove-nth-node-from-end-of-list/ -// discuss: https://leetcode.com/problems/remove-nth-node-from-end-of-list/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// one pass (two pointer runner pattern) cannot make borrow checker happy -// but two pass don't takes longer time -impl Solution { - pub fn remove_nth_from_end(head: Option>, n: i32) -> Option> { - let mut dummy_head = Some(Box::new(ListNode { val: 0, next: head })); - let mut len = 0; - { - let mut p = dummy_head.as_ref(); - while p.unwrap().next.is_some() { - len += 1; - p = p.unwrap().next.as_ref(); - } - } - let idx = len - n; - { - let mut p = dummy_head.as_mut(); - for _ in 0..(idx) { - p = p.unwrap().next.as_mut(); - } - let next = p.as_mut().unwrap().next.as_mut().unwrap().next.take(); - p.as_mut().unwrap().next = next; - } - dummy_head.unwrap().next - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_19() { - assert_eq!( - Solution::remove_nth_from_end(to_list(vec![1, 2, 3, 4, 5]), 2), - to_list(vec![1, 2, 3, 5]) - ); - assert_eq!(Solution::remove_nth_from_end(to_list(vec![1]), 1), None); - } -} diff --git a/src/solution/s0020_valid_parentheses.rs b/src/solution/s0020_valid_parentheses.rs deleted file mode 100644 index 3c0940b9..00000000 --- a/src/solution/s0020_valid_parentheses.rs +++ /dev/null @@ -1,94 +0,0 @@ -/** - * [20] Valid Parentheses - * - * Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. - * - * An input string is valid if: - * - *
    - * Open brackets must be closed by the same type of brackets. - * Open brackets must be closed in the correct order. - *
- * - * Note that an empty string is also considered valid. - * - * Example 1: - * - * - * Input: "()" - * Output: true - * - * - * Example 2: - * - * - * Input: "()[]{}" - * Output: true - * - * - * Example 3: - * - * - * Input: "(]" - * Output: false - * - * - * Example 4: - * - * - * Input: "([)]" - * Output: false - * - * - * Example 5: - * - * - * Input: "{[]}" - * Output: true - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/valid-parentheses/ -// discuss: https://leetcode.com/problems/valid-parentheses/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn is_valid(s: String) -> bool { - let mut stack: Vec = Vec::new(); - for ch in s.chars().into_iter() { - match stack.last() { - None => {} - Some(&last) => { - if Solution::pair(last, ch) { - stack.pop(); - continue; - } - } - } - stack.push(ch); - } - stack.is_empty() - } - - #[inline(always)] - fn pair(open: char, close: char) -> bool { - (open == '{' && close == '}') - || (open == '(' && close == ')') - || (open == '[' && close == ']') - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_20() { - assert_eq!(Solution::is_valid("()[]{}".to_string()), true); - } -} diff --git a/src/solution/s0021_merge_two_sorted_lists.rs b/src/solution/s0021_merge_two_sorted_lists.rs deleted file mode 100644 index 54d7f256..00000000 --- a/src/solution/s0021_merge_two_sorted_lists.rs +++ /dev/null @@ -1,75 +0,0 @@ -/** - * [21] Merge Two Sorted Lists - * - * Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. - * - * Example: - * - * Input: 1->2->4, 1->3->4 - * Output: 1->1->2->3->4->4 - * - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; - -// problem: https://leetcode.com/problems/merge-two-sorted-lists/ -// discuss: https://leetcode.com/problems/merge-two-sorted-lists/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// recursive will be much easier to understand -impl Solution { - pub fn merge_two_lists( - l1: Option>, - l2: Option>, - ) -> Option> { - let mut dummy_head = Some(Box::new(ListNode { val: 0, next: None })); - let mut head = &mut dummy_head; - let (mut l1, mut l2) = (l1, l2); - while l1.is_some() || l2.is_some() { - if l1.is_none() { - head.as_mut().unwrap().next = l2; - break; - } else if l2.is_none() { - head.as_mut().unwrap().next = l1; - break; - } - let next = if l1.as_ref().unwrap().val < l2.as_ref().unwrap().val { - let (origin, next) = Solution::take_head(l1); - l1 = origin; - next - } else { - let (origin, next) = Solution::take_head(l2); - l2 = origin; - next - }; - head.as_mut().unwrap().next = next; - head = &mut head.as_mut().unwrap().next; - } - dummy_head.unwrap().next - } - - #[inline(always)] - fn take_head(mut l: Option>) -> (Option>, Option>) { - let l_next = l.as_mut().unwrap().next.take(); - let next = l.take(); - l = l_next; - (l, next) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_21() { - assert_eq!( - Solution::merge_two_lists(to_list(vec![1, 2, 4]), to_list(vec![1, 3, 4])), - to_list(vec![1, 1, 2, 3, 4, 4]) - ); - } -} diff --git a/src/solution/s0022_generate_parentheses.rs b/src/solution/s0022_generate_parentheses.rs deleted file mode 100644 index 9e0e33df..00000000 --- a/src/solution/s0022_generate_parentheses.rs +++ /dev/null @@ -1,72 +0,0 @@ -/** - * [22] Generate Parentheses - * - * - * Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. - * - * - * - * For example, given n = 3, a solution set is: - * - * - * [ - * "((()))", - * "(()())", - * "(())()", - * "()(())", - * "()()()" - * ] - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/generate-parentheses/ -// discuss: https://leetcode.com/problems/generate-parentheses/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// DFS -impl Solution { - pub fn generate_parenthesis(n: i32) -> Vec { - if n < 1 { - return vec![]; - } - let mut result = Vec::new(); - Solution::dfs(n, 0, 0, &mut result, String::new()); - result - } - - fn dfs(n: i32, left: i32, right: i32, result: &mut Vec, mut path: String) { - if left == n && right == n { - result.push(path); - return; - } - if left < n { - let mut new_path = path.clone(); - new_path.push('('); - Solution::dfs(n, left + 1, right, result, new_path); - } - if right < left { - // reuse path to avoid clone overhead - path.push(')'); - Solution::dfs(n, left, right + 1, result, path); - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_22() { - assert_eq!(Solution::generate_parenthesis(1), vec!["()"]); - assert_eq!(Solution::generate_parenthesis(2), vec!["(())", "()()"]); - assert_eq!( - Solution::generate_parenthesis(3), - vec!["((()))", "(()())", "(())()", "()(())", "()()()"] - ); - } -} diff --git a/src/solution/s0023_merge_k_sorted_lists.rs b/src/solution/s0023_merge_k_sorted_lists.rs deleted file mode 100644 index eeaf3695..00000000 --- a/src/solution/s0023_merge_k_sorted_lists.rs +++ /dev/null @@ -1,95 +0,0 @@ -/** - * [23] Merge k Sorted Lists - * - * Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. - * - * Example: - * - * - * Input: - * [ - * 1->4->5, - * 1->3->4, - * 2->6 - * ] - * Output: 1->1->2->3->4->4->5->6 - * - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; - -// problem: https://leetcode.com/problems/merge-k-sorted-lists/ -// discuss: https://leetcode.com/problems/merge-k-sorted-lists/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here -use std::cmp::Ordering; -use std::collections::BinaryHeap; - -// head value and the index -struct Node(i32, usize); - -// sort in reverse order of head value -impl Ord for Node { - fn cmp(&self, other: &Self) -> Ordering { - self.0.cmp(&other.0).reverse() - } -} -impl PartialEq for Node { - fn eq(&self, other: &Self) -> bool { - self.0.eq(&other.0) - } -} -impl Eq for Node {} -impl PartialOrd for Node { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.0.cmp(&other.0).reverse()) - } -} - -impl Solution { - pub fn merge_k_lists(lists: Vec>>) -> Option> { - let mut heap: BinaryHeap = BinaryHeap::new(); - for (idx, node) in lists.iter().enumerate() { - node.as_ref() - .and_then(|n| Some(heap.push(Node(n.val, idx)))); - } - Solution::next(lists, &mut heap) - } - - fn next( - mut lists: Vec>>, - heap: &mut BinaryHeap, - ) -> Option> { - heap.pop().map(|node| { - let next = lists[node.1].take().unwrap().next; - next.as_ref() - .and_then(|n| Some(heap.push(Node(n.val, node.1)))); - lists[node.1] = next; - Box::new(ListNode { - val: node.0, - next: Solution::next(lists, heap), - }) - }) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_23() { - assert_eq!( - Solution::merge_k_lists(vec![ - to_list(vec![1, 4, 5]), - to_list(vec![1, 3, 4]), - to_list(vec![2, 6]), - ]), - to_list(vec![1, 1, 2, 3, 4, 4, 5, 6]) - ); - assert_eq!(Solution::merge_k_lists(vec![]), None); - } -} diff --git a/src/solution/s0024_swap_nodes_in_pairs.rs b/src/solution/s0024_swap_nodes_in_pairs.rs deleted file mode 100644 index 4a6deb3e..00000000 --- a/src/solution/s0024_swap_nodes_in_pairs.rs +++ /dev/null @@ -1,73 +0,0 @@ -/** - * [24] Swap Nodes in Pairs - * - * Given a linked list, swap every two adjacent nodes and return its head. - * - * Example: - * - * - * Given 1->2->3->4, you should return the list as 2->1->4->3. - * - * Note: - * - * - * Your algorithm should use only constant extra space. - * You may not modify the values in the list's nodes, only nodes itself may be changed. - * - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; - -// problem: https://leetcode.com/problems/swap-nodes-in-pairs/ -// discuss: https://leetcode.com/problems/swap-nodes-in-pairs/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn swap_pairs(head: Option>) -> Option> { - let mut dummy_head = Some(Box::new(ListNode { val: 0, next: head })); - let mut head = dummy_head.as_mut(); - loop { - let mut left = head.as_mut().unwrap().next.take(); - if left.is_none() { - break; - } - let mut right = left.as_mut().unwrap().next.take(); - // handle the un-paired one, e.g. [1, 2, 3] -> [2, 1, 3], 3 is un-paired - if right.is_none() { - head.as_mut().unwrap().next = left; - break; - } - let mut next = right.as_mut().unwrap().next.take(); - // BEFORE: head -> left -> right -> next - // AFTER: head -> right -> left -> next - left.as_mut().unwrap().next = next; - right.as_mut().unwrap().next = left; - head.as_mut().unwrap().next = right; - head = head.unwrap().next.as_mut().unwrap().next.as_mut(); - } - dummy_head.unwrap().next - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_24() { - assert_eq!( - Solution::swap_pairs(to_list(vec![1, 2, 3, 4])), - to_list(vec![2, 1, 4, 3]) - ); - assert_eq!(Solution::swap_pairs(to_list(vec![])), to_list(vec![])); - assert_eq!( - Solution::swap_pairs(to_list(vec![1, 2, 3])), - to_list(vec![2, 1, 3]) - ); - assert_eq!(Solution::swap_pairs(to_list(vec![1])), to_list(vec![1])); - } -} diff --git a/src/solution/s0025_reverse_nodes_in_k_group.rs b/src/solution/s0025_reverse_nodes_in_k_group.rs deleted file mode 100644 index 5d39cd1e..00000000 --- a/src/solution/s0025_reverse_nodes_in_k_group.rs +++ /dev/null @@ -1,106 +0,0 @@ -/** - * [25] Reverse Nodes in k-Group - * - * Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. - * - * k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is. - * - * - * - * - * Example: - * - * Given this linked list: 1->2->3->4->5 - * - * For k = 2, you should return: 2->1->4->3->5 - * - * For k = 3, you should return: 3->2->1->4->5 - * - * Note: - * - * - * Only constant extra memory is allowed. - * You may not alter the values in the list's nodes, only nodes itself may be changed. - * - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; - -// problem: https://leetcode.com/problems/reverse-nodes-in-k-group/ -// discuss: https://leetcode.com/problems/reverse-nodes-in-k-group/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn reverse_k_group(head: Option>, k: i32) -> Option> { - let mut dummy_head = Some(Box::new(ListNode { val: 0, next: head })); - let mut head = dummy_head.as_mut(); - 'outer: loop { - let mut start = head.as_mut().unwrap().next.take(); - if start.is_none() { - break 'outer; - } - let mut end = start.as_mut(); - for _ in 0..(k - 1) { - end = end.unwrap().next.as_mut(); - if end.is_none() { - head.as_mut().unwrap().next = start; - break 'outer; - } - } - let mut tail = end.as_mut().unwrap().next.take(); - // BEFORE: head -> start -> 123456... -> end -> tail - // AFTER: head -> end -> ...654321 -> start -> tail - let end = Solution::reverse(start, tail); - head.as_mut().unwrap().next = end; - for _ in 0..k { - head = head.unwrap().next.as_mut() - } - } - dummy_head.unwrap().next - } - - #[inline(always)] - fn reverse( - mut head: Option>, - tail: Option>, - ) -> Option> { - let mut prev = tail; - let mut current = head; - while let Some(mut current_node_inner) = current { - let mut next = current_node_inner.next.take(); - current_node_inner.next = prev.take(); - prev = Some(current_node_inner); - current = next; - } - prev - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_25() { - assert_eq!( - Solution::reverse_k_group(to_list(vec![1, 2, 3, 4, 5]), 2), - to_list(vec![2, 1, 4, 3, 5]) - ); - assert_eq!( - Solution::reverse_k_group(to_list(vec![1, 2, 3, 4, 5]), 3), - to_list(vec![3, 2, 1, 4, 5]) - ); - assert_eq!( - Solution::reverse_k_group(to_list(vec![1, 2, 3, 4, 5]), 5), - to_list(vec![5, 4, 3, 2, 1]) - ); - assert_eq!( - Solution::reverse_k_group(to_list(vec![1]), 1), - to_list(vec![1]) - ); - } -} diff --git a/src/solution/s0026_remove_duplicates_from_sorted_array.rs b/src/solution/s0026_remove_duplicates_from_sorted_array.rs deleted file mode 100644 index 286b7c54..00000000 --- a/src/solution/s0026_remove_duplicates_from_sorted_array.rs +++ /dev/null @@ -1,87 +0,0 @@ -/** - * [26] Remove Duplicates from Sorted Array - * - * Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length. - * - * Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory. - * - * Example 1: - * - * - * Given nums = [1,1,2], - * - * Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively. - * - * It doesn't matter what you leave beyond the returned length. - * - * Example 2: - * - * - * Given nums = [0,0,1,1,1,2,2,3,3,4], - * - * Your function should return length = 5, with the first five elements of nums being modified to 0, 1, 2, 3, and 4 respectively. - * - * It doesn't matter what values are set beyond the returned length. - * - * - * Clarification: - * - * Confused why the returned value is an integer but your answer is an array? - * - * Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well. - * - * Internally you can think of this: - * - * - * // nums is passed in by reference. (i.e., without making a copy) - * int len = removeDuplicates(nums); - * - * // any modification to nums in your function would be known by the caller. - * // using the length returned by your function, it prints the first len elements. - * for (int i = 0; i < len; i++) { - * print(nums[i]); - * } - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/remove-duplicates-from-sorted-array/ -// discuss: https://leetcode.com/problems/remove-duplicates-from-sorted-array/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn remove_duplicates(nums: &mut Vec) -> i32 { - let len = nums.len(); - if len <= 1 { - return len as i32; - } - let mut slow = 0usize; - for fast in 1..len { - if nums[slow] != nums[fast] { - slow += 1; - nums[slow] = nums[fast]; - } - } - nums.truncate(slow + 1); - (slow + 1) as i32 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_26() { - assert_eq!(Solution::remove_duplicates(&mut vec![]), 0); - let mut vec1 = vec![1, 1, 1, 1, 3]; - assert_eq!(Solution::remove_duplicates(&mut vec1), 2); - assert_eq!(vec1, vec![1, 3]); - let mut vec2 = vec![1, 1, 2]; - assert_eq!(Solution::remove_duplicates(&mut vec2), 2); - assert_eq!(vec2, vec![1, 2]); - } -} diff --git a/src/solution/s0027_remove_element.rs b/src/solution/s0027_remove_element.rs deleted file mode 100644 index 7144d3e9..00000000 --- a/src/solution/s0027_remove_element.rs +++ /dev/null @@ -1,97 +0,0 @@ -/** - * [27] Remove Element - * - * Given an array nums and a value val, remove all instances of that value in-place and return the new length. - * - * Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory. - * - * The order of elements can be changed. It doesn't matter what you leave beyond the new length. - * - * Example 1: - * - * - * Given nums = [3,2,2,3], val = 3, - * - * Your function should return length = 2, with the first two elements of nums being 2. - * - * It doesn't matter what you leave beyond the returned length. - * - * - * Example 2: - * - * - * Given nums = [0,1,2,2,3,0,4,2], val = 2, - * - * Your function should return length = 5, with the first five elements of nums containing 0, 1, 3, 0, and 4. - * - * Note that the order of those five elements can be arbitrary. - * - * It doesn't matter what values are set beyond the returned length. - * - * Clarification: - * - * Confused why the returned value is an integer but your answer is an array? - * - * Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well. - * - * Internally you can think of this: - * - * - * // nums is passed in by reference. (i.e., without making a copy) - * int len = removeElement(nums, val); - * - * // any modification to nums in your function would be known by the caller. - * // using the length returned by your function, it prints the first len elements. - * for (int i = 0; i < len; i++) { - * print(nums[i]); - * } - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/remove-element/ -// discuss: https://leetcode.com/problems/remove-element/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn remove_element(nums: &mut Vec, val: i32) -> i32 { - if nums.len() < 1 { - return 0; - } - let (mut start, mut end) = (0_usize, nums.len() - 1); - while start < end { - if nums[start] == val { - nums[start] = nums[end - 1]; - end -= 1; - } else { - start += 1; - } - } - end as i32 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_27() { - let mut vec1 = vec![0, 1, 2, 2, 3, 0, 4, 2]; - assert_eq!(Solution::remove_element(&mut vec1, 2), 5); - assert_eq!(vec1[0..5], [0, 1, 4, 0, 3]); - assert_eq!(Solution::remove_element(&mut vec![], 2), 0); - assert_eq!( - Solution::remove_element(&mut vec![1, 2, 2, 2, 2, 2, 2], 2), - 1 - ); - assert_eq!( - Solution::remove_element(&mut vec![2, 2, 2, 2, 2, 2, 2], 2), - 0 - ); - assert_eq!(Solution::remove_element(&mut vec![1], 1), 0); - } -} diff --git a/src/solution/s0028_implement_strstr.rs b/src/solution/s0028_implement_strstr.rs deleted file mode 100644 index e0d944ee..00000000 --- a/src/solution/s0028_implement_strstr.rs +++ /dev/null @@ -1,55 +0,0 @@ -/** - * [28] Implement strStr() - * - * Implement strStr(). - * - * Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. - * - * Example 1: - * - * - * Input: haystack = "hello", needle = "ll" - * Output: 2 - * - * - * Example 2: - * - * - * Input: haystack = "aaaaa", needle = "bba" - * Output: -1 - * - * - * Clarification: - * - * What should we return when needle is an empty string? This is a great question to ask during an interview. - * - * For the purpose of this problem, we will return 0 when needle is an empty string. This is consistent to C's strstr() and Java's indexOf(). - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/implement-strstr/ -// discuss: https://leetcode.com/problems/implement-strstr/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn str_str(haystack: String, needle: String) -> i32 { - if needle.is_empty() { - return 0; - } - haystack.find(&needle).map_or(-1_i32, |v| v as i32) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_28() { - assert_eq!(Solution::str_str("hello".to_string(), "ll".to_string()), 2) - } -} diff --git a/src/solution/s0029_divide_two_integers.rs b/src/solution/s0029_divide_two_integers.rs deleted file mode 100644 index e8f13435..00000000 --- a/src/solution/s0029_divide_two_integers.rs +++ /dev/null @@ -1,52 +0,0 @@ -/** - * [29] Divide Two Integers - * - * Given two integers dividend and divisor, divide two integers without using multiplication, division and mod operator. - * - * Return the quotient after dividing dividend by divisor. - * - * The integer division should truncate toward zero. - * - * Example 1: - * - * - * Input: dividend = 10, divisor = 3 - * Output: 3 - * - * Example 2: - * - * - * Input: dividend = 7, divisor = -3 - * Output: -2 - * - * Note: - * - * - * Both dividend and divisor will be 32-bit signed integers. - * The divisor will never be 0. - * Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [-2^31, 2^31 - 1]. For the purpose of this problem, assume that your function returns 2^31 - 1 when the division result overflows. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/divide-two-integers/ -// discuss: https://leetcode.com/problems/divide-two-integers/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn divide(dividend: i32, divisor: i32) -> i32 { - 0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_29() {} -} diff --git a/src/solution/s0030_substring_with_concatenation_of_all_words.rs b/src/solution/s0030_substring_with_concatenation_of_all_words.rs deleted file mode 100644 index 002ae9a3..00000000 --- a/src/solution/s0030_substring_with_concatenation_of_all_words.rs +++ /dev/null @@ -1,175 +0,0 @@ -/** - * [30] Substring with Concatenation of All Words - * - * You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters. - * - * Example 1: - * - * - * Input: - * s = "barfoothefoobarman", - * words = ["foo","bar"] - * Output: [0,9] - * Explanation: Substrings starting at index 0 and 9 are "barfoor" and "foobar" respectively. - * The output order does not matter, returning [9,0] is fine too. - * - * - * Example 2: - * - * - * Input: - * s = "wordgoodgoodgoodbestword", - * words = ["word","good","best","word"] - * Output: [] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/substring-with-concatenation-of-all-words/ -// discuss: https://leetcode.com/problems/substring-with-concatenation-of-all-words/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here -struct Term { - expect: i32, - count: i32, -} -impl Term { - fn new(expect: i32, count: i32) -> Self { - Term { expect, count } - } - fn inc_expect(&mut self) { - self.expect += 1; - } - fn inc(&mut self) { - self.count += 1; - } - fn dec(&mut self) { - self.count -= 1; - } - fn exhausted(&self) -> bool { - self.count > self.expect - } - fn reset(&mut self) { - self.count = 0; - } -} - -use std::collections::hash_map::Entry; -use std::collections::HashMap; - -impl Solution { - pub fn find_substring(s: String, words: Vec) -> Vec { - if words.len() < 1 { - return vec![]; - } - let word_len = words[0].len(); - if word_len < 1 { - return vec![]; - } - let substr_len = word_len * words.len(); - let mut map: HashMap<&str, Term> = HashMap::with_capacity(words.len()); - for word in words.iter() { - map.entry(word).or_insert(Term::new(0, 0)).inc_expect(); - } - let mut result: Vec = Vec::new(); - // we can split terms in N ways, where N = word_len - for shift in 0..word_len { - let mut i = shift; - let mut j = shift; - // we do a sliding window for each round - while j + word_len - 1 < s.len() { - match map.entry(&s[j..j + word_len]) { - Entry::Occupied(mut entry) => { - entry.get_mut().inc(); - // term exhausted, shrink the window to release - if entry.get().exhausted() { - while i < j { - let term = &s[i..i + word_len]; - map.entry(term).and_modify(|t| t.dec()); - i += word_len; - if term == &s[j..j + word_len] { - break; - } - } - j += word_len; - } else { - if j - i < (words.len() - 1) * word_len { - j += word_len; - } else { - // matched! - result.push(i as i32); - // move the whole window, release the dropped term - map.entry(&s[i..i + word_len]).and_modify(|t| t.dec()); - j += word_len; - i += word_len; - } - } - } - // bad term, move over and do a reset - Entry::Vacant(entry) => { - map.iter_mut().for_each(|(_, v)| v.reset()); - j += word_len; - i = j; - } - } - } - map.iter_mut().for_each(|(_, v)| v.reset()) - } - result - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_30() { - assert_eq!( - Solution::find_substring( - "barfoothefoobarman".to_string(), - vec!["foo".to_string(), "bar".to_string()] - ), - vec![0, 9] - ); - assert_eq!( - Solution::find_substring( - "wordgoodgoodgoodbestword".to_string(), - vec![ - "word".to_string(), - "good".to_string(), - "best".to_string(), - "word".to_string() - ] - ), - vec![] - ); - assert_eq!( - Solution::find_substring( - "wordgoodgoodgoodbestword".to_string(), - vec![ - "word".to_string(), - "good".to_string(), - "best".to_string(), - "good".to_string() - ] - ), - vec![8] - ); - assert_eq!( - Solution::find_substring( - "xxwordgoodgoodgoodbestword".to_string(), - vec![ - "word".to_string(), - "good".to_string(), - "best".to_string(), - "good".to_string() - ] - ), - vec![10] - ); - } -} diff --git a/src/solution/s0031_next_permutation.rs b/src/solution/s0031_next_permutation.rs deleted file mode 100644 index b448dfa1..00000000 --- a/src/solution/s0031_next_permutation.rs +++ /dev/null @@ -1,89 +0,0 @@ -/** - * [31] Next Permutation - * - * Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers. - * - * If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order). - * - * The replacement must be in-place and use only constant extra memory. - * - * Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column. - * - * 1,2,3 → 1,3,2
- * 3,2,1 → 1,2,3
- * 1,1,5 → 1,5,1 - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/next-permutation/ -// discuss: https://leetcode.com/problems/next-permutation/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn next_permutation(nums: &mut Vec) { - let len = nums.len(); - let mut i = (len - 1) as i32; - let mut prev = -1; - // find the decrement digit from end - while i >= 0 { - if nums[i as usize] < prev { - break; - } - prev = nums[i as usize]; - i -= 1; - } - let mut j = len - 1; - // find the first digit larger than nums[i] - // we can do binary search here to make a slightly improvement - if i >= 0 { - while j > (i as usize) { - if nums[j] > nums[i as usize] { - nums.swap(i as usize, j); - break; - } - j -= 1; - } - } - let slice = &mut nums[((i + 1) as usize)..len]; - slice.reverse(); - } -} - -// submission codes end - -/* -// a clean solution (from leetcode submissions) -impl Solution { - pub fn next_permutation(a: &mut Vec) { - let n = a.len(); - - if let Some(i) = (1..n).rev().find(|&i| a[i - 1] < a[i]) { - let j = (i..n).rev().find(|&j| a[i - 1] < a[j]) - .unwrap(); - - a.swap(i - 1, j); - a[i..].reverse(); - } else { - a.reverse(); - } - } -} - */ - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_31() { - let mut vec1 = vec![1, 2, 3, 4, 5]; - Solution::next_permutation(&mut vec1); - assert_eq!(vec1, vec![1, 2, 3, 5, 4]); - - let mut vec2 = vec![5, 4, 3, 2, 1]; - Solution::next_permutation(&mut vec2); - assert_eq!(vec2, vec![1, 2, 3, 4, 5]); - } -} diff --git a/src/solution/s0032_longest_valid_parentheses.rs b/src/solution/s0032_longest_valid_parentheses.rs deleted file mode 100644 index d970de2b..00000000 --- a/src/solution/s0032_longest_valid_parentheses.rs +++ /dev/null @@ -1,95 +0,0 @@ -/** - * [32] Longest Valid Parentheses - * - * Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring. - * - * Example 1: - * - * - * Input: "(()" - * Output: 2 - * Explanation: The longest valid parentheses substring is "()" - * - * - * Example 2: - * - * - * Input: ")()())" - * Output: 4 - * Explanation: The longest valid parentheses substring is "()()" - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/longest-valid-parentheses/ -// discuss: https://leetcode.com/problems/longest-valid-parentheses/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// time: O(N) space: O(1) -impl Solution { - pub fn longest_valid_parentheses(s: String) -> i32 { - let mut seq: Vec = s.chars().collect(); - let forward_max = Solution::longest(&seq, '('); - seq.reverse(); - let backward_max = Solution::longest(&seq, ')'); - i32::max(forward_max, backward_max) - } - - fn longest(seq: &Vec, plus_char: char) -> i32 { - let mut stack = 0; - let mut max_len = 0; - let (mut i, mut j) = (0_usize, 0_usize); - while j < seq.len() { - if seq[j] == plus_char { - stack += 1; - } else { - // stack exhausted, shift over - if stack < 1 { - i = j + 1; - } else { - stack -= 1; - if stack == 0 { - max_len = i32::max(max_len, (j - i + 1) as i32); - } - } - } - j += 1; - } - max_len - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_32() { - assert_eq!(Solution::longest_valid_parentheses(")()())".to_string()), 4); - assert_eq!(Solution::longest_valid_parentheses(")(".to_string()), 0); - assert_eq!(Solution::longest_valid_parentheses("(()".to_string()), 2); - assert_eq!( - Solution::longest_valid_parentheses("(((((()()".to_string()), - 4 - ); - assert_eq!( - Solution::longest_valid_parentheses("((((((((()))".to_string()), - 6 - ); - assert_eq!(Solution::longest_valid_parentheses("()".to_string()), 2); - assert_eq!(Solution::longest_valid_parentheses("()(()".to_string()), 2); - assert_eq!( - Solution::longest_valid_parentheses(")()(((())))(".to_string()), - 10 - ); - assert_eq!( - Solution::longest_valid_parentheses("(()(((()".to_string()), - 2 - ); - assert_eq!(Solution::longest_valid_parentheses("".to_string()), 0); - } -} diff --git a/src/solution/s0033_search_in_rotated_sorted_array.rs b/src/solution/s0033_search_in_rotated_sorted_array.rs deleted file mode 100644 index ab5c13d3..00000000 --- a/src/solution/s0033_search_in_rotated_sorted_array.rs +++ /dev/null @@ -1,105 +0,0 @@ -/** - * [33] Search in Rotated Sorted Array - * - * Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. - * - * (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]). - * - * You are given a target value to search. If found in the array return its index, otherwise return -1. - * - * You may assume no duplicate exists in the array. - * - * Your algorithm's runtime complexity must be in the order of O(log n). - * - * Example 1: - * - * - * Input: nums = [4,5,6,7,0,1,2], target = 0 - * Output: 4 - * - * - * Example 2: - * - * - * Input: nums = [4,5,6,7,0,1,2], target = 3 - * Output: -1 - * - */ -pub struct Solution {} - -/* - \ - 8 - 7 9 - 6 1 - 5 2 - 3 \ -Consider the given array as ring, each time we split the ring and judge which part is the target belong to, then it's ordinary binary search. -*/ - -// problem: https://leetcode.com/problems/search-in-rotated-sorted-array/ -// discuss: https://leetcode.com/problems/search-in-rotated-sorted-array/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn search(nums: Vec, target: i32) -> i32 { - let mut size = nums.len(); - if size == 0 { - return -1; - } - let mut base = 0_usize; - while size > 1 { - let half = size / 2; - let mid = base + half; - if nums[mid] == target { - return mid as i32; - } - // we split the ring to [base..half] & [half+1..base-1] - // if target not in [base..half] ring, move base to select another ring - if !(((nums[base] < nums[mid]) && (target >= nums[base] && target <= nums[mid])) - || ((nums[base] > nums[mid]) && (target >= nums[base] || target <= nums[mid]))) - { - base = mid; - } - size -= half; - } - if nums[base] == target { - base as i32 - } else { - -1 - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_33() { - assert_eq!(Solution::search(vec![7, 8, 1, 2, 3, 4, 5, 6], 2), 3); - assert_eq!( - Solution::search( - vec![ - 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 0, 1, 2, 3, 4, 5, 6, 7, 8 - ], - 0 - ), - 9 - ); - assert_eq!( - Solution::search( - vec![ - 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 0, 1, 2, 3, 4, 5, 6, 7, 8 - ], - 1006 - ), - 2 - ); - assert_eq!(Solution::search(vec![4, 5, 6, 7, 0, 1, 2], 3), -1); - assert_eq!(Solution::search(vec![], 3), -1); - } -} diff --git a/src/solution/s0034_find_first_and_last_position_of_element_in_sorted_array.rs b/src/solution/s0034_find_first_and_last_position_of_element_in_sorted_array.rs deleted file mode 100644 index eba1c01c..00000000 --- a/src/solution/s0034_find_first_and_last_position_of_element_in_sorted_array.rs +++ /dev/null @@ -1,45 +0,0 @@ -/** - * [34] Find First and Last Position of Element in Sorted Array - * - * Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value. - * - * Your algorithm's runtime complexity must be in the order of O(log n). - * - * If the target is not found in the array, return [-1, -1]. - * - * Example 1: - * - * - * Input: nums = [5,7,7,8,8,10], target = 8 - * Output: [3,4] - * - * Example 2: - * - * - * Input: nums = [5,7,7,8,8,10], target = 6 - * Output: [-1,-1] - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/ -// discuss: https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// TODO -impl Solution { - pub fn search_range(nums: Vec, target: i32) -> Vec { - vec![] - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_34() {} -} diff --git a/src/solution/s0035_search_insert_position.rs b/src/solution/s0035_search_insert_position.rs deleted file mode 100644 index 31c1c38b..00000000 --- a/src/solution/s0035_search_insert_position.rs +++ /dev/null @@ -1,59 +0,0 @@ -/** - * [35] Search Insert Position - * - * Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order. - * - * You may assume no duplicates in the array. - * - * Example 1: - * - * - * Input: [1,3,5,6], 5 - * Output: 2 - * - * - * Example 2: - * - * - * Input: [1,3,5,6], 2 - * Output: 1 - * - * - * Example 3: - * - * - * Input: [1,3,5,6], 7 - * Output: 4 - * - * - * Example 4: - * - * - * Input: [1,3,5,6], 0 - * Output: 0 - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/search-insert-position/ -// discuss: https://leetcode.com/problems/search-insert-position/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// TODO -impl Solution { - pub fn search_insert(nums: Vec, target: i32) -> i32 { - 0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_35() {} -} diff --git a/src/solution/s0036_valid_sudoku.rs b/src/solution/s0036_valid_sudoku.rs deleted file mode 100644 index 5a595774..00000000 --- a/src/solution/s0036_valid_sudoku.rs +++ /dev/null @@ -1,172 +0,0 @@ -/** - * [36] Valid Sudoku - * - * Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules: - * - *
    - * Each row must contain the digits 1-9 without repetition. - * Each column must contain the digits 1-9 without repetition. - * Each of the 9 3x3 sub-boxes of the grid must contain the digits 1-9 without repetition. - *
- * - *
- * A partially filled sudoku which is valid. - * - * The Sudoku board could be partially filled, where empty cells are filled with the character '.'. - * - * Example 1: - * - * - * Input: - * [ - * ["5","3",".",".","7",".",".",".","."], - * ["6",".",".","1","9","5",".",".","."], - * [".","9","8",".",".",".",".","6","."], - * ["8",".",".",".","6",".",".",".","3"], - * ["4",".",".","8",".","3",".",".","1"], - * ["7",".",".",".","2",".",".",".","6"], - * [".","6",".",".",".",".","2","8","."], - * [".",".",".","4","1","9",".",".","5"], - * [".",".",".",".","8",".",".","7","9"] - * ] - * Output: true - * - * - * Example 2: - * - * - * Input: - * [ - * ["8","3",".",".","7",".",".",".","."], - * ["6",".",".","1","9","5",".",".","."], - * [".","9","8",".",".",".",".","6","."], - * ["8",".",".",".","6",".",".",".","3"], - * ["4",".",".","8",".","3",".",".","1"], - * ["7",".",".",".","2",".",".",".","6"], - * [".","6",".",".",".",".","2","8","."], - * [".",".",".","4","1","9",".",".","5"], - * [".",".",".",".","8",".",".","7","9"] - * ] - * Output: false - * Explanation: Same as Example 1, except with the 5 in the top left corner being - * modified to 8. Since there are two 8's in the top left 3x3 sub-box, it is invalid. - * - * - * Note: - * - * - * A Sudoku board (partially filled) could be valid but is not necessarily solvable. - * Only the filled cells need to be validated according to the mentioned rules. - * The given board contain only digits 1-9 and the character '.'. - * The given board size is always 9x9. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/valid-sudoku/ -// discuss: https://leetcode.com/problems/valid-sudoku/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// just brute force -impl Solution { - pub fn is_valid_sudoku(board: Vec>) -> bool { - let mut table = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - for row in board.iter() { - for z in 1..10 { - table[z] = 0; - } - for ch in row { - match ch.to_digit(10) { - None => continue, - Some(idx) => { - if table[idx as usize] > 0 { - return false; - } else { - table[idx as usize] = 1 - } - } - } - } - } - for i in 0..9 { - for z in 1..10 { - table[z] = 0; - } - for row in board.iter() { - match row[i].to_digit(10) { - None => continue, - Some(idx) => { - if table[idx as usize] > 0 { - return false; - } else { - table[idx as usize] = 1 - } - } - } - } - } - for i in 0..3 { - for j in 0..3 { - for z in 1..10 { - table[z] = 0; - } - for row in 3 * i..3 * (i + 1) { - for column in 3 * j..3 * (j + 1) { - match board[row][column].to_digit(10) { - None => continue, - Some(idx) => { - if table[idx as usize] > 0 { - return false; - } else { - table[idx as usize] = 1 - } - } - } - } - } - } - } - true - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_36() { - assert_eq!( - Solution::is_valid_sudoku(vec![ - vec!['8', '3', '.', '.', '7', '.', '.', '.', '.'], - vec!['6', '.', '.', '1', '9', '5', '.', '.', '.'], - vec!['.', '9', '8', '.', '.', '.', '.', '6', '.'], - vec!['8', '.', '.', '.', '6', '.', '.', '.', '3'], - vec!['4', '.', '.', '8', '.', '3', '.', '.', '1'], - vec!['7', '.', '.', '.', '2', '.', '.', '.', '6'], - vec!['.', '6', '.', '.', '.', '.', '2', '8', '.'], - vec!['.', '.', '.', '4', '1', '9', '.', '.', '5'], - vec!['.', '.', '.', '.', '8', '.', '.', '7', '9'], - ]), - false - ); - assert_eq!( - Solution::is_valid_sudoku(vec![ - vec!['5', '3', '.', '.', '7', '.', '.', '.', '.'], - vec!['6', '.', '.', '1', '9', '5', '.', '.', '.'], - vec!['.', '9', '8', '.', '.', '.', '.', '6', '.'], - vec!['8', '.', '.', '.', '6', '.', '.', '.', '3'], - vec!['4', '.', '.', '8', '.', '3', '.', '.', '1'], - vec!['7', '.', '.', '.', '2', '.', '.', '.', '6'], - vec!['.', '6', '.', '.', '.', '.', '2', '8', '.'], - vec!['.', '.', '.', '4', '1', '9', '.', '.', '5'], - vec!['.', '.', '.', '.', '8', '.', '.', '7', '9'] - ]), - true - ); - } -} diff --git a/src/solution/s0037_sudoku_solver.rs b/src/solution/s0037_sudoku_solver.rs deleted file mode 100644 index d0187582..00000000 --- a/src/solution/s0037_sudoku_solver.rs +++ /dev/null @@ -1,51 +0,0 @@ -/** - * [37] Sudoku Solver - * - * Write a program to solve a Sudoku puzzle by filling the empty cells. - * - * A sudoku solution must satisfy all of the following rules: - * - *
    - * Each of the digits 1-9 must occur exactly once in each row. - * Each of the digits 1-9 must occur exactly once in each column. - * Each of the the digits 1-9 must occur exactly once in each of the 9 3x3 sub-boxes of the grid. - *
- * - * Empty cells are indicated by the character '.'. - * - *
- * A sudoku puzzle... - * - *
- * ...and its solution numbers marked in red. - * - * Note: - * - * - * The given board contain only digits 1-9 and the character '.'. - * You may assume that the given Sudoku puzzle will have a single unique solution. - * The given board size is always 9x9. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/sudoku-solver/ -// discuss: https://leetcode.com/problems/sudoku-solver/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// TODO -impl Solution { - pub fn solve_sudoku(board: &mut Vec>) {} -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_37() {} -} diff --git a/src/solution/s0038_count_and_say.rs b/src/solution/s0038_count_and_say.rs deleted file mode 100644 index 6305b2a5..00000000 --- a/src/solution/s0038_count_and_say.rs +++ /dev/null @@ -1,81 +0,0 @@ -/** - * [38] Count and Say - * - * The count-and-say sequence is the sequence of integers with the first five terms as following: - * - * - * 1. 1 - * 2. 11 - * 3. 21 - * 4. 1211 - * 5. 111221 - * - * - * 1 is read off as "one 1" or 11.
- * 11 is read off as "two 1s" or 21.
- * 21 is read off as "one 2, then one 1" or 1211. - * - * Given an integer n where 1 <= n <= 30, generate the n^th term of the count-and-say sequence. - * - * Note: Each term of the sequence of integers will be represented as a string. - * - * - * - * Example 1: - * - * - * Input: 1 - * Output: "1" - * - * - * Example 2: - * - * - * Input: 4 - * Output: "1211" - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/count-and-say/ -// discuss: https://leetcode.com/problems/count-and-say/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::char::from_digit; -impl Solution { - pub fn count_and_say(n: i32) -> String { - let mut res = vec!['1']; - for _ in 0..n - 1 { - let mut temp = Vec::new(); - let mut i = 0_usize; - while i < res.len() { - let mut j = i + 1; - while j < res.len() && res[j] == res[i] { - j += 1; - } - temp.push(from_digit((j - i) as u32, 10).unwrap()); - temp.push(res[i]); - i = j; - } - res = temp; - } - res.iter().collect() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_38() { - assert_eq!(Solution::count_and_say(1), "1"); - assert_eq!(Solution::count_and_say(2), "11"); - assert_eq!(Solution::count_and_say(3), "21"); - assert_eq!(Solution::count_and_say(4), "1211"); - assert_eq!(Solution::count_and_say(5), "111221"); - } -} diff --git a/src/solution/s0039_combination_sum.rs b/src/solution/s0039_combination_sum.rs deleted file mode 100644 index b31e397e..00000000 --- a/src/solution/s0039_combination_sum.rs +++ /dev/null @@ -1,100 +0,0 @@ -/** - * [39] Combination Sum - * - * Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target. - * - * The same repeated number may be chosen from candidates unlimited number of times. - * - * Note: - * - * - * All numbers (including target) will be positive integers. - * The solution set must not contain duplicate combinations. - * - * - * Example 1: - * - * - * Input: candidates = [2,3,6,7], target = 7, - * A solution set is: - * [ - * [7], - * [2,2,3] - * ] - * - * - * Example 2: - * - * - * Input: candidates = [2,3,5], target = 8, - * A solution set is: - * [ - * [2,2,2,2], - * [2,3,3], - * [3,5] - * ] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/combination-sum/ -// discuss: https://leetcode.com/problems/combination-sum/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn combination_sum(candidates: Vec, target: i32) -> Vec> { - let mut seq = candidates; - let mut res = Vec::new(); - seq.sort_unstable_by(|a, b| b.cmp(a)); - let mut vec = Vec::new(); - Solution::backtrack(&seq, target, vec, &mut res, 0); - res - } - - fn backtrack( - seq: &Vec, - target: i32, - mut curr: Vec, - result: &mut Vec>, - start_idx: usize, - ) { - for i in start_idx..seq.len() { - let item = seq[i]; - if target - item < 0 { - continue; - } - let mut new_vec = curr.clone(); - new_vec.push(item); - if target == item { - result.push(new_vec); - } else { - Solution::backtrack(seq, target - item, new_vec, result, i); - } - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_39() { - assert_eq!( - Solution::combination_sum(vec![1], 7), - vec![vec![1, 1, 1, 1, 1, 1, 1]] - ); - assert_eq!( - Solution::combination_sum(vec![2, 3, 6, 7], 7), - vec![vec![7], vec![3, 2, 2],] - ); - assert_eq!( - Solution::combination_sum(vec![2, 3, 5], 8), - vec![vec![5, 3], vec![3, 3, 2], vec![2, 2, 2, 2],] - ); - } -} diff --git a/src/solution/s0040_combination_sum_ii.rs b/src/solution/s0040_combination_sum_ii.rs deleted file mode 100644 index 0445bfb9..00000000 --- a/src/solution/s0040_combination_sum_ii.rs +++ /dev/null @@ -1,107 +0,0 @@ -/** - * [40] Combination Sum II - * - * Given a collection of candidate numbers (candidates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target. - * - * Each number in candidates may only be used once in the combination. - * - * Note: - * - * - * All numbers (including target) will be positive integers. - * The solution set must not contain duplicate combinations. - * - * - * Example 1: - * - * - * Input: candidates = [10,1,2,7,6,1,5], target = 8, - * A solution set is: - * [ - * [1, 7], - * [1, 2, 5], - * [2, 6], - * [1, 1, 6] - * ] - * - * - * Example 2: - * - * - * Input: candidates = [2,5,2,1,2], target = 5, - * A solution set is: - * [ - * [1,2,2], - * [5] - * ] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/combination-sum-ii/ -// discuss: https://leetcode.com/problems/combination-sum-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn combination_sum2(candidates: Vec, target: i32) -> Vec> { - let mut seq = candidates; - let mut res = Vec::new(); - seq.sort_unstable_by(|a, b| b.cmp(a)); - let mut vec = Vec::new(); - Solution::backtrack(&seq, target, vec, &mut res, 0); - res - } - - fn backtrack( - seq: &Vec, - target: i32, - mut curr: Vec, - result: &mut Vec>, - start_idx: usize, - ) { - let mut i = start_idx; - while i < seq.len() { - let item = seq[i]; - if target - item < 0 { - i += 1; - continue; - } - let mut new_vec = curr.clone(); - new_vec.push(item); - if target == item { - result.push(new_vec); - } else { - Solution::backtrack(seq, target - item, new_vec, result, i + 1); - } - // skip duplicate result - while i < seq.len() && seq[i] == item { - i += 1; - } - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_40() { - assert_eq!( - Solution::combination_sum2(vec![1, 1, 1, 1, 1, 1, 1], 7), - vec![vec![1, 1, 1, 1, 1, 1, 1]] - ); - assert_eq!( - Solution::combination_sum2(vec![10, 1, 2, 7, 6, 1, 5], 8), - vec![vec![7, 1], vec![6, 2], vec![6, 1, 1], vec![5, 2, 1],] - ); - assert_eq!( - Solution::combination_sum2(vec![2, 5, 2, 1, 2], 5), - vec![vec![5], vec![2, 2, 1],] - ); - } -} diff --git a/src/solution/s0041_first_missing_positive.rs b/src/solution/s0041_first_missing_positive.rs deleted file mode 100644 index 80cd8d8e..00000000 --- a/src/solution/s0041_first_missing_positive.rs +++ /dev/null @@ -1,91 +0,0 @@ -/** - * [41] First Missing Positive - * - * Given an unsorted integer array, find the smallest missing positive integer. - * - * Example 1: - * - * - * Input: [1,2,0] - * Output: 3 - * - * - * Example 2: - * - * - * Input: [3,4,-1,1] - * Output: 2 - * - * - * Example 3: - * - * - * Input: [7,8,9,11,12] - * Output: 1 - * - * - * Note: - * - * Your algorithm should run in O(n) time and uses constant extra space. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/first-missing-positive/ -// discuss: https://leetcode.com/problems/first-missing-positive/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn first_missing_positive(nums: Vec) -> i32 { - let mut nums = nums; - let len = nums.len(); - let mut i = 0; - let mut c = 0; - while i < len { - let num = nums[i]; - if num > 0 && num - 1 < (len as i32) { - c += 1; - nums.swap((num - 1) as usize, i); - if (num - 1) > (i as i32) && (num != nums[i]) { - continue; - } - } - i += 1; - } - println!("{}", c); - for (i, &num) in nums.iter().enumerate() { - if num != ((i + 1) as i32) { - return (i + 1) as i32; - } - } - return (len + 1) as i32; - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_41() { - assert_eq!(Solution::first_missing_positive(vec![2, 2]), 1); - assert_eq!( - Solution::first_missing_positive(vec![12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2]), - 1 - ); - assert_eq!( - Solution::first_missing_positive(vec![2, 2, 2, 2, 2, 2, 2]), - 1 - ); - assert_eq!(Solution::first_missing_positive(vec![3, 4, -1, 1]), 2); - assert_eq!(Solution::first_missing_positive(vec![2, 1, 0]), 3); - assert_eq!(Solution::first_missing_positive(vec![7, 8, 9, 11, 12]), 1); - assert_eq!( - Solution::first_missing_positive(vec![7, 8, 1, 2, 3, 3, 3, 3, 3, 3, 3, -5, -7, 1234]), - 4 - ); - } -} diff --git a/src/solution/s0042_trapping_rain_water.rs b/src/solution/s0042_trapping_rain_water.rs deleted file mode 100644 index 9d961994..00000000 --- a/src/solution/s0042_trapping_rain_water.rs +++ /dev/null @@ -1,38 +0,0 @@ -/** - * [42] Trapping Rain Water - * - * Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining. - * - *
- * The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image! - * - * Example: - * - * - * Input: [0,1,0,2,1,0,1,3,2,1,2,1] - * Output: 6 - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/trapping-rain-water/ -// discuss: https://leetcode.com/problems/trapping-rain-water/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// TODO -impl Solution { - pub fn trap(height: Vec) -> i32 { - 0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_42() {} -} diff --git a/src/solution/s0043_multiply_strings.rs b/src/solution/s0043_multiply_strings.rs deleted file mode 100644 index 8c487b8e..00000000 --- a/src/solution/s0043_multiply_strings.rs +++ /dev/null @@ -1,67 +0,0 @@ -/** - * [43] Multiply Strings - * - * Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2, also represented as a string. - * - * Example 1: - * - * - * Input: num1 = "2", num2 = "3" - * Output: "6" - * - * Example 2: - * - * - * Input: num1 = "123", num2 = "456" - * Output: "56088" - * - * - * Note: - * - *
    - * The length of both num1 and num2 is < 110. - * Both num1 and num2 contain only digits 0-9. - * Both num1 and num2 do not contain any leading zero, except the number 0 itself. - * You must not use any built-in BigInteger library or convert the inputs to integer directly. - *
- * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/multiply-strings/ -// discuss: https://leetcode.com/problems/multiply-strings/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// TODO -use std::char::from_digit; -use std::collections::VecDeque; -impl Solution { - pub fn multiply(num1: String, num2: String) -> String { - let mut num1: Vec = num1.chars().map(|ch| ch.to_digit(10).unwrap()).collect(); - let mut num2: Vec = num2.chars().map(|ch| ch.to_digit(10).unwrap()).collect(); - let mut buffer = VecDeque::with_capacity(num2.len() + 1); - let mut res: Vec = Vec::new(); - let mut carry = 0_u32; - num1.reverse(); - num2.reverse(); - for (i, multiplier) in num1.into_iter().enumerate() { - buffer - .pop_back() - .and_then(|digit| Some(res.push(from_digit(digit, 10).unwrap()))); - for &multiplicand in num2.iter() {} - } - res.reverse(); - res.into_iter().collect() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_43() {} -} diff --git a/src/solution/s0044_wildcard_matching.rs b/src/solution/s0044_wildcard_matching.rs deleted file mode 100644 index e875131a..00000000 --- a/src/solution/s0044_wildcard_matching.rs +++ /dev/null @@ -1,91 +0,0 @@ -/** - * [44] Wildcard Matching - * - * Given an input string (s) and a pattern (p), implement wildcard pattern matching with support for '?' and '*'. - * - * - * '?' Matches any single character. - * '*' Matches any sequence of characters (including the empty sequence). - * - * - * The matching should cover the entire input string (not partial). - * - * Note: - * - * - * s could be empty and contains only lowercase letters a-z. - * p could be empty and contains only lowercase letters a-z, and characters like ? or *. - * - * - * Example 1: - * - * - * Input: - * s = "aa" - * p = "a" - * Output: false - * Explanation: "a" does not match the entire string "aa". - * - * - * Example 2: - * - * - * Input: - * s = "aa" - * p = "*" - * Output: true - * Explanation: '*' matches any sequence. - * - * - * Example 3: - * - * - * Input: - * s = "cb" - * p = "?a" - * Output: false - * Explanation: '?' matches 'c', but the second letter is 'a', which does not match 'b'. - * - * - * Example 4: - * - * - * Input: - * s = "adceb" - * p = "*a*b" - * Output: true - * Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce". - * - * - * Example 5: - * - * - * Input: - * s = "acdcb" - * p = "a*c?b" - * Output: false - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/wildcard-matching/ -// discuss: https://leetcode.com/problems/wildcard-matching/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn is_match(s: String, p: String) -> bool { - false - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_44() {} -} diff --git a/src/solution/s0045_jump_game_ii.rs b/src/solution/s0045_jump_game_ii.rs deleted file mode 100644 index 3922e20b..00000000 --- a/src/solution/s0045_jump_game_ii.rs +++ /dev/null @@ -1,45 +0,0 @@ -/** - * [45] Jump Game II - * - * Given an array of non-negative integers, you are initially positioned at the first index of the array. - * - * Each element in the array represents your maximum jump length at that position. - * - * Your goal is to reach the last index in the minimum number of jumps. - * - * Example: - * - * - * Input: [2,3,1,1,4] - * Output: 2 - * Explanation: The minimum number of jumps to reach the last index is 2. - * Jump 1 step from index 0 to 1, then 3 steps to the last index. - * - * Note: - * - * You can assume that you can always reach the last index. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/jump-game-ii/ -// discuss: https://leetcode.com/problems/jump-game-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// TODO: shortest path from backward -impl Solution { - pub fn jump(nums: Vec) -> i32 { - 0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_45() {} -} diff --git a/src/solution/s0046_permutations.rs b/src/solution/s0046_permutations.rs deleted file mode 100644 index ef9354c8..00000000 --- a/src/solution/s0046_permutations.rs +++ /dev/null @@ -1,70 +0,0 @@ -/** - * [46] Permutations - * - * Given a collection of distinct integers, return all possible permutations. - * - * Example: - * - * - * Input: [1,2,3] - * Output: - * [ - * [1,2,3], - * [1,3,2], - * [2,1,3], - * [2,3,1], - * [3,1,2], - * [3,2,1] - * ] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/permutations/ -// discuss: https://leetcode.com/problems/permutations/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn permute(nums: Vec) -> Vec> { - if nums.len() <= 1 { - return vec![nums]; - } - nums.iter() - .flat_map(|&num| { - let mut sub = nums.clone().into_iter().filter(|&x| x != num).collect(); - Solution::permute(sub) - .into_iter() - .map(|vec| { - let mut vec = vec; - vec.push(num); - vec - }) - .collect::>>() - }) - .collect() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_46() { - assert_eq!( - Solution::permute(vec![1, 2, 3]), - vec![ - vec![3, 2, 1], - vec![2, 3, 1], - vec![3, 1, 2], - vec![1, 3, 2], - vec![2, 1, 3], - vec![1, 2, 3], - ] - ) - } -} diff --git a/src/solution/s0047_permutations_ii.rs b/src/solution/s0047_permutations_ii.rs deleted file mode 100644 index 7dceb55b..00000000 --- a/src/solution/s0047_permutations_ii.rs +++ /dev/null @@ -1,179 +0,0 @@ -/** - * [47] Permutations II - * - * Given a collection of numbers that might contain duplicates, return all possible unique permutations. - * - * Example: - * - * - * Input: [1,1,2] - * Output: - * [ - * [1,1,2], - * [1,2,1], - * [2,1,1] - * ] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/permutations-ii/ -// discuss: https://leetcode.com/problems/permutations-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn permute_unique(nums: Vec) -> Vec> { - let mut nums = nums; - nums.sort_unstable(); - Solution::permute(nums) - } - - fn permute(mut nums: Vec) -> Vec> { - if nums.len() <= 1 { - return vec![nums]; - } - let mut prev: Option = None; - let mut res = Vec::new(); - for (i, &num) in nums.iter().enumerate() { - if prev.is_some() && prev.unwrap() == num { - continue; - } else { - prev = Some(num) - } - let mut sub = nums.clone(); - sub.remove(i); - let mut permutations: Vec> = Solution::permute(sub) - .into_iter() - .map(|x| { - let mut x = x; - x.push(num); - x - }) - .collect(); - res.append(&mut permutations); - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_47() { - assert_eq!( - Solution::permute(vec![1, 1, 2]), - vec![vec![2, 1, 1], vec![1, 2, 1], vec![1, 1, 2],] - ); - assert_eq!(Solution::permute(vec![1, 1, 1]), vec![vec![1, 1, 1],]); - assert_eq!( - Solution::permute(vec![1, 1, 1, 2]), - vec![ - vec![2, 1, 1, 1], - vec![1, 2, 1, 1], - vec![1, 1, 2, 1], - vec![1, 1, 1, 2], - ] - ); - assert_eq!( - Solution::permute(vec![1, 1, 2, 2, 3, 3]), - vec![ - vec![3, 3, 2, 2, 1, 1], - vec![3, 2, 3, 2, 1, 1], - vec![2, 3, 3, 2, 1, 1], - vec![3, 2, 2, 3, 1, 1], - vec![2, 3, 2, 3, 1, 1], - vec![2, 2, 3, 3, 1, 1], - vec![3, 3, 2, 1, 2, 1], - vec![3, 2, 3, 1, 2, 1], - vec![2, 3, 3, 1, 2, 1], - vec![3, 3, 1, 2, 2, 1], - vec![3, 1, 3, 2, 2, 1], - vec![1, 3, 3, 2, 2, 1], - vec![3, 2, 1, 3, 2, 1], - vec![2, 3, 1, 3, 2, 1], - vec![3, 1, 2, 3, 2, 1], - vec![1, 3, 2, 3, 2, 1], - vec![2, 1, 3, 3, 2, 1], - vec![1, 2, 3, 3, 2, 1], - vec![3, 2, 2, 1, 3, 1], - vec![2, 3, 2, 1, 3, 1], - vec![2, 2, 3, 1, 3, 1], - vec![3, 2, 1, 2, 3, 1], - vec![2, 3, 1, 2, 3, 1], - vec![3, 1, 2, 2, 3, 1], - vec![1, 3, 2, 2, 3, 1], - vec![2, 1, 3, 2, 3, 1], - vec![1, 2, 3, 2, 3, 1], - vec![2, 2, 1, 3, 3, 1], - vec![2, 1, 2, 3, 3, 1], - vec![1, 2, 2, 3, 3, 1], - vec![3, 3, 2, 1, 1, 2], - vec![3, 2, 3, 1, 1, 2], - vec![2, 3, 3, 1, 1, 2], - vec![3, 3, 1, 2, 1, 2], - vec![3, 1, 3, 2, 1, 2], - vec![1, 3, 3, 2, 1, 2], - vec![3, 2, 1, 3, 1, 2], - vec![2, 3, 1, 3, 1, 2], - vec![3, 1, 2, 3, 1, 2], - vec![1, 3, 2, 3, 1, 2], - vec![2, 1, 3, 3, 1, 2], - vec![1, 2, 3, 3, 1, 2], - vec![3, 3, 1, 1, 2, 2], - vec![3, 1, 3, 1, 2, 2], - vec![1, 3, 3, 1, 2, 2], - vec![3, 1, 1, 3, 2, 2], - vec![1, 3, 1, 3, 2, 2], - vec![1, 1, 3, 3, 2, 2], - vec![3, 2, 1, 1, 3, 2], - vec![2, 3, 1, 1, 3, 2], - vec![3, 1, 2, 1, 3, 2], - vec![1, 3, 2, 1, 3, 2], - vec![2, 1, 3, 1, 3, 2], - vec![1, 2, 3, 1, 3, 2], - vec![3, 1, 1, 2, 3, 2], - vec![1, 3, 1, 2, 3, 2], - vec![1, 1, 3, 2, 3, 2], - vec![2, 1, 1, 3, 3, 2], - vec![1, 2, 1, 3, 3, 2], - vec![1, 1, 2, 3, 3, 2], - vec![3, 2, 2, 1, 1, 3], - vec![2, 3, 2, 1, 1, 3], - vec![2, 2, 3, 1, 1, 3], - vec![3, 2, 1, 2, 1, 3], - vec![2, 3, 1, 2, 1, 3], - vec![3, 1, 2, 2, 1, 3], - vec![1, 3, 2, 2, 1, 3], - vec![2, 1, 3, 2, 1, 3], - vec![1, 2, 3, 2, 1, 3], - vec![2, 2, 1, 3, 1, 3], - vec![2, 1, 2, 3, 1, 3], - vec![1, 2, 2, 3, 1, 3], - vec![3, 2, 1, 1, 2, 3], - vec![2, 3, 1, 1, 2, 3], - vec![3, 1, 2, 1, 2, 3], - vec![1, 3, 2, 1, 2, 3], - vec![2, 1, 3, 1, 2, 3], - vec![1, 2, 3, 1, 2, 3], - vec![3, 1, 1, 2, 2, 3], - vec![1, 3, 1, 2, 2, 3], - vec![1, 1, 3, 2, 2, 3], - vec![2, 1, 1, 3, 2, 3], - vec![1, 2, 1, 3, 2, 3], - vec![1, 1, 2, 3, 2, 3], - vec![2, 2, 1, 1, 3, 3], - vec![2, 1, 2, 1, 3, 3], - vec![1, 2, 2, 1, 3, 3], - vec![2, 1, 1, 2, 3, 3], - vec![1, 2, 1, 2, 3, 3], - vec![1, 1, 2, 2, 3, 3] - ] - ); - } -} diff --git a/src/solution/s0048_rotate_image.rs b/src/solution/s0048_rotate_image.rs deleted file mode 100644 index 6f6fdffa..00000000 --- a/src/solution/s0048_rotate_image.rs +++ /dev/null @@ -1,122 +0,0 @@ -/** - * [48] Rotate Image - * - * You are given an n x n 2D matrix representing an image. - * - * Rotate the image by 90 degrees (clockwise). - * - * Note: - * - * You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation. - * - * Example 1: - * - * - * Given input matrix = - * [ - * [1,2,3], - * [4,5,6], - * [7,8,9] - * ], - * - * rotate the input matrix in-place such that it becomes: - * [ - * [7,4,1], - * [8,5,2], - * [9,6,3] - * ] - * - * - * Example 2: - * - * - * Given input matrix = - * [ - * [ 5, 1, 9,11], - * [ 2, 4, 8,10], - * [13, 3, 6, 7], - * [15,14,12,16] - * ], - * - * rotate the input matrix in-place such that it becomes: - * [ - * [15,13, 2, 5], - * [14, 3, 4, 1], - * [12, 6, 8, 9], - * [16, 7,10,11] - * ] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/rotate-image/ -// discuss: https://leetcode.com/problems/rotate-image/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// x,y -> y,n-x 2-dimension vector rotate -90 degree: -// ^ x 0 1 y -// | | * = -// v y -1 0 -x -// n-y,x <- n-x,n-y if we consider axis transform, then: rotate(x, y) = (y, -x + n) - -// we only need to iterate a 1/4 corner matrix, for odd matrix, we take an extra part in x direction -// -// even: -// -// x x o o -// x x o o -// o o o o -// o o o o -// -// odd: -// -// x x o o o -// x x o o o -// x x o o o -// o o o o o -// o o o o o - -impl Solution { - pub fn rotate(matrix: &mut Vec>) { - let mut matrix = matrix; - let (len, n) = (matrix.len(), matrix.len() - 1); - for x in 0..len / 2 { - for y in 0..(len + 1) / 2 { - let temp = matrix[x][y]; - matrix[x][y] = matrix[n - y][x]; - matrix[n - y][x] = matrix[n - x][n - y]; - matrix[n - x][n - y] = matrix[y][n - x]; - matrix[y][n - x] = temp; - } - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_48() { - let mut matrix = vec![ - vec![5, 1, 9, 11], - vec![2, 4, 8, 10], - vec![13, 3, 6, 7], - vec![15, 14, 12, 16], - ]; - Solution::rotate(&mut matrix); - assert_eq!( - matrix, - vec![ - vec![15, 13, 2, 5], - vec![14, 3, 4, 1], - vec![12, 6, 8, 9], - vec![16, 7, 10, 11] - ] - ); - } -} diff --git a/src/solution/s0049_group_anagrams.rs b/src/solution/s0049_group_anagrams.rs deleted file mode 100644 index 64200ea3..00000000 --- a/src/solution/s0049_group_anagrams.rs +++ /dev/null @@ -1,67 +0,0 @@ -/** - * [49] Group Anagrams - * - * Given an array of strings, group anagrams together. - * - * Example: - * - * - * Input: ["eat", "tea", "tan", "ate", "nat", "bat"], - * Output: - * [ - * ["ate","eat","tea"], - * ["nat","tan"], - * ["bat"] - * ] - * - * Note: - * - * - * All inputs will be in lowercase. - * The order of your output does not matter. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/group-anagrams/ -// discuss: https://leetcode.com/problems/group-anagrams/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::collections::HashMap; -impl Solution { - pub fn group_anagrams(strs: Vec) -> Vec> { - let mut map = HashMap::new(); - for s in strs.into_iter() { - let mut key = [0; 26]; - for ch in s.chars() { - key[(ch as u32 - 'a' as u32) as usize] += 1; - } - map.entry(key).or_insert(Vec::new()).push(s); - } - map.into_iter().map(|(_, v)| v).collect() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - use std::collections::HashSet; - // TODO: implement arbitrary match macro - #[test] - #[ignore] - fn test_49() { - assert_eq!( - Solution::group_anagrams(vec_string!["eat", "tea", "tan", "ate", "nat", "bat"]), - vec![ - vec_string!["tan", "nat"], - vec_string!["bat"], - vec_string!["eat", "ate", "tea"], - ] - ); - } -} diff --git a/src/solution/s0050_powx_n.rs b/src/solution/s0050_powx_n.rs deleted file mode 100644 index 3e2e9b3e..00000000 --- a/src/solution/s0050_powx_n.rs +++ /dev/null @@ -1,64 +0,0 @@ -/** - * [50] Pow(x, n) - * - * Implement pow(x, n), which calculates x raised to the power n (x^n). - * - * Example 1: - * - * - * Input: 2.00000, 10 - * Output: 1024.00000 - * - * - * Example 2: - * - * - * Input: 2.10000, 3 - * Output: 9.26100 - * - * - * Example 3: - * - * - * Input: 2.00000, -2 - * Output: 0.25000 - * Explanation: 2^-2 = 1/2^2 = 1/4 = 0.25 - * - * - * Note: - * - * - * -100.0 < x < 100.0 - * n is a 32-bit signed integer, within the range [-2^31, 2^31 - 1] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/powx-n/ -// discuss: https://leetcode.com/problems/powx-n/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn my_pow(x: f64, n: i32) -> f64 { - x.powi(n) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_50() { - assert_eq!(Solution::my_pow(2.0, -2), 0.25); - assert_eq!(Solution::my_pow(2.0, 4), 16.0); - assert_eq!(Solution::my_pow(2.0, 5), 32.0); - assert_eq!(Solution::my_pow(2.0, 1), 2.0); - assert_eq!(Solution::my_pow(2.0, -1), 0.5); - assert_eq!(Solution::my_pow(2.0, 10), 1024.0); - } -} diff --git a/src/solution/s0051_n_queens.rs b/src/solution/s0051_n_queens.rs deleted file mode 100644 index d78435a9..00000000 --- a/src/solution/s0051_n_queens.rs +++ /dev/null @@ -1,109 +0,0 @@ -/** - * [51] N-Queens - * - * The n-queens puzzle is the problem of placing n queens on an n*n chessboard such that no two queens attack each other. - * - * - * - * Given an integer n, return all distinct solutions to the n-queens puzzle. - * - * Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively. - * - * Example: - * - * - * Input: 4 - * Output: [ - * [".Q..", // Solution 1 - * "...Q", - * "Q...", - * "..Q."], - * - * ["..Q.", // Solution 2 - * "Q...", - * "...Q", - * ".Q.."] - * ] - * Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/n-queens/ -// discuss: https://leetcode.com/problems/n-queens/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn solve_n_queens(n: i32) -> Vec> { - let mut board = vec![vec!['.'; n as usize]; n as usize]; - let mut solution = Vec::new(); - Solution::schedule_queens(&mut board, &mut solution, n as usize, 0); - solution - } - - fn schedule_queens( - board: &mut Vec>, - solution: &mut Vec>, - len: usize, - row: usize, - ) { - for col in 0..len { - if !Solution::collision(&board, len, row, col) { - board[row][col] = 'Q'; - if row == len - 1 { - solution.push(board.iter().map(|vec| vec.iter().collect()).collect()); - } else { - Solution::schedule_queens(board, solution, len, row + 1); - } - board[row][col] = '.'; - } - } - } - - #[inline(always)] - fn collision(board: &Vec>, len: usize, x: usize, y: usize) -> bool { - for i in 0..x { - if board[i][y] == 'Q' { - return true; - } - } - let (mut i, mut j) = (x as i32 - 1, y as i32 - 1); - while i >= 0 && j >= 0 { - if board[i as usize][j as usize] == 'Q' { - return true; - } - i -= 1; - j -= 1; - } - let (mut i, mut j) = (x as i32 - 1, y as i32 + 1); - while i >= 0 && j < len as i32 { - if board[i as usize][j as usize] == 'Q' { - return true; - } - i -= 1; - j += 1; - } - false - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_51() { - assert_eq!( - Solution::solve_n_queens(4), - vec![ - vec![".Q..", "...Q", "Q...", "..Q."], - vec!["..Q.", "Q...", "...Q", ".Q.."] - ] - ); - assert_eq!(Solution::solve_n_queens(8).len(), 92); - } -} diff --git a/src/solution/s0052_n_queens_ii.rs b/src/solution/s0052_n_queens_ii.rs deleted file mode 100644 index 7c9b1987..00000000 --- a/src/solution/s0052_n_queens_ii.rs +++ /dev/null @@ -1,99 +0,0 @@ -/** - * [52] N-Queens II - * - * The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other. - * - * - * - * Given an integer n, return the number of distinct solutions to the n-queens puzzle. - * - * Example: - * - * - * Input: 4 - * Output: 2 - * Explanation: There are two distinct solutions to the 4-queens puzzle as shown below. - * [ - * [".Q..", // Solution 1 - * "...Q", - * "Q...", - * "..Q."], - * - * ["..Q.", // Solution 2 - * "Q...", - * "...Q", - * ".Q.."] - * ] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/n-queens-ii/ -// discuss: https://leetcode.com/problems/n-queens-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn total_n_queens(n: i32) -> i32 { - let mut board = vec![vec!['.'; n as usize]; n as usize]; - let mut num = 0; - Solution::schedule_queens(&mut board, &mut num, n as usize, 0); - num - } - - fn schedule_queens(board: &mut Vec>, num: &mut i32, len: usize, row: usize) { - for col in 0..len { - if !Solution::collision(&board, len, row, col) { - board[row][col] = 'Q'; - if row == len - 1 { - *num += 1; - } else { - Solution::schedule_queens(board, num, len, row + 1); - } - board[row][col] = '.'; - } - } - } - - #[inline(always)] - fn collision(board: &Vec>, len: usize, x: usize, y: usize) -> bool { - for i in 0..x { - if board[i][y] == 'Q' { - return true; - } - } - let (mut i, mut j) = (x as i32 - 1, y as i32 - 1); - while i >= 0 && j >= 0 { - if board[i as usize][j as usize] == 'Q' { - return true; - } - i -= 1; - j -= 1; - } - let (mut i, mut j) = (x as i32 - 1, y as i32 + 1); - while i >= 0 && j < len as i32 { - if board[i as usize][j as usize] == 'Q' { - return true; - } - i -= 1; - j += 1; - } - false - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_52() { - assert_eq!(Solution::total_n_queens(4), 2); - assert_eq!(Solution::total_n_queens(8), 92); - assert_eq!(Solution::total_n_queens(13), 73712); - // assert_eq!(Solution::total_n_queens(14), 365596); - } -} diff --git a/src/solution/s0053_maximum_subarray.rs b/src/solution/s0053_maximum_subarray.rs deleted file mode 100644 index 7967fb00..00000000 --- a/src/solution/s0053_maximum_subarray.rs +++ /dev/null @@ -1,57 +0,0 @@ -/** - * [53] Maximum Subarray - * - * Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. - * - * Example: - * - * - * Input: [-2,1,-3,4,-1,2,1,-5,4], - * Output: 6 - * Explanation: [4,-1,2,1] has the largest sum = 6. - * - * - * Follow up: - * - * If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/maximum-subarray/ -// discuss: https://leetcode.com/problems/maximum-subarray/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn max_sub_array(nums: Vec) -> i32 { - let mut j = 0_usize; - let mut max = i32::min_value(); - let mut curr = 0; - for j in 0..nums.len() { - curr += nums[j]; - max = i32::max(max, curr); - if curr <= 0 { - curr = 0; - } - } - max - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_53() { - assert_eq!( - Solution::max_sub_array(vec![-2, 1, -3, 4, -1, 2, 1, -5, 4]), - 6 - ); - assert_eq!(Solution::max_sub_array(vec![-8]), -8); - assert_eq!(Solution::max_sub_array(vec![-8, -2]), -2); - } -} diff --git a/src/solution/s0054_spiral_matrix.rs b/src/solution/s0054_spiral_matrix.rs deleted file mode 100644 index ac90b769..00000000 --- a/src/solution/s0054_spiral_matrix.rs +++ /dev/null @@ -1,101 +0,0 @@ -/** - * [54] Spiral Matrix - * - * Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order. - * - * Example 1: - * - * - * Input: - * [ - * [ 1, 2, 3 ], - * [ 4, 5, 6 ], - * [ 7, 8, 9 ] - * ] - * Output: [1,2,3,6,9,8,7,4,5] - * - * - * Example 2: - * - * Input: - * [ - * [1, 2, 3, 4], - * [5, 6, 7, 8], - * [9,10,11,12] - * ] - * Output: [1,2,3,4,8,12,11,10,9,5,6,7] - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/spiral-matrix/ -// discuss: https://leetcode.com/problems/spiral-matrix/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn spiral_order(matrix: Vec>) -> Vec { - let mut res = Vec::new(); - if matrix.len() < 1 { - return res; - } - let (height, width) = (matrix.len(), matrix[0].len()); - let (mut x_min, mut x_max, mut y_min, mut y_max) = (0, height, 0, width); - loop { - for y in y_min..y_max { - res.push(matrix[x_min][y]) - } - x_min += 1; - if x_min == x_max { - break; - } - for x in x_min..x_max { - res.push(matrix[x][y_max - 1]) - } - y_max -= 1; - if y_min == y_max { - break; - } - for y in (y_min..y_max).rev() { - res.push(matrix[x_max - 1][y]) - } - x_max -= 1; - if x_min == x_max { - break; - } - for x in (x_min..x_max).rev() { - res.push(matrix[x][y_min]) - } - y_min += 1; - if y_min == y_max { - break; - } - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_54() { - assert_eq!( - Solution::spiral_order(vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]]), - vec![1, 2, 3, 6, 9, 8, 7, 4, 5] - ); - assert_eq!(Solution::spiral_order(vec![vec![1, 2, 3]]), vec![1, 2, 3]); - assert_eq!( - Solution::spiral_order(vec![vec![1], vec![2], vec![3],]), - vec![1, 2, 3] - ); - assert_eq!(Solution::spiral_order(vec![vec![1],]), vec![1]); - assert_eq!( - Solution::spiral_order(vec![vec![1, 2], vec![4, 5],]), - vec![1, 2, 5, 4] - ); - } -} diff --git a/src/solution/s0055_jump_game.rs b/src/solution/s0055_jump_game.rs deleted file mode 100644 index 8dc35842..00000000 --- a/src/solution/s0055_jump_game.rs +++ /dev/null @@ -1,66 +0,0 @@ -/** - * [55] Jump Game - * - * Given an array of non-negative integers, you are initially positioned at the first index of the array. - * - * Each element in the array represents your maximum jump length at that position. - * - * Determine if you are able to reach the last index. - * - * Example 1: - * - * - * Input: [2,3,1,1,4] - * Output: true - * Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index. - * - * - * Example 2: - * - * - * Input: [3,2,1,0,4] - * Output: false - * Explanation: You will always arrive at index 3 no matter what. Its maximum - * jump length is 0, which makes it impossible to reach the last index. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/jump-game/ -// discuss: https://leetcode.com/problems/jump-game/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn can_jump(nums: Vec) -> bool { - let mut max_idx = 0_usize; - let mut start = 0_usize; - while start < nums.len() && start <= max_idx { - max_idx = usize::max(start + nums[start] as usize, max_idx); - start += 1; - } - return max_idx >= (nums.len() - 1); - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_55() { - assert_eq!(Solution::can_jump(vec![2, 3, 1, 1, 4]), true); - assert_eq!(Solution::can_jump(vec![3, 2, 1, 0, 4]), false); - assert_eq!(Solution::can_jump(vec![2, 3, 1, 1, 0, 0, 0, 4]), false); - assert_eq!(Solution::can_jump(vec![8, 3, 1, 1, 0, 0, 0, 4]), true); - assert_eq!(Solution::can_jump(vec![0]), true); - assert_eq!(Solution::can_jump(vec![1, 1, 2, 2, 0, 1, 1]), true); - assert_eq!( - Solution::can_jump(vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0]), - true - ); - } -} diff --git a/src/solution/s0056_merge_intervals.rs b/src/solution/s0056_merge_intervals.rs deleted file mode 100644 index 108c043b..00000000 --- a/src/solution/s0056_merge_intervals.rs +++ /dev/null @@ -1,85 +0,0 @@ -/** - * [56] Merge Intervals - * - * Given a collection of intervals, merge all overlapping intervals. - * - * Example 1: - * - * - * Input: [[1,3],[2,6],[8,10],[15,18]] - * Output: [[1,6],[8,10],[15,18]] - * Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6]. - * - * - * Example 2: - * - * - * Input: [[1,4],[4,5]] - * Output: [[1,5]] - * Explanation: Intervals [1,4] and [4,5] are considered overlapping. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/merge-intervals/ -// discuss: https://leetcode.com/problems/merge-intervals/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// Definition for an interval. -#[derive(Debug, PartialEq, Eq)] -pub struct Interval { - pub start: i32, - pub end: i32, -} - -impl Interval { - #[inline] - pub fn new(start: i32, end: i32) -> Self { - Interval { start, end } - } -} -impl Solution { - pub fn merge(intervals: Vec) -> Vec { - let mut intervals = intervals; - intervals.sort_unstable_by_key(|interval| interval.start); - let mut result: Vec = Vec::new(); - for interval in intervals.into_iter() { - match result.last_mut() { - Some(mut last_inter) => { - if last_inter.end >= interval.start { - last_inter.end = i32::max(last_inter.end, interval.end); - continue; - } - } - None => {} - } - result.push(interval); - } - result - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_56() { - assert_eq!( - Solution::merge(vec![ - Interval::new(1, 3), - Interval::new(2, 6), - Interval::new(8, 10), - Interval::new(15, 18) - ]), - vec![ - Interval::new(1, 6), - Interval::new(8, 10), - Interval::new(15, 18) - ] - ); - } -} diff --git a/src/solution/s0057_insert_interval.rs b/src/solution/s0057_insert_interval.rs deleted file mode 100644 index 0afe62b4..00000000 --- a/src/solution/s0057_insert_interval.rs +++ /dev/null @@ -1,126 +0,0 @@ -/** - * [57] Insert Interval - * - * Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary). - * - * You may assume that the intervals were initially sorted according to their start times. - * - * Example 1: - * - * - * Input: intervals = [[1,3],Interval::new(6,9)], newInterval = [2,5] - * Output: [[1,5],[6,9]] - * - * - * Example 2: - * - * - * Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8] - * Output: [[1,2],[3,10],[12,16]] - * Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10]. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/insert-interval/ -// discuss: https://leetcode.com/problems/insert-interval/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// Definition for an interval. -#[derive(Debug, PartialEq, Eq)] -pub struct Interval { - pub start: i32, - pub end: i32, -} - -impl Interval { - #[inline] - pub fn new(start: i32, end: i32) -> Self { - Interval { start, end } - } -} -impl Solution { - pub fn insert(intervals: Vec, new_interval: Interval) -> Vec { - let mut result = Vec::new(); - let mut new_interval = new_interval; - let mut inserting = false; - let mut inserted = false; - for interval in intervals.into_iter() { - if new_interval.start <= interval.end && !inserted { - inserting = true; - } - if inserting { - if new_interval.end >= interval.start { - new_interval.start = i32::min(new_interval.start, interval.start); - new_interval.end = i32::max(new_interval.end, interval.end); - } else { - result.push(Interval::new(new_interval.start, new_interval.end)); - inserting = false; - inserted = true; - } - } - if !inserting { - result.push(interval); - } - } - if !inserted { - result.push(new_interval); - } - result - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_57() { - assert_eq!( - Solution::insert( - vec![Interval::new(1, 3), Interval::new(6, 9)], - Interval::new(2, 5) - ), - vec![Interval::new(1, 5), Interval::new(6, 9)] - ); - assert_eq!( - Solution::insert( - vec![ - Interval::new(1, 2), - Interval::new(3, 5), - Interval::new(6, 7), - Interval::new(8, 10), - Interval::new(12, 16) - ], - Interval::new(4, 8) - ), - vec![ - Interval::new(1, 2), - Interval::new(3, 10), - Interval::new(12, 16) - ] - ); - assert_eq!( - Solution::insert(vec![Interval::new(3, 4)], Interval::new(1, 2)), - vec![Interval::new(1, 2), Interval::new(3, 4)] - ); - assert_eq!( - Solution::insert(vec![Interval::new(1, 2)], Interval::new(3, 4)), - vec![Interval::new(1, 2), Interval::new(3, 4)] - ); - assert_eq!( - Solution::insert(vec![Interval::new(1, 2)], Interval::new(2, 3)), - vec![Interval::new(1, 3)] - ); - assert_eq!( - Solution::insert( - vec![Interval::new(1, 2), Interval::new(3, 4)], - Interval::new(0, 6) - ), - vec![Interval::new(0, 6)] - ); - } -} diff --git a/src/solution/s0058_length_of_last_word.rs b/src/solution/s0058_length_of_last_word.rs deleted file mode 100644 index 4889c739..00000000 --- a/src/solution/s0058_length_of_last_word.rs +++ /dev/null @@ -1,55 +0,0 @@ -/** - * [58] Length of Last Word - * - * Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the length of last word in the string. - * - * If the last word does not exist, return 0. - * - * Note: A word is defined as a character sequence consists of non-space characters only. - * - * Example: - * - * Input: "Hello World" - * Output: 5 - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/length-of-last-word/ -// discuss: https://leetcode.com/problems/length-of-last-word/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn length_of_last_word(s: String) -> i32 { - let seq: Vec = s.chars().rev().collect(); - let mut result = 0; - let mut find = false; - for ch in seq { - if ch == ' ' && find { - break; - } - if ch != ' ' { - find = true; - result += 1; - } - } - result - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_58() { - assert_eq!(Solution::length_of_last_word("Hello World".to_owned()), 5); - assert_eq!(Solution::length_of_last_word(" ".to_owned()), 0); - assert_eq!(Solution::length_of_last_word("".to_owned()), 0); - assert_eq!(Solution::length_of_last_word(" rrrrr ".to_owned()), 5); - } -} diff --git a/src/solution/s0059_spiral_matrix_ii.rs b/src/solution/s0059_spiral_matrix_ii.rs deleted file mode 100644 index d54f57b4..00000000 --- a/src/solution/s0059_spiral_matrix_ii.rs +++ /dev/null @@ -1,87 +0,0 @@ -/** - * [59] Spiral Matrix II - * - * Given a positive integer n, generate a square matrix filled with elements from 1 to n^2 in spiral order. - * - * Example: - * - * - * Input: 3 - * Output: - * [ - * [ 1, 2, 3 ], - * [ 8, 9, 4 ], - * [ 7, 6, 5 ] - * ] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/spiral-matrix-ii/ -// discuss: https://leetcode.com/problems/spiral-matrix-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn generate_matrix(n: i32) -> Vec> { - let mut res = vec![vec![0; n as usize]; n as usize]; - if n < 1 { - return res; - } - let (mut x_min, mut x_max, mut y_min, mut y_max) = (0, n as usize, 0, n as usize); - let mut i = 1; - loop { - for y in y_min..y_max { - res[x_min][y] = i; - i += 1; - } - x_min += 1; - if x_min == x_max { - break; - } - for x in x_min..x_max { - res[x][y_max - 1] = i; - i += 1; - } - y_max -= 1; - if y_min == y_max { - break; - } - for y in (y_min..y_max).rev() { - res[x_max - 1][y] = i; - i += 1; - } - x_max -= 1; - if x_min == x_max { - break; - } - for x in (x_min..x_max).rev() { - res[x][y_min] = i; - i += 1; - } - y_min += 1; - if y_min == y_max { - break; - } - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_59() { - assert_eq!(Solution::generate_matrix(1), vec![vec![1]]); - assert_eq!(Solution::generate_matrix(2), vec![vec![1, 2], vec![4, 3]]); - assert_eq!( - Solution::generate_matrix(3), - vec![vec![1, 2, 3], vec![8, 9, 4], vec![7, 6, 5],] - ); - } -} diff --git a/src/solution/s0060_permutation_sequence.rs b/src/solution/s0060_permutation_sequence.rs deleted file mode 100644 index 0136a0b4..00000000 --- a/src/solution/s0060_permutation_sequence.rs +++ /dev/null @@ -1,76 +0,0 @@ -/** - * [60] Permutation Sequence - * - * The set [1,2,3,...,n] contains a total of n! unique permutations. - * - * By listing and labeling all of the permutations in order, we get the following sequence for n = 3: - * - *
    - * "123" - * "132" - * "213" - * "231" - * "312" - * "321" - *
- * - * Given n and k, return the k^th permutation sequence. - * - * Note: - * - * - * Given n will be between 1 and 9 inclusive. - * Given k will be between 1 and n! inclusive. - * - * - * Example 1: - * - * - * Input: n = 3, k = 3 - * Output: "213" - * - * - * Example 2: - * - * - * Input: n = 4, k = 9 - * Output: "2314" - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/permutation-sequence/ -// discuss: https://leetcode.com/problems/permutation-sequence/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// target: split k = i! + j! + ... -use std::char::from_digit; -impl Solution { - pub fn get_permutation(n: i32, k: i32) -> String { - let factorials = [0, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]; - let mut k = k; - let mut i = n; - let mut res = String::new(); - while i > 0 { - if k > factorials[i as usize] { - let round = k / factorials[i as usize]; - if round >= n {} - } else { - i -= 1; - } - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_60() {} -} diff --git a/src/solution/s0061_rotate_list.rs b/src/solution/s0061_rotate_list.rs deleted file mode 100644 index bbfb059f..00000000 --- a/src/solution/s0061_rotate_list.rs +++ /dev/null @@ -1,50 +0,0 @@ -/** - * [61] Rotate List - * - * Given a linked list, rotate the list to the right by k places, where k is non-negative. - * - * Example 1: - * - * - * Input: 1->2->3->4->5->NULL, k = 2 - * Output: 4->5->1->2->3->NULL - * Explanation: - * rotate 1 steps to the right: 5->1->2->3->4->NULL - * rotate 2 steps to the right: 4->5->1->2->3->NULL - * - * - * Example 2: - * - * - * Input: 0->1->2->NULL, k = 4 - * Output: 2->0->1->NULL - * Explanation: - * rotate 1 steps to the right: 2->0->1->NULL - * rotate 2 steps to the right: 1->2->0->NULL - * rotate 3 steps to the right: 0->1->2->NULL - * rotate 4 steps to the right: 2->0->1->NULL - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; - -// problem: https://leetcode.com/problems/rotate-list/ -// discuss: https://leetcode.com/problems/rotate-list/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn rotate_right(head: Option>, k: i32) -> Option> { - None - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_61() {} -} diff --git a/src/solution/s0062_unique_paths.rs b/src/solution/s0062_unique_paths.rs deleted file mode 100644 index 3a158326..00000000 --- a/src/solution/s0062_unique_paths.rs +++ /dev/null @@ -1,80 +0,0 @@ -/** - * [62] Unique Paths - * - * A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). - * - * The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). - * - * How many possible unique paths are there? - * - *
- * Above is a 7 x 3 grid. How many possible unique paths are there? - * - * Note: m and n will be at most 100. - * - * Example 1: - * - * - * Input: m = 3, n = 2 - * Output: 3 - * Explanation: - * From the top-left corner, there are a total of 3 ways to reach the bottom-right corner: - * 1. Right -> Right -> Down - * 2. Right -> Down -> Right - * 3. Down -> Right -> Right - * - * - * Example 2: - * - * - * Input: m = 7, n = 3 - * Output: 28 - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/unique-paths/ -// discuss: https://leetcode.com/problems/unique-paths/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// its high school math: C(r,n) = n! / r!(n-r)! ...are you fxxking kidding me? -// ...high school math will attempt to i32 overflow, we have to do it clever -impl Solution { - pub fn unique_paths(m: i32, n: i32) -> i32 { - let (m, n) = ((m - 1) as u64, (n - 1) as u64); - let sum = m + n; - (Solution::partial_factorial(u64::max(m, n), sum) - / Solution::partial_factorial(0, u64::min(m, n))) as i32 - } - - #[inline(always)] - pub fn partial_factorial(start: u64, mut end: u64) -> u64 { - if start > end { - unreachable!() - } - let mut res = 1; - while end > start { - println!("{}", end); - res *= end; - end -= 1; - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_62() { - assert_eq!(Solution::unique_paths(7, 3), 28); - assert_eq!(Solution::unique_paths(3, 7), 28); - assert_eq!(Solution::unique_paths(1, 1), 1); - assert_eq!(Solution::unique_paths(2, 2), 2); - assert_eq!(Solution::unique_paths(36, 7), 4496388); - } -} diff --git a/src/solution/s0063_unique_paths_ii.rs b/src/solution/s0063_unique_paths_ii.rs deleted file mode 100644 index 04d84911..00000000 --- a/src/solution/s0063_unique_paths_ii.rs +++ /dev/null @@ -1,111 +0,0 @@ -/** - * [63] Unique Paths II - * - * A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). - * - * The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). - * - * Now consider if some obstacles are added to the grids. How many unique paths would there be? - * - * - * - * An obstacle and empty space is marked as 1 and 0 respectively in the grid. - * - * Note: m and n will be at most 100. - * - * Example 1: - * - * - * Input: - * [ - * [0,0,0], - * [0,1,0], - * [0,0,0] - * ] - * Output: 2 - * Explanation: - * There is one obstacle in the middle of the 3x3 grid above. - * There are two ways to reach the bottom-right corner: - * 1. Right -> Right -> Down -> Down - * 2. Down -> Down -> Right -> Right - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/unique-paths-ii/ -// discuss: https://leetcode.com/problems/unique-paths-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// Bottom-Up DP -impl Solution { - pub fn unique_paths_with_obstacles(obstacle_grid: Vec>) -> i32 { - let (height, width) = (obstacle_grid.len(), obstacle_grid[0].len()); - let mut paths: Vec> = vec![vec![0; width]; height]; - if obstacle_grid[0][0] != 1 { - paths[0][0] = 1; - } - let mut step = 1; - while step <= height + width - 2 { - for x in 0..(step + 1) { - let y = step - x; - if x >= height || y >= width || obstacle_grid[x][y] == 1 { - continue; - } - if y >= 1 { - paths[x][y] = paths[x][y] + paths[x][y - 1]; - } - if x >= 1 { - paths[x][y] = paths[x][y] + paths[x - 1][y]; - } - } - step += 1; - } - paths[height - 1][width - 1] - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_63() { - assert_eq!(Solution::unique_paths_with_obstacles(vec![vec![0]]), 1); - assert_eq!( - Solution::unique_paths_with_obstacles(vec![vec![0, 0], vec![0, 0],]), - 2 - ); - assert_eq!( - Solution::unique_paths_with_obstacles(vec![vec![0, 1], vec![1, 0],]), - 0 - ); - assert_eq!( - Solution::unique_paths_with_obstacles(vec![ - vec![0, 0, 0], - vec![0, 1, 0], - vec![0, 0, 0], - ]), - 2 - ); - assert_eq!( - Solution::unique_paths_with_obstacles(vec![ - vec![0, 0, 0, 0], - vec![0, 0, 0, 0], - vec![0, 0, 0, 0], - ]), - 10 - ); - assert_eq!( - Solution::unique_paths_with_obstacles(vec![ - vec![0, 0, 0, 0], - vec![0, 0, 0, 1], - vec![0, 0, 1, 0], - ]), - 0 - ); - } -} diff --git a/src/solution/s0064_minimum_path_sum.rs b/src/solution/s0064_minimum_path_sum.rs deleted file mode 100644 index d6340d50..00000000 --- a/src/solution/s0064_minimum_path_sum.rs +++ /dev/null @@ -1,69 +0,0 @@ -/** - * [64] Minimum Path Sum - * - * Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path. - * - * Note: You can only move either down or right at any point in time. - * - * Example: - * - * - * Input: - * [ - * [1,3,1], - * [1,5,1], - * [4,2,1] - * ] - * Output: 7 - * Explanation: Because the path 1→3→1→1→1 minimizes the sum. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/minimum-path-sum/ -// discuss: https://leetcode.com/problems/minimum-path-sum/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn min_path_sum(grid: Vec>) -> i32 { - let (height, width) = (grid.len(), grid[0].len()); - let mut grid = grid; - let mut step = 1; - while step <= height + width - 2 { - for x in 0..(step + 1) { - let y = step - x; - if x >= height || y >= width { - continue; - } - if x < 1 { - grid[x][y] += grid[x][y - 1]; - } else if y < 1 { - grid[x][y] += grid[x - 1][y]; - } else { - grid[x][y] += i32::min(grid[x][y - 1], grid[x - 1][y]); - } - } - step += 1; - } - grid[height - 1][width - 1] - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_64() { - assert_eq!(Solution::min_path_sum(vec![vec![2]]), 2); - assert_eq!( - Solution::min_path_sum(vec![vec![1, 3, 1], vec![1, 5, 1], vec![4, 2, 1],]), - 7 - ); - assert_eq!(Solution::min_path_sum(vec![vec![1, 3, 1],]), 5); - } -} diff --git a/src/solution/s0065_valid_number.rs b/src/solution/s0065_valid_number.rs deleted file mode 100644 index 11c5753d..00000000 --- a/src/solution/s0065_valid_number.rs +++ /dev/null @@ -1,60 +0,0 @@ -/** - * [65] Valid Number - * - * Validate if a given string can be interpreted as a decimal number. - * - * Some examples:
- * "0" => true
- * " 0.1 " => true
- * "abc" => false
- * "1 a" => false
- * "2e10" => true
- * " -90e3 " => true
- * " 1e" => false
- * "e3" => false
- * " 6e-1" => true
- * " 99e2.5 " => false
- * "53.5e93" => true
- * " --6 " => false
- * "-+3" => false
- * "95a54e53" => false - * - * Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one. However, here is a list of characters that can be in a valid decimal number: - * - * - * Numbers 0-9 - * Exponent - "e" - * Positive/negative sign - "+"/"-" - * Decimal point - "." - * - * - * Of course, the context of these characters also matters in the input. - * - * Update (2015-02-10):
- * The signature of the C++ function had been updated. If you still see your function signature accepts a const char * argument, please click the reload button to reset your code definition. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/valid-number/ -// discuss: https://leetcode.com/problems/valid-number/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// hope that regex was included in std library... -// TODO: NFA -impl Solution { - pub fn is_number(s: String) -> bool { - false - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_65() {} -} diff --git a/src/solution/s0066_plus_one.rs b/src/solution/s0066_plus_one.rs deleted file mode 100644 index fb1ea045..00000000 --- a/src/solution/s0066_plus_one.rs +++ /dev/null @@ -1,72 +0,0 @@ -/** - * [66] Plus One - * - * Given a non-empty array of digits representing a non-negative integer, plus one to the integer. - * - * The digits are stored such that the most significant digit is at the head of the list, and each element in the array contain a single digit. - * - * You may assume the integer does not contain any leading zero, except the number 0 itself. - * - * Example 1: - * - * - * Input: [1,2,3] - * Output: [1,2,4] - * Explanation: The array represents the integer 123. - * - * - * Example 2: - * - * - * Input: [4,3,2,1] - * Output: [4,3,2,2] - * Explanation: The array represents the integer 4321. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/plus-one/ -// discuss: https://leetcode.com/problems/plus-one/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn plus_one(digits: Vec) -> Vec { - let mut digits = digits; - let mut carry = 0; - for i in (0..digits.len()).rev() { - digits[i] = if digits[i] == 9 { - carry = 1; - 0 - } else { - carry = 0; - digits[i] + 1 - }; - if carry == 0 { - break; - } - } - if carry > 0 { - digits.insert(0, 1); - } - digits - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_66() { - assert_eq!(Solution::plus_one(vec![0]), vec![1]); - assert_eq!(Solution::plus_one(vec![9, 9, 9, 9]), vec![1, 0, 0, 0, 0]); - assert_eq!( - Solution::plus_one(vec![1, 0, 9, 9, 9, 9]), - vec![1, 1, 0, 0, 0, 0] - ); - } -} diff --git a/src/solution/s0067_add_binary.rs b/src/solution/s0067_add_binary.rs deleted file mode 100644 index 8c9951cc..00000000 --- a/src/solution/s0067_add_binary.rs +++ /dev/null @@ -1,79 +0,0 @@ -/** - * [67] Add Binary - * - * Given two binary strings, return their sum (also a binary string). - * - * The input strings are both non-empty and contains only characters 1 or 0. - * - * Example 1: - * - * - * Input: a = "11", b = "1" - * Output: "100" - * - * Example 2: - * - * - * Input: a = "1010", b = "1011" - * Output: "10101" - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/add-binary/ -// discuss: https://leetcode.com/problems/add-binary/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::char::from_digit; -impl Solution { - pub fn add_binary(a: String, b: String) -> String { - let mut buf = Vec::with_capacity(usize::max(a.len(), b.len()) + 1); - let mut a: Vec = a.chars().collect(); - let mut b: Vec = b.chars().collect(); - let mut carry = 0; - while !(a.is_empty() && b.is_empty()) { - let mut sum = a.pop().map_or(0, |ch| ch.to_digit(10).unwrap()) - + b.pop().map_or(0, |ch| ch.to_digit(10).unwrap()) - + carry; - if sum > 1 { - sum -= 2; - carry = 1; - } else { - carry = 0; - } - buf.push(from_digit(sum, 10).unwrap()) - } - if carry > 0 { - buf.push('1') - } - buf.into_iter().rev().collect() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_67() { - assert_eq!( - Solution::add_binary("0".to_owned(), "0".to_owned()), - "0".to_owned() - ); - assert_eq!( - Solution::add_binary("1010".to_owned(), "1011".to_owned()), - "10101".to_owned() - ); - assert_eq!( - Solution::add_binary("11".to_owned(), "1".to_owned()), - "100".to_owned() - ); - assert_eq!( - Solution::add_binary("1111".to_owned(), "1111".to_owned()), - "11110".to_owned() - ); - } -} diff --git a/src/solution/s0068_text_justification.rs b/src/solution/s0068_text_justification.rs deleted file mode 100644 index 827fa4f8..00000000 --- a/src/solution/s0068_text_justification.rs +++ /dev/null @@ -1,200 +0,0 @@ -/** - * [68] Text Justification - * - * Given an array of words and a width maxWidth, format the text such that each line has exactly maxWidth characters and is fully (left and right) justified. - * - * You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pad extra spaces ' ' when necessary so that each line has exactly maxWidth characters. - * - * Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line do not divide evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right. - * - * For the last line of text, it should be left justified and no extra space is inserted between words. - * - * Note: - * - * - * A word is defined as a character sequence consisting of non-space characters only. - * Each word's length is guaranteed to be greater than 0 and not exceed maxWidth. - * The input array words contains at least one word. - * - * - * Example 1: - * - * - * Input: - * words = ["This", "is", "an", "example", "of", "text", "justification."] - * maxWidth = 16 - * Output: - * [ - * "This is an", - * "example of text", - * "justification. " - * ] - * - * - * Example 2: - * - * - * Input: - * words = ["What","must","be","acknowledgment","shall","be"] - * maxWidth = 16 - * Output: - * [ - * "What must be", - * "acknowledgment ", - * "shall be " - * ] - * Explanation: Note that the last line is "shall be " instead of "shall be", - * because the last line must be left-justified instead of fully-justified. - * Note that the second line is also left-justified becase it contains only one word. - * - * - * Example 3: - * - * - * Input: - * words = ["Science","is","what","we","understand","well","enough","to","explain", - * "to","a","computer.","Art","is","everything","else","we","do"] - * maxWidth = 20 - * Output: - * [ - * "Science is what we", - * "understand well", - * "enough to explain to", - * "a computer. Art is", - * "everything else we", - * "do " - * ] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/text-justification/ -// discuss: https://leetcode.com/problems/text-justification/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn full_justify(words: Vec, max_width: i32) -> Vec { - let mut res = Vec::new(); - let max_width = max_width as usize; - let mut i = 0; - let mut row_len = 0; - let mut buf = Vec::new(); - while i < words.len() { - if words[i].len() > max_width { - unreachable!() - } - let old_len = row_len; - row_len += words[i].len() + if row_len > 0 { 1 } else { 0 }; - if row_len > max_width { - res.push(Solution::compact(buf, max_width, old_len)); - buf = Vec::new(); - row_len = 0; - } else { - buf.push(words[i].clone()); - i += 1; - } - } - res.push(Solution::compact_last(buf, max_width)); - res - } - - fn compact(words: Vec, max_width: usize, row_len: usize) -> String { - let spaces = max_width - (row_len - words.len() + 1); - let avg_spaces = spaces / usize::max(1, words.len() - 1); - let mut extra_spaces = spaces - avg_spaces * usize::max(1, words.len() - 1);; - let mut res = String::new(); - for (i, word) in words.iter().enumerate() { - res.push_str(word); - if words.len() < 2 || (i < words.len() - 1) { - res.push_str(&" ".repeat(avg_spaces)); - if extra_spaces > 0 { - res.push(' '); - extra_spaces -= 1; - } - } - } - res - } - - fn compact_last(words: Vec, max_width: usize) -> String { - let mut res = String::new(); - for (i, word) in words.iter().enumerate() { - res.push_str(word); - if i < words.len() - 1 { - res.push(' '); - } - } - res.push_str(&" ".repeat(max_width - res.len())); - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_68() { - assert_eq!( - Solution::full_justify( - vec_string![ - "This", - "is", - "an", - "example", - "of", - "text", - "justification." - ], - 16 - ), - vec_string!["This is an", "example of text", "justification. "] - ); - - assert_eq!( - Solution::full_justify( - vec_string!["What", "must", "be", "acknowledgment", "shall", "be"], - 16 - ), - vec_string!["What must be", "acknowledgment ", "shall be "] - ); - - assert_eq!( - Solution::full_justify( - vec_string![ - "Science", - "is", - "what", - "we", - "understand", - "well", - "enough", - "to", - "explain", - "to", - "a", - "computer.", - "Art", - "is", - "everything", - "else", - "we", - "do" - ], - 20 - ), - vec_string![ - "Science is what we", - "understand well", - "enough to explain to", - "a computer. Art is", - "everything else we", - "do ", - ] - ); - } -} diff --git a/src/solution/s0069_sqrtx.rs b/src/solution/s0069_sqrtx.rs deleted file mode 100644 index 256f88be..00000000 --- a/src/solution/s0069_sqrtx.rs +++ /dev/null @@ -1,72 +0,0 @@ -/** - * [69] Sqrt(x) - * - * Implement int sqrt(int x). - * - * Compute and return the square root of x, where x is guaranteed to be a non-negative integer. - * - * Since the return type is an integer, the decimal digits are truncated and only the integer part of the result is returned. - * - * Example 1: - * - * - * Input: 4 - * Output: 2 - * - * - * Example 2: - * - * - * Input: 8 - * Output: 2 - * Explanation: The square root of 8 is 2.82842..., and since - * the decimal part is truncated, 2 is returned. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/sqrtx/ -// discuss: https://leetcode.com/problems/sqrtx/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// Newton-Raphson for: root^2 - n = 0 -// Tangent equation: y = 2 * root * x - (root^2 + n) -// Zero point: (root^2 + n) / (2 * root) -impl Solution { - pub fn my_sqrt(x: i32) -> i32 { - let mut size = x; - let mut base = 1; - while size > 1 { - let half = size / 2; - let mid = base + half; - if mid <= x / mid { - base = mid; - } - size -= half; - } - base - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_69() { - assert_eq!(Solution::my_sqrt(8), 2); - assert_eq!(Solution::my_sqrt(16), 4); - assert_eq!(Solution::my_sqrt(17), 4); - assert_eq!(Solution::my_sqrt(81), 9); - assert_eq!(Solution::my_sqrt(82), 9); - assert_eq!(Solution::my_sqrt(100480577), 10024); - assert_eq!(Solution::my_sqrt(100480575), 10023); - assert_eq!(Solution::my_sqrt(100480575), 10023); - assert_eq!(Solution::my_sqrt(80), 8); - assert_eq!(Solution::my_sqrt(2), 1); - } -} diff --git a/src/solution/s0070_climbing_stairs.rs b/src/solution/s0070_climbing_stairs.rs deleted file mode 100644 index 2ef4153b..00000000 --- a/src/solution/s0070_climbing_stairs.rs +++ /dev/null @@ -1,71 +0,0 @@ -/** - * [70] Climbing Stairs - * - * You are climbing a stair case. It takes n steps to reach to the top. - * - * Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? - * - * Note: Given n will be a positive integer. - * - * Example 1: - * - * - * Input: 2 - * Output: 2 - * Explanation: There are two ways to climb to the top. - * 1. 1 step + 1 step - * 2. 2 steps - * - * - * Example 2: - * - * - * Input: 3 - * Output: 3 - * Explanation: There are three ways to climb to the top. - * 1. 1 step + 1 step + 1 step - * 2. 1 step + 2 steps - * 3. 2 steps + 1 step - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/climbing-stairs/ -// discuss: https://leetcode.com/problems/climbing-stairs/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// Bottom-up DP -impl Solution { - pub fn climb_stairs(n: i32) -> i32 { - let n = n as usize; - if n == 1 { - return 1; - } - if n == 2 { - return 2; - } - let (mut prev, mut curr) = (1, 2); - for i in 2..n { - let next = prev + curr; - prev = curr; - curr = next; - } - curr - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_70() { - assert_eq!(Solution::climb_stairs(3), 3); - assert_eq!(Solution::climb_stairs(4), 5); - assert_eq!(Solution::climb_stairs(5), 8); - } -} diff --git a/src/solution/s0071_simplify_path.rs b/src/solution/s0071_simplify_path.rs deleted file mode 100644 index 4b61f7be..00000000 --- a/src/solution/s0071_simplify_path.rs +++ /dev/null @@ -1,112 +0,0 @@ -/** - * [71] Simplify Path - * - * Given an absolute path for a file (Unix-style), simplify it. Or in other words, convert it to the canonical path. - * - * In a UNIX-style file system, a period . refers to the current directory. Furthermore, a double period .. moves the directory up a level. For more information, see: Absolute path vs relative path in Linux/Unix - * - * Note that the returned canonical path must always begin with a slash /, and there must be only a single slash / between two directory names. The last directory name (if it exists) must not end with a trailing /. Also, the canonical path must be the shortest string representing the absolute path. - * - * - * - * Example 1: - * - * - * Input: "/home/" - * Output: "/home" - * Explanation: Note that there is no trailing slash after the last directory name. - * - * - * Example 2: - * - * - * Input: "/../" - * Output: "/" - * Explanation: Going one level up from the root directory is a no-op, as the root level is the highest level you can go. - * - * - * Example 3: - * - * - * Input: "/home//foo/" - * Output: "/home/foo" - * Explanation: In the canonical path, multiple consecutive slashes are replaced by a single one. - * - * - * Example 4: - * - * - * Input: "/a/./b/../../c/" - * Output: "/c" - * - * - * Example 5: - * - * - * Input: "/a/../../b/../c//.//" - * Output: "/c" - * - * - * Example 6: - * - * - * Input: "/a//b////c/d//././/.." - * Output: "/a/b/c" - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/simplify-path/ -// discuss: https://leetcode.com/problems/simplify-path/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn simplify_path(path: String) -> String { - let mut stack = Vec::new(); - for s in path.split('/') { - match s { - "." => {} - "/" => {} - "" => {} - ".." => { - stack.pop(); - } - _ => stack.push(s), - } - } - let mut res = String::new(); - for s in stack { - res.push('/'); - res.push_str(s); - } - if res.len() > 0 { - res - } else { - "/".to_owned() - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_71() { - assert_eq!(Solution::simplify_path("/home/".to_owned()), "/home"); - assert_eq!(Solution::simplify_path("/../".to_owned()), "/"); - assert_eq!(Solution::simplify_path("/a/./b/../../c/".to_owned()), "/c"); - assert_eq!( - Solution::simplify_path("/a/../../b/../c//.//".to_owned()), - "/c" - ); - assert_eq!( - Solution::simplify_path("/a//b////c/d//././/..".to_owned()), - "/a/b/c" - ); - } -} diff --git a/src/solution/s0072_edit_distance.rs b/src/solution/s0072_edit_distance.rs deleted file mode 100644 index d50d9fa3..00000000 --- a/src/solution/s0072_edit_distance.rs +++ /dev/null @@ -1,60 +0,0 @@ -/** - * [72] Edit Distance - * - * Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2. - * - * You have the following 3 operations permitted on a word: - * - *
    - * Insert a character - * Delete a character - * Replace a character - *
- * - * Example 1: - * - * - * Input: word1 = "horse", word2 = "ros" - * Output: 3 - * Explanation: - * horse -> rorse (replace 'h' with 'r') - * rorse -> rose (remove 'r') - * rose -> ros (remove 'e') - * - * - * Example 2: - * - * - * Input: word1 = "intention", word2 = "execution" - * Output: 5 - * Explanation: - * intention -> inention (remove 't') - * inention -> enention (replace 'i' with 'e') - * enention -> exention (replace 'n' with 'x') - * exention -> exection (replace 'n' with 'c') - * exection -> execution (insert 'u') - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/edit-distance/ -// discuss: https://leetcode.com/problems/edit-distance/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn min_distance(word1: String, word2: String) -> i32 { - 0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_72() {} -} diff --git a/src/solution/s0073_set_matrix_zeroes.rs b/src/solution/s0073_set_matrix_zeroes.rs deleted file mode 100644 index 8d8cdab8..00000000 --- a/src/solution/s0073_set_matrix_zeroes.rs +++ /dev/null @@ -1,68 +0,0 @@ -/** - * [73] Set Matrix Zeroes - * - * Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in-place. - * - * Example 1: - * - * - * Input: - * [ - * [1,1,1], - * [1,0,1], - * [1,1,1] - * ] - * Output: - * [ - * [1,0,1], - * [0,0,0], - * [1,0,1] - * ] - * - * - * Example 2: - * - * - * Input: - * [ - * [0,1,2,0], - * [3,4,5,2], - * [1,3,1,5] - * ] - * Output: - * [ - * [0,0,0,0], - * [0,4,5,0], - * [0,3,1,0] - * ] - * - * - * Follow up: - * - * - * A straight forward solution using O(mn) space is probably a bad idea. - * A simple improvement uses O(m + n) space, but still not the best solution. - * Could you devise a constant space solution? - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/set-matrix-zeroes/ -// discuss: https://leetcode.com/problems/set-matrix-zeroes/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn set_zeroes(matrix: &mut Vec>) {} -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_73() {} -} diff --git a/src/solution/s0074_search_a_2d_matrix.rs b/src/solution/s0074_search_a_2d_matrix.rs deleted file mode 100644 index 90975918..00000000 --- a/src/solution/s0074_search_a_2d_matrix.rs +++ /dev/null @@ -1,92 +0,0 @@ -/** - * [74] Search a 2D Matrix - * - * Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties: - * - * - * Integers in each row are sorted from left to right. - * The first integer of each row is greater than the last integer of the previous row. - * - * - * Example 1: - * - * - * Input: - * matrix = [ - * [1, 3, 5, 7], - * [10, 11, 16, 20], - * [23, 30, 34, 50] - * ] - * target = 3 - * Output: true - * - * - * Example 2: - * - * - * Input: - * matrix = [ - * [1, 3, 5, 7], - * [10, 11, 16, 20], - * [23, 30, 34, 50] - * ] - * target = 13 - * Output: false - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/search-a-2d-matrix/ -// discuss: https://leetcode.com/problems/search-a-2d-matrix/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn search_matrix(matrix: Vec>, target: i32) -> bool { - if matrix.is_empty() { - return false; - } - let (height, width) = (matrix.len(), matrix[0].len()); - if height < 1 || width < 1 { - return false; - } - let mut size = height * width; - let mut base = 0_usize; - while size > 1 { - let half = size / 2; - let mid = base + half; - if target == matrix[mid / width][mid % width] { - return true; - } else if (target > matrix[mid / width][mid % width]) { - base = mid; - } - size -= half; - } - target == matrix[base / width][base % width] - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_74() { - assert_eq!( - Solution::search_matrix( - vec![vec![1, 3, 5, 7], vec![10, 11, 16, 20], vec![23, 30, 34, 50]], - 3 - ), - true - ); - assert_eq!( - Solution::search_matrix( - vec![vec![1, 3, 5, 7], vec![10, 11, 16, 20], vec![23, 30, 34, 50]], - 13 - ), - false - ); - } -} diff --git a/src/solution/s0075_sort_colors.rs b/src/solution/s0075_sort_colors.rs deleted file mode 100644 index 6b72ac88..00000000 --- a/src/solution/s0075_sort_colors.rs +++ /dev/null @@ -1,84 +0,0 @@ -/** - * [75] Sort Colors - * - * Given an array with n objects colored red, white or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white and blue. - * - * Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively. - * - * Note: You are not suppose to use the library's sort function for this problem. - * - * Example: - * - * - * Input: [2,0,2,1,1,0] - * Output: [0,0,1,1,2,2] - * - * Follow up: - * - * - * A rather straight forward solution is a two-pass algorithm using counting sort.
- * First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's. - * Could you come up with a one-pass algorithm using only constant space? - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/sort-colors/ -// discuss: https://leetcode.com/problems/sort-colors/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// three-way partition -impl Solution { - pub fn sort_colors(nums: &mut Vec) { - if nums.is_empty() { - return; - } - let (mut lower_idx, mut upper_idx) = (0_usize, nums.len() - 1); - let mut i = 0_usize; - while i <= upper_idx { - if nums[i] < 1 { - // lower_idx <= i, we've scanned it so we know nums[lower_idx] <= 1, i++ - nums.swap(lower_idx, i); - i += 1; - lower_idx += 1; - } else if nums[i] > 1 { - nums.swap(upper_idx, i); - if upper_idx < 1 { - break; - } - upper_idx -= 1; - } else { - i += 1; - } - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_75() { - let mut vec = vec![ - 1, 2, 0, 1, 2, 2, 2, 0, 0, 0, 2, 1, 1, 2, 0, 1, 2, 2, 1, 1, 0, - ]; - Solution::sort_colors(&mut vec); - assert_eq!( - vec, - vec![0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2] - ); - - let mut vec = vec![]; - Solution::sort_colors(&mut vec); - assert_eq!(vec, vec![]); - - let mut vec = vec![2, 2, 2]; - Solution::sort_colors(&mut vec); - assert_eq!(vec, vec![2, 2, 2]); - } -} diff --git a/src/solution/s0076_minimum_window_substring.rs b/src/solution/s0076_minimum_window_substring.rs deleted file mode 100644 index 9d190533..00000000 --- a/src/solution/s0076_minimum_window_substring.rs +++ /dev/null @@ -1,56 +0,0 @@ -/** - * [76] Minimum Window Substring - * - * Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n). - * - * Example: - * - * - * Input: S = "ADOBECODEBANC", T = "ABC" - * Output: "BANC" - * - * - * Note: - * - * - * If there is no such window in S that covers all characters in T, return the empty string "". - * If there is such window, you are guaranteed that there will always be only one unique minimum window in S. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/minimum-window-substring/ -// discuss: https://leetcode.com/problems/minimum-window-substring/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here -use std::collections::HashMap; -impl Solution { - pub fn min_window(s: String, t: String) -> String { - if t.is_empty() || t.len() > s.len() { - return "".to_owned(); - } - let (mut start, mut end) = (0_usize, 0_usize); - let mut result = (0_usize, 0_usize); - loop {} - s[result.0..result.1].to_owned() - } - - fn count_char(s: String) -> HashMap { - let mut res = HashMap::new(); - for ch in s.chars().into_iter() { - *res.entry(ch).or_insert(0) += 1; - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_76() {} -} diff --git a/src/solution/s0077_combinations.rs b/src/solution/s0077_combinations.rs deleted file mode 100644 index 6bb10d6b..00000000 --- a/src/solution/s0077_combinations.rs +++ /dev/null @@ -1,77 +0,0 @@ -/** - * [77] Combinations - * - * Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. - * - * Example: - * - * - * Input: n = 4, k = 2 - * Output: - * [ - * [2,4], - * [3,4], - * [2,3], - * [1,2], - * [1,3], - * [1,4], - * ] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/combinations/ -// discuss: https://leetcode.com/problems/combinations/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn combine(n: i32, k: i32) -> Vec> { - let mut res: Vec> = Vec::new(); - Solution::backtrack(1, n, k, vec![], &mut res); - res - } - - fn backtrack(start: i32, end: i32, k: i32, curr: Vec, result: &mut Vec>) { - if k < 1 { - result.push(curr); - return; - } - if end - start + 1 < k { - // elements is not enough, return quickly - return; - } - for i in start..end + 1 { - let mut vec = curr.clone(); - vec.push(i); - Solution::backtrack(i + 1, end, k - 1, vec, result); - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_77() { - assert_eq!( - Solution::combine(4, 2), - vec![ - vec![1, 2], - vec![1, 3], - vec![1, 4], - vec![2, 3], - vec![2, 4], - vec![3, 4] - ] - ); - assert_eq!(Solution::combine(1, 1), vec![vec![1]]); - let empty: Vec> = vec![]; - assert_eq!(Solution::combine(0, 1), empty); - assert_eq!(Solution::combine(2, 1), vec![vec![1], vec![2]]); - } -} diff --git a/src/solution/s0078_subsets.rs b/src/solution/s0078_subsets.rs deleted file mode 100644 index 2db34925..00000000 --- a/src/solution/s0078_subsets.rs +++ /dev/null @@ -1,67 +0,0 @@ -/** - * [78] Subsets - * - * Given a set of distinct integers, nums, return all possible subsets (the power set). - * - * Note: The solution set must not contain duplicate subsets. - * - * Example: - * - * - * Input: nums = [1,2,3] - * Output: - * [ - * [3], - * [1], - * [2], - * [1,2,3], - * [1,3], - * [2,3], - * [1,2], - * [] - * ] - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/subsets/ -// discuss: https://leetcode.com/problems/subsets/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn subsets(nums: Vec) -> Vec> { - let mut res = Vec::new(); - Solution::backtrack(0, vec![], &nums, &mut res); - res - } - - fn backtrack(start: usize, mut curr: Vec, nums: &Vec, result: &mut Vec>) { - if start >= nums.len() { - result.push(curr); - return; - } - // current element dropped - Solution::backtrack(start + 1, curr.clone(), nums, result); - // current element picked - curr.push(nums[start]); - Solution::backtrack(start + 1, curr, nums, result); - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_78() { - assert_eq!(Solution::subsets(vec![]), vec![vec![]]); - assert_eq!(Solution::subsets(vec![1]), vec![vec![], vec![1]]); - assert_eq!( - Solution::subsets(vec![1, 2]), - vec![vec![], vec![2], vec![1], vec![1, 2]] - ); - } -} diff --git a/src/solution/s0079_word_search.rs b/src/solution/s0079_word_search.rs deleted file mode 100644 index 07c4a705..00000000 --- a/src/solution/s0079_word_search.rs +++ /dev/null @@ -1,133 +0,0 @@ -/** - * [79] Word Search - * - * Given a 2D board and a word, find if the word exists in the grid. - * - * The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once. - * - * Example: - * - * - * board = - * [ - * ['A','B','C','E'], - * ['S','F','C','S'], - * ['A','D','E','E'] - * ] - * - * Given word = "ABCCED", return true. - * Given word = "SEE", return true. - * Given word = "ABCB", return false. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/word-search/ -// discuss: https://leetcode.com/problems/word-search/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// TODO: use HashSet to record visited pos -impl Solution { - pub fn exist(board: Vec>, word: String) -> bool { - if board.is_empty() || word.len() < 1 { - return false; - } - let (height, width) = (board.len(), board[0].len()); - if height < 1 || width < 1 { - return false; - } - let seq: Vec = word.chars().collect(); - - for i in 0..height * width { - if Solution::dfs( - i / width, - i % width, - &seq[..], - &board, - vec![], - height, - width, - ) { - return true; - } - } - false - } - - fn dfs( - x: usize, - y: usize, - seq: &[char], - board: &Vec>, - mut visited: Vec<(usize, usize)>, - height: usize, - width: usize, - ) -> bool { - if seq[0] != board[x][y] { - return false; - } - if seq.len() < 2 { - return true; - } - visited.push((x, y)); - return (x > 0 - && !visited.contains(&(x - 1, y)) - && Solution::dfs(x - 1, y, &seq[1..], board, visited.clone(), height, width)) - || (x + 1 < height - && !visited.contains(&(x + 1, y)) - && Solution::dfs(x + 1, y, &seq[1..], board, visited.clone(), height, width)) - || (y > 0 - && !visited.contains(&(x, y - 1)) - && Solution::dfs(x, y - 1, &seq[1..], board, visited.clone(), height, width)) - || (y + 1 < width - && !visited.contains(&(x, y + 1)) - && Solution::dfs(x, y + 1, &seq[1..], board, visited.clone(), height, width)); - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_79() { - assert_eq!(Solution::exist(vec![vec!['a']], "a".to_owned()), true); - assert_eq!( - Solution::exist( - vec![ - vec!['A', 'B', 'C', 'E'], - vec!['S', 'F', 'C', 'S'], - vec!['A', 'D', 'E', 'E'], - ], - "ABCCED".to_owned() - ), - true - ); - assert_eq!( - Solution::exist( - vec![ - vec!['A', 'B', 'C', 'E'], - vec!['S', 'F', 'C', 'S'], - vec!['A', 'D', 'E', 'E'], - ], - "SEE".to_owned() - ), - true - ); - assert_eq!( - Solution::exist( - vec![ - vec!['A', 'B', 'C', 'E'], - vec!['S', 'F', 'C', 'S'], - vec!['A', 'D', 'E', 'E'], - ], - "ABCB".to_owned() - ), - false - ); - } -} diff --git a/src/solution/s0080_remove_duplicates_from_sorted_array_ii.rs b/src/solution/s0080_remove_duplicates_from_sorted_array_ii.rs deleted file mode 100644 index 70b3cf82..00000000 --- a/src/solution/s0080_remove_duplicates_from_sorted_array_ii.rs +++ /dev/null @@ -1,68 +0,0 @@ -/** - * [80] Remove Duplicates from Sorted Array II - * - * Given a sorted array nums, remove the duplicates in-place such that duplicates appeared at most twice and return the new length. - * - * Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory. - * - * Example 1: - * - * - * Given nums = [1,1,1,2,2,3], - * - * Your function should return length = 5, with the first five elements of nums being 1, 1, 2, 2 and 3 respectively. - * - * It doesn't matter what you leave beyond the returned length. - * - * Example 2: - * - * - * Given nums = [0,0,1,1,1,1,2,3,3], - * - * Your function should return length = 7, with the first seven elements of nums being modified to 0, 0, 1, 1, 2, 3 and 3 respectively. - * - * It doesn't matter what values are set beyond the returned length. - * - * - * Clarification: - * - * Confused why the returned value is an integer but your answer is an array? - * - * Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well. - * - * Internally you can think of this: - * - * - * // nums is passed in by reference. (i.e., without making a copy) - * int len = removeDuplicates(nums); - * - * // any modification to nums in your function would be known by the caller. - * // using the length returned by your function, it prints the first len elements. - * for (int i = 0; i < len; i++) { - * print(nums[i]); - * } - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/ -// discuss: https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn remove_duplicates(nums: &mut Vec) -> i32 { - 0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_80() {} -} diff --git a/src/solution/s0081_search_in_rotated_sorted_array_ii.rs b/src/solution/s0081_search_in_rotated_sorted_array_ii.rs deleted file mode 100644 index 7972a16f..00000000 --- a/src/solution/s0081_search_in_rotated_sorted_array_ii.rs +++ /dev/null @@ -1,52 +0,0 @@ -/** - * [81] Search in Rotated Sorted Array II - * - * Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. - * - * (i.e., [0,0,1,2,2,5,6] might become [2,5,6,0,0,1,2]). - * - * You are given a target value to search. If found in the array return true, otherwise return false. - * - * Example 1: - * - * - * Input: nums = [2,5,6,0,0,1,2], target = 0 - * Output: true - * - * - * Example 2: - * - * - * Input: nums = [2,5,6,0,0,1,2], target = 3 - * Output: false - * - * Follow up: - * - * - * This is a follow up problem to Search in Rotated Sorted Array, where nums may contain duplicates. - * Would this affect the run-time complexity? How and why? - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/search-in-rotated-sorted-array-ii/ -// discuss: https://leetcode.com/problems/search-in-rotated-sorted-array-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn search(nums: Vec, target: i32) -> bool { - false - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_81() {} -} diff --git a/src/solution/s0082_remove_duplicates_from_sorted_list_ii.rs b/src/solution/s0082_remove_duplicates_from_sorted_list_ii.rs deleted file mode 100644 index 067d0c79..00000000 --- a/src/solution/s0082_remove_duplicates_from_sorted_list_ii.rs +++ /dev/null @@ -1,59 +0,0 @@ -/** - * [82] Remove Duplicates from Sorted List II - * - * Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list. - * - * Example 1: - * - * - * Input: 1->2->3->3->4->4->5 - * Output: 1->2->5 - * - * - * Example 2: - * - * - * Input: 1->1->1->2->3 - * Output: 2->3 - * - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; - -// problem: https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/ -// discuss: https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// Definition for singly-linked list. -// #[derive(PartialEq, Eq, Debug)] -// pub struct ListNode { -// pub val: i32, -// pub next: Option> -// } -// -// impl ListNode { -// #[inline] -// fn new(val: i32) -> Self { -// ListNode { -// next: None, -// val -// } -// } -// } -impl Solution { - pub fn delete_duplicates(head: Option>) -> Option> { - None - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_82() {} -} diff --git a/src/solution/s0083_remove_duplicates_from_sorted_list.rs b/src/solution/s0083_remove_duplicates_from_sorted_list.rs deleted file mode 100644 index 5c9552cc..00000000 --- a/src/solution/s0083_remove_duplicates_from_sorted_list.rs +++ /dev/null @@ -1,59 +0,0 @@ -/** - * [83] Remove Duplicates from Sorted List - * - * Given a sorted linked list, delete all duplicates such that each element appear only once. - * - * Example 1: - * - * - * Input: 1->1->2 - * Output: 1->2 - * - * - * Example 2: - * - * - * Input: 1->1->2->3->3 - * Output: 1->2->3 - * - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; - -// problem: https://leetcode.com/problems/remove-duplicates-from-sorted-list/ -// discuss: https://leetcode.com/problems/remove-duplicates-from-sorted-list/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// Definition for singly-linked list. -// #[derive(PartialEq, Eq, Debug)] -// pub struct ListNode { -// pub val: i32, -// pub next: Option> -// } -// -// impl ListNode { -// #[inline] -// fn new(val: i32) -> Self { -// ListNode { -// next: None, -// val -// } -// } -// } -impl Solution { - pub fn delete_duplicates(head: Option>) -> Option> { - None - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_83() {} -} diff --git a/src/solution/s0084_largest_rectangle_in_histogram.rs b/src/solution/s0084_largest_rectangle_in_histogram.rs deleted file mode 100644 index d33b9bda..00000000 --- a/src/solution/s0084_largest_rectangle_in_histogram.rs +++ /dev/null @@ -1,91 +0,0 @@ -/** - * [84] Largest Rectangle in Histogram - * - * Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram. - * - * - * - *
- * Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3]. - * - * - * - *
- * The largest rectangle is shown in the shaded area, which has area = 10 unit. - * - * - * - * Example: - * - * - * Input: [2,1,5,6,2,3] - * Output: 10 - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/largest-rectangle-in-histogram/ -// discuss: https://leetcode.com/problems/largest-rectangle-in-histogram/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// record the height and start position using 2 stack, thus we reuse the previously scanned information -impl Solution { - pub fn largest_rectangle_area(heights: Vec) -> i32 { - let mut positions = Vec::new(); - let mut hs = Vec::new(); - let mut max_area = 0; - let len = heights.len(); - for (i, h) in heights.into_iter().enumerate() { - let mut last_pop = None; - while hs.last().is_some() && *hs.last().unwrap() >= h { - max_area = i32::max( - max_area, - hs.last().unwrap() * ((i - positions.last().unwrap()) as i32), - ); - hs.pop(); - last_pop = positions.pop(); - } - if last_pop.is_some() { - positions.push(last_pop.unwrap()); - } else { - positions.push(i); - } - hs.push(h); - } - // drain stack - while !hs.is_empty() { - max_area = i32::max( - max_area, - hs.last().unwrap() * ((len - positions.last().unwrap()) as i32), - ); - positions.pop(); - hs.pop(); - } - max_area - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_84() { - assert_eq!(Solution::largest_rectangle_area(vec![2, 1, 5, 6, 2, 3]), 10); - assert_eq!( - Solution::largest_rectangle_area(vec![1, 1, 1, 1, 1, 1, 1, 1]), - 8 - ); - assert_eq!(Solution::largest_rectangle_area(vec![2, 2]), 4); - assert_eq!( - Solution::largest_rectangle_area(vec![1, 2, 8, 8, 2, 2, 1]), - 16 - ); - assert_eq!(Solution::largest_rectangle_area(vec![2, 1, 2]), 3); - assert_eq!(Solution::largest_rectangle_area(vec![1, 3, 2, 1, 2]), 5); - } -} diff --git a/src/solution/s0085_maximal_rectangle.rs b/src/solution/s0085_maximal_rectangle.rs deleted file mode 100644 index 6dbf2951..00000000 --- a/src/solution/s0085_maximal_rectangle.rs +++ /dev/null @@ -1,43 +0,0 @@ -/** - * [85] Maximal Rectangle - * - * Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area. - * - * Example: - * - * - * Input: - * [ - * ["1","0","1","0","0"], - * ["1","0","1","1","1"], - * ["1","1","1","1","1"], - * ["1","0","0","1","0"] - * ] - * Output: 6 - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/maximal-rectangle/ -// discuss: https://leetcode.com/problems/maximal-rectangle/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn maximal_rectangle(matrix: Vec>) -> i32 { - let mut max_area = 0; - - max_area - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_85() {} -} diff --git a/src/solution/s0086_partition_list.rs b/src/solution/s0086_partition_list.rs deleted file mode 100644 index 1f4952dd..00000000 --- a/src/solution/s0086_partition_list.rs +++ /dev/null @@ -1,65 +0,0 @@ -/** - * [86] Partition List - * - * Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x. - * - * You should preserve the original relative order of the nodes in each of the two partitions. - * - * Example: - * - * - * Input: head = 1->4->3->2->5->2, x = 3 - * Output: 1->2->2->4->3->5 - * - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; - -// problem: https://leetcode.com/problems/partition-list/ -// discuss: https://leetcode.com/problems/partition-list/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn partition(head: Option>, x: i32) -> Option> { - let mut lower = Some(Box::new(ListNode::new(0))); - let mut higher = Some(Box::new(ListNode::new(0))); - let mut lower_tail = lower.as_mut(); - let mut higher_tail = higher.as_mut(); - let mut head = head; - while let Some(mut inner) = head { - let mut next = inner.next.take(); - if inner.val < x { - lower_tail.as_mut().unwrap().next = Some(inner); - lower_tail = lower_tail.unwrap().next.as_mut(); - } else { - higher_tail.as_mut().unwrap().next = Some(inner); - higher_tail = higher_tail.unwrap().next.as_mut(); - } - head = next - } - lower_tail.as_mut().unwrap().next = higher.unwrap().next.take(); - lower.unwrap().next.take() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_86() { - assert_eq!( - Solution::partition(linked![1, 4, 3, 2, 5, 2], 3), - linked![1, 2, 2, 4, 3, 5] - ); - assert_eq!( - Solution::partition(linked![1, 4, 3, 2, 5, 2], 8), - linked![1, 4, 3, 2, 5, 2] - ); - assert_eq!(Solution::partition(linked![], 0), linked![]); - } -} diff --git a/src/solution/s0087_scramble_string.rs b/src/solution/s0087_scramble_string.rs deleted file mode 100644 index 19b47dc0..00000000 --- a/src/solution/s0087_scramble_string.rs +++ /dev/null @@ -1,85 +0,0 @@ -/** - * [87] Scramble String - * - * Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively. - * - * Below is one possible representation of s1 = "great": - * - * - * great - * / \ - * gr eat - * / \ / \ - * g r e at - * / \ - * a t - * - * - * To scramble the string, we may choose any non-leaf node and swap its two children. - * - * For example, if we choose the node "gr" and swap its two children, it produces a scrambled string "rgeat". - * - * - * rgeat - * / \ - * rg eat - * / \ / \ - * r g e at - * / \ - * a t - * - * - * We say that "rgeat" is a scrambled string of "great". - * - * Similarly, if we continue to swap the children of nodes "eat" and "at", it produces a scrambled string "rgtae". - * - * - * rgtae - * / \ - * rg tae - * / \ / \ - * r g ta e - * / \ - * t a - * - * - * We say that "rgtae" is a scrambled string of "great". - * - * Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1. - * - * Example 1: - * - * - * Input: s1 = "great", s2 = "rgeat" - * Output: true - * - * - * Example 2: - * - * - * Input: s1 = "abcde", s2 = "caebd" - * Output: false - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/scramble-string/ -// discuss: https://leetcode.com/problems/scramble-string/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn is_scramble(s1: String, s2: String) -> bool { - false - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_87() {} -} diff --git a/src/solution/s0088_merge_sorted_array.rs b/src/solution/s0088_merge_sorted_array.rs deleted file mode 100644 index bdcc2a1a..00000000 --- a/src/solution/s0088_merge_sorted_array.rs +++ /dev/null @@ -1,72 +0,0 @@ -/** - * [88] Merge Sorted Array - * - * Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. - * - * Note: - * - * - * The number of elements initialized in nums1 and nums2 are m and n respectively. - * You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2. - * - * - * Example: - * - * - * Input: - * nums1 = [1,2,3,0,0,0], m = 3 - * nums2 = [2,5,6], n = 3 - * - * Output: [1,2,2,3,5,6] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/merge-sorted-array/ -// discuss: https://leetcode.com/problems/merge-sorted-array/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn merge(nums1: &mut Vec, m: i32, nums2: &mut Vec, n: i32) { - let mut i = m - 1; - let mut j = n - 1; - let mut z = m + n - 1; - while z >= 0 { - if i >= 0 && (j < 0 || nums1[i as usize] >= nums2[j as usize]) { - nums1[z as usize] = nums1[i as usize]; - i -= 1; - } else { - nums1[z as usize] = nums2[j as usize]; - j -= 1; - } - z -= 1; - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_88() { - let mut vec1 = vec![1, 2, 3, 0, 0, 0]; - let mut vec2 = vec![2, 5, 6]; - Solution::merge(&mut vec1, 3, &mut vec2, 3); - assert_eq!(vec1, vec![1, 2, 2, 3, 5, 6]); - - let mut vec1 = vec![1, 2, 3]; - let mut vec2 = vec![]; - Solution::merge(&mut vec1, 3, &mut vec2, 0); - assert_eq!(vec1, vec![1, 2, 3]); - - let mut vec1 = vec![0, 0, 0]; - let mut vec2 = vec![1, 2, 3]; - Solution::merge(&mut vec1, 0, &mut vec2, 3); - assert_eq!(vec1, vec![1, 2, 3]); - } -} diff --git a/src/solution/s0089_gray_code.rs b/src/solution/s0089_gray_code.rs deleted file mode 100644 index 039283eb..00000000 --- a/src/solution/s0089_gray_code.rs +++ /dev/null @@ -1,82 +0,0 @@ -/** - * [89] Gray Code - * - * The gray code is a binary numeral system where two successive values differ in only one bit. - * - * Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0. - * - * Example 1: - * - * - * Input: 2 - * Output: [0,1,3,2] - * Explanation: - * 00 - 0 - * 01 - 1 - * 11 - 3 - * 10 - 2 - * - * For a given n, a gray code sequence may not be uniquely defined. - * For example, [0,2,3,1] is also a valid gray code sequence. - * - * 00 - 0 - * 10 - 2 - * 11 - 3 - * 01 - 1 - * - * - * Example 2: - * - * - * Input: 0 - * Output: [0] - * Explanation: We define the gray code sequence to begin with 0. - * A gray code sequence of n has size = 2^n, which for n = 0 the size is 2^0 = 1. - * Therefore, for n = 0 the gray code sequence is [0]. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/gray-code/ -// discuss: https://leetcode.com/problems/gray-code/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -0000 -0001 <- flip [0] to 1, traverse [] in reverse order -0011 <- flip [1] to 1, traverse [0] in reverse order -0010 -0110 <- flip [2] to 1, traverse [1,0] in reverse order -0111 -0101 -0100 -1100 <- flip [3] to 1, traverse [2,1,0] in reverse order - */ -impl Solution { - pub fn gray_code(n: i32) -> Vec { - let mut res = vec![0]; - for i in 0..n { - for j in (0..res.len()).rev() { - res.push(2_i32.pow(i as u32) + res[j]); - } - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_89() { - assert_eq!(Solution::gray_code(2), vec![0, 1, 3, 2]); - assert_eq!(Solution::gray_code(1), vec![0, 1]); - assert_eq!(Solution::gray_code(0), vec![0]); - assert_eq!(Solution::gray_code(3), vec![0, 1, 3, 2, 6, 7, 5, 4]); - } -} diff --git a/src/solution/s0090_subsets_ii.rs b/src/solution/s0090_subsets_ii.rs deleted file mode 100644 index e859e2d1..00000000 --- a/src/solution/s0090_subsets_ii.rs +++ /dev/null @@ -1,95 +0,0 @@ -/** - * [90] Subsets II - * - * Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set). - * - * Note: The solution set must not contain duplicate subsets. - * - * Example: - * - * - * Input: [1,2,2] - * Output: - * [ - * [2], - * [1], - * [1,2,2], - * [2,2], - * [1,2], - * [] - * ] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/subsets-ii/ -// discuss: https://leetcode.com/problems/subsets-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -count the repeats of each number, -then in backtracking, each number can be picked up for 0..repeat times - -using BTreeMap to preserve order (easy for test) -*/ -use std::collections::BTreeMap; -impl Solution { - pub fn subsets_with_dup(nums: Vec) -> Vec> { - let mut res = Vec::new(); - let nums = nums - .into_iter() - .fold(BTreeMap::new(), |mut map, v| { - *map.entry(v).or_insert(0) += 1; - map - }) - .into_iter() - .collect::>(); - Solution::backtrack(0, vec![], &nums, &mut res); - res - } - - fn backtrack( - start: usize, - mut curr: Vec, - nums: &Vec<(i32, i32)>, - result: &mut Vec>, - ) { - if start >= nums.len() { - result.push(curr); - return; - } - for repeat in 0..nums[start].1 + 1 { - let mut inner = curr.clone(); - for _ in 0..repeat { - inner.push(nums[start].0); - } - Solution::backtrack(start + 1, inner, nums, result); - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_90() { - assert_eq!( - Solution::subsets_with_dup(vec![1, 2, 2]), - vec![ - vec![], - vec![2], - vec![2, 2], - vec![1], - vec![1, 2], - vec![1, 2, 2], - ] - ); - assert_eq!(Solution::subsets_with_dup(vec![1]), vec![vec![], vec![1],]); - assert_eq!(Solution::subsets_with_dup(vec![]), vec![vec![],]); - } -} diff --git a/src/solution/s0091_decode_ways.rs b/src/solution/s0091_decode_ways.rs deleted file mode 100644 index bbecc932..00000000 --- a/src/solution/s0091_decode_ways.rs +++ /dev/null @@ -1,52 +0,0 @@ -/** - * [91] Decode Ways - * - * A message containing letters from A-Z is being encoded to numbers using the following mapping: - * - * - * 'A' -> 1 - * 'B' -> 2 - * ... - * 'Z' -> 26 - * - * - * Given a non-empty string containing only digits, determine the total number of ways to decode it. - * - * Example 1: - * - * - * Input: "12" - * Output: 2 - * Explanation: It could be decoded as "AB" (1 2) or "L" (12). - * - * - * Example 2: - * - * - * Input: "226" - * Output: 3 - * Explanation: It could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6). - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/decode-ways/ -// discuss: https://leetcode.com/problems/decode-ways/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn num_decodings(s: String) -> i32 { - 0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_91() {} -} diff --git a/src/solution/s0092_reverse_linked_list_ii.rs b/src/solution/s0092_reverse_linked_list_ii.rs deleted file mode 100644 index 318c0d15..00000000 --- a/src/solution/s0092_reverse_linked_list_ii.rs +++ /dev/null @@ -1,54 +0,0 @@ -/** - * [92] Reverse Linked List II - * - * Reverse a linked list from position m to n. Do it in one-pass. - * - * Note: 1 ≤ m ≤ n ≤ length of list. - * - * Example: - * - * - * Input: 1->2->3->4->5->NULL, m = 2, n = 4 - * Output: 1->4->3->2->5->NULL - * - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; - -// problem: https://leetcode.com/problems/reverse-linked-list-ii/ -// discuss: https://leetcode.com/problems/reverse-linked-list-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// Definition for singly-linked list. -// #[derive(PartialEq, Eq, Debug)] -// pub struct ListNode { -// pub val: i32, -// pub next: Option> -// } -// -// impl ListNode { -// #[inline] -// fn new(val: i32) -> Self { -// ListNode { -// next: None, -// val -// } -// } -// } -impl Solution { - pub fn reverse_between(head: Option>, m: i32, n: i32) -> Option> { - None - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_92() {} -} diff --git a/src/solution/s0093_restore_ip_addresses.rs b/src/solution/s0093_restore_ip_addresses.rs deleted file mode 100644 index 5c2706b4..00000000 --- a/src/solution/s0093_restore_ip_addresses.rs +++ /dev/null @@ -1,35 +0,0 @@ -/** - * [93] Restore IP Addresses - * - * Given a string containing only digits, restore it by returning all possible valid IP address combinations. - * - * Example: - * - * - * Input: "25525511135" - * Output: ["255.255.11.135", "255.255.111.35"] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/restore-ip-addresses/ -// discuss: https://leetcode.com/problems/restore-ip-addresses/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn restore_ip_addresses(s: String) -> Vec { - vec![] - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_93() {} -} diff --git a/src/solution/s0094_binary_tree_inorder_traversal.rs b/src/solution/s0094_binary_tree_inorder_traversal.rs deleted file mode 100644 index 01afb57a..00000000 --- a/src/solution/s0094_binary_tree_inorder_traversal.rs +++ /dev/null @@ -1,64 +0,0 @@ -/** - * [94] Binary Tree Inorder Traversal - * - * Given a binary tree, return the inorder traversal of its nodes' values. - * - * Example: - * - * - * Input: [1,null,2,3] - * 1 - * \ - * 2 - * / - * 3 - * - * Output: [1,3,2] - * - * Follow up: Recursive solution is trivial, could you do it iteratively? - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/binary-tree-inorder-traversal/ -// discuss: https://leetcode.com/problems/binary-tree-inorder-traversal/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use crate::util::tree::{to_tree, TreeNode}; -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn inorder_traversal(root: Option>>) -> Vec { - let mut res = Vec::new(); - Solution::inorder_traverse(root.as_ref(), &mut (|v| res.push(v))); - res - } - - fn inorder_traverse(root: Option<&Rc>>, consumer: &mut F) { - if let Some(node) = root { - Solution::inorder_traverse(node.borrow().left.as_ref(), consumer); - consumer(root.as_ref().unwrap().borrow().val); - Solution::inorder_traverse(node.borrow().right.as_ref(), consumer); - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_94() { - assert_eq!( - Solution::inorder_traversal(tree![1, null, 2, 3]), - vec![1, 3, 2] - ); - assert_eq!( - Solution::inorder_traversal(tree![1, 2, 3, 4, 5, 6, 7]), - vec![4, 2, 5, 1, 6, 3, 7] - ); - } -} diff --git a/src/solution/s0095_unique_binary_search_trees_ii.rs b/src/solution/s0095_unique_binary_search_trees_ii.rs deleted file mode 100644 index 1f75639d..00000000 --- a/src/solution/s0095_unique_binary_search_trees_ii.rs +++ /dev/null @@ -1,89 +0,0 @@ -/** - * [95] Unique Binary Search Trees II - * - * Given an integer n, generate all structurally unique BST's (binary search trees) that store values 1 ... n. - * - * Example: - * - * - * Input: 3 - * Output: - * [ - * [1,null,3,2], - * [3,2,null,1], - * [3,1,null,null,2], - * [2,1,3], - * [1,null,2,null,3] - * ] - * Explanation: - * The above output corresponds to the 5 unique BST's shown below: - * - * 1 3 3 2 1 - * \ / / / \ \ - * 3 2 1 1 3 2 - * / / \ \ - * 2 1 2 3 - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/unique-binary-search-trees-ii/ -// discuss: https://leetcode.com/problems/unique-binary-search-trees-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* - 1 - - 1 2 - \ / - 2 1 - - 1 3 3 2 1 - \ / / / \ \ - 3 2 1 1 3 2 - / / \ \ - 2 1 2 3 - - 4 1 - / \ -(5*) 3 - / \ - 2 4 - */ -use crate::util::tree::{to_tree, TreeNode}; -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn generate_trees(n: i32) -> Vec>>> { - if n < 1 { - return vec![]; - } - let mut res = vec![Some(Rc::new(RefCell::new(TreeNode::new(1))))]; - for val in 2..n + 1 { - let mut next = Vec::new(); - for root in res.into_iter() { - let mut dummy = Some(Rc::new(RefCell::new(TreeNode { - val: 0, - left: None, - right: None, - }))); - let mut parent = dummy.as_ref().unwrap().clone(); - let mut node = root; - // we know that val is larger than all the elements in the tree - } - res = next; - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_95() {} -} diff --git a/src/solution/s0096_unique_binary_search_trees.rs b/src/solution/s0096_unique_binary_search_trees.rs deleted file mode 100644 index 4f64c26c..00000000 --- a/src/solution/s0096_unique_binary_search_trees.rs +++ /dev/null @@ -1,43 +0,0 @@ -/** - * [96] Unique Binary Search Trees - * - * Given n, how many structurally unique BST's (binary search trees) that store values 1 ... n? - * - * Example: - * - * - * Input: 3 - * Output: 5 - * Explanation: - * Given n = 3, there are a total of 5 unique BST's: - * - * 1 3 3 2 1 - * \ / / / \ \ - * 3 2 1 1 3 2 - * / / \ \ - * 2 1 2 3 - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/unique-binary-search-trees/ -// discuss: https://leetcode.com/problems/unique-binary-search-trees/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn num_trees(n: i32) -> i32 { - 0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_96() {} -} diff --git a/src/solution/s0097_interleaving_string.rs b/src/solution/s0097_interleaving_string.rs deleted file mode 100644 index 8d69d851..00000000 --- a/src/solution/s0097_interleaving_string.rs +++ /dev/null @@ -1,115 +0,0 @@ -/** - * [97] Interleaving String - * - * Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. - * - * Example 1: - * - * - * Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac" - * Output: true - * - * - * Example 2: - * - * - * Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc" - * Output: false - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/interleaving-string/ -// discuss: https://leetcode.com/problems/interleaving-string/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// DFS with memorization -/* -思路: DFS, 三个指针 i,j,k 分别指向 s1, s2, s3 已经消费到的 char 位置, 下一个可以走的路径是 s3 当前消费到的 char 值 - -如 aaaaaas aaaaaaaw aaaaaaaaaaaaaasw -那么第一步可以从 s1 或 s2 取一个 char, 用 DFS 的方式搜索整个解空间 - -优化: 直接 DFS 非常慢, 还是上面的例子, 最差情况是大量重复字符, 时间复杂度直接是 2^(M+N), 优化方式借鉴 DP 经常用到的 -memorize, 使用一个二维数组缓存每一对遍历过的 i,j 最后是否能产生合法的 interleaving. - -优化后通过缓存剪除的路径比较难分析, 但很显然能知道最差情况也只需要将所有 M*N 的组合进行标记, 因此最差时间复杂度 O(M*N) -空间复杂度 O(M*N) -*/ - -impl Solution { - pub fn is_interleave(s1: String, s2: String, s3: String) -> bool { - let mut cache = vec![vec![false; s2.len() + 1]; s1.len() + 1]; - Solution::dfs( - &s1.chars().collect(), - &s2.chars().collect(), - &s3.chars().collect(), - 0, - 0, - 0, - &mut cache, - ) - } - - fn dfs( - s1: &Vec, - s2: &Vec, - s3: &Vec, - i: usize, - j: usize, - k: usize, - invalid: &mut Vec>, - ) -> bool { - if invalid[i][j] { - return false; - } - if i == s1.len() && j == s2.len() && k == s3.len() { - return true; - } - let valid = (i < s1.len() - && k < s3.len() - && s1[i] == s3[k] - && Solution::dfs(s1, s2, s3, i + 1, j, k + 1, invalid)) - || (j < s2.len() - && k < s3.len() - && s2[j] == s3[k] - && Solution::dfs(s1, s2, s3, i, j + 1, k + 1, invalid)); - if !valid { - invalid[i][j] = true - } - valid - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_97() { - assert_eq!( - Solution::is_interleave( - "aabcc".to_owned(), - "dbbca".to_owned(), - "aadbbcbcac".to_owned() - ), - true - ); - assert_eq!( - Solution::is_interleave( - "aabcc".to_owned(), - "dbbca".to_owned(), - "aadbbbaccc".to_owned() - ), - false - ); - assert_eq!( - Solution::is_interleave("a".to_owned(), "b".to_owned(), "a".to_owned()), - false - ); - } -} diff --git a/src/solution/s0098_validate_binary_search_tree.rs b/src/solution/s0098_validate_binary_search_tree.rs deleted file mode 100644 index 09098c18..00000000 --- a/src/solution/s0098_validate_binary_search_tree.rs +++ /dev/null @@ -1,97 +0,0 @@ -/** - * [98] Validate Binary Search Tree - * - * Given a binary tree, determine if it is a valid binary search tree (BST). - * - * Assume a BST is defined as follows: - * - * - * The left subtree of a node contains only nodes with keys less than the node's key. - * The right subtree of a node contains only nodes with keys greater than the node's key. - * Both the left and right subtrees must also be binary search trees. - * - * - * Example 1: - * - * - * Input: - * 2 - * / \ - * 1 3 - * Output: true - * - * - * Example 2: - * - * - * 5 - * / \ - * 1 4 - * / \ - * 3 6 - * Output: false - * Explanation: The input is: [5,1,4,null,null,3,6]. The root node's value - * is 5 but its right child's value is 4. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/validate-binary-search-tree/ -// discuss: https://leetcode.com/problems/validate-binary-search-tree/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// Definition for a binary tree node. -use crate::util::tree::{to_tree, TreeNode}; - -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn is_valid_bst(root: Option>>) -> bool { - let mut vec = vec![]; - Solution::preorder_traverse(root.as_ref(), &mut vec) - } - - fn preorder_traverse( - root: Option<&Rc>>, - formers: &mut Vec<(i32, i32)>, - ) -> bool { - if let Some(node) = root { - let root_val = root.as_ref().unwrap().borrow().val; - for former in formers.iter() { - if (former.0 < 0 && root_val >= former.1) || (former.0 > 0 && root_val <= former.1) - { - return false; - } - } - let mut to_right = formers.clone(); - formers.push((-1, root_val)); - to_right.push((1, root_val)); - Solution::preorder_traverse(node.borrow().left.as_ref(), formers) - && Solution::preorder_traverse(node.borrow().right.as_ref(), &mut to_right) - } else { - true - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_98() { - assert_eq!( - Solution::is_valid_bst(tree![5, 1, 4, null, null, 3, 6]), - false - ); - assert_eq!(Solution::is_valid_bst(tree![2, 1, 3]), true); - assert_eq!( - Solution::is_valid_bst(tree![10, 5, 15, null, null, 6, 20]), - false - ); - } -} diff --git a/src/solution/s0099_recover_binary_search_tree.rs b/src/solution/s0099_recover_binary_search_tree.rs deleted file mode 100644 index 2401231a..00000000 --- a/src/solution/s0099_recover_binary_search_tree.rs +++ /dev/null @@ -1,162 +0,0 @@ -/** - * [99] Recover Binary Search Tree - * - * Two elements of a binary search tree (BST) are swapped by mistake. - * - * Recover the tree without changing its structure. - * - * Example 1: - * - * - * Input: [1,3,null,null,2] - * - * 1 - * / - * 3 - * \ - * 2 - * - * Output: [3,1,null,null,2] - * - * 3 - * / - * 1 - * \ - * 2 - * - * - * Example 2: - * - * - * Input: [3,1,4,null,null,2] - * - * 3 - * / \ - * 1 4 - * / - * 2 - * - * Output: [2,1,4,null,null,3] - * - * 2 - * / \ - * 1 4 - * / - * 3 - * - * - * Follow up: - * - * - * A solution using O(n) space is pretty straight forward. - * Could you devise a constant space solution? - * - * - */ -pub struct Solution {} - -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/recover-binary-search-tree/ -// discuss: https://leetcode.com/problems/recover-binary-search-tree/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -基本思路: 对 root, 收集左右两侧的节点值: - - - 右侧有值小于 root, 左侧有值大于 root: 交换这两个值 - - 一侧有值不合法, 另一侧合法: 交换不合法的值与 root - - 两侧都合法: 递归对左右子树进行上述操作 - -直接使用上述思路会重复迭代子树, 因此可以先用一次中序遍历, 将值的分布记录在数组中, 之后可以用 O(1) 的时间得到某个 node 两侧的值分布 - -这种办法的时间空间复杂度都是 O(N) - -原题中的 follow up 部分提出可以想一个常数空间复杂度的算法, 因此可以继续优化. - -最开始的办法会重复迭代子树是因为 Top-down, 可以尝试一下 Bottom-up 能不能解决问题: - -- 后序遍历递归校验每个 node 是否合法 -- 假如 node 合法, 那么只需要把这个子树中的最大值和最小值返回到上一个层级来帮助判断上一个层级的子树是否合法即可, 无需记录这个子树的所有值 -- 假如 node 不合法, 按最开始的办法进行处理, 除非... -- 只有一侧值不合法, 这时候由于是 Bottom-up, 不能直接交换不合法的值与 root, 而要判断交换后能否合法(Top-down 的办法中由于题目给定了有且仅有 swap 一次, 因此与 root 交换必然是合法的) - -这个办法时间复杂度 O(N), 空间 O(1). 题解就用 Bottom-up 来写. - */ -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn recover_tree(root: &mut Option>>) { - Solution::recover_helper(root.as_ref()); - } - - fn recover_helper( - root: Option<&Rc>>, - ) -> ( - Option>>, - Option>>, - bool, - ) { - if let Some(node) = root { - let (l_min, l_max, l_flag) = Solution::recover_helper(node.borrow().left.as_ref()); - let (r_min, r_max, r_flag) = Solution::recover_helper(node.borrow().right.as_ref()); - // we've already find a swap, return quickly - if l_flag || r_flag { - return (None, None, true); - } - let root_val = node.borrow().val; - let l_err = l_max.as_ref().map_or(false, |v| v.borrow().val > root_val); - let r_err = r_min.as_ref().map_or(false, |v| v.borrow().val < root_val); - // invalid sub-tree found, do swap - if l_err || r_err { - if l_err && r_err { - } else if l_err { - std::mem::swap( - &mut l_max.unwrap().borrow_mut().val, - &mut node.borrow_mut().val, - ); - } else if r_err { - std::mem::swap( - &mut r_min.unwrap().borrow_mut().val, - &mut node.borrow_mut().val, - ) - } - return (None, None, true); - } - ( - if l_min.is_some() { - l_min - } else { - Some(node.clone()) - }, - if r_max.is_some() { - r_max - } else { - Some(node.clone()) - }, - false, - ) - } else { - (None, None, false) - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_99() { - let mut tree = tree![3, 1, 4, null, null, 2]; - Solution::recover_tree(&mut tree); - assert_eq!(tree, tree![2, 1, 4, null, null, 3]); - - let mut tree = tree![2, 6, 5, null, null, 3, 1, null, 4]; - Solution::recover_tree(&mut tree); - assert_eq!(tree, tree![2, 1, 5, null, null, 3, 6, null, 4]); - } -} diff --git a/src/solution/s0100_same_tree.rs b/src/solution/s0100_same_tree.rs deleted file mode 100644 index c7dc1372..00000000 --- a/src/solution/s0100_same_tree.rs +++ /dev/null @@ -1,76 +0,0 @@ -/** - * [100] Same Tree - * - * Given two binary trees, write a function to check if they are the same or not. - * - * Two binary trees are considered the same if they are structurally identical and the nodes have the same value. - * - * Example 1: - * - * - * Input: 1 1 - * / \ / \ - * 2 3 2 3 - * - * [1,2,3], [1,2,3] - * - * Output: true - * - * - * Example 2: - * - * - * Input: 1 1 - * / \ - * 2 2 - * - * [1,2], [1,null,2] - * - * Output: false - * - * - * Example 3: - * - * - * Input: 1 1 - * / \ / \ - * 2 1 1 2 - * - * [1,2,1], [1,1,2] - * - * Output: false - * - * - */ -pub struct Solution {} - -use crate::util::tree::{to_tree, TreeNode}; -// problem: https://leetcode.com/problems/same-tree/ -// discuss: https://leetcode.com/problems/same-tree/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn is_same_tree( - p: Option>>, - q: Option>>, - ) -> bool { - p == q - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_100() { - assert_eq!( - Solution::is_same_tree(tree![1, 2, 3, 4, null, 5], tree![1, 2, 3, 4, null, 5]), - true - ) - } -} diff --git a/src/solution/s0101_symmetric_tree.rs b/src/solution/s0101_symmetric_tree.rs deleted file mode 100644 index 41f44bc8..00000000 --- a/src/solution/s0101_symmetric_tree.rs +++ /dev/null @@ -1,87 +0,0 @@ -/** - * [101] Symmetric Tree - * - * Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). - * - * - * For example, this binary tree [1,2,2,3,4,4,3] is symmetric: - * - * 1 - * / \ - * 2 2 - * / \ / \ - * 3 4 4 3 - * - * - * - * But the following [1,2,2,null,3,null,3] is not:
- * - * 1 - * / \ - * 2 2 - * \ \ - * 3 3 - * - * - * - * - * Note:
- * Bonus points if you could solve it both recursively and iteratively. - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/symmetric-tree/ -// discuss: https://leetcode.com/problems/symmetric-tree/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn is_symmetric(root: Option>>) -> bool { - Solution::symmetric_helper( - root.as_ref().and_then(|v| v.borrow().left.clone()), - root.as_ref().and_then(|v| v.borrow().right.clone()), - ) - } - - fn symmetric_helper( - left: Option>>, - right: Option>>, - ) -> bool { - match (left, right) { - (Some(left), Some(right)) => { - left.borrow().val == right.borrow().val - && Solution::symmetric_helper( - left.borrow().left.clone(), - right.borrow().right.clone(), - ) - && Solution::symmetric_helper( - left.borrow().right.clone(), - right.borrow().left.clone(), - ) - } - (None, None) => true, - _ => false, - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_101() { - assert_eq!(Solution::is_symmetric(tree![1, 2, 2, 3, 4, 4, 3]), true); - assert_eq!( - Solution::is_symmetric(tree![1, 2, 2, null, 3, null, 3]), - false - ); - assert_eq!(Solution::is_symmetric(tree![]), true); - } -} diff --git a/src/solution/s0102_binary_tree_level_order_traversal.rs b/src/solution/s0102_binary_tree_level_order_traversal.rs deleted file mode 100644 index a5a3fd13..00000000 --- a/src/solution/s0102_binary_tree_level_order_traversal.rs +++ /dev/null @@ -1,81 +0,0 @@ -/** - * [102] Binary Tree Level Order Traversal - * - * Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). - * - * - * For example:
- * Given binary tree [3,9,20,null,null,15,7],
- * - * 3 - * / \ - * 9 20 - * / \ - * 15 7 - * - * - * - * return its level order traversal as:
- * - * [ - * [3], - * [9,20], - * [15,7] - * ] - * - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/binary-tree-level-order-traversal/ -// discuss: https://leetcode.com/problems/binary-tree-level-order-traversal/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::collections::VecDeque; -use std::rc::Rc; -impl Solution { - pub fn level_order(root: Option>>) -> Vec> { - let mut res = Vec::new(); - let mut current_level = 0; - if root.is_none() { - return res; - } - let mut deq = VecDeque::new(); - deq.push_back((0, root.clone())); - let mut vec = Vec::new(); - while !deq.is_empty() { - if let Some((level, Some(node))) = deq.pop_front() { - deq.push_back((level + 1, node.borrow().left.clone())); - deq.push_back((level + 1, node.borrow().right.clone())); - if level > current_level { - res.push(vec); - vec = Vec::new(); - current_level = level; - } - vec.push(node.borrow().val); - } - } - if !vec.is_empty() { - res.push(vec) - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_102() { - assert_eq!( - Solution::level_order(tree![3, 9, 20, null, null, 15, 7]), - vec![vec![3], vec![9, 20], vec![15, 7]] - ); - } -} diff --git a/src/solution/s0103_binary_tree_zigzag_level_order_traversal.rs b/src/solution/s0103_binary_tree_zigzag_level_order_traversal.rs deleted file mode 100644 index 78aa7b5e..00000000 --- a/src/solution/s0103_binary_tree_zigzag_level_order_traversal.rs +++ /dev/null @@ -1,87 +0,0 @@ -/** - * [103] Binary Tree Zigzag Level Order Traversal - * - * Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between). - * - * - * For example:
- * Given binary tree [3,9,20,null,null,15,7],
- * - * 3 - * / \ - * 9 20 - * / \ - * 15 7 - * - * - * - * return its zigzag level order traversal as:
- * - * [ - * [3], - * [20,9], - * [15,7] - * ] - * - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/ -// discuss: https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::collections::VecDeque; -use std::rc::Rc; -impl Solution { - pub fn zigzag_level_order(root: Option>>) -> Vec> { - let mut res = Vec::new(); - let mut current_level = 0; - if root.is_none() { - return res; - } - let mut deq = VecDeque::new(); - deq.push_back((0, root.clone())); - let mut vec = Vec::new(); - while !deq.is_empty() { - if let Some((level, Some(node))) = deq.pop_front() { - deq.push_back((level + 1, node.borrow().left.clone())); - deq.push_back((level + 1, node.borrow().right.clone())); - if level > current_level { - if current_level % 2 == 1 { - vec.reverse(); - } - res.push(vec); - vec = Vec::new(); - current_level = level; - } - vec.push(node.borrow().val); - } - } - if !vec.is_empty() { - if current_level % 2 == 1 { - vec.reverse(); - } - res.push(vec) - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_103() { - assert_eq!( - Solution::zigzag_level_order(tree![3, 9, 20, null, null, 15, 7]), - vec![vec![3], vec![20, 9], vec![15, 7]] - ); - } -} diff --git a/src/solution/s0104_maximum_depth_of_binary_tree.rs b/src/solution/s0104_maximum_depth_of_binary_tree.rs deleted file mode 100644 index 2b2a51d4..00000000 --- a/src/solution/s0104_maximum_depth_of_binary_tree.rs +++ /dev/null @@ -1,61 +0,0 @@ -/** - * [104] Maximum Depth of Binary Tree - * - * Given a binary tree, find its maximum depth. - * - * The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. - * - * Note: A leaf is a node with no children. - * - * Example: - * - * Given binary tree [3,9,20,null,null,15,7], - * - * - * 3 - * / \ - * 9 20 - * / \ - * 15 7 - * - * return its depth = 3. - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/maximum-depth-of-binary-tree/ -// discuss: https://leetcode.com/problems/maximum-depth-of-binary-tree/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn max_depth(root: Option>>) -> i32 { - let mut max = 0; - Solution::depth_helper(root.as_ref(), &mut max, 0); - max - } - - fn depth_helper(root: Option<&Rc>>, max: &mut i32, curr: i32) { - if let Some(node) = root { - *max = i32::max(*max, curr + 1); - Solution::depth_helper(node.borrow().left.as_ref(), max, curr + 1); - Solution::depth_helper(node.borrow().right.as_ref(), max, curr + 1); - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_104() { - assert_eq!(Solution::max_depth(tree![]), 0); - assert_eq!(Solution::max_depth(tree![3, 9, 20, null, null, 15, 7]), 3); - } -} diff --git a/src/solution/s0105_construct_binary_tree_from_preorder_and_inorder_traversal.rs b/src/solution/s0105_construct_binary_tree_from_preorder_and_inorder_traversal.rs deleted file mode 100644 index 809ae654..00000000 --- a/src/solution/s0105_construct_binary_tree_from_preorder_and_inorder_traversal.rs +++ /dev/null @@ -1,71 +0,0 @@ -/** - * [105] Construct Binary Tree from Preorder and Inorder Traversal - * - * Given preorder and inorder traversal of a tree, construct the binary tree. - * - * Note:
- * You may assume that duplicates do not exist in the tree. - * - * For example, given - * - * - * preorder = [3,9,20,15,7] - * inorder = [9,3,15,20,7] - * - * Return the following binary tree: - * - * - * 3 - * / \ - * 9 20 - * / \ - * 15 7 - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/ -// discuss: https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn build_tree(preorder: Vec, inorder: Vec) -> Option>> { - Solution::build_tree_helper(&preorder[..], &inorder[..]) - } - - fn build_tree_helper(preorder: &[i32], inorder: &[i32]) -> Option>> { - if preorder.is_empty() { - return None; - } - let root_idx = inorder.iter().position(|&v| v == preorder[0]).unwrap(); - Some(Rc::new(RefCell::new(TreeNode { - val: preorder[0], - left: Solution::build_tree_helper(&preorder[1..root_idx + 1], &inorder[0..root_idx]), - right: Solution::build_tree_helper(&preorder[root_idx + 1..], &inorder[root_idx + 1..]), - }))) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_105() { - assert_eq!( - Solution::build_tree(vec![3, 9, 20, 15, 7], vec![9, 3, 15, 20, 7]), - tree![3, 9, 20, null, null, 15, 7] - ); - assert_eq!( - Solution::build_tree(vec![3, 20, 7], vec![3, 20, 7]), - tree![3, null, 20, null, 7] - ); - assert_eq!(Solution::build_tree(vec![], vec![]), tree![]); - } -} diff --git a/src/solution/s0106_construct_binary_tree_from_inorder_and_postorder_traversal.rs b/src/solution/s0106_construct_binary_tree_from_inorder_and_postorder_traversal.rs deleted file mode 100644 index df215bbc..00000000 --- a/src/solution/s0106_construct_binary_tree_from_inorder_and_postorder_traversal.rs +++ /dev/null @@ -1,78 +0,0 @@ -/** - * [106] Construct Binary Tree from Inorder and Postorder Traversal - * - * Given inorder and postorder traversal of a tree, construct the binary tree. - * - * Note:
- * You may assume that duplicates do not exist in the tree. - * - * For example, given - * - * - * inorder = [9,3,15,20,7] - * postorder = [9,15,7,20,3] - * - * Return the following binary tree: - * - * - * 3 - * / \ - * 9 20 - * / \ - * 15 7 - * - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/ -// discuss: https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn build_tree(inorder: Vec, postorder: Vec) -> Option>> { - Solution::build_tree_helper(&postorder[..], &inorder[..]) - } - - fn build_tree_helper(postorder: &[i32], inorder: &[i32]) -> Option>> { - if postorder.is_empty() { - return None; - } - let root_idx = inorder - .iter() - .position(|v| v == postorder.last().unwrap()) - .unwrap(); - Some(Rc::new(RefCell::new(TreeNode { - val: *postorder.last().unwrap(), - left: Solution::build_tree_helper(&postorder[0..root_idx], &inorder[0..root_idx]), - right: Solution::build_tree_helper( - &postorder[root_idx..postorder.len() - 1], - &inorder[root_idx + 1..], - ), - }))) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_106() { - assert_eq!( - Solution::build_tree(vec![9, 3, 15, 20, 7], vec![9, 15, 7, 20, 3]), - tree![3, 9, 20, null, null, 15, 7] - ); - assert_eq!( - Solution::build_tree(vec![3, 20, 7], vec![7, 20, 3]), - tree![3, null, 20, null, 7] - ); - assert_eq!(Solution::build_tree(vec![], vec![]), tree![]); - } -} diff --git a/src/solution/s0107_binary_tree_level_order_traversal_ii.rs b/src/solution/s0107_binary_tree_level_order_traversal_ii.rs deleted file mode 100644 index 4b74e0d7..00000000 --- a/src/solution/s0107_binary_tree_level_order_traversal_ii.rs +++ /dev/null @@ -1,82 +0,0 @@ -/** - * [107] Binary Tree Level Order Traversal II - * - * Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root). - * - * - * For example:
- * Given binary tree [3,9,20,null,null,15,7],
- * - * 3 - * / \ - * 9 20 - * / \ - * 15 7 - * - * - * - * return its bottom-up level order traversal as:
- * - * [ - * [15,7], - * [9,20], - * [3] - * ] - * - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/binary-tree-level-order-traversal-ii/ -// discuss: https://leetcode.com/problems/binary-tree-level-order-traversal-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::collections::VecDeque; -use std::rc::Rc; -impl Solution { - pub fn level_order_bottom(root: Option>>) -> Vec> { - let mut res = Vec::new(); - let mut current_level = 0; - if root.is_none() { - return res; - } - let mut deq = VecDeque::new(); - deq.push_back((0, root.clone())); - let mut vec = Vec::new(); - while !deq.is_empty() { - if let Some((level, Some(node))) = deq.pop_front() { - deq.push_back((level + 1, node.borrow().left.clone())); - deq.push_back((level + 1, node.borrow().right.clone())); - if level > current_level { - res.push(vec); - vec = Vec::new(); - current_level = level; - } - vec.push(node.borrow().val); - } - } - if !vec.is_empty() { - res.push(vec) - } - res.reverse(); - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_107() { - assert_eq!( - Solution::level_order_bottom(tree![3, 9, 20, null, null, 15, 7]), - vec![vec![15, 7], vec![9, 20], vec![3],] - ); - } -} diff --git a/src/solution/s0108_convert_sorted_array_to_binary_search_tree.rs b/src/solution/s0108_convert_sorted_array_to_binary_search_tree.rs deleted file mode 100644 index 2cefab5c..00000000 --- a/src/solution/s0108_convert_sorted_array_to_binary_search_tree.rs +++ /dev/null @@ -1,64 +0,0 @@ -/** - * [108] Convert Sorted Array to Binary Search Tree - * - * Given an array where elements are sorted in ascending order, convert it to a height balanced BST. - * - * For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1. - * - * Example: - * - * - * Given the sorted array: [-10,-3,0,5,9], - * - * One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST: - * - * 0 - * / \ - * -3 9 - * / / - * -10 5 - * - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/ -// discuss: https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn sorted_array_to_bst(nums: Vec) -> Option>> { - Solution::bst_helper(&nums[..]) - } - - fn bst_helper(nums: &[i32]) -> Option>> { - if nums.is_empty() { - return None; - } - Some(Rc::new(RefCell::new(TreeNode { - val: nums[nums.len() / 2], - left: Solution::bst_helper(&nums[0..(nums.len() / 2)]), - right: Solution::bst_helper(&nums[(nums.len() / 2 + 1)..]), - }))) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_108() { - assert_eq!( - Solution::sorted_array_to_bst(vec![-10, -3, 0, 5, 9]), - tree![0, -3, 9, -10, null, 5] - ); - assert_eq!(Solution::sorted_array_to_bst(vec![]), tree![]); - } -} diff --git a/src/solution/s0109_convert_sorted_list_to_binary_search_tree.rs b/src/solution/s0109_convert_sorted_list_to_binary_search_tree.rs deleted file mode 100644 index e2070965..00000000 --- a/src/solution/s0109_convert_sorted_list_to_binary_search_tree.rs +++ /dev/null @@ -1,70 +0,0 @@ -/** - * [109] Convert Sorted List to Binary Search Tree - * - * Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST. - * - * For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1. - * - * Example: - * - * - * Given the sorted linked list: [-10,-3,0,5,9], - * - * One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST: - * - * 0 - * / \ - * -3 9 - * / / - * -10 5 - * - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/ -// discuss: https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn sorted_list_to_bst(head: Option>) -> Option>> { - let mut arr = Vec::new(); - let mut head = head; - while let Some(node) = head { - arr.push(node.val); - head = node.next; - } - Solution::bst_helper(&arr[..]) - } - - fn bst_helper(nums: &[i32]) -> Option>> { - if nums.is_empty() { - return None; - } - Some(Rc::new(RefCell::new(TreeNode { - val: nums[nums.len() / 2], - left: Solution::bst_helper(&nums[0..(nums.len() / 2)]), - right: Solution::bst_helper(&nums[(nums.len() / 2 + 1)..]), - }))) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_109() { - assert_eq!( - Solution::sorted_list_to_bst(linked![-10, -3, 0, 5, 9]), - tree![0, -3, 9, -10, null, 5] - ); - } -} diff --git a/src/solution/s0110_balanced_binary_tree.rs b/src/solution/s0110_balanced_binary_tree.rs deleted file mode 100644 index c3171126..00000000 --- a/src/solution/s0110_balanced_binary_tree.rs +++ /dev/null @@ -1,97 +0,0 @@ -/** - * [110] Balanced Binary Tree - * - * Given a binary tree, determine if it is height-balanced. - * - * For this problem, a height-balanced binary tree is defined as: - * - *
- * a binary tree in which the depth of the two subtrees of every node never differ by more than 1. - *
- * - * Example 1: - * - * Given the following tree [3,9,20,null,null,15,7]: - * - * - * 3 - * / \ - * 9 20 - * / \ - * 15 7 - * - * Return true.
- *
- * Example 2: - * - * Given the following tree [1,2,2,3,3,null,null,4,4]: - * - * - * 1 - * / \ - * 2 2 - * / \ - * 3 3 - * / \ - * 4 4 - * - * - * Return false. - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/balanced-binary-tree/ -// discuss: https://leetcode.com/problems/balanced-binary-tree/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn is_balanced(root: Option>>) -> bool { - Solution::balanced_helper(root.as_ref()).is_some() - } - - fn balanced_helper(root: Option<&Rc>>) -> Option { - if let Some(node) = root { - let pair = ( - Solution::balanced_helper(node.borrow().left.as_ref()), - Solution::balanced_helper(node.borrow().right.as_ref()), - ); - match pair { - (Some(left), Some(right)) => { - if i32::abs(left - right) < 2 { - return Some(i32::max(left, right) + 1); - } else { - return None; - } - } - _ => return None, - } - } else { - Some(0) - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_110() { - assert_eq!(Solution::is_balanced(tree![]), true); - assert_eq!( - Solution::is_balanced(tree![3, 9, 20, null, null, 15, 7]), - true - ); - assert_eq!( - Solution::is_balanced(tree![1, 2, 2, 3, 3, null, null, 4, 4]), - false - ); - } -} diff --git a/src/solution/s0111_minimum_depth_of_binary_tree.rs b/src/solution/s0111_minimum_depth_of_binary_tree.rs deleted file mode 100644 index a73e49f0..00000000 --- a/src/solution/s0111_minimum_depth_of_binary_tree.rs +++ /dev/null @@ -1,65 +0,0 @@ -/** - * [111] Minimum Depth of Binary Tree - * - * Given a binary tree, find its minimum depth. - * - * The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. - * - * Note: A leaf is a node with no children. - * - * Example: - * - * Given binary tree [3,9,20,null,null,15,7], - * - * - * 3 - * / \ - * 9 20 - * / \ - * 15 7 - * - * return its minimum depth = 2. - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/minimum-depth-of-binary-tree/ -// discuss: https://leetcode.com/problems/minimum-depth-of-binary-tree/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::collections::VecDeque; -use std::rc::Rc; -impl Solution { - pub fn min_depth(root: Option>>) -> i32 { - if root.is_none() { - return 0; - } - let mut deq = VecDeque::new(); - deq.push_back((1, root.clone())); - while !deq.is_empty() { - if let Some((level, Some(node))) = deq.pop_front() { - if node.borrow().left.is_none() && node.borrow().right.is_none() { - return level; - } - deq.push_back((level + 1, node.borrow().left.clone())); - deq.push_back((level + 1, node.borrow().right.clone())); - } - } - 0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_111() { - assert_eq!(Solution::min_depth(tree![3, 9, 20, null, null, 15, 7]), 2); - } -} diff --git a/src/solution/s0112_path_sum.rs b/src/solution/s0112_path_sum.rs deleted file mode 100644 index e2e0a235..00000000 --- a/src/solution/s0112_path_sum.rs +++ /dev/null @@ -1,80 +0,0 @@ -/** - * [112] Path Sum - * - * Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. - * - * Note: A leaf is a node with no children. - * - * Example: - * - * Given the below binary tree and sum = 22, - * - * - * 5 - * / \ - * 4 8 - * / / \ - * 11 13 4 - * / \ \ - * 7 2 1 - * - * - * return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22. - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/path-sum/ -// discuss: https://leetcode.com/problems/path-sum/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::collections::VecDeque; -use std::rc::Rc; -impl Solution { - pub fn has_path_sum(root: Option>>, sum: i32) -> bool { - if root.is_none() { - return false; - } - let mut deq = VecDeque::new(); - deq.push_back((0, root.unwrap().clone())); - while !deq.is_empty() { - if let Some((acc, node)) = deq.pop_front() { - let acc = acc + node.borrow().val; - if node.borrow().left.is_none() && node.borrow().right.is_none() { - if acc == sum { - return true; - } - } else { - if node.borrow().left.is_some() { - deq.push_back((acc, node.borrow().left.as_ref().unwrap().clone())) - }; - if node.borrow().right.is_some() { - deq.push_back((acc, node.borrow().right.as_ref().unwrap().clone())) - }; - } - } - } - false - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_112() { - assert_eq!( - Solution::has_path_sum( - tree![5, 4, 8, 11, null, 13, 4, 7, 2, null, null, null, 1], - 22 - ), - true - ); - } -} diff --git a/src/solution/s0113_path_sum_ii.rs b/src/solution/s0113_path_sum_ii.rs deleted file mode 100644 index 106d1921..00000000 --- a/src/solution/s0113_path_sum_ii.rs +++ /dev/null @@ -1,86 +0,0 @@ -/** - * [113] Path Sum II - * - * Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum. - * - * Note: A leaf is a node with no children. - * - * Example: - * - * Given the below binary tree and sum = 22, - * - * - * 5 - * / \ - * 4 8 - * / / \ - * 11 13 4 - * / \ / \ - * 7 2 5 1 - * - * - * Return: - * - * - * [ - * [5,4,11,2], - * [5,8,4,5] - * ] - * - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/path-sum-ii/ -// discuss: https://leetcode.com/problems/path-sum-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::collections::VecDeque; -use std::rc::Rc; -impl Solution { - pub fn path_sum(root: Option>>, sum: i32) -> Vec> { - let mut res = Vec::new(); - if root.is_none() { - return res; - } - let mut deq = VecDeque::new(); - deq.push_back((0, Vec::new(), root.clone())); - while !deq.is_empty() { - if let Some((acc, mut vec, Some(node))) = deq.pop_front() { - let acc = acc + node.borrow().val; - vec.push(node.borrow().val); - if node.borrow().left.is_none() && node.borrow().right.is_none() { - if acc == sum { - res.push(vec); - } - } else { - if node.borrow().left.is_some() { - deq.push_back((acc, vec.clone(), node.borrow().left.clone())); - } - if node.borrow().right.is_some() { - deq.push_back((acc, vec.clone(), node.borrow().right.clone())); - } - } - } - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_113() { - assert_eq!( - Solution::path_sum(tree![5, 4, 8, 11, null, 13, 4, 7, 2, null, null, 5, 1], 22), - vec![vec![5, 4, 11, 2], vec![5, 8, 4, 5]] - ) - } -} diff --git a/src/solution/s0114_flatten_binary_tree_to_linked_list.rs b/src/solution/s0114_flatten_binary_tree_to_linked_list.rs deleted file mode 100644 index 63668c47..00000000 --- a/src/solution/s0114_flatten_binary_tree_to_linked_list.rs +++ /dev/null @@ -1,90 +0,0 @@ -/** - * [114] Flatten Binary Tree to Linked List - * - * Given a binary tree, flatten it to a linked list in-place. - * - * For example, given the following tree: - * - * - * 1 - * / \ - * 2 5 - * / \ \ - * 3 4 6 - * - * - * The flattened tree should look like: - * - * - * 1 - * \ - * 2 - * \ - * 3 - * \ - * 4 - * \ - * 5 - * \ - * 6 - * - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/flatten-binary-tree-to-linked-list/ -// discuss: https://leetcode.com/problems/flatten-binary-tree-to-linked-list/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn flatten(root: &mut Option>>) { - Solution::flatten_helper(root.clone()); - } - - fn flatten_helper(root: Option>>) -> Option>> { - if let Some(node) = root { - let tail = Solution::flatten_helper(node.borrow().left.clone()); - Solution::flatten_helper(node.borrow_mut().right.clone()); - let mut right = node.borrow().right.clone(); - let mut ptr = node.clone(); - if let Some(tail) = tail { - let head = node.borrow_mut().left.take(); - node.borrow_mut().right = head; - tail.borrow_mut().right = right.clone(); - ptr = tail.clone(); - } - while let Some(next) = ptr.clone().borrow().right.clone() { - ptr = next - } - Some(ptr) - } else { - None - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_114() { - let mut tree = tree![1, 2, 5, 3, 4, null, 6]; - Solution::flatten(&mut tree); - assert_eq!(tree, tree![1, null, 2, null, 3, null, 4, null, 5, null, 6]); - - let mut tree = tree![1, 2, null, 3]; - Solution::flatten(&mut tree); - assert_eq!(tree, tree![1, null, 2, null, 3]); - - let mut tree = tree![1, null, 2, 3]; - Solution::flatten(&mut tree); - assert_eq!(tree, tree![1, null, 2, null, 3]); - } -} diff --git a/src/solution/s0115_distinct_subsequences.rs b/src/solution/s0115_distinct_subsequences.rs deleted file mode 100644 index 7af3d08b..00000000 --- a/src/solution/s0115_distinct_subsequences.rs +++ /dev/null @@ -1,122 +0,0 @@ -/** - * [115] Distinct Subsequences - * - * Given a string S and a string T, count the number of distinct subsequences of S which equals T. - * - * A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not). - * - * Example 1: - * - * - * Input: S = "rabbbit", T = "rabbit" - * Output: 3 - * Explanation: - * - * As shown below, there are 3 ways you can generate "rabbit" from S. - * (The caret symbol ^ means the chosen letters) - * - * rabbbit - * ^^^^ ^^ - * rabbbit - * ^^ ^^^^ - * rabbbit - * ^^^ ^^^ - * - * - * Example 2: - * - * - * Input: S = "babgbag", T = "bag" - * Output: 5 - * Explanation: - * - * As shown below, there are 5 ways you can generate "bag" from S. - * (The caret symbol ^ means the chosen letters) - * - * babgbag - * ^^ ^ - * babgbag - * ^^ ^ - * babgbag - * ^ ^^ - * babgbag - * ^ ^^ - * babgbag - * ^^^ - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/distinct-subsequences/ -// discuss: https://leetcode.com/problems/distinct-subsequences/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -首先想到 DFS. 但这里 DFS 有重复计算, 因为我们不需要列出所有的路径, 复杂度可以考虑 "aaaaaaaaaaaaaaaaaaaa" -里找 "aaaaaaaaa", 直接搜索的话复杂度是指数级的(阶乘), 原因很明显, 这本身是个排列组合, 可以套 combination 公式 -20! / ((20-10)! * 10!) 得到结果是 184756 - -要把复杂度从指数级降下来, 那么必须干掉重复计算, 那就想到 memorize, 想到 memorize 就想到 DP 和 Bottom-Up 递推, -回顾一下 #62 和 #63 这两个问题 (unique paths), 使用的是Bottom-Up DP, 到达每个格子的可能路径是上下两个格子的 -可能路径的和. 这里就跳过了很多的计算, 不需要把每条路径都遍历出来了. 在 unique paths 问题中, 到达右下角的路径数的 -子问题是到达右下角左侧格子的路径数以及到达右下角上侧格子的路径数. 这个问题也是一样的道理, s 中找子序列 t: - -* s[0..i] 包含的 t 序列数就是所有 s[0..j] (j < i) 包含的 t[0..t.len()-1] 的序列数 - -以 babgbag 中找 bag 为例, 做一次 Bottom-Up 递推: - - b a b g b a g -b 1 1 1 3 找 'b' 这个子序列, 那么以 [0, 2, 4] 这三个下标结尾各有一种 -a 1 3 4 找 'ba' 这个子序列, 那么以 1 结尾有1种(0 < 1), 以 5 结尾有 3 种 (0,2,4 都 < 5) -g 1 4 5 同理, 以 3 结尾有 1 种, 以 6 结尾有 4 种, 共 5 种 - -显然, 计算第 N 行时只依赖第 N-1 行的结果, 因此我们不需要存储整个矩阵, 只需要存储一行即可 - -时间复杂度是 O(M*N), 空间复杂度是 O(M) -*/ -impl Solution { - pub fn num_distinct(s: String, t: String) -> i32 { - let s = s.chars().collect::>(); - let mut cache = vec![0; s.len()]; - for (i, ch) in t.chars().into_iter().enumerate() { - let mut acc = 0; - // first char initialization - if i == 0 { - for i in 0..s.len() { - if ch == s[i] { - cache[i] = 1 - } - } - continue; - } - for i in 0..s.len() { - let new_acc = acc + cache[i]; - cache[i] = if s[i] == ch { acc } else { 0 }; - acc = new_acc; - } - } - cache.into_iter().fold(0, |acc, x| acc + x) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_115() { - //assert_eq!(Solution::num_distinct("rabbbit".to_owned(), "rabbit".to_owned()), 3); - assert_eq!( - Solution::num_distinct("babgbag".to_owned(), "bag".to_owned()), - 5 - ); - assert_eq!( - Solution::num_distinct("aaaaaaaaaaaaaaaaaaaa".to_owned(), "aaaaaaaaaa".to_owned()), - 184756 - ); - } -} diff --git a/src/solution/s0118_pascals_triangle.rs b/src/solution/s0118_pascals_triangle.rs deleted file mode 100644 index d593242d..00000000 --- a/src/solution/s0118_pascals_triangle.rs +++ /dev/null @@ -1,70 +0,0 @@ -/** - * [118] Pascal's Triangle - * - * Given a non-negative integer numRows, generate the first numRows of Pascal's triangle. - * - *
- * In Pascal's triangle, each number is the sum of the two numbers directly above it. - * - * Example: - * - * - * Input: 5 - * Output: - * [ - * [1], - * [1,1], - * [1,2,1], - * [1,3,3,1], - * [1,4,6,4,1] - * ] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/pascals-triangle/ -// discuss: https://leetcode.com/problems/pascals-triangle/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn generate(num_rows: i32) -> Vec> { - let mut res = Vec::new(); - if num_rows < 1 { - return res; - } - let mut curr = vec![1]; - for _ in 0..num_rows { - let mut next = vec![1; curr.len() + 1]; - for i in 1..curr.len() { - next[i] = curr[i - 1] + curr[i]; - } - res.push(curr); - curr = next; - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_118() { - assert_eq!(Solution::generate(1), vec![vec![1]]); - assert_eq!( - Solution::generate(5), - vec![ - vec![1], - vec![1, 1], - vec![1, 2, 1], - vec![1, 3, 3, 1], - vec![1, 4, 6, 4, 1] - ] - ); - } -} diff --git a/src/solution/s0119_pascals_triangle_ii.rs b/src/solution/s0119_pascals_triangle_ii.rs deleted file mode 100644 index 588a9835..00000000 --- a/src/solution/s0119_pascals_triangle_ii.rs +++ /dev/null @@ -1,64 +0,0 @@ -/** - * [119] Pascal's Triangle II - * - * Given a non-negative index k where k ≤ 33, return the k^th index row of the Pascal's triangle. - * - * Note that the row index starts from 0. - * - *
- * In Pascal's triangle, each number is the sum of the two numbers directly above it. - * - * Example: - * - * - * Input: 3 - * Output: [1,3,3,1] - * - * - * Follow up: - * - * Could you optimize your algorithm to use only O(k) extra space? - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/pascals-triangle-ii/ -// discuss: https://leetcode.com/problems/pascals-triangle-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -in-place algorithm - -1 1 1 1 1 -1 2 1 1 1 -1 3 3 1 1 -1 4 6 4 1 -*/ -impl Solution { - pub fn get_row(row_index: i32) -> Vec { - let mut curr = vec![1; (row_index + 1) as usize]; - for i in 0..row_index + 1 { - let mut prev = 1; - for j in 1..i { - let temp = curr[j as usize]; - curr[j as usize] = temp + prev; - prev = temp; - } - } - curr - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_119() { - assert_eq!(Solution::get_row(0), vec![1]); - assert_eq!(Solution::get_row(4), vec![1, 4, 6, 4, 1]) - } -} diff --git a/src/solution/s0120_triangle.rs b/src/solution/s0120_triangle.rs deleted file mode 100644 index 93c38d33..00000000 --- a/src/solution/s0120_triangle.rs +++ /dev/null @@ -1,67 +0,0 @@ -/** - * [120] Triangle - * - * Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below. - * - * For example, given the following triangle - * - * - * [ - * [2], - * [3,4], - * [6,5,7], - * [4,1,8,3] - * ] - * - * - * The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11). - * - * Note: - * - * Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/triangle/ -// discuss: https://leetcode.com/problems/triangle/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn minimum_total(triangle: Vec>) -> i32 { - let mut cache = vec![0; triangle.len()]; - for row in triangle.iter() { - let mut prev = 0; - for i in 0..row.len() { - let temp = cache[i]; - cache[i] = if i == 0 { - cache[i] - } else if i == row.len() - 1 { - prev - } else { - i32::min(cache[i], prev) - } + row[i]; - prev = temp; - } - } - cache - .into_iter() - .fold(i32::max_value(), |min, x| i32::min(min, x)) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_120() { - assert_eq!( - Solution::minimum_total(vec![vec![2], vec![3, 4], vec![6, 5, 7], vec![4, 1, 8, 3]]), - 11 - ) - } -} diff --git a/src/solution/s0121_best_time_to_buy_and_sell_stock.rs b/src/solution/s0121_best_time_to_buy_and_sell_stock.rs deleted file mode 100644 index d5d3746d..00000000 --- a/src/solution/s0121_best_time_to_buy_and_sell_stock.rs +++ /dev/null @@ -1,62 +0,0 @@ -/** - * [121] Best Time to Buy and Sell Stock - * - * Say you have an array for which the i^th element is the price of a given stock on day i. - * - * If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit. - * - * Note that you cannot sell a stock before you buy one. - * - * Example 1: - * - * - * Input: [7,1,5,3,6,4] - * Output: 5 - * Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5. - * Not 7-1 = 6, as selling price needs to be larger than buying price. - * - * - * Example 2: - * - * - * Input: [7,6,4,3,1] - * Output: 0 - * Explanation: In this case, no transaction is done, i.e. max profit = 0. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ -// discuss: https://leetcode.com/problems/best-time-to-buy-and-sell-stock/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn max_profit(prices: Vec) -> i32 { - let mut max = 0; - let mut curr = 0; - for i in 1..prices.len() { - curr = curr + prices[i] - prices[i - 1]; - if curr <= 0 { - curr = 0; - } else { - max = i32::max(max, curr); - } - } - max - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_121() { - assert_eq!(Solution::max_profit(vec![7, 1, 5, 3, 6, 4]), 5); - assert_eq!(Solution::max_profit(vec![7, 6, 4, 3, 1]), 0); - } -} diff --git a/src/solution/s0122_best_time_to_buy_and_sell_stock_ii.rs b/src/solution/s0122_best_time_to_buy_and_sell_stock_ii.rs deleted file mode 100644 index 803c71b6..00000000 --- a/src/solution/s0122_best_time_to_buy_and_sell_stock_ii.rs +++ /dev/null @@ -1,67 +0,0 @@ -/** - * [122] Best Time to Buy and Sell Stock II - * - * Say you have an array for which the i^th element is the price of a given stock on day i. - * - * Design an algorithm to find the maximum profit. You may complete as many transactions as you like (i.e., buy one and sell one share of the stock multiple times). - * - * Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again). - * - * Example 1: - * - * - * Input: [7,1,5,3,6,4] - * Output: 7 - * Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4. - * Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3. - * - * - * Example 2: - * - * - * Input: [1,2,3,4,5] - * Output: 4 - * Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4. - * Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are - * engaging multiple transactions at the same time. You must sell before buying again. - * - * - * Example 3: - * - * - * Input: [7,6,4,3,1] - * Output: 0 - * Explanation: In this case, no transaction is done, i.e. max profit = 0. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/ -// discuss: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn max_profit(prices: Vec) -> i32 { - let mut max = 0; - for i in 1..prices.len() { - if prices[i] > prices[i - 1] { - max += prices[i] - prices[i - 1]; - } - } - max - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_122() { - assert_eq!(Solution::max_profit(vec![7, 1, 5, 3, 6, 4]), 7); - assert_eq!(Solution::max_profit(vec![1, 2, 3, 4, 5]), 4); - } -} diff --git a/src/solution/s0123_best_time_to_buy_and_sell_stock_iii.rs b/src/solution/s0123_best_time_to_buy_and_sell_stock_iii.rs deleted file mode 100644 index bb068273..00000000 --- a/src/solution/s0123_best_time_to_buy_and_sell_stock_iii.rs +++ /dev/null @@ -1,106 +0,0 @@ -/** - * [123] Best Time to Buy and Sell Stock III - * - * Say you have an array for which the i^th element is the price of a given stock on day i. - * - * Design an algorithm to find the maximum profit. You may complete at most two transactions. - * - * Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again). - * - * Example 1: - * - * - * Input: [3,3,5,0,0,3,1,4] - * Output: 6 - * Explanation: Buy on day 4 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3. - * Then buy on day 7 (price = 1) and sell on day 8 (price = 4), profit = 4-1 = 3. - * - * Example 2: - * - * - * Input: [1,2,3,4,5] - * Output: 4 - * Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4. - * Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are - * engaging multiple transactions at the same time. You must sell before buying again. - * - * - * Example 3: - * - * - * Input: [7,6,4,3,1] - * Output: 0 - * Explanation: In this case, no transaction is done, i.e. max profit = 0. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/ -// discuss: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -先考虑只进行 1 次交易的情况, 我们求以 i *为售出点*, 只进行 1 次交易获得的最大利润, 那么: - -f[i] = if f[i-1] > 0 { f[i-1] } else { 0 } + prices[i] - prices[i-1] - -这很容易解, 解完之后找出 f 里的最大值即可, 但这不容易推广到 K 次交易的情况, 因为这时 f[i] 不代表到 i *为止*的最大利润, 无法作为单独的交易帮助递推 -(到 i 为止的含义是售出点可以在 [0,i] 之间) - -我们可以稍作改进, 变成求以 i 为结束点, 只进行 1 次交易获得的最大利润, 那么: - -f[i] = max( - f[i-1], - prices[i] - min(prices[j] { j in [0, i-1] }) -) - -这仍然是一个 O(N) 的解法, 因为 min(prices[j] { j in [0, i-1] }) 不需要遍历, 可以在递推过程中直接维护好 - -现在再推广到进行 K 次交易的情况, 那我们要求以 i 为结束点, 进行 k 次交易获得的最大利润, 这时有了变化, 我们可以在 j 之前再进行 K - 1 次交易: - -f[k, i] = max( - f[k, i-1], - prices[i] + max(f[k-1, j] - prices[j]) { j in [0, i-1] } ) -) - -显然, f[0, i] = 0, f[k, 0] = 0 - -这个算法可以形象地描述一下, 在 k = 1 时, 我们每次要找的就是 i 之前的最低谷点作为这次交易的开始点 j, 而当 k > 1 时, -我们 i 之前就有可能已经进行过交易了, 这时我们在找开始点 j 时, 就要同时考虑 "直到 j 为止, k-1 次交易的最大收益" - "j 本身的值". 以此来找到一个最佳点 j - -在实现时, 假如用 Bottom-Up 递推, 那么只需要维护一个 vec[i], 因为每轮递推时只会考虑上一轮的数据, 我们可以复用这个 O(N) 的额外存储空间 -*/ -impl Solution { - pub fn max_profit(prices: Vec) -> i32 { - if prices.is_empty() { - return 0; - } - let max_trans = 2; - let mut cache = vec![0; prices.len()]; - for trans in 0..max_trans { - // best_by_in 维护了考虑前 N 次交易的最佳的买入点, 即 max(f[k-1, j] - prices[j]) { j in [0, i-1] } - let mut best_buy_in = cache[0] - prices[0]; - for i in 1..prices.len() { - // 复用 vec 前暂存一下前一次的计算结果 - let temp = cache[i]; - cache[i] = i32::max(cache[i - 1], best_buy_in + prices[i]); - // 更新 best_buy_in - best_buy_in = i32::max(best_buy_in, temp - prices[i]); - } - } - return *cache.last().unwrap(); - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_123() { - assert_eq!(Solution::max_profit(vec![3, 3, 5, 0, 0, 3, 1, 4]), 6); - } -} diff --git a/src/solution/s0124_binary_tree_maximum_path_sum.rs b/src/solution/s0124_binary_tree_maximum_path_sum.rs deleted file mode 100644 index e7c57b49..00000000 --- a/src/solution/s0124_binary_tree_maximum_path_sum.rs +++ /dev/null @@ -1,100 +0,0 @@ -/** - * [124] Binary Tree Maximum Path Sum - * - * Given a non-empty binary tree, find the maximum path sum. - * - * For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path must contain at least one node and does not need to go through the root. - * - * Example 1: - * - * - * Input: [1,2,3] - * - * 1 - * / \ - * 2 3 - * - * Output: 6 - * - * - * Example 2: - * - * - * Input: [-10,9,20,null,null,15,7] - * - * -10 - * / \ - * 9 20 - * / \ - * 15 7 - * - * Output: 42 - * - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/binary-tree-maximum-path-sum/ -// discuss: https://leetcode.com/problems/binary-tree-maximum-path-sum/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -典型的动态规划, 我们求以 node_i 为 root 的最大和, 可以下推到求 root 的左右子树, 这里要注意, 路径是不能分叉的, 因此 -我们记 f[node] 为以 node 为根的最大和, 记 g[node] 为 node 为根, *最多连通一侧子树*的最大和 - -我们在递推时要用 g[node], f[node] 在递推过程中每次计算一下用于更新 max 即可 - -g[node_i] = node_i.val + max(g[node_i.left], g[node_i.right], 0) -f[node_i] = node_i.val + max(g[node_i.left], 0) + max(g[node_i.right], 0) - -显然, g[None] = 0 (None 即空子树), 最终计算到 g[root] 中止, f 的最大值会在计算过程中出现(注意 f[root] 不一定是最大值) - -每个 node 最大和只依赖与其左右子树的最大和, 因此 Top-down 需要 O(N) 的空间 -Bottom-up 只需要 O(1) 空间 (做后序遍历从叶节点向上递推即可) -*/ -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn max_path_sum(root: Option>>) -> i32 { - let mut max = i32::min_value(); - Solution::postorder(root.as_ref(), &mut max); - max - } - - fn postorder(root: Option<&Rc>>, max: &mut i32) -> i32 { - if let Some(node) = root { - let left = Solution::postorder(node.borrow().left.as_ref(), max); - let right = Solution::postorder(node.borrow().right.as_ref(), max); - *max = i32::max( - node.borrow().val + i32::max(left, 0) + i32::max(right, 0), - *max, - ); - node.borrow().val + i32::max(i32::max(left, right), 0) - } else { - 0 - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_124() { - assert_eq!(Solution::max_path_sum(tree![1, 2, 3]), 6); - assert_eq!( - Solution::max_path_sum(tree![-10, 9, 20, null, null, 15, 7]), - 42 - ); - assert_eq!( - Solution::max_path_sum(tree![5, 4, 8, 11, null, 13, 4, 7, 2, null, null, null, 1]), - 48 - ); - assert_eq!(Solution::max_path_sum(tree![-3]), -3); - } -} diff --git a/src/solution/s0125_valid_palindrome.rs b/src/solution/s0125_valid_palindrome.rs deleted file mode 100644 index 2f090b72..00000000 --- a/src/solution/s0125_valid_palindrome.rs +++ /dev/null @@ -1,72 +0,0 @@ -/** - * [125] Valid Palindrome - * - * Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. - * - * Note: For the purpose of this problem, we define empty string as valid palindrome. - * - * Example 1: - * - * - * Input: "A man, a plan, a canal: Panama" - * Output: true - * - * - * Example 2: - * - * - * Input: "race a car" - * Output: false - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/valid-palindrome/ -// discuss: https://leetcode.com/problems/valid-palindrome/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn is_palindrome(s: String) -> bool { - if s.is_empty() { - return true; - } - let seq = s.chars().collect::>(); - let (mut i, mut j) = (0_usize, seq.len() - 1); - while i < j { - while i < seq.len() && !seq[i].is_ascii_alphanumeric() { - i += 1; - } - while j > 0 && !seq[j].is_ascii_alphanumeric() { - j -= 1; - } - if i >= j { - break; - } - if seq[i].to_ascii_lowercase() != seq[j].to_ascii_lowercase() { - return false; - } - i += 1; - j -= 1; - } - true - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_125() { - assert_eq!( - Solution::is_palindrome("A man, a plan, a canal: Panama".to_owned()), - true - ); - assert_eq!(Solution::is_palindrome("race a car".to_owned()), false); - assert_eq!(Solution::is_palindrome("0P".to_owned()), false); - } -} diff --git a/src/solution/s0126_word_ladder_ii.rs b/src/solution/s0126_word_ladder_ii.rs deleted file mode 100644 index 32169865..00000000 --- a/src/solution/s0126_word_ladder_ii.rs +++ /dev/null @@ -1,258 +0,0 @@ -/** - * [126] Word Ladder II - * - * Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that: - * - *
    - * Only one letter can be changed at a time - * Each transformed word must exist in the word list. Note that beginWord is not a transformed word. - *
- * - * Note: - * - * - * Return an empty list if there is no such transformation sequence. - * All words have the same length. - * All words contain only lowercase alphabetic characters. - * You may assume no duplicates in the word list. - * You may assume beginWord and endWord are non-empty and are not the same. - * - * - * Example 1: - * - * - * Input: - * beginWord = "hit", - * endWord = "cog", - * wordList = ["hot","dot","dog","lot","log","cog"] - * - * Output: - * [ - * ["hit","hot","dot","dog","cog"], - * ["hit","hot","lot","log","cog"] - * ] - * - * - * Example 2: - * - * - * Input: - * beginWord = "hit" - * endWord = "cog" - * wordList = ["hot","dot","dog","lot","log"] - * - * Output: [] - * - * Explanation: The endWord "cog" is not in wordList, therefore no possible transformation. - * - * - * - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/word-ladder-ii/ -// discuss: https://leetcode.com/problems/word-ladder-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -假如 A 经过一个字符的变换能得到 B, 则认为 A 与 B 之间有通路, 转化为一个 BFS 找无权图最短路径的问题 - -实现时, 可以先把图构造出来, 复杂度 O(L*N^2) (L 是字符串长度), 也可以每次都回到数组里去找连通点, 时间复杂度不变 - -由于要记录所有的路径, 因此我们需要把每个点的可能前置节点都记录下来, 最后用一个 DFS 或 BFS 找出所有路径 - -暂时想不到更好的办法 -*/ - -use std::collections::HashSet; -use std::collections::VecDeque; -impl Solution { - pub fn find_ladders( - begin_word: String, - end_word: String, - word_list: Vec, - ) -> Vec> { - let mut res = Vec::new(); - let len = word_list.len(); - let target = word_list.iter().position(|s| s == &end_word); - if target.is_none() { - return res; - } - let target = target.unwrap(); - let mut deq = VecDeque::new(); - deq.push_back(target); - // paths record the distance & previous index, we use 'len' to represent empty prev - let mut paths: Vec<(i32, Vec)> = vec![(i32::max_value(), vec![]); len]; - paths[target].0 = 0; - let mut find_shortest = false; - let mut shortest = i32::max_value(); - let mut in_queue = HashSet::new(); - while let Some(i) = deq.pop_front() { - if Solution::connect(&begin_word, &word_list[i]) { - // complete the path using dfs - if paths[i].0 > shortest { - continue; - } - Solution::dfs(i, vec![begin_word.clone()], &word_list, &paths, &mut res); - shortest = paths[i].0; - find_shortest = true; - } - // we have found the shortest path, just drain all the nodes in deq - if find_shortest { - continue; - } - for j in 0..len { - if j == i { - continue; - } - if Solution::connect(&word_list[i], &word_list[j]) { - if paths[i].0 + 1 <= paths[j].0 { - let mut prev = &mut paths[j].1; - prev.push(i); - paths[j].0 = paths[i].0 + 1; - if !in_queue.contains(&j) { - deq.push_back(j); - in_queue.insert(j); - } - } - } - } - } - res - } - - fn dfs( - curr: usize, - mut path: Vec, - words: &Vec, - paths: &Vec<(i32, Vec)>, - res: &mut Vec>, - ) { - path.push(words[curr].clone()); - if paths[curr].1.is_empty() { - res.push(path); - return; - } - for &prev in paths[curr].1.iter() { - Solution::dfs(prev, path.clone(), words, paths, res); - } - } - - #[inline(always)] - fn connect(s1: &str, s2: &str) -> bool { - if s1.len() != s2.len() { - return false; - } - let mut iter1 = s1.chars().into_iter(); - let mut iter2 = s2.chars().into_iter(); - let mut diff = 0; - while let (Some(c1), Some(c2)) = (iter1.next(), iter2.next()) { - if c1 != c2 { - diff += 1; - if diff >= 2 { - return false; - } - } - } - true - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_126() { - assert_eq!( - Solution::find_ladders( - "hit".to_owned(), - "cog".to_owned(), - vec_string!["hot", "dot", "dog", "lot", "log", "cog"] - ), - vec![ - vec_string!["hit", "hot", "dot", "dog", "cog"], - vec_string!["hit", "hot", "lot", "log", "cog"], - ] - ); - assert_eq!( - Solution::find_ladders( - "cet".to_owned(), - "ism".to_owned(), - vec_string![ - "kid", "tag", "pup", "ail", "tun", "woo", "erg", "luz", "brr", "gay", "sip", - "kay", "per", "val", "mes", "ohs", "now", "boa", "cet", "pal", "bar", "die", - "war", "hay", "eco", "pub", "lob", "rue", "fry", "lit", "rex", "jan", "cot", - "bid", "ali", "pay", "col", "gum", "ger", "row", "won", "dan", "rum", "fad", - "tut", "sag", "yip", "sui", "ark", "has", "zip", "fez", "own", "ump", "dis", - "ads", "max", "jaw", "out", "btu", "ana", "gap", "cry", "led", "abe", "box", - "ore", "pig", "fie", "toy", "fat", "cal", "lie", "noh", "sew", "ono", "tam", - "flu", "mgm", "ply", "awe", "pry", "tit", "tie", "yet", "too", "tax", "jim", - "san", "pan", "map", "ski", "ova", "wed", "non", "wac", "nut", "why", "bye", - "lye", "oct", "old", "fin", "feb", "chi", "sap", "owl", "log", "tod", "dot", - "bow", "fob", "for", "joe", "ivy", "fan", "age", "fax", "hip", "jib", "mel", - "hus", "sob", "ifs", "tab", "ara", "dab", "jag", "jar", "arm", "lot", "tom", - "sax", "tex", "yum", "pei", "wen", "wry", "ire", "irk", "far", "mew", "wit", - "doe", "gas", "rte", "ian", "pot", "ask", "wag", "hag", "amy", "nag", "ron", - "soy", "gin", "don", "tug", "fay", "vic", "boo", "nam", "ave", "buy", "sop", - "but", "orb", "fen", "paw", "his", "sub", "bob", "yea", "oft", "inn", "rod", - "yam", "pew", "web", "hod", "hun", "gyp", "wei", "wis", "rob", "gad", "pie", - "mon", "dog", "bib", "rub", "ere", "dig", "era", "cat", "fox", "bee", "mod", - "day", "apr", "vie", "nev", "jam", "pam", "new", "aye", "ani", "and", "ibm", - "yap", "can", "pyx", "tar", "kin", "fog", "hum", "pip", "cup", "dye", "lyx", - "jog", "nun", "par", "wan", "fey", "bus", "oak", "bad", "ats", "set", "qom", - "vat", "eat", "pus", "rev", "axe", "ion", "six", "ila", "lao", "mom", "mas", - "pro", "few", "opt", "poe", "art", "ash", "oar", "cap", "lop", "may", "shy", - "rid", "bat", "sum", "rim", "fee", "bmw", "sky", "maj", "hue", "thy", "ava", - "rap", "den", "fla", "auk", "cox", "ibo", "hey", "saw", "vim", "sec", "ltd", - "you", "its", "tat", "dew", "eva", "tog", "ram", "let", "see", "zit", "maw", - "nix", "ate", "gig", "rep", "owe", "ind", "hog", "eve", "sam", "zoo", "any", - "dow", "cod", "bed", "vet", "ham", "sis", "hex", "via", "fir", "nod", "mao", - "aug", "mum", "hoe", "bah", "hal", "keg", "hew", "zed", "tow", "gog", "ass", - "dem", "who", "bet", "gos", "son", "ear", "spy", "kit", "boy", "due", "sen", - "oaf", "mix", "hep", "fur", "ada", "bin", "nil", "mia", "ewe", "hit", "fix", - "sad", "rib", "eye", "hop", "haw", "wax", "mid", "tad", "ken", "wad", "rye", - "pap", "bog", "gut", "ito", "woe", "our", "ado", "sin", "mad", "ray", "hon", - "roy", "dip", "hen", "iva", "lug", "asp", "hui", "yak", "bay", "poi", "yep", - "bun", "try", "lad", "elm", "nat", "wyo", "gym", "dug", "toe", "dee", "wig", - "sly", "rip", "geo", "cog", "pas", "zen", "odd", "nan", "lay", "pod", "fit", - "hem", "joy", "bum", "rio", "yon", "dec", "leg", "put", "sue", "dim", "pet", - "yaw", "nub", "bit", "bur", "sid", "sun", "oil", "red", "doc", "moe", "caw", - "eel", "dix", "cub", "end", "gem", "off", "yew", "hug", "pop", "tub", "sgt", - "lid", "pun", "ton", "sol", "din", "yup", "jab", "pea", "bug", "gag", "mil", - "jig", "hub", "low", "did", "tin", "get", "gte", "sox", "lei", "mig", "fig", - "lon", "use", "ban", "flo", "nov", "jut", "bag", "mir", "sty", "lap", "two", - "ins", "con", "ant", "net", "tux", "ode", "stu", "mug", "cad", "nap", "gun", - "fop", "tot", "sow", "sal", "sic", "ted", "wot", "del", "imp", "cob", "way", - "ann", "tan", "mci", "job", "wet", "ism", "err", "him", "all", "pad", "hah", - "hie", "aim", "ike", "jed", "ego", "mac", "baa", "min", "com", "ill", "was", - "cab", "ago", "ina", "big", "ilk", "gal", "tap", "duh", "ola", "ran", "lab", - "top", "gob", "hot", "ora", "tia", "kip", "han", "met", "hut", "she", "sac", - "fed", "goo", "tee", "ell", "not", "act", "gil", "rut", "ala", "ape", "rig", - "cid", "god", "duo", "lin", "aid", "gel", "awl", "lag", "elf", "liz", "ref", - "aha", "fib", "oho", "tho", "her", "nor", "ace", "adz", "fun", "ned", "coo", - "win", "tao", "coy", "van", "man", "pit", "guy", "foe", "hid", "mai", "sup", - "jay", "hob", "mow", "jot", "are", "pol", "arc", "lax", "aft", "alb", "len", - "air", "pug", "pox", "vow", "got", "meg", "zoe", "amp", "ale", "bud", "gee", - "pin", "dun", "pat", "ten", "mob" - ] - ), - vec![ - vec_string![ - "cet", "get", "gee", "gte", "ate", "ats", "its", "ito", "ibo", "ibm", "ism" - ], - vec_string![ - "cet", "cat", "can", "ian", "inn", "ins", "its", "ito", "ibo", "ibm", "ism" - ], - vec_string![ - "cet", "cot", "con", "ion", "inn", "ins", "its", "ito", "ibo", "ibm", "ism" - ], - ] - ); - } -} diff --git a/src/solution/s0127_word_ladder.rs b/src/solution/s0127_word_ladder.rs deleted file mode 100644 index a67465fa..00000000 --- a/src/solution/s0127_word_ladder.rs +++ /dev/null @@ -1,132 +0,0 @@ -/** - * [127] Word Ladder - * - * Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that: - * - *
    - * Only one letter can be changed at a time. - * Each transformed word must exist in the word list. Note that beginWord is not a transformed word. - *
- * - * Note: - * - * - * Return 0 if there is no such transformation sequence. - * All words have the same length. - * All words contain only lowercase alphabetic characters. - * You may assume no duplicates in the word list. - * You may assume beginWord and endWord are non-empty and are not the same. - * - * - * Example 1: - * - * - * Input: - * beginWord = "hit", - * endWord = "cog", - * wordList = ["hot","dot","dog","lot","log","cog"] - * - * Output: 5 - * - * Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog", - * return its length 5. - * - * - * Example 2: - * - * - * Input: - * beginWord = "hit" - * endWord = "cog" - * wordList = ["hot","dot","dog","lot","log"] - * - * Output: 0 - * - * Explanation: The endWord "cog" is not in wordList, therefore no possible transformation. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/word-ladder/ -// discuss: https://leetcode.com/problems/word-ladder/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::collections::HashSet; -use std::collections::VecDeque; -impl Solution { - pub fn ladder_length(begin_word: String, end_word: String, word_list: Vec) -> i32 { - let len = word_list.len(); - let target = word_list.iter().position(|s| s == &end_word); - if target.is_none() { - return 0; - } - let target = target.unwrap(); - let mut deq = VecDeque::new(); - let mut distance = vec![0; len]; - let mut remain = (0..len).collect::>(); - deq.push_back(target); - remain.remove(&target); - while let Some(i) = deq.pop_front() { - if Solution::connect(&begin_word, &word_list[i]) { - return distance[i] + 2; - } - remain.retain(|&j| { - if Solution::connect(&word_list[i], &word_list[j]) { - distance[j] = distance[i] + 1; - deq.push_back(j); - false - } else { - true - } - }); - } - 0 - } - - #[inline(always)] - fn connect(s1: &str, s2: &str) -> bool { - if s1.len() != s2.len() { - return false; - } - let mut iter1 = s1.chars().into_iter(); - let mut iter2 = s2.chars().into_iter(); - let mut diff = 0; - while let (Some(c1), Some(c2)) = (iter1.next(), iter2.next()) { - if c1 != c2 { - diff += 1; - if diff >= 2 { - return false; - } - } - } - true - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_127() { - assert_eq!( - Solution::ladder_length( - "hit".to_owned(), - "cog".to_owned(), - vec_string!["hot", "dot", "dog", "lot", "log", "cog"] - ), - 5 - ); - assert_eq!( - Solution::ladder_length( - "hit".to_owned(), - "cog".to_owned(), - vec_string!["hot", "dot", "dog", "lot", "log"] - ), - 0 - ); - } -} diff --git a/src/solution/s0128_longest_consecutive_sequence.rs b/src/solution/s0128_longest_consecutive_sequence.rs deleted file mode 100644 index f0e0806f..00000000 --- a/src/solution/s0128_longest_consecutive_sequence.rs +++ /dev/null @@ -1,65 +0,0 @@ -/** - * [128] Longest Consecutive Sequence - * - * Given an unsorted array of integers, find the length of the longest consecutive elements sequence. - * - * Your algorithm should run in O(n) complexity. - * - * Example: - * - * - * Input: [100, 4, 200, 1, 3, 2] - * Output: 4 - * Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is 4. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/longest-consecutive-sequence/ -// discuss: https://leetcode.com/problems/longest-consecutive-sequence/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -要找到连续子串, 基本策略就是对每个 num, 判断 num+1, num+2, num+3... 是否在数组中, 直到不再连续 - -工程里写的话用排序是最清晰可维护的(需求变了很好改), 排序之后查找 num+1 是否存在就只需要 O(1) 的复杂度了: -看下一个元素是不是 num+1 即可 - -但题目一定要求 O(N) 的解法, 只能想些奇怪的办法了, HashSet 也能达到 O(1) 的查找效率. 但假如对每个元素 -都做一遍, 最差就是 O(N^2) 了, 可以发现对于一个连续序列 1,2,3,4,5,6 我们从 1 开始查就能找到这个序列, -从 2,3,4,5,6 开始查都是在做重复计算, 因此对于一个 num, 假如 num-1 存在于 HashSet 中, 我们就不需要考虑 -它了, 因为它是一次重复的计算. -*/ -use std::collections::HashSet; -impl Solution { - pub fn longest_consecutive(nums: Vec) -> i32 { - let mut max = 0; - let nums = nums.into_iter().collect::>(); - for &num in nums.iter() { - if !nums.contains(&(num - 1)) { - let mut curr = num; - let mut curr_max = 1; - while nums.contains(&(curr + 1)) { - curr += 1; - curr_max += 1; - } - max = i32::max(curr_max, max); - } - } - max - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_128() { - assert_eq!(Solution::longest_consecutive(vec![100, 4, 200, 1, 3, 2]), 4) - } -} diff --git a/src/solution/s0129_sum_root_to_leaf_numbers.rs b/src/solution/s0129_sum_root_to_leaf_numbers.rs deleted file mode 100644 index 1e44fb68..00000000 --- a/src/solution/s0129_sum_root_to_leaf_numbers.rs +++ /dev/null @@ -1,87 +0,0 @@ -/** - * [129] Sum Root to Leaf Numbers - * - * Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number. - * - * An example is the root-to-leaf path 1->2->3 which represents the number 123. - * - * Find the total sum of all root-to-leaf numbers. - * - * Note: A leaf is a node with no children. - * - * Example: - * - * - * Input: [1,2,3] - * 1 - * / \ - * 2 3 - * Output: 25 - * Explanation: - * The root-to-leaf path 1->2 represents the number 12. - * The root-to-leaf path 1->3 represents the number 13. - * Therefore, sum = 12 + 13 = 25. - * - * Example 2: - * - * - * Input: [4,9,0,5,1] - * 4 - * / \ - * 9 0 - * / \ - * 5 1 - * Output: 1026 - * Explanation: - * The root-to-leaf path 4->9->5 represents the number 495. - * The root-to-leaf path 4->9->1 represents the number 491. - * The root-to-leaf path 4->0 represents the number 40. - * Therefore, sum = 495 + 491 + 40 = 1026. - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/sum-root-to-leaf-numbers/ -// discuss: https://leetcode.com/problems/sum-root-to-leaf-numbers/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::collections::VecDeque; -use std::rc::Rc; -impl Solution { - pub fn sum_numbers(root: Option>>) -> i32 { - let mut sum = 0; - if root.is_none() { - return sum; - } - let mut deq = VecDeque::new(); - deq.push_back((root.clone(), 0)); - while let Some(item) = deq.pop_front() { - if let (Some(node), acc) = item { - let acc = acc * 10 + node.borrow().val; - if node.borrow().left.is_none() && node.borrow().right.is_none() { - sum += acc; - continue; - } - deq.push_back((node.borrow().left.clone(), acc)); - deq.push_back((node.borrow().right.clone(), acc)); - } - } - sum - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_129() { - assert_eq!(Solution::sum_numbers(tree![1, 2, 3]), 25); - assert_eq!(Solution::sum_numbers(tree![4, 9, 0, 5, 1]), 1026); - } -} diff --git a/src/solution/s0130_surrounded_regions.rs b/src/solution/s0130_surrounded_regions.rs deleted file mode 100644 index 411286b4..00000000 --- a/src/solution/s0130_surrounded_regions.rs +++ /dev/null @@ -1,221 +0,0 @@ -/** - * [130] Surrounded Regions - * - * Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'. - * - * A region is captured by flipping all 'O's into 'X's in that surrounded region. - * - * Example: - * - * - * X X X X - * X O O X - * X X O X - * X O X X - * - * - * After running your function, the board should be: - * - * - * X X X X - * X X X X - * X X X X - * X O X X - * - * - * Explanation: - * - * Surrounded regions shouldn’t be on the border, which means that any 'O' on the border of the board are not flipped to 'X'. Any 'O' that is not on the border and it is not connected to an 'O' on the border will be flipped to 'X'. Two cells are connected if they are adjacent cells connected horizontally or vertically. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/surrounded-regions/ -// discuss: https://leetcode.com/problems/surrounded-regions/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -从最外层开始, 基于为 'O' 的格子做 DFS, 将与边界连接的所有 'O' 标记为一个特殊 char, 最后将没有标记到的 'O' 全部标记为 'X' -*/ -impl Solution { - pub fn solve(board: &mut Vec>) { - if board.is_empty() || board[0].is_empty() { - return; - } - let (height, width) = (board.len(), board[0].len()); - // 遍历最外层的 4 条边 - for j in 0..width { - Solution::dfs(0, j, height, width, board); - Solution::dfs(height - 1, j, height, width, board); - } - for i in 1..height - 1 { - Solution::dfs(i, 0, height, width, board); - Solution::dfs(i, width - 1, height, width, board); - } - for k in 0..height * width { - board[k / width][k % width] = if board[k / width][k % width] == '_' { - 'O' - } else { - 'X' - } - } - } - - fn dfs(i: usize, j: usize, height: usize, width: usize, board: &mut Vec>) { - if board[i][j] == 'O' { - board[i][j] = '_'; - if i > 1 { - Solution::dfs(i - 1, j, height, width, board) - } - if j > 1 { - Solution::dfs(i, j - 1, height, width, board) - } - if i + 1 < height { - Solution::dfs(i + 1, j, height, width, board) - } - if j + 1 < width { - Solution::dfs(i, j + 1, height, width, board) - } - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_130() { - let mut matrix = vec![ - vec!['X', 'X', 'X', 'X'], - vec!['X', 'O', 'O', 'X'], - vec!['X', 'X', 'O', 'X'], - vec!['X', 'O', 'X', 'X'], - ]; - Solution::solve(&mut matrix); - assert_eq!( - matrix, - vec![ - vec!['X', 'X', 'X', 'X'], - vec!['X', 'X', 'X', 'X'], - vec!['X', 'X', 'X', 'X'], - vec!['X', 'O', 'X', 'X'], - ] - ); - - let mut matrix = vec![ - vec!['X', 'X', 'X', 'X'], - vec!['X', 'O', 'O', 'X'], - vec!['X', 'O', 'O', 'X'], - vec!['X', 'X', 'X', 'X'], - ]; - Solution::solve(&mut matrix); - assert_eq!( - matrix, - vec![ - vec!['X', 'X', 'X', 'X'], - vec!['X', 'X', 'X', 'X'], - vec!['X', 'X', 'X', 'X'], - vec!['X', 'X', 'X', 'X'], - ] - ); - - let mut matrix = vec![ - vec!['X', 'X', 'X', 'X'], - vec!['O', 'X', 'O', 'X'], - vec!['O', 'X', 'O', 'X'], - vec!['X', 'O', 'X', 'X'], - ]; - Solution::solve(&mut matrix); - assert_eq!( - matrix, - vec![ - vec!['X', 'X', 'X', 'X'], - vec!['O', 'X', 'X', 'X'], - vec!['O', 'X', 'X', 'X'], - vec!['X', 'O', 'X', 'X'], - ] - ); - - let mut matrix = vec![ - vec!['X', 'X', 'X', 'X', 'O', 'X'], - vec!['O', 'X', 'X', 'O', 'O', 'X'], - vec!['X', 'O', 'X', 'O', 'O', 'O'], - vec!['X', 'O', 'O', 'O', 'X', 'O'], - vec!['O', 'O', 'X', 'X', 'O', 'X'], - vec!['X', 'O', 'X', 'O', 'X', 'X'], - ]; - Solution::solve(&mut matrix); - assert_eq!( - matrix, - vec![ - vec!['X', 'X', 'X', 'X', 'O', 'X'], - vec!['O', 'X', 'X', 'O', 'O', 'X'], - vec!['X', 'O', 'X', 'O', 'O', 'O'], - vec!['X', 'O', 'O', 'O', 'X', 'O'], - vec!['O', 'O', 'X', 'X', 'X', 'X'], - vec!['X', 'O', 'X', 'O', 'X', 'X'], - ] - ); - - let mut matrix = vec![ - vec![ - 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', - 'X', 'X', 'X', 'X', - ], - vec![ - 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'O', 'O', 'O', 'X', 'X', 'X', 'X', - 'X', 'X', 'X', 'X', - ], - vec![ - 'X', 'X', 'X', 'X', 'X', 'O', 'O', 'O', 'X', 'O', 'X', 'O', 'X', 'X', 'X', 'X', - 'X', 'X', 'X', 'X', - ], - vec![ - 'X', 'X', 'X', 'X', 'X', 'O', 'X', 'O', 'X', 'O', 'X', 'O', 'O', 'O', 'X', 'X', - 'X', 'X', 'X', 'X', - ], - vec![ - 'X', 'X', 'X', 'X', 'X', 'O', 'X', 'O', 'O', 'O', 'X', 'X', 'X', 'X', 'X', 'X', - 'X', 'X', 'X', 'X', - ], - vec![ - 'X', 'X', 'X', 'X', 'X', 'O', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', - 'X', 'X', 'X', 'X', - ], - ]; - Solution::solve(&mut matrix); - assert_eq!( - matrix, - vec![ - vec![ - 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', - 'X', 'X', 'X', 'X' - ], - vec![ - 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'O', 'O', 'O', 'X', 'X', 'X', 'X', - 'X', 'X', 'X', 'X' - ], - vec![ - 'X', 'X', 'X', 'X', 'X', 'O', 'O', 'O', 'X', 'O', 'X', 'O', 'X', 'X', 'X', 'X', - 'X', 'X', 'X', 'X' - ], - vec![ - 'X', 'X', 'X', 'X', 'X', 'O', 'X', 'O', 'X', 'O', 'X', 'O', 'O', 'O', 'X', 'X', - 'X', 'X', 'X', 'X' - ], - vec![ - 'X', 'X', 'X', 'X', 'X', 'O', 'X', 'O', 'O', 'O', 'X', 'X', 'X', 'X', 'X', 'X', - 'X', 'X', 'X', 'X' - ], - vec![ - 'X', 'X', 'X', 'X', 'X', 'O', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', - 'X', 'X', 'X', 'X' - ] - ] - ); - } -} diff --git a/src/solution/s0131_palindrome_partitioning.rs b/src/solution/s0131_palindrome_partitioning.rs deleted file mode 100644 index 22a92dfd..00000000 --- a/src/solution/s0131_palindrome_partitioning.rs +++ /dev/null @@ -1,120 +0,0 @@ -/** - * [131] Palindrome Partitioning - * - * Given a string s, partition s such that every substring of the partition is a palindrome. - * - * Return all possible palindrome partitioning of s. - * - * Example: - * - * - * Input: "aab" - * Output: - * [ - * ["aa","b"], - * ["a","a","b"] - * ] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/palindrome-partitioning/ -// discuss: https://leetcode.com/problems/palindrome-partitioning/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -记 n 个字符的回文拆分方式是 f(n) 种, 则: - -f(n) = (0..n).iter().fold(0, |acc, i| { - if is_palindrome(s[i..n]) { acc + f(i-1) } else { acc } -}) - -按这种方式向上递推即可, 时间复杂度为 O(N^3), 空间复杂度 O(N), 显然, is_palindrome 这一步仍然有重复计算 - -is_palindrome(s[i..n]) = s[i] == s[n] && is_palindrome(s[i+1..n-1]) - -存储所有 i, n 的 is_palindrome 结果, 则可以优化 is_palindrome 的时间到 O(1) - -最后的复杂度: 时间 O(N^2), 空间 O(N^2) -*/ -impl Solution { - pub fn partition(s: String) -> Vec> { - let s = s.chars().collect::>(); - if s.is_empty() { - return Vec::new(); - } - let mut palindrome_cache = vec![vec![None; s.len()]; s.len()]; - let mut res: Vec>> = Vec::with_capacity(s.len()); - res.push(vec![vec![(0, 1)]]); - for n in 1..s.len() { - let mut curr: Vec> = Vec::new(); - for i in 0..n + 1 { - if Solution::is_palindrome(&mut palindrome_cache, &s, i, n) { - if i > 0 { - for vec in res[i - 1].iter() { - let mut new_vec = vec.clone(); - new_vec.push((i, n + 1)); - curr.push(new_vec); - } - } else { - curr.push(vec![(i, n + 1)]); - } - } - } - res.push(curr); - } - (*res[s.len() - 1]) - .into_iter() - .map(|vec| { - vec.iter() - .map(|&range| s[range.0..range.1].iter().collect::()) - .collect::>() - }) - .collect() - } - - fn is_palindrome( - cache: &mut Vec>>, - s: &Vec, - i: usize, - j: usize, - ) -> bool { - if j <= i { - return true; - } - if let Some(result) = cache[i][j] { - result - } else { - let result = s[i] == s[j] - && (i + 1 > s.len() || j < 1 || Solution::is_palindrome(cache, s, i + 1, j - 1)); - cache[i][j] = Some(result); - result - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_131() { - assert_eq!( - Solution::partition("aab".to_owned()), - vec![vec_string!["aa", "b"], vec_string!["a", "a", "b"],] - ); - assert_eq!( - Solution::partition("aaa".to_owned()), - vec![ - vec_string!["aaa"], - vec_string!["a", "aa"], - vec_string!["aa", "a"], - vec_string!["a", "a", "a"], - ] - ); - } -} diff --git a/src/solution/s0132_palindrome_partitioning_ii.rs b/src/solution/s0132_palindrome_partitioning_ii.rs deleted file mode 100644 index 81b75cf6..00000000 --- a/src/solution/s0132_palindrome_partitioning_ii.rs +++ /dev/null @@ -1,91 +0,0 @@ -/** - * [132] Palindrome Partitioning II - * - * Given a string s, partition s such that every substring of the partition is a palindrome. - * - * Return the minimum cuts needed for a palindrome partitioning of s. - * - * Example: - * - * - * Input: "aab" - * Output: 1 - * Explanation: The palindrome partitioning ["aa","b"] could be produced using 1 cut. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/palindrome-partitioning-ii/ -// discuss: https://leetcode.com/problems/palindrome-partitioning-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -为了方便讨论, 我们记 n 个字符的最少回文分段是 f(n), 则切分次数为 f(n)-1, 接下来递推 f(n): - -f(n) = min(f(n-i) + 1) { i in [0..n] and s[i..n] is palindrome } - -显然, f(1) 为 1, f(0) 为 0 - -判断 is_palindrome 也需要优化, 使用一个备忘录, 将判断回文的操作优化到 O(1): - -is_palindrome(s[i..n]) = s[i] == s[n] && is_palindrome(s[i+1..n-1]) - -最后的复杂度: 时间 O(N^2), 空间 O(N^2) -*/ -impl Solution { - pub fn min_cut(s: String) -> i32 { - let s = s.chars().collect::>(); - if s.is_empty() { - return 0; - } - let mut palindrome_cache: Vec>> = vec![vec![None; s.len()]; s.len()]; - let mut min = Vec::with_capacity(s.len() + 1); - min.push(0); - min.push(1); - for i in 1..s.len() { - let mut local_min = i32::max_value(); - for j in 0..i + 1 { - if Solution::is_palindrome(&mut palindrome_cache, &s, j, i) { - local_min = i32::min(1 + min[j], local_min); - } - } - min.push(local_min); - } - min[s.len()] - 1 - } - - fn is_palindrome( - cache: &mut Vec>>, - s: &Vec, - i: usize, - j: usize, - ) -> bool { - if j <= i { - return true; - } - if let Some(result) = cache[i][j] { - result - } else { - let result = s[i] == s[j] - && (i + 1 > s.len() || j < 1 || Solution::is_palindrome(cache, s, i + 1, j - 1)); - cache[i][j] = Some(result); - result - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_132() { - assert_eq!(Solution::min_cut("aab".to_owned()), 1); - assert_eq!(Solution::min_cut("aaa".to_owned()), 0); - assert_eq!(Solution::min_cut("aabb".to_owned()), 1); - } -} diff --git a/src/solution/s0134_gas_station.rs b/src/solution/s0134_gas_station.rs deleted file mode 100644 index 352990f9..00000000 --- a/src/solution/s0134_gas_station.rs +++ /dev/null @@ -1,77 +0,0 @@ -/** - * [134] Gas Station - * - * There are N gas stations along a circular route, where the amount of gas at station i is gas[i]. - * - * You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next station (i+1). You begin the journey with an empty tank at one of the gas stations. - * - * Return the starting gas station's index if you can travel around the circuit once in the clockwise direction, otherwise return -1. - * - * Note: - * - * - * If there exists a solution, it is guaranteed to be unique. - * Both input arrays are non-empty and have the same length. - * Each element in the input arrays is a non-negative integer. - * - * - * Example 1: - * - * - * Input: - * gas = [1,2,3,4,5] - * cost = [3,4,5,1,2] - * - * Output: 3 - * - * Explanation: - * Start at station 3 (index 3) and fill up with 4 unit of gas. Your tank = 0 + 4 = 4 - * Travel to station 4. Your tank = 4 - 1 + 5 = 8 - * Travel to station 0. Your tank = 8 - 2 + 1 = 7 - * Travel to station 1. Your tank = 7 - 3 + 2 = 6 - * Travel to station 2. Your tank = 6 - 4 + 3 = 5 - * Travel to station 3. The cost is 5. Your gas is just enough to travel back to station 3. - * Therefore, return 3 as the starting index. - * - * - * Example 2: - * - * - * Input: - * gas = [2,3,4] - * cost = [3,4,3] - * - * Output: -1 - * - * Explanation: - * You can't start at station 0 or 1, as there is not enough gas to travel to the next station. - * Let's start at station 2 and fill up with 4 unit of gas. Your tank = 0 + 4 = 4 - * Travel to station 0. Your tank = 4 - 3 + 2 = 3 - * Travel to station 1. Your tank = 3 - 3 + 3 = 3 - * You cannot travel back to station 2, as it requires 4 unit of gas but you only have 3. - * Therefore, you can't travel around the circuit once no matter where you start. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/gas-station/ -// discuss: https://leetcode.com/problems/gas-station/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn can_complete_circuit(gas: Vec, cost: Vec) -> i32 { - 0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_134() {} -} diff --git a/src/solution/s0135_candy.rs b/src/solution/s0135_candy.rs deleted file mode 100644 index debb29d0..00000000 --- a/src/solution/s0135_candy.rs +++ /dev/null @@ -1,84 +0,0 @@ -/** - * [135] Candy - * - * There are N children standing in a line. Each child is assigned a rating value. - * - * You are giving candies to these children subjected to the following requirements: - * - * - * Each child must have at least one candy. - * Children with a higher rating get more candies than their neighbors. - * - * - * What is the minimum candies you must give? - * - * Example 1: - * - * - * Input: [1,0,2] - * Output: 5 - * Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively. - * - * - * Example 2: - * - * - * Input: [1,2,2] - * Output: 4 - * Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively. - * The third child gets 1 candy because it satisfies the above two conditions. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/candy/ -// discuss: https://leetcode.com/problems/candy/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn candy(ratings: Vec) -> i32 { - let mut from = 0; - let mut n = 1; - let mut last = 1; - let mut ascending = false; - for i in 1..ratings.len() { - if ratings[i] == ratings[i - 1] { - n += 1; - from = i; - ascending = false; - } else if ratings[i] >= ratings[i - 1] { - from = i; - ascending = true; - last += 1; - n += last; - } else { - if ascending { - last = 1; - from = i; - ascending = false; - } - n += (i - from + 1) as i32; - } - } - n - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_135() { - assert_eq!(Solution::candy(vec![3, 2, 1, 2, 3]), 11); - assert_eq!(Solution::candy(vec![2, 2, 1, 2, 2]), 7); - assert_eq!(Solution::candy(vec![1, 0, 2]), 5); - assert_eq!(Solution::candy(vec![1, 2, 2]), 4); - assert_eq!(Solution::candy(vec![1, 1, 1, 1, 1, 1]), 6); - assert_eq!(Solution::candy(vec![1, 2, 2, 2, 2, 2, 2, 0]), 10); - } -} diff --git a/src/solution/s0136_single_number.rs b/src/solution/s0136_single_number.rs deleted file mode 100644 index 580d1213..00000000 --- a/src/solution/s0136_single_number.rs +++ /dev/null @@ -1,48 +0,0 @@ -/** - * [136] Single Number - * - * Given a non-empty array of integers, every element appears twice except for one. Find that single one. - * - * Note: - * - * Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory? - * - * Example 1: - * - * - * Input: [2,2,1] - * Output: 1 - * - * - * Example 2: - * - * - * Input: [4,1,2,1,2] - * Output: 4 - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/single-number/ -// discuss: https://leetcode.com/problems/single-number/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here -impl Solution { - pub fn single_number(nums: Vec) -> i32 { - nums.iter().fold(0, |acc, &num| acc ^ num) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_136() { - assert_eq!(Solution::single_number(vec![2, 2, 1]), 1); - assert_eq!(Solution::single_number(vec![4, 1, 2, 1, 2]), 4); - } -} diff --git a/src/solution/s0137_single_number_ii.rs b/src/solution/s0137_single_number_ii.rs deleted file mode 100644 index 5e99cd84..00000000 --- a/src/solution/s0137_single_number_ii.rs +++ /dev/null @@ -1,94 +0,0 @@ -/** - * [137] Single Number II - * - * Given a non-empty array of integers, every element appears three times except for one, which appears exactly once. Find that single one. - * - * Note: - * - * Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory? - * - * Example 1: - * - * - * Input: [2,2,3,2] - * Output: 3 - * - * - * Example 2: - * - * - * Input: [0,1,0,1,0,1,99] - * Output: 99 - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/single-number-ii/ -// discuss: https://leetcode.com/problems/single-number-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -糅合了一下 https://leetcode.com/problems/single-number-ii/discuss/43296/An-General-Way-to-Handle-All-this-sort-of-questions. 和 https://leetcode.com/problems/single-number-ii/discuss/43294/Challenge-me-thx - -第一个链接给出了通用解法: 对于一个数出现 M 次其它数都出现了 K 的场景, 我们可以用位运算记录 K 种状态(作为一个计数器)来解 - -这题的真值表(3种状态使用2位): - -a b c/c a'b'/a'b' -0 0 1/0 0 1 /0 0 -0 1 1/0 1 0 /0 1 -1 0 1/0 0 0 /1 0 - -根据数电的知识, 要根据这个真值表写出逻辑表达式, 以输出端为 '1' 的结果为准, 将每行的输入变量写成 AND 形式, 其中为 0 的输入量需要取反, 再将这几个 AND 形式做 OR 即可 - -令 a' = 1, 则: - -a b c a' -0 1 1 1 ~a & b & c -1 0 0 1 a & ~b & ~c - -a' = (~a & b & c) | (a & ~b & ~c) - -同理: - -b' = (~a & b & ~c) | (~a & ~b & c) - -这个每轮计算的位次数达到 17 次, 可以再优化一下: - -对 b' 化简: b' = ~a & (b & ~c | ~b & c) = ~a & b ^ c - -但这时 a 仍然比较复杂, 我们可以考虑能否用每轮算出的 b' 来简化 a 的计算, 则: - -a (b) b' c a' b' -1 (0) 0 0 1 0 -0 (1) 0 1 1 0 - -重写一下就是 a' = (a & ~b' & ~c) | (~a & ~b' & c) = ~b' & (a & ~c | ~a & c) = ~b' & a ^ c - -这个就和最开始第二链接里给出的超简洁解法一致了 - -最后的话, a 或 b 为 1 都可以输出到 1 (目标数出现1次或出现2次), 输出 a | b 即可 -*/ -impl Solution { - pub fn single_number(nums: Vec) -> i32 { - let (mut a, mut b) = (0, 0); - for &num in nums.iter() { - b = !a & (b ^ num); - a = !b & (a ^ num); - } - return a | b; - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_137() { - assert_eq!(Solution::single_number(vec![0, 0, 0, 1, 1, 1, 5]), 5); - } -} diff --git a/src/solution/s0139_word_break.rs b/src/solution/s0139_word_break.rs deleted file mode 100644 index ce9e2684..00000000 --- a/src/solution/s0139_word_break.rs +++ /dev/null @@ -1,93 +0,0 @@ -/** - * [139] Word Break - * - * Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words. - * - * Note: - * - * - * The same word in the dictionary may be reused multiple times in the segmentation. - * You may assume the dictionary does not contain duplicate words. - * - * - * Example 1: - * - * - * Input: s = "leetcode", wordDict = ["leet", "code"] - * Output: true - * Explanation: Return true because "leetcode" can be segmented as "leet code". - * - * - * Example 2: - * - * - * Input: s = "applepenapple", wordDict = ["apple", "pen"] - * Output: true - * Explanation: Return true because "applepenapple" can be segmented as "apple pen apple". - * Note that you are allowed to reuse a dictionary word. - * - * - * Example 3: - * - * - * Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"] - * Output: false - * - * - */ -pub struct Solution {} - -/* -记 f[n] 表示从 0 开始长度为 n 的 substring 是否可以被组成,那么: - -f[n] = f[k] && (s[k..n] in dict) -f[0] = true - -DP 向上递推即可 - -BFS 也是可以的 -*/ - -// problem: https://leetcode.com/problems/word-break/ -// discuss: https://leetcode.com/problems/word-break/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::collections::HashSet; -impl Solution { - pub fn word_break(s: String, word_dict: Vec) -> bool { - let word_dict = word_dict.into_iter().collect::>(); - let mut dp = vec![false; s.len() + 1]; - dp[0] = true; - for i in 1..s.len() + 1 { - for j in 0..s.len() { - if dp[j] && word_dict.contains(&s[j..i]) { - dp[i] = true; - } - } - } - dp[s.len()] - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_139() { - assert_eq!( - Solution::word_break("leetcode".to_owned(), vec_string!["leet", "code"]), - true - ); - assert_eq!( - Solution::word_break( - "catsandog".to_owned(), - vec_string!["cats", "dog", "sand", "and", "cat"] - ), - false - ); - } -} diff --git a/src/solution/s0140_word_break_ii.rs b/src/solution/s0140_word_break_ii.rs deleted file mode 100644 index 68c1319e..00000000 --- a/src/solution/s0140_word_break_ii.rs +++ /dev/null @@ -1,72 +0,0 @@ -/** - * [140] Word Break II - * - * Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, add spaces in s to construct a sentence where each word is a valid dictionary word. Return all such possible sentences. - * - * Note: - * - * - * The same word in the dictionary may be reused multiple times in the segmentation. - * You may assume the dictionary does not contain duplicate words. - * - * - * Example 1: - * - * - * Input: - * s = "catsanddog" - * wordDict = ["cat", "cats", "and", "sand", "dog"] - * Output: - * [ - * "cats and dog", - * "cat sand dog" - * ] - * - * - * Example 2: - * - * - * Input: - * s = "pineapplepenapple" - * wordDict = ["apple", "pen", "applepen", "pine", "pineapple"] - * Output: - * [ - * "pine apple pen apple", - * "pineapple pen apple", - * "pine applepen apple" - * ] - * Explanation: Note that you are allowed to reuse a dictionary word. - * - * - * Example 3: - * - * - * Input: - * s = "catsandog" - * wordDict = ["cats", "dog", "sand", "and", "cat"] - * Output: - * [] - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/word-break-ii/ -// discuss: https://leetcode.com/problems/word-break-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn word_break(s: String, word_dict: Vec) -> Vec { - vec![] - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_140() {} -} diff --git a/src/solution/s0143_reorder_list.rs b/src/solution/s0143_reorder_list.rs deleted file mode 100644 index 1a7854cc..00000000 --- a/src/solution/s0143_reorder_list.rs +++ /dev/null @@ -1,50 +0,0 @@ -/** - * [143] Reorder List - * - * Given a singly linked list L: L0→L1→…→Ln-1→Ln,
- * reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… - * - * You may not modify the values in the list's nodes, only nodes itself may be changed. - * - * Example 1: - * - * - * Given 1->2->3->4, reorder it to 1->4->2->3. - * - * Example 2: - * - * - * Given 1->2->3->4->5, reorder it to 1->5->2->4->3. - * - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; - -// problem: https://leetcode.com/problems/reorder-list/ -// discuss: https://leetcode.com/problems/reorder-list/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* - 1->2->3->4->5 - - 1->2->3<-4<-5 - - 1->5->2->4->3 -*/ -impl Solution { - pub fn reorder_list(head: &mut Option>) { - // TODO - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_143() {} -} diff --git a/src/solution/s0144_binary_tree_preorder_traversal.rs b/src/solution/s0144_binary_tree_preorder_traversal.rs deleted file mode 100644 index 3d823976..00000000 --- a/src/solution/s0144_binary_tree_preorder_traversal.rs +++ /dev/null @@ -1,61 +0,0 @@ -/** - * [144] Binary Tree Preorder Traversal - * - * Given a binary tree, return the preorder traversal of its nodes' values. - * - * Example: - * - * - * Input: [1,null,2,3] - * 1 - * \ - * 2 - * / - * 3 - * - * Output: [1,2,3] - * - * - * Follow up: Recursive solution is trivial, could you do it iteratively? - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/binary-tree-preorder-traversal/ -// discuss: https://leetcode.com/problems/binary-tree-preorder-traversal/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn preorder_traversal(root: Option>>) -> Vec { - let mut res = Vec::new(); - Solution::helper(root, &mut res); - res - } - - fn helper(root: Option>>, vec: &mut Vec) { - if let Some(node) = root { - vec.push(node.borrow().val); - Solution::helper(node.borrow().left.clone(), vec); - Solution::helper(node.borrow().right.clone(), vec); - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_144() { - assert_eq!( - Solution::preorder_traversal(tree![1, null, 2, 3]), - vec![1, 2, 3] - ); - } -} diff --git a/src/solution/s0145_binary_tree_postorder_traversal.rs b/src/solution/s0145_binary_tree_postorder_traversal.rs deleted file mode 100644 index 63197e88..00000000 --- a/src/solution/s0145_binary_tree_postorder_traversal.rs +++ /dev/null @@ -1,61 +0,0 @@ -/** - * [145] Binary Tree Postorder Traversal - * - * Given a binary tree, return the postorder traversal of its nodes' values. - * - * Example: - * - * - * Input: [1,null,2,3] - * 1 - * \ - * 2 - * / - * 3 - * - * Output: [3,2,1] - * - * - * Follow up: Recursive solution is trivial, could you do it iteratively? - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/binary-tree-postorder-traversal/ -// discuss: https://leetcode.com/problems/binary-tree-postorder-traversal/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn postorder_traversal(root: Option>>) -> Vec { - let mut res = Vec::new(); - Solution::helper(root, &mut res); - res - } - - fn helper(root: Option>>, vec: &mut Vec) { - if let Some(node) = root { - Solution::helper(node.borrow().left.clone(), vec); - Solution::helper(node.borrow().right.clone(), vec); - vec.push(node.borrow().val); - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_145() { - assert_eq!( - Solution::postorder_traversal(tree![1, null, 2, 3]), - vec![3, 2, 1] - ); - } -} diff --git a/src/solution/s0146_lru_cache.rs b/src/solution/s0146_lru_cache.rs deleted file mode 100644 index 226cbf77..00000000 --- a/src/solution/s0146_lru_cache.rs +++ /dev/null @@ -1,200 +0,0 @@ -/** - * [146] LRU Cache - * - * - * Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put. - * - * - * - * get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
- * put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item. - * - * - * Follow up:
- * Could you do both operations in O(1) time complexity? - * - * Example: - * - * LRUCache cache = new LRUCache( 2 /* capacity */ ); - * - * cache.put(1, 1); - * cache.put(2, 2); - * cache.get(1); // returns 1 - * cache.put(3, 3); // evicts key 2 - * cache.get(2); // returns -1 (not found) - * cache.put(4, 4); // evicts key 1 - * cache.get(1); // returns -1 (not found) - * cache.get(3); // returns 3 - * cache.get(4); // returns 4 - * - * - */ -// problem: https://leetcode.com/problems/lru-cache/ -// discuss: https://leetcode.com/problems/lru-cache/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -Least Recently Used, 最近最少使用, 关键在于追踪每一个 entry 的 age, 每次淘汰最小的那一个 key - -假如淘汰逻辑要做到 O(1) 复杂度, 我们可以引入一个链表, 每次 touch 一个值时, 就删掉它重新 push_back, 而当达到容量要驱逐时, 则 pop_front - -Rust 的链表不支持根据引用删除任意元素,也没有 LinkedHashMap,需要自己实现一个 -*/ -use std::collections::HashMap; -use std::mem; -use std::ptr; - -// Entry is either a map entry and a link-list node -pub struct LRUEntry { - key: i32, - val: i32, - prev: *mut LRUEntry, - next: *mut LRUEntry, -} - -impl LRUEntry { - pub fn new(key: i32, val: i32) -> Self { - LRUEntry { - key: key, - val: val, - prev: ptr::null_mut(), - next: ptr::null_mut(), - } - } -} - -pub struct LRUCache { - map: HashMap>, - cap: usize, - - // head and tail is dummy node of the double-linked-list - head: *mut LRUEntry, - tail: *mut LRUEntry, -} - -impl LRUCache { - pub fn new(capacity: i32) -> Self { - let capacity = capacity as usize; - let map = HashMap::with_capacity(capacity); - let cache = LRUCache { - map: map, - cap: capacity, - head: unsafe { Box::into_raw(Box::new(mem::uninitialized::())) }, - tail: unsafe { Box::into_raw(Box::new(mem::uninitialized::())) }, - }; - unsafe { - (*cache.head).next = cache.tail; - (*cache.tail).prev = cache.head; - } - - cache - } - - pub fn get(&mut self, key: i32) -> i32 { - let (ptr, val) = match self.map.get_mut(&key) { - None => (None, None), - Some(entry) => { - let ptr: *mut LRUEntry = &mut **entry; - (Some(ptr), Some(unsafe { (*entry).val })) - } - }; - - if let Some(ptr) = ptr { - self.detach(ptr); - self.push(ptr); - } - val.unwrap_or(-1) - } - - pub fn put(&mut self, key: i32, value: i32) { - let ptr = self.map.get_mut(&key).map(|entry| { - let ptr: *mut LRUEntry = &mut **entry; - ptr - }); - - match ptr { - Some(ptr) => { - // key already exist, update it - unsafe { (*ptr).val = value }; - self.detach(ptr); - self.push(ptr); - } - None => { - // insert new key, cache is full, evict - if self.map.len() == self.cap { - let mut old_entry = self.pop().unwrap(); - old_entry.key = key; - old_entry.val = value; - self.push(&mut *old_entry); - self.map.insert(key, old_entry); - } else { - let mut new_entry = Box::new(LRUEntry::new(key, value)); - self.push(&mut *new_entry); - self.map.insert(key, new_entry); - } - } - } - } - - // pop() remove the entry from map, detach the entry from head of linked-list, and return it - fn pop(&mut self) -> Option> { - let next; - unsafe { next = (*self.head).next } - // list is empty - if next == self.tail { - return None; - } - let key = unsafe { (*next).key }; - let mut old_entry = self.map.remove(&key).unwrap(); - self.detach(&mut *old_entry); - Some(old_entry) - } - - // push() pushs an entry to the tail of linked-list - fn push(&mut self, entry: *mut LRUEntry) { - unsafe { - // prev <-> tail - // prev <-> entry <-> tail - (*entry).prev = (*self.tail).prev; - (*entry).next = self.tail; - (*self.tail).prev = entry; - (*(*entry).prev).next = entry; - } - } - - // detach() remove an entry from the linked-list - fn detach(&mut self, entry: *mut LRUEntry) { - unsafe { - // prev <-> entry <-> next - // prev <-> next - (*(*entry).prev).next = (*entry).next; - (*(*entry).next).prev = (*entry).prev; - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_146() { - println!("init cache"); - let mut lru_cache = LRUCache::new(2); - lru_cache.put(1, 1); - lru_cache.put(2, 2); - println!("return 1"); - assert_eq!(lru_cache.get(1), 1); // returns 1 - println!("evict key 2"); - lru_cache.put(3, 3); // evicts key 2 - println!("return -1"); - assert_eq!(lru_cache.get(2), -1); // returns -1 (not found) - lru_cache.put(4, 4); // evicts key 1 - assert_eq!(lru_cache.get(1), -1); // returns -1 (not found) - assert_eq!(lru_cache.get(3), 3); // returns 3 - assert_eq!(lru_cache.get(4), 4); // returns 4 - } -} diff --git a/src/solution/s0147_insertion_sort_list.rs b/src/solution/s0147_insertion_sort_list.rs deleted file mode 100644 index 09aff82b..00000000 --- a/src/solution/s0147_insertion_sort_list.rs +++ /dev/null @@ -1,64 +0,0 @@ -/** - * [147] Insertion Sort List - * - * Sort a linked list using insertion sort. - * - *
    - *
- * - *
- * A graphical example of insertion sort. The partial sorted list (black) initially contains only the first element in the list.
- * With each iteration one element (red) is removed from the input data and inserted in-place into the sorted list

- * - * - *
    - *
- * - * Algorithm of Insertion Sort: - * - *
    - * Insertion sort iterates, consuming one input element each repetition, and growing a sorted output list. - * At each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there. - * It repeats until no input elements remain. - *
- * - *
- * Example 1: - * - * - * Input: 4->2->1->3 - * Output: 1->2->3->4 - * - * - * Example 2: - * - * - * Input: -1->5->3->4->0 - * Output: -1->0->3->4->5 - * - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; - -// problem: https://leetcode.com/problems/insertion-sort-list/ -// discuss: https://leetcode.com/problems/insertion-sort-list/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// TODO; boring -impl Solution { - pub fn insertion_sort_list(head: Option>) -> Option> { - None - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_147() {} -} diff --git a/src/solution/s0148_sort_list.rs b/src/solution/s0148_sort_list.rs deleted file mode 100644 index 78b7f08c..00000000 --- a/src/solution/s0148_sort_list.rs +++ /dev/null @@ -1,125 +0,0 @@ -/** - * [148] Sort List - * - * Sort a linked list in O(n log n) time using constant space complexity. - * - * Example 1: - * - * - * Input: 4->2->1->3 - * Output: 1->2->3->4 - * - * - * Example 2: - * - * - * Input: -1->5->3->4->0 - * Output: -1->0->3->4->5 - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; - -// problem: https://leetcode.com/problems/sort-list/ -// discuss: https://leetcode.com/problems/sort-list/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -堆排序需要额外空间, 不行 - -快排: - * 不行, 单链表要快排必须同时持有两个 mut 引用, 而 rust 里这是不可能的(不知道用 unsafe 行不行) - * 不用 rust 的话应该是可行的, Lomuto-partition, 用一个慢指针记录 no_lager_than 位置 - -归并,有点慢, 每次切分要遍历找到切分点, 而且递归栈深度 O(logN) 也不算严格的 O(1) 空间 - -Rust 标准库的 std::collections::LinkedList 都没有实现 sort() 你敢信... - -这题用 rust 解对我而言真的是 Hard 级而不是 Medium 级了... - -这里也是前置知识不足, GG 了解到链表的最佳排序方式确实就是 merge-sort -*/ -impl Solution { - pub fn sort_list(mut head: Option>) -> Option> { - let mut len = 0; - let mut ptr = head.as_ref(); - while let Some(node) = ptr { - len += 1; - ptr = node.next.as_ref(); - } - Solution::merge_sort(head, len) - } - - fn merge_sort(mut head: Option>, len: i32) -> Option> { - if len < 2 { - return head; - } - let mut next = head.as_mut(); - let mut i = 1; - while i < len / 2 { - next = next.unwrap().next.as_mut(); - i += 1; - } - let mut l2 = next.unwrap().next.take(); - let mut l1 = Solution::merge_sort(head, len / 2); - let mut l2 = Solution::merge_sort(l2, len - len / 2); - Solution::merge(l1, l2) - } - - fn merge( - mut l1: Option>, - mut l2: Option>, - ) -> Option> { - let mut dummy = Some(Box::new(ListNode::new(0))); - let mut next = dummy.as_mut(); - loop { - match (l1, l2) { - (Some(mut node1), Some(mut node2)) => { - let node = if node1.val > node2.val { - // give back ownership - l2 = node2.next.take(); - l1 = Some(node1); - node2 - } else { - l1 = node1.next.take(); - l2 = Some(node2); - node1 - }; - next.as_mut().unwrap().next = Some(node); - next = next.unwrap().next.as_mut(); - } - (Some(mut node1), None) => { - next.unwrap().next = Some(node1); - break; - } - (None, Some(mut node2)) => { - next.unwrap().next = Some(node2); - break; - } - (None, None) => break, - } - } - dummy.unwrap().next - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_148() { - assert_eq!( - Solution::sort_list(linked![4, 2, 1, 3]), - linked![1, 2, 3, 4] - ); - assert_eq!( - Solution::sort_list(linked![-1, 5, 3, 4, 0]), - linked![-1, 0, 3, 4, 5] - ); - assert_eq!(Solution::sort_list(linked![]), linked![]); - } -} diff --git a/src/solution/s0149_max_points_on_a_line.rs b/src/solution/s0149_max_points_on_a_line.rs deleted file mode 100644 index 31ea4c62..00000000 --- a/src/solution/s0149_max_points_on_a_line.rs +++ /dev/null @@ -1,178 +0,0 @@ -/** - * [149] Max Points on a Line - * - * Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. - * - * Example 1: - * - * - * Input: [[1,1],[2,2],[3,3]] - * Output: 3 - * Explanation: - * ^ - * | - * | o - * | o - * | o - * +-------------> - * 0 1 2 3 4 - * - * - * Example 2: - * - * - * Input: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]] - * Output: 4 - * Explanation: - * ^ - * | - * | o - * | o o - * | o - * | o o - * +-------------------> - * 0 1 2 3 4 5 6 - * - * - */ -pub struct Solution {} -use crate::util::point::Point; - -// problem: https://leetcode.com/problems/max-points-on-a-line/ -// discuss: https://leetcode.com/problems/max-points-on-a-line/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -要回顾下高中数学:已知两点, 求解一般式: - - * Ax + By + C = 0 - * A = y2 - y1, B = x1 - x2, C = x2y1 - x1y2 - -有这个知识之后,化为一般式,做三层遍历就行,再加上一个 HashSet,避免对同一直线上点的重复计算,时间复杂度可以是 O(N^2) - -有两个坑要注意避免: - - * 给的 case 会导致 i32 溢出,这里直接用了 i64 表示 - * 给的 case 里有相同的点,直接处理相同点的话会导致最坏情况复杂度到 O(N^3),因此要先做一次转化,归并相同的点 - -用 Rust 实现有另一点注意的,给的 Point 没有实现 Hash Trait,要自己转化一下 -*/ -// straight-line expression: Ax + By + C = 0 -// A = y2 - y1, B = x1 - x2, C = x2y1 - x1y2 -#[derive(PartialEq, Hash, Eq, Debug)] -struct Line(i64, i64, i64); - -impl Line { - // Assumes that there is no same point - fn new(p1: &Point, p2: &Point) -> Self { - let x1 = p1.x as i64; - let x2 = p2.x as i64; - let y1 = p1.y as i64; - let y2 = p2.y as i64; - Line(y2 - y1, x1 - x2, x2 * y1 - x1 * y2) - } - fn contains(&self, p: &Point) -> bool { - self.0 * p.x as i64 + self.1 * p.y as i64 + self.2 == 0_i64 - } -} - -use std::collections::HashMap; -use std::collections::HashSet; -impl Solution { - pub fn max_points(points: Vec) -> i32 { - // fold same point, record the point count - let points: Vec<(Point, i32)> = points - .into_iter() - .fold(HashMap::new(), |mut map, v| { - *map.entry((v.x, v.y)).or_insert(0) += 1; - map - }) - .into_iter() - .map(|(k, v)| (Point::new(k.0, k.1), v)) // Point did not implement Hash trait - .collect(); - - // any two points in a straight-line, return quickly - if points.len() < 3 { - return points.into_iter().fold(0, |acc, v| acc + v.1); - } - let mut max = 2; - let mut set: HashSet = HashSet::new(); - for i in 0..(points.len() - 1) { - for j in i + 1..points.len() { - let line = Line::new(&points[i].0, &points[j].0); - if set.contains(&line) { - continue; - } - let mut curr = points[i].1 + points[j].1; - for k in j + 1..points.len() { - if line.contains(&points[k].0) { - curr += points[k].1; - } - } - max = i32::max(max, curr); - } - } - max - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_149() { - assert_eq!( - Solution::max_points(vec![point![1, 1], point![2, 2], point![3, 3]]), - 3 - ); - assert_eq!( - Solution::max_points(vec![ - point![1, 1], - point![3, 2], - point![5, 3], - point![4, 1], - point![2, 3], - point![1, 4] - ]), - 4 - ); - assert_eq!( - Solution::max_points(vec![point![0, 0], point![1, 65536], point![65536, 0]]), - 2 - ); - assert_eq!( - Solution::max_points(vec![point![1, 1], point![1, 1], point![1, 1]]), - 3 - ); - assert_eq!( - Solution::max_points(vec![ - point![0, 9], - point![138, 429], - point![115, 359], - point![115, 359], - point![-30, -102], - point![230, 709], - point![-150, -686], - point![-135, -613], - point![-60, -248], - point![-161, -481], - point![207, 639], - point![23, 79], - point![-230, -691], - point![-115, -341], - point![92, 289], - point![60, 336], - point![-105, -467], - point![135, 701], - point![-90, -394], - point![-184, -551], - point![150, 774] - ]), - 12 - ) - } -} diff --git a/src/solution/s0150_evaluate_reverse_polish_notation.rs b/src/solution/s0150_evaluate_reverse_polish_notation.rs deleted file mode 100644 index 048824dd..00000000 --- a/src/solution/s0150_evaluate_reverse_polish_notation.rs +++ /dev/null @@ -1,91 +0,0 @@ -/** - * [150] Evaluate Reverse Polish Notation - * - * Evaluate the value of an arithmetic expression in Reverse Polish Notation. - * - * Valid operators are +, -, *, /. Each operand may be an integer or another expression. - * - * Note: - * - * - * Division between two integers should truncate toward zero. - * The given RPN expression is always valid. That means the expression would always evaluate to a result and there won't be any divide by zero operation. - * - * - * Example 1: - * - * - * Input: ["2", "1", "+", "3", "*"] - * Output: 9 - * Explanation: ((2 + 1) * 3) = 9 - * - * - * Example 2: - * - * - * Input: ["4", "13", "5", "/", "+"] - * Output: 6 - * Explanation: (4 + (13 / 5)) = 6 - * - * - * Example 3: - * - * - * Input: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"] - * Output: 22 - * Explanation: - * ((10 * (6 / ((9 + 3) * -11))) + 17) + 5 - * = ((10 * (6 / (12 * -11))) + 17) + 5 - * = ((10 * (6 / -132)) + 17) + 5 - * = ((10 * 0) + 17) + 5 - * = (0 + 17) + 5 - * = 17 + 5 - * = 22 - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/evaluate-reverse-polish-notation/ -// discuss: https://leetcode.com/problems/evaluate-reverse-polish-notation/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn eval_rpn(tokens: Vec) -> i32 { - let mut stack: Vec = Vec::new(); - for t in tokens.iter() { - if let Ok(num) = t.parse::() { - stack.push(num); - } else { - let right = stack.pop().unwrap(); - let left = stack.pop().unwrap(); - match (t as &str) { - "*" => stack.push(left * right), - "+" => stack.push(left + right), - "/" => stack.push(left / right), - "-" => stack.push(left - right), - _ => unreachable!(), - } - } - } - stack.pop().unwrap() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_150() { - assert_eq!( - Solution::eval_rpn(vec_string![ - "10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+" - ]), - 22 - ); - } -} diff --git a/src/solution/s0151_reverse_words_in_a_string.rs b/src/solution/s0151_reverse_words_in_a_string.rs deleted file mode 100644 index 627f0dd6..00000000 --- a/src/solution/s0151_reverse_words_in_a_string.rs +++ /dev/null @@ -1,93 +0,0 @@ -/** - * [151] Reverse Words in a String - * - * Given an input string, reverse the string word by word. - * - * - * - * Example 1: - * - * - * Input: "the sky is blue" - * Output: "blue is sky the" - * - * - * Example 2: - * - * - * Input: " hello world! " - * Output: "world! hello" - * Explanation: Your reversed string should not contain leading or trailing spaces. - * - * - * Example 3: - * - * - * Input: "a good example" - * Output: "example good a" - * Explanation: You need to reduce multiple spaces between two words to a single space in the reversed string. - * - * - * - * - * Note: - * - * - * A word is defined as a sequence of non-space characters. - * Input string may contain leading or trailing spaces. However, your reversed string should not contain leading or trailing spaces. - * You need to reduce multiple spaces between two words to a single space in the reversed string. - * - * - * - * - * Follow up: - * - * For C programmers, try to solve it in-place in O(1) extra space. - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/reverse-words-in-a-string/ -// discuss: https://leetcode.com/problems/reverse-words-in-a-string/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn reverse_words(mut s: String) -> String { - let mut seq = s.trim().chars().collect::>(); - seq.reverse(); - let mut start_idx = 0_usize; - let mut i = 0_usize; - while i < seq.len() { - if seq[i] == ' ' { - if i == start_idx { - seq.remove(i); - continue; - } - seq[start_idx..i].reverse(); - start_idx = i + 1; - } - i += 1; - } - seq[start_idx..].reverse(); - seq.into_iter().collect() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_151() { - assert_eq!( - Solution::reverse_words("the sky is blue".to_owned()), - "blue is sky the".to_owned() - ); - assert_eq!( - Solution::reverse_words(" hello world! ".to_owned()), - "world! hello".to_owned() - ); - } -} diff --git a/src/solution/s0152_maximum_product_subarray.rs b/src/solution/s0152_maximum_product_subarray.rs deleted file mode 100644 index b85b5ecb..00000000 --- a/src/solution/s0152_maximum_product_subarray.rs +++ /dev/null @@ -1,81 +0,0 @@ -/** - * [152] Maximum Product Subarray - * - * Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which has the largest product. - * - * Example 1: - * - * - * Input: [2,3,-2,4] - * Output: 6 - * Explanation: [2,3] has the largest product 6. - * - * - * Example 2: - * - * - * Input: [-2,0,-1] - * Output: 0 - * Explanation: The result cannot be 2, because [-2,-1] is not a subarray. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/maximum-product-subarray/ -// discuss: https://leetcode.com/problems/maximum-product-subarray/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -f[i], g[i] means the max positive value and max negative value for the sub-seq end with index i - -then we have: - -f[i], g[i] = if nums[i] == 0 { - 0, 0 -} else if nums[i] > 0 { - f[i-1] * nums[i], g[i-1] * nums[i] -} else if nums[i] < 0 { - g[i-1] * nums[i], f[i-1] * nums[i] -} -*/ - -impl Solution { - pub fn max_product(nums: Vec) -> i32 { - let mut max = nums[0]; - let mut neg_max = 0; - let mut pos_max = 0; - for num in nums.into_iter() { - if num == 0 { - neg_max = 0; - pos_max = 0; - max = i32::max(max, 0); - } else if num > 0 { - pos_max = i32::max(pos_max * num, num); - neg_max = neg_max * num; - } else { - let pos_pre = pos_max; - pos_max = neg_max * num; - neg_max = i32::min(pos_pre * num, num); - } - if pos_max != 0 { - max = i32::max(max, pos_max); - } - } - max - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_152() { - assert_eq!(Solution::max_product(vec![2, 3, -2, 4]), 6); - assert_eq!(Solution::max_product(vec![-2, 0, -1]), 0); - assert_eq!(Solution::max_product(vec![-4, -3, -2]), 12); - } -} diff --git a/src/solution/s0153_find_minimum_in_rotated_sorted_array.rs b/src/solution/s0153_find_minimum_in_rotated_sorted_array.rs deleted file mode 100644 index 03b7e7f1..00000000 --- a/src/solution/s0153_find_minimum_in_rotated_sorted_array.rs +++ /dev/null @@ -1,64 +0,0 @@ -/** - * [153] Find Minimum in Rotated Sorted Array - * - * Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. - * - * (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]). - * - * Find the minimum element. - * - * You may assume no duplicate exists in the array. - * - * Example 1: - * - * - * Input: [3,4,5,1,2] - * Output: 1 - * - * - * Example 2: - * - * - * Input: [4,5,6,7,0,1,2] - * Output: 0 - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/ -// discuss: https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn find_min(nums: Vec) -> i32 { - let mut size = nums.len(); - if size == 0 { - return -1; - } - let mut base = 0_usize; - while size > 1 { - let half = size / 2; - let mid = base + half; - if nums[mid] > nums[base] { - base = mid; - } - size -= half; - } - i32::min(nums[base], nums[(base + 1) % nums.len()]) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_153() { - assert_eq!(Solution::find_min(vec![4, 5, 6, 1, 2, 3]), 1); - assert_eq!(Solution::find_min(vec![4, 5, 6, 7, 0, 1, 2]), 0); - } -} diff --git a/src/solution/s0154_find_minimum_in_rotated_sorted_array_ii.rs b/src/solution/s0154_find_minimum_in_rotated_sorted_array_ii.rs deleted file mode 100644 index cdb23ac3..00000000 --- a/src/solution/s0154_find_minimum_in_rotated_sorted_array_ii.rs +++ /dev/null @@ -1,79 +0,0 @@ -/** - * [154] Find Minimum in Rotated Sorted Array II - * - * Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. - * - * (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]). - * - * Find the minimum element. - * - * The array may contain duplicates. - * - * Example 1: - * - * - * Input: [1,3,5] - * Output: 1 - * - * Example 2: - * - * - * Input: [2,2,2,0,1] - * Output: 0 - * - * Note: - * - * - * This is a follow up problem to Find Minimum in Rotated Sorted Array. - * Would allow duplicates affect the run-time complexity? How and why? - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii/ -// discuss: https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -针对无重复的做法, 只要二分搜索找折点即可: 假如 nums[mid] > nums[base] 那么转折点一定在右侧, 否则在左侧 - -但假如有重复, 就可能有 nums[mid] == nums[base], 这时就尴尬了, 无法确定转折点在左半部分还是右半部分 - -可以考虑一个数组, [1,1,1,1,1,1,1,0,1,1,1,1,1,1] 这个数组无论怎么去找 0, 时间复杂度无法低于 O(N) - -但假如不是这种极端情况, 那么二分搜索还是能优化的, 在 153 的基础上, 碰到相等就跳过即可 -*/ -impl Solution { - pub fn find_min(nums: Vec) -> i32 { - let mut lo = 0; - let mut hi = nums.len() - 1; - let mut mid = 0; - while lo < hi { - mid = lo + (hi - lo) / 2; - if (nums[mid] > nums[hi]) { - lo = mid + 1; - } else if (nums[mid] < nums[hi]) { - hi = mid; - } else { - hi -= 1; - } - } - return nums[lo]; - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_154() { - assert_eq!(Solution::find_min(vec![1, 2, 2, 2, 2, 2]), 1); - assert_eq!(Solution::find_min(vec![1, 3, 3]), 1); - assert_eq!(Solution::find_min(vec![3, 1, 3, 3]), 1); - } -} diff --git a/src/solution/s0155_min_stack.rs b/src/solution/s0155_min_stack.rs deleted file mode 100644 index 99a96698..00000000 --- a/src/solution/s0155_min_stack.rs +++ /dev/null @@ -1,116 +0,0 @@ -/** - * [155] Min Stack - * - * - * Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. - * - * - * push(x) -- Push element x onto stack. - * - * - * pop() -- Removes the element on top of the stack. - * - * - * top() -- Get the top element. - * - * - * getMin() -- Retrieve the minimum element in the stack. - * - * - * - * - * Example:
- * - * MinStack minStack = new MinStack(); - * minStack.push(-2); - * minStack.push(0); - * minStack.push(-3); - * minStack.getMin(); --> Returns -3. - * minStack.pop(); - * minStack.top(); --> Returns 0. - * minStack.getMin(); --> Returns -2. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/min-stack/ -// discuss: https://leetcode.com/problems/min-stack/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -这题居然是 easy... 我怀疑人生了, getMin() 怎么能做到常数时间? Heap 也是 LogN 啊 - -看了最高票解之后...........天哪, 我可太菜了 - -核心思想是保证每次 pop 时都能以常数时间更新最小值, 这就需要在空间上以某种方式记录下来 - -那一种做法就是存储每个元素和最小值之间的差值, 这样 pop 的时候就能不断还原出原始值 - -另一种更直观的做法就是每次入栈 min 时, 都把前一个 min (当前第二小的数字) 放在它前面, 作为记录 -*/ -struct MinStack { - vec: Vec, - min: i32, -} - -impl MinStack { - /** initialize your data structure here. */ - pub fn new() -> Self { - MinStack { - vec: Vec::new(), - min: i32::max_value(), - } - } - - pub fn push(&mut self, x: i32) { - if x <= self.min { - self.vec.push(self.min); - self.min = x; - } - self.vec.push(x); - } - - pub fn pop(&mut self) { - if self.vec.pop().unwrap() == self.min { - self.min = self.vec.pop().unwrap(); - } - } - - pub fn top(&self) -> i32 { - *self.vec.last().unwrap() - } - - pub fn get_min(&self) -> i32 { - self.min - } -} - -/** - * Your MinStack object will be instantiated and called as such: - * let obj = MinStack::new(); - * obj.push(x); - * obj.pop(); - * let ret_3: i32 = obj.top(); - * let ret_4: i32 = obj.get_min(); - */ - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - pub fn test_155() { - let mut min_stack = MinStack::new(); - min_stack.push(-2); - min_stack.push(0); - min_stack.push(-3); - assert_eq!(min_stack.get_min(), -3); // --> Returns -3. - min_stack.pop(); - assert_eq!(min_stack.top(), 0); // --> Returns 0. - assert_eq!(min_stack.get_min(), -2); // --> Returns -2.[] - } -} diff --git a/src/solution/s0162_find_peak_element.rs b/src/solution/s0162_find_peak_element.rs deleted file mode 100644 index 3888b998..00000000 --- a/src/solution/s0162_find_peak_element.rs +++ /dev/null @@ -1,67 +0,0 @@ -/** - * [162] Find Peak Element - * - * A peak element is an element that is greater than its neighbors. - * - * Given an input array nums, where nums[i] ≠ nums[i+1], find a peak element and return its index. - * - * The array may contain multiple peaks, in that case return the index to any one of the peaks is fine. - * - * You may imagine that nums[-1] = nums[n] = -∞. - * - * Example 1: - * - * - * Input: nums = [1,2,3,1] - * Output: 2 - * Explanation: 3 is a peak element and your function should return the index number 2. - * - * Example 2: - * - * - * Input: nums = [1,2,1,3,5,6,4] - * Output: 1 or 5 - * Explanation: Your function can return either index number 1 where the peak element is 2, - * or index number 5 where the peak element is 6. - * - * - * Note: - * - * Your solution should be in logarithmic complexity. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/find-peak-element/ -// discuss: https://leetcode.com/problems/find-peak-element/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn find_peak_element(nums: Vec) -> i32 { - let (mut lo, mut hi) = (0_usize, nums.len() - 1); - let mut mid = 0; - while lo < hi { - mid = (hi - lo) / 2 + lo; - if mid + 1 < nums.len() && nums[mid] < nums[mid + 1] { - lo = mid + 1; - } else { - hi = mid; - } - } - lo as i32 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_162() { - assert_eq!(Solution::find_peak_element(vec![1, 2, 3, 1]), 2); - assert_eq!(Solution::find_peak_element(vec![1, 2, 1, 3, 5, 6, 4]), 5); - } -} diff --git a/src/solution/s0164_maximum_gap.rs b/src/solution/s0164_maximum_gap.rs deleted file mode 100644 index bd961db7..00000000 --- a/src/solution/s0164_maximum_gap.rs +++ /dev/null @@ -1,66 +0,0 @@ -/** - * [164] Maximum Gap - * - * Given an unsorted array, find the maximum difference between the successive elements in its sorted form. - * - * Return 0 if the array contains less than 2 elements. - * - * Example 1: - * - * - * Input: [3,6,9,1] - * Output: 3 - * Explanation: The sorted form of the array is [1,3,6,9], either - * (3,6) or (6,9) has the maximum difference 3. - * - * Example 2: - * - * - * Input: [10] - * Output: 0 - * Explanation: The array contains less than 2 elements, therefore return 0. - * - * Note: - * - * - * You may assume all elements in the array are non-negative integers and fit in the 32-bit signed integer range. - * Try to solve it in linear time/space. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/maximum-gap/ -// discuss: https://leetcode.com/problems/maximum-gap/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here -/* -想不出来, 一看解析居然是 Radix Sort 或 Bucket Sort, 我就 ??? 了... - -最佳算法是 Bucket Sort 吗? (桶大小取 max - min / len 那种), 看时间复杂度好像是这样 - -但假如整体排布非常稠密, 那么这个聪明的算法也就退化成了桶大小为 1 的桶排序 -*/ -impl Solution { - pub fn maximum_gap(nums: Vec) -> i32 { - let mut nums = nums; - nums.sort_unstable(); - let mut gap = 0; - for i in 1..nums.len() { - gap = i32::max(nums[i] - nums[i - 1], gap); - } - gap - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_164() { - assert_eq!(Solution::maximum_gap(vec![3, 6, 9, 1]), 3); - } -} diff --git a/src/solution/s0165_compare_version_numbers.rs b/src/solution/s0165_compare_version_numbers.rs deleted file mode 100644 index b53f1bbb..00000000 --- a/src/solution/s0165_compare_version_numbers.rs +++ /dev/null @@ -1,112 +0,0 @@ -/** - * [165] Compare Version Numbers - * - * Compare two version numbers version1 and version2.
- * If version1 > version2 return 1; if version1 < version2 return -1;otherwise return 0. - * - * You may assume that the version strings are non-empty and contain only digits and the . character. - * The . character does not represent a decimal point and is used to separate number sequences. - * For instance, 2.5 is not "two and a half" or "half way to version three", it is the fifth second-level revision of the second first-level revision. - * You may assume the default revision number for each level of a version number to be 0. For example, version number 3.4 has a revision number of 3 and 4 for its first and second level revision number. Its third and fourth level revision number are both 0. - * - * - * - * Example 1: - * - * Input: version1 = "0.1", version2 = "1.1" - * Output: -1 - * - * Example 2: - * - * Input: version1 = "1.0.1", version2 = "1" - * Output: 1 - * - * Example 3: - * - * Input: version1 = "7.5.2.4", version2 = "7.5.3" - * Output: -1 - * - * Example 4: - * - * Input: version1 = "1.01", version2 = "1.001" - * Output: 0 - * Explanation: Ignoring leading zeroes, both “01” and “001" represent the same number “1” - * - * Example 5: - * - * Input: version1 = "1.0", version2 = "1.0.0" - * Output: 0 - * Explanation: The first version number does not have a third level revision number, which means its third level revision number is default to "0" - * - * - * - * Note: - *
    - * Version strings are composed of numeric strings separated by dots . and this numeric strings may have leading zeroes. - * Version strings do not start or end with dots, and they will not be two consecutive dots. - *
- */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/compare-version-numbers/ -// discuss: https://leetcode.com/problems/compare-version-numbers/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn compare_version(version1: String, version2: String) -> i32 { - let v1: Vec<&str> = version1.split('.').collect::>(); - let v2: Vec<&str> = version2.split('.').collect::>(); - let mut i = 0_usize; - while i < v1.len() && i < v2.len() { - let left = v1[i].parse::().unwrap(); - let right = v2[i].parse::().unwrap(); - if left > right { - return 1; - } else if left < right { - return -1; - } - i += 1; - } - while i < v1.len() { - if v1[i].parse::().unwrap() > 0 { - return 1; - } - i += 1; - } - while i < v2.len() { - if v2[i].parse::().unwrap() > 0 { - return -1; - } - i += 1; - } - return 0; - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_165() { - assert_eq!( - Solution::compare_version("0.1".to_owned(), "1.1".to_owned()), - -1 - ); - assert_eq!( - Solution::compare_version("1.0.1".to_owned(), "1".to_owned()), - 1 - ); - assert_eq!( - Solution::compare_version("7.5.2.4".to_owned(), "7.5.3".to_owned()), - -1 - ); - assert_eq!( - Solution::compare_version("1.01".to_owned(), "1.0001".to_owned()), - 0 - ); - } -} diff --git a/src/solution/s0166_fraction_to_recurring_decimal.rs b/src/solution/s0166_fraction_to_recurring_decimal.rs deleted file mode 100644 index 4585738f..00000000 --- a/src/solution/s0166_fraction_to_recurring_decimal.rs +++ /dev/null @@ -1,51 +0,0 @@ -/** - * [166] Fraction to Recurring Decimal - * - * Given two integers representing the numerator and denominator of a fraction, return the fraction in string format. - * - * If the fractional part is repeating, enclose the repeating part in parentheses. - * - * Example 1: - * - * - * Input: numerator = 1, denominator = 2 - * Output: "0.5" - * - * - * Example 2: - * - * - * Input: numerator = 2, denominator = 1 - * Output: "2" - * - * Example 3: - * - * - * Input: numerator = 2, denominator = 3 - * Output: "0.(6)" - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/fraction-to-recurring-decimal/ -// discuss: https://leetcode.com/problems/fraction-to-recurring-decimal/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// TODO -impl Solution { - pub fn fraction_to_decimal(numerator: i32, denominator: i32) -> String { - "".to_owned() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_166() {} -} diff --git a/src/solution/s0167_two_sum_ii_input_array_is_sorted.rs b/src/solution/s0167_two_sum_ii_input_array_is_sorted.rs deleted file mode 100644 index 58de2e86..00000000 --- a/src/solution/s0167_two_sum_ii_input_array_is_sorted.rs +++ /dev/null @@ -1,58 +0,0 @@ -/** - * [167] Two Sum II - Input array is sorted - * - * Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number. - * - * The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. - * - * Note: - * - * - * Your returned answers (both index1 and index2) are not zero-based. - * You may assume that each input would have exactly one solution and you may not use the same element twice. - * - * - * Example: - * - * - * Input: numbers = [2,7,11,15], target = 9 - * Output: [1,2] - * Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/ -// discuss: https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn two_sum(numbers: Vec, target: i32) -> Vec { - let mut i = 0_usize; - let mut j = numbers.len() - 1; - while i < j { - let sum = numbers[i] + numbers[j]; - if sum > target { - j -= 1; - } else if sum < target { - i += 1; - } else { - break; - } - } - return vec![i as i32 + 1, j as i32 + 1]; - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_167() { - assert_eq!(Solution::two_sum(vec![2, 7, 11, 15], 9), vec![1, 2]); - } -} diff --git a/src/solution/s0168_excel_sheet_column_title.rs b/src/solution/s0168_excel_sheet_column_title.rs deleted file mode 100644 index 5a9dc585..00000000 --- a/src/solution/s0168_excel_sheet_column_title.rs +++ /dev/null @@ -1,78 +0,0 @@ -/** - * [168] Excel Sheet Column Title - * - * Given a positive integer, return its corresponding column title as appear in an Excel sheet. - * - * For example: - * - * - * 1 -> A - * 2 -> B - * 3 -> C - * ... - * 26 -> Z - * 27 -> AA - * 28 -> AB - * ... - * - * - * Example 1: - * - * - * Input: 1 - * Output: "A" - * - * - * Example 2: - * - * - * Input: 28 - * Output: "AB" - * - * - * Example 3: - * - * - * Input: 701 - * Output: "ZY" - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/excel-sheet-column-title/ -// discuss: https://leetcode.com/problems/excel-sheet-column-title/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn convert_to_title(n: i32) -> String { - let base = 26; - let mut n = n; - let mut res = Vec::new(); - while n > 0 { - let mut code = (n % base) as u8; - n = n / base; - if code == 0 { - n -= 1; - code = base as u8; - }; - let alphabetic = (('A' as u8) + (code - 1_u8)) as char; - res.push(alphabetic); - } - res.reverse(); - res.into_iter().collect() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_168() { - assert_eq!(Solution::convert_to_title(28), "AB".to_owned()); - assert_eq!(Solution::convert_to_title(1), "A".to_owned()); - } -} diff --git a/src/solution/s0169_majority_element.rs b/src/solution/s0169_majority_element.rs deleted file mode 100644 index be59bea6..00000000 --- a/src/solution/s0169_majority_element.rs +++ /dev/null @@ -1,73 +0,0 @@ -/** - * [169] Majority Element - * - * Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times. - * - * You may assume that the array is non-empty and the majority element always exist in the array. - * - * Example 1: - * - * - * Input: [3,2,3] - * Output: 3 - * - * Example 2: - * - * - * Input: [2,2,1,1,1,2,2] - * Output: 2 - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/majority-element/ -// discuss: https://leetcode.com/problems/majority-element/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -抄的题解:Boyer-Moore Voting Algorithm -自己只能想到 HashMap 和排序, 真是太鸡儿菜了... - -Boyer-Moore Voting Algorithm 的思路是假设当前值为主元素, 碰到当前值则 +1, 非当前值则 -1, 计数器一旦归零, -就取下一个数为主元素 - -最后留下的数一定主元素 - -证明也很简单, 假设我们从第 i 位开始选择了一个数 A, 并且这个数 A 保持到了循环终止, 那么: - -我们知道, 第 nums[i..n] 中, A 是主元素, nums[0..i] 中, 有一个数 B 出现了一半的次数 - -假如 A = B, 那么 A 出现了大于一半的次数, A 一定是主元素 - -假如 A != B, 且主元素不是 A, 那么 B 包括其他任何数在整个数组中出现的次数一定不到一半(因为 B 包括其他任何数 -在前半部分**至多**出现一半, 而在后半部分不到一半), 因此不存在主元素, 这与题目给定的"一定存在主元素"矛盾, 因此 -A 一定是主元素 -*/ - -impl Solution { - pub fn majority_element(nums: Vec) -> i32 { - let mut count = 0; - let mut candidate = 0; - for &num in nums.iter() { - if count == 0 { - candidate = num; - } - count += if num == candidate { 1 } else { -1 }; - } - candidate - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_169() { - assert_eq!(Solution::majority_element(vec![2, 2, 1, 1, 1, 2, 2]), 2); - } -} diff --git a/src/solution/s0171_excel_sheet_column_number.rs b/src/solution/s0171_excel_sheet_column_number.rs deleted file mode 100644 index 1b2f611f..00000000 --- a/src/solution/s0171_excel_sheet_column_number.rs +++ /dev/null @@ -1,62 +0,0 @@ -/** - * [171] Excel Sheet Column Number - * - * Given a column title as appear in an Excel sheet, return its corresponding column number. - * - * For example: - * - * - * A -> 1 - * B -> 2 - * C -> 3 - * ... - * Z -> 26 - * AA -> 27 - * AB -> 28 - * ... - * - * - * Example 1: - * - * - * Input: "A" - * Output: 1 - * - * - * Example 2: - * - * - * Input: "AB" - * Output: 28 - * - * - * Example 3: - * - * - * Input: "ZY" - * Output: 701 - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/excel-sheet-column-number/ -// discuss: https://leetcode.com/problems/excel-sheet-column-number/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// TODO: boring -impl Solution { - pub fn title_to_number(s: String) -> i32 { - 0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_171() {} -} diff --git a/src/solution/s0172_factorial_trailing_zeroes.rs b/src/solution/s0172_factorial_trailing_zeroes.rs deleted file mode 100644 index 9a54916d..00000000 --- a/src/solution/s0172_factorial_trailing_zeroes.rs +++ /dev/null @@ -1,55 +0,0 @@ -/** - * [172] Factorial Trailing Zeroes - * - * Given an integer n, return the number of trailing zeroes in n!. - * - * Example 1: - * - * - * Input: 3 - * Output: 0 - * Explanation: 3! = 6, no trailing zero. - * - * Example 2: - * - * - * Input: 5 - * Output: 1 - * Explanation: 5! = 120, one trailing zero. - * - * Note: Your solution should be in logarithmic time complexity. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/factorial-trailing-zeroes/ -// discuss: https://leetcode.com/problems/factorial-trailing-zeroes/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn trailing_zeroes(n: i32) -> i32 { - let mut five_count = 0; - let mut n = n; - while n > 0 { - n = n / 5; - five_count += n; - } - five_count - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_172() { - assert_eq!(Solution::trailing_zeroes(3), 0); - assert_eq!(Solution::trailing_zeroes(5), 1); - assert_eq!(Solution::trailing_zeroes(20), 4); - assert_eq!(Solution::trailing_zeroes(1808548329), 452137076); - } -} diff --git a/src/solution/s0173_binary_search_tree_iterator.rs b/src/solution/s0173_binary_search_tree_iterator.rs deleted file mode 100644 index b350600d..00000000 --- a/src/solution/s0173_binary_search_tree_iterator.rs +++ /dev/null @@ -1,116 +0,0 @@ -/** - * [173] Binary Search Tree Iterator - * - * Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the root node of a BST. - * - * Calling next() will return the next smallest number in the BST. - * - * - * - * - * - * - * Example: - * - * - * - * - * BSTIterator iterator = new BSTIterator(root); - * iterator.next(); // return 3 - * iterator.next(); // return 7 - * iterator.hasNext(); // return true - * iterator.next(); // return 9 - * iterator.hasNext(); // return true - * iterator.next(); // return 15 - * iterator.hasNext(); // return true - * iterator.next(); // return 20 - * iterator.hasNext(); // return false - * - * - * - * - * Note: - * - * - * next() and hasNext() should run in average O(1) time and uses O(h) memory, where h is the height of the tree. - * You may assume that next() call will always be valid, that is, there will be at least a next smallest number in the BST when next() is called. - * - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; -use std::cell::RefCell; -use std::rc::Rc; - -// problem: https://leetcode.com/problems/binary-search-tree-iterator/ -// discuss: https://leetcode.com/problems/binary-search-tree-iterator/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -非递归中序遍历 -*/ -pub struct BSTIterator { - stack: Vec>>, -} - -/** - * `&self` means the method takes an immutable reference. - * If you need a mutable reference, change it to `&mut self` instead. - */ -impl BSTIterator { - pub fn new(root: Option>>) -> Self { - let mut node = root; - let mut stack = Vec::new(); - while let Some(inner) = node.clone() { - stack.push(inner.clone()); - node = node.unwrap().borrow().left.clone(); - } - BSTIterator { stack: stack } - } - - /** @return the next smallest number */ - pub fn next(&mut self) -> i32 { - let node = self.stack.pop().unwrap(); - let res = node.borrow().val; - let mut next = node.borrow().right.clone(); - while let Some(inner) = next.clone() { - self.stack.push(inner.clone()); - next = next.unwrap().borrow().left.clone(); - } - res - } - - /** @return whether we have a next smallest number */ - pub fn has_next(&self) -> bool { - !self.stack.is_empty() - } -} - -/** - * Your BSTIterator object will be instantiated and called as such: - * let obj = BSTIterator::new(root); - * let ret_1: i32 = obj.next(); - * let ret_2: bool = obj.has_next(); - */ - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_173() { - let mut iterator = BSTIterator::new(tree![7, 3, 15, null, null, 9, 20]); - assert_eq!(iterator.next(), 3); // return 3 - assert_eq!(iterator.next(), 7); // return 7 - assert_eq!(iterator.has_next(), true); // return true - assert_eq!(iterator.next(), 9); // return 9 - assert_eq!(iterator.has_next(), true); // return true - assert_eq!(iterator.next(), 15); // return 15 - assert_eq!(iterator.has_next(), true); // return true - assert_eq!(iterator.next(), 20); // return 20 - assert_eq!(iterator.has_next(), false); // return false - } -} diff --git a/src/solution/s0174_dungeon_game.rs b/src/solution/s0174_dungeon_game.rs deleted file mode 100644 index 23be4d97..00000000 --- a/src/solution/s0174_dungeon_game.rs +++ /dev/null @@ -1,115 +0,0 @@ -/** - * [174] Dungeon Game - * - * - * The demons had captured the princess (P) and imprisoned her in the bottom-right corner of a dungeon. The dungeon consists of M x N rooms laid out in a 2D grid. Our valiant knight (K) was initially positioned in the top-left room and must fight his way through the dungeon to rescue the princess. - * - * The knight has an initial health point represented by a positive integer. If at any point his health point drops to 0 or below, he dies immediately. - * - * Some of the rooms are guarded by demons, so the knight loses health (negative integers) upon entering these rooms; other rooms are either empty (0's) or contain magic orbs that increase the knight's health (positive integers). - * - * In order to reach the princess as quickly as possible, the knight decides to move only rightward or downward in each step. - * - * - * - * Write a function to determine the knight's minimum initial health so that he is able to rescue the princess. - * - * For example, given the dungeon below, the initial health of the knight must be at least 7 if he follows the optimal path RIGHT-> RIGHT -> DOWN -> DOWN. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
-2 (K)-33
-5-101
1030-5 (P)
- * - * - * - * Note: - * - * - * The knight's health has no upper bound. - * Any room can contain threats or power-ups, even the first room the knight enters and the bottom-right room where the princess is imprisoned. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/dungeon-game/ -// discuss: https://leetcode.com/problems/dungeon-game/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -DP, 即从每个格子出发到达终点所需的最小生命值为 hp[i][j] - -则显然, hp[M-1][N-1] = min(dungeon[M-1][N-1], 0) + 1; - -hp[i][j] = min(min(hp[i+1][j], hp[i][j+1]) - dungeon[i][j], 1); - -倒推到 hp[0][0] 即可 - -这里倒推很重要, 因为正推很难 dp(有后效性) - -其实可以优化成 O(M+N) 空间复杂度, 从斜对角线往后推就只需要保存一个小数组, 但是下面这样更简明 -*/ -impl Solution { - pub fn calculate_minimum_hp(dungeon: Vec>) -> i32 { - let (height, width) = (dungeon.len(), dungeon[0].len()); - // Using dummy row to simplify logic - let mut hp = vec![vec![i32::max_value(); width + 1]; height + 1]; - hp[height][width - 1] = 1; - hp[height - 1][width] = 1; - for i in (0..height).rev() { - for j in (0..width).rev() { - hp[i][j] = i32::max(i32::min(hp[i + 1][j], hp[i][j + 1]) - dungeon[i][j], 1); - } - } - hp[0][0] - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_174() { - assert_eq!( - Solution::calculate_minimum_hp(vec![ - vec![-2, -3, 3], - vec![-5, -10, 1], - vec![10, 30, -5], - ]), - 7 - ); - assert_eq!( - Solution::calculate_minimum_hp(vec![vec![1, -4, 5, -99], vec![2, -2, -2, -1]]), - 3 - ); - } -} diff --git a/src/solution/s0179_largest_number.rs b/src/solution/s0179_largest_number.rs deleted file mode 100644 index 65348165..00000000 --- a/src/solution/s0179_largest_number.rs +++ /dev/null @@ -1,60 +0,0 @@ -/** - * [179] Largest Number - * - * Given a list of non negative integers, arrange them such that they form the largest number. - * - * Example 1: - * - * - * Input: [10,2] - * Output: "210" - * - * Example 2: - * - * - * Input: [3,30,34,5,9] - * Output: "9534330" - * - * - * Note: The result may be very large, so you need to return a string instead of an integer. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/largest-number/ -// discuss: https://leetcode.com/problems/largest-number/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn largest_number(nums: Vec) -> String { - let mut nums = nums - .into_iter() - .map(|num| num.to_string()) - .collect::>(); - nums.sort_unstable_by(|a, b| format!("{}{}", b, a).cmp(&format!("{}{}", a, b))); - if nums[0] == "0" { - return "0".to_owned(); - } - nums.iter().fold(String::new(), |mut s, num| { - s.push_str(num); - s - }) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_179() { - assert_eq!( - Solution::largest_number(vec![3, 30, 34, 5, 9]), - "9534330".to_owned() - ); - assert_eq!(Solution::largest_number(vec![121, 12]), "12121".to_owned()); - } -} diff --git a/src/solution/s0187_repeated_dna_sequences.rs b/src/solution/s0187_repeated_dna_sequences.rs deleted file mode 100644 index 9ceb86cb..00000000 --- a/src/solution/s0187_repeated_dna_sequences.rs +++ /dev/null @@ -1,100 +0,0 @@ -/** - * [187] Repeated DNA Sequences - * - * All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACGAATTCCG". When studying DNA, it is sometimes useful to identify repeated sequences within the DNA. - * - * Write a function to find all the 10-letter-long sequences (substrings) that occur more than once in a DNA molecule. - * - * Example: - * - * - * Input: s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT" - * - * Output: ["AAAAACCCCC", "CCCCCAAAAA"] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/repeated-dna-sequences/ -// discuss: https://leetcode.com/problems/repeated-dna-sequences/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -首先想到直接长度为 10 的 sliding window 滑过去加一个 HashSet - -但这种方法在空间上和每次操作的耗时上都比较差, 可以转化为四进制或者二进制编码来考虑 - -A,C,G,T <-> [00, 01, 10, 11] - -那就简单很多了, 往后滑动一格不再需要调整整个 substring, 只需要移位, HashSet 也就存个 u32 即可 -*/ -use std::collections::HashSet; -impl Solution { - pub fn find_repeated_dna_sequences(s: String) -> Vec { - let mut seq_code: u32 = 0; - let mut set: HashSet = HashSet::new(); - let mut repeat: HashSet = HashSet::new(); - let mut count = 0; - for ch in s.chars() { - seq_code <<= 2; - match ch { - 'A' => seq_code |= 0_u32, - 'C' => seq_code |= 1_u32, - 'G' => seq_code |= 2_u32, - 'T' => seq_code |= 3_u32, - _ => unreachable!(), - } - // skip first 9 chars - if count < 9 { - count += 1; - continue; - } - // mask high 12-bits - seq_code &= 0b0000_0000_0000_1111_1111_1111_1111_1111; - if !set.insert(seq_code) { - repeat.insert(seq_code); - } - } - // bits code to seq string - repeat - .iter() - .map(|&code| { - let mut substr = String::new(); - let mut code = code; - for _ in 0..10 { - // take the first 2 bits each time - substr.push(match code & 0b0000_0000_0000_1100_0000_0000_0000_0000 { - 0b0000_0000_0000_0000_0000_0000_0000_0000 => 'A', - 0b0000_0000_0000_0100_0000_0000_0000_0000 => 'C', - 0b0000_0000_0000_1000_0000_0000_0000_0000 => 'G', - 0b0000_0000_0000_1100_0000_0000_0000_0000 => 'T', - _ => unreachable!(), - }); - code <<= 2; - } - substr - }) - .collect() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_187() { - assert_eq!( - Solution::find_repeated_dna_sequences("AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT".to_owned()), - vec_string!["AAAAACCCCC", "CCCCCAAAAA"] - ); - assert_eq!( - Solution::find_repeated_dna_sequences("GAGAGAGAGAGA".to_owned()), - vec_string!["GAGAGAGAGA"] - ); - } -} diff --git a/src/solution/s0188_best_time_to_buy_and_sell_stock_iv.rs b/src/solution/s0188_best_time_to_buy_and_sell_stock_iv.rs deleted file mode 100644 index e9c23319..00000000 --- a/src/solution/s0188_best_time_to_buy_and_sell_stock_iv.rs +++ /dev/null @@ -1,103 +0,0 @@ -/** - * [188] Best Time to Buy and Sell Stock IV - * - * Say you have an array for which the i^th element is the price of a given stock on day i. - * - * Design an algorithm to find the maximum profit. You may complete at most k transactions. - * - * Note:
- * You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again). - * - * Example 1: - * - * - * Input: [2,4,1], k = 2 - * Output: 2 - * Explanation: Buy on day 1 (price = 2) and sell on day 2 (price = 4), profit = 4-2 = 2. - * - * - * Example 2: - * - * - * Input: [3,2,6,5,0,3], k = 2 - * Output: 7 - * Explanation: Buy on day 2 (price = 2) and sell on day 3 (price = 6), profit = 6-2 = 4. - * Then buy on day 5 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/ -// discuss: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -已经在 #123 里解过了, 为了方便阅读直接把那题的分析拷贝到这里 - -先考虑只进行 1 次交易的情况, 我们求以 i *为售出点*, 只进行 1 次交易获得的最大利润, 那么: - -f[i] = if f[i-1] > 0 { f[i-1] } else { 0 } + prices[i] - prices[i-1] - -这很容易解, 解完之后找出 f 里的最大值即可, 但这不容易推广到 K 次交易的情况, 因为这时 f[i] 不代表到 i *为止*的最大利润, 无法作为单独的交易帮助递推 -(到 i 为止的含义是售出点可以在 [0,i] 之间) - -我们可以稍作改进, 变成求以 i 为结束点, 只进行 1 次交易获得的最大利润, 那么: - -f[i] = max( - f[i-1], - prices[i] - min(prices[j] { j in [0, i-1] }) -) - -这仍然是一个 O(N) 的解法, 因为 min(prices[j] { j in [0, i-1] }) 不需要遍历, 可以在递推过程中直接维护好 - -现在再推广到进行 K 次交易的情况, 那我们要求以 i 为结束点, 进行 k 次交易获得的最大利润, 这时有了变化, 我们可以在 j 之前再进行 K - 1 次交易: - -f[k, i] = max( - f[k, i-1], - prices[i] + max(f[k-1, j] - prices[j]) { j in [0, i-1] } ) -) - -显然, f[0, i] = 0, f[k, 0] = 0 - -这个算法可以形象地描述一下, 在 k = 1 时, 我们每次要找的就是 i 之前的最低谷点作为这次交易的开始点 j, 而当 k > 1 时, -我们 i 之前就有可能已经进行过交易了, 这时我们在找开始点 j 时, 就要同时考虑 "直到 j 为止, k-1 次交易的最大收益" - "j 本身的值". 以此来找到一个最佳点 j - -在实现时, 假如用 Bottom-Up 递推, 那么只需要维护一个 vec[i], 因为每轮递推时只会考虑上一轮的数据, 我们可以复用这个 O(N) 的额外存储空间 - -最后, 这题会给 k 非常大的 corner case, 实际上 k 大于 prices.len() / 2 后面就没有意义了, 可以 shortcut 掉(== 允许无穷次交易的场景), 下面写的比较糙, -直接限制了一下循环次数, 实际跑的时候运行时间会长一点 -*/ -impl Solution { - pub fn max_profit(k: i32, prices: Vec) -> i32 { - if prices.is_empty() { - return 0; - } - let max_trans = k as usize; - let mut cache = vec![0; prices.len()]; - for _ in 0..usize::min(max_trans, prices.len() / 2 + 1) { - // best_by_in 维护了考虑前 N 次交易的最佳的买入点, 即 max(f[k-1, j] - prices[j]) { j in [0, i-1] } - let mut best_buy_in = cache[0] - prices[0]; - for i in 1..prices.len() { - // 复用 vec 前暂存一下前一次的计算结果 - let temp = cache[i]; - cache[i] = i32::max(cache[i - 1], best_buy_in + prices[i]); - // 更新 best_buy_in - best_buy_in = i32::max(best_buy_in, temp - prices[i]); - } - } - return *cache.last().unwrap(); - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_188() { - assert_eq!(Solution::max_profit(2, vec![3, 2, 6, 5, 0, 3]), 7); - } -} diff --git a/src/solution/s0189_rotate_array.rs b/src/solution/s0189_rotate_array.rs deleted file mode 100644 index 1a4d2ab8..00000000 --- a/src/solution/s0189_rotate_array.rs +++ /dev/null @@ -1,79 +0,0 @@ -/** - * [189] Rotate Array - * - * Given an array, rotate the array to the right by k steps, where k is non-negative. - * - * Example 1: - * - * - * Input: [1,2,3,4,5,6,7] and k = 3 - * Output: [5,6,7,1,2,3,4] - * Explanation: - * rotate 1 steps to the right: [7,1,2,3,4,5,6] - * rotate 2 steps to the right: [6,7,1,2,3,4,5] - * rotate 3 steps to the right: [5,6,7,1,2,3,4] - * - * - * Example 2: - * - * - * Input: [-1,-100,3,99] and k = 2 - * Output: [3,99,-1,-100] - * Explanation: - * rotate 1 steps to the right: [99,-1,-100,3] - * rotate 2 steps to the right: [3,99,-1,-100] - * - * - * Note: - * - * - * Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem. - * Could you do it in-place with O(1) extra space? - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/rotate-array/ -// discuss: https://leetcode.com/problems/rotate-array/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn rotate(nums: &mut Vec, k: i32) { - let offset = (k as usize) % nums.len(); - if offset == 0 { - return; - } - let mut idx = 0; - let mut num = nums[0]; - let mut start_idx = 0; - for _ in 0..nums.len() { - idx = (idx + offset) % nums.len(); - let temp = num; - num = nums[idx]; - nums[idx] = temp; - if idx == start_idx { - idx += 1; - start_idx = idx; - num = nums[idx]; - } - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_189() { - let mut nums = vec![1, 2, 3, 4, 5, 6, 7]; - Solution::rotate(&mut nums, 3); - assert_eq!(nums, vec![5, 6, 7, 1, 2, 3, 4]); - let mut nums = vec![1, 2, 3, 4, 5, 6]; - Solution::rotate(&mut nums, 2); - assert_eq!(nums, vec![5, 6, 1, 2, 3, 4]); - } -} diff --git a/src/solution/s0198_house_robber.rs b/src/solution/s0198_house_robber.rs deleted file mode 100644 index 446e63f1..00000000 --- a/src/solution/s0198_house_robber.rs +++ /dev/null @@ -1,68 +0,0 @@ -/** - * [198] House Robber - * - * You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night. - * - * Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police. - * - * Example 1: - * - * - * Input: [1,2,3,1] - * Output: 4 - * Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3). - * Total amount you can rob = 1 + 3 = 4. - * - * Example 2: - * - * - * Input: [2,7,9,3,1] - * Output: 12 - * Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1). - * Total amount you can rob = 2 + 9 + 1 = 12. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/house-robber/ -// discuss: https://leetcode.com/problems/house-robber/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -动态规划, 记抢到第 i 户为止的最大收益为 F[i], 则: - -i 有两种情况, 抢或不抢, 抢的话则最大收益是 F[i-2] + nums[i], -不抢则保持和前一次结束的收益一致, 等于 F[i-1], 于是: - -F[i] = i32::max(nums[i] + F[i-2], F[i-1]) - -观察到 F[i] 只依赖 F[i-1] 和 F[i-2], 可以用常数空间复杂度完成 -*/ -impl Solution { - pub fn rob(nums: Vec) -> i32 { - let mut former_max = 0; - let mut curr_max = 0; - for &num in nums.iter() { - let mut temp = curr_max; - curr_max = i32::max(former_max + num, curr_max); - former_max = temp; - } - curr_max - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_198() { - assert_eq!(Solution::rob(vec![2, 7, 9, 3, 1]), 12); - assert_eq!(Solution::rob(vec![2, 7, 9, 10, 1]), 17); - assert_eq!(Solution::rob(vec![2, 1, 1, 2]), 4); - } -} diff --git a/src/solution/s0199_binary_tree_right_side_view.rs b/src/solution/s0199_binary_tree_right_side_view.rs deleted file mode 100644 index e07dc998..00000000 --- a/src/solution/s0199_binary_tree_right_side_view.rs +++ /dev/null @@ -1,68 +0,0 @@ -/** - * [199] Binary Tree Right Side View - * - * Given a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom. - * - * Example: - * - * - * Input: [1,2,3,null,5,null,4] - * Output: [1, 3, 4] - * Explanation: - * - * 1 <--- - * / \ - * 2 3 <--- - * \ \ - * 5 4 <--- - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/binary-tree-right-side-view/ -// discuss: https://leetcode.com/problems/binary-tree-right-side-view/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::collections::VecDeque; -use std::rc::Rc; -impl Solution { - pub fn right_side_view(root: Option>>) -> Vec { - let mut res = Vec::new(); - let mut current_level = 0; - if root.is_none() { - return res; - } - let mut deq = VecDeque::new(); - deq.push_back((0, root.clone())); - res.push(root.as_ref().unwrap().borrow().val); - while !deq.is_empty() { - if let Some((level, Some(node))) = deq.pop_front() { - deq.push_back((level + 1, node.borrow().right.clone())); - deq.push_back((level + 1, node.borrow().left.clone())); - if level > current_level { - res.push(node.borrow().val); - current_level = level; - } - } - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_199() { - assert_eq!( - Solution::right_side_view(tree![1, 2, 3, null, 5, null, 4]), - vec![1, 3, 4] - ); - } -} diff --git a/src/solution/s0200_number_of_islands.rs b/src/solution/s0200_number_of_islands.rs deleted file mode 100644 index 262f0315..00000000 --- a/src/solution/s0200_number_of_islands.rs +++ /dev/null @@ -1,122 +0,0 @@ -/** - * [200] Number of Islands - * - * Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water. - * - * Example 1: - * - * - * Input: - * 11110 - * 11010 - * 11000 - * 00000 - * - * Output: 1 - * - * - * Example 2: - * - * - * Input: - * 11000 - * 11000 - * 00100 - * 00011 - * - * Output: 3 - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/number-of-islands/ -// discuss: https://leetcode.com/problems/number-of-islands/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// Union-Find Set -impl Solution { - pub fn num_islands(grid: Vec>) -> i32 { - if grid.is_empty() || grid[0].is_empty() { - return 0; - } - let (height, width) = (grid.len(), grid[0].len()); - let mut parent = vec![vec![(width, height); width]; height]; - for i in 0..height { - for j in 0..width { - if grid[i][j] != '1' { - continue; - } - parent[i][j] = (i, j); - if i > 0 && grid[i - 1][j] == '1' { - Solution::union(&mut parent, (i, j), (i - 1, j)); - } - if j > 0 && grid[i][j - 1] == '1' { - Solution::union(&mut parent, (i, j), (i, j - 1)); - } - } - } - let mut cnt = 0; - for i in 0..height { - for j in 0..width { - if parent[i][j] == (i, j) { - cnt += 1; - } - } - } - cnt - } - - fn get_parent(parent: &mut Vec>, p: (usize, usize)) -> (usize, usize) { - let mut child = p; - let mut p = p; - while parent[p.0][p.1] != p { - p = parent[p.0][p.1]; - } - // path compression, adjust all the node's parent to root along the path - while child != p { - let temp = parent[child.0][child.1]; - parent[child.0][child.1] = p; - child = temp; - } - p - } - - fn union(parent: &mut Vec>, p1: (usize, usize), p2: (usize, usize)) { - let p1 = Solution::get_parent(parent, p1); - let p2 = Solution::get_parent(parent, p2); - if p1 == p2 { - return; - } - parent[p1.0][p1.1] = p2 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_200() { - assert_eq!( - Solution::num_islands(vec![ - vec!['1', '1', '1', '1', '0',], - vec!['1', '1', '0', '1', '0',], - vec!['1', '1', '0', '0', '0',], - vec!['0', '0', '0', '0', '0',], - ]), - 1 - ); - assert_eq!( - Solution::num_islands(vec![ - vec!['1', '1', 'o', '1', '0',], - vec!['1', '1', '0', '1', '0',], - vec!['1', '1', '0', '0', '0',], - vec!['0', '0', '0', '1', '1',], - ]), - 3 - ); - } -} diff --git a/src/solution/s0201_bitwise_and_of_numbers_range.rs b/src/solution/s0201_bitwise_and_of_numbers_range.rs deleted file mode 100644 index 6c46e74f..00000000 --- a/src/solution/s0201_bitwise_and_of_numbers_range.rs +++ /dev/null @@ -1,58 +0,0 @@ -/** - * [201] Bitwise AND of Numbers Range - * - * Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range, inclusive. - * - * Example 1: - * - * - * Input: [5,7] - * Output: 4 - * - * - * Example 2: - * - * - * Input: [0,1] - * Output: 0 - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/bitwise-and-of-numbers-range/ -// discuss: https://leetcode.com/problems/bitwise-and-of-numbers-range/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// just find the highest bit 1 of m and n -impl Solution { - pub fn range_bitwise_and(m: i32, n: i32) -> i32 { - let mut m = m; - let mut n = n; - if m == 0 { - return 0; - } - let mut step = 1; - while m != n { - // shortcut - if m == 0 { - return 0; - } - m >>= 1; - n >>= 1; - step <<= 1; - } - return m * step; - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_201() { - assert_eq!(Solution::range_bitwise_and(5, 7), 4); - } -} diff --git a/src/solution/s0202_happy_number.rs b/src/solution/s0202_happy_number.rs deleted file mode 100644 index 076f2736..00000000 --- a/src/solution/s0202_happy_number.rs +++ /dev/null @@ -1,68 +0,0 @@ -/** - * [202] Happy Number - * - * Write an algorithm to determine if a number is "happy". - * - * A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers. - * - * Example: - * - * - * Input: 19 - * Output: true - * Explanation: - * 1^2 + 9^2 = 82 - * 8^2 + 2^2 = 68 - * 6^2 + 8^2 = 100 - * 1^2 + 0^2 + 0^2 = 1 - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/happy-number/ -// discuss: https://leetcode.com/problems/happy-number/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::collections::HashSet; -impl Solution { - pub fn is_happy(n: i32) -> bool { - let mut set = HashSet::new(); - let mut n = n; - loop { - set.insert(n); - let temp = Solution::next(n); - if temp == 1 { - return true; - } - if !set.insert(temp) { - return false; - } - n = temp - } - return false; - } - - fn next(n: i32) -> i32 { - let mut res = 0; - let mut n = n; - while n != 0 { - res += (n % 10).pow(2); - n = n / 10; - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_202() { - assert_eq!(Solution::is_happy(19), true); - assert_eq!(Solution::is_happy(235123), false); - } -} diff --git a/src/solution/s0203_remove_linked_list_elements.rs b/src/solution/s0203_remove_linked_list_elements.rs deleted file mode 100644 index 3e48d811..00000000 --- a/src/solution/s0203_remove_linked_list_elements.rs +++ /dev/null @@ -1,50 +0,0 @@ -/** - * [203] Remove Linked List Elements - * - * Remove all elements from a linked list of integers that have value val. - * - * Example: - * - * - * Input: 1->2->6->3->4->5->6, val = 6 - * Output: 1->2->3->4->5 - * - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; - -// problem: https://leetcode.com/problems/remove-linked-list-elements/ -// discuss: https://leetcode.com/problems/remove-linked-list-elements/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn remove_elements(mut head: Option>, val: i32) -> Option> { - let mut dummy = Some(Box::new(ListNode::new(0))); - let mut next = dummy.as_mut(); - while let Some(mut inner) = head { - head = inner.next.take(); - if inner.val != val { - next.as_mut().unwrap().next = Some(inner); - next = next.unwrap().next.as_mut(); - } - } - dummy.unwrap().next - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_203() { - assert_eq!( - Solution::remove_elements(linked![1, 2, 6, 3, 4, 5, 6], 6), - linked![1, 2, 3, 4, 5] - ); - } -} diff --git a/src/solution/s0204_count_primes.rs b/src/solution/s0204_count_primes.rs deleted file mode 100644 index d6f0f134..00000000 --- a/src/solution/s0204_count_primes.rs +++ /dev/null @@ -1,68 +0,0 @@ -/** - * [204] Count Primes - * - * Count the number of prime numbers less than a non-negative number, n. - * - * Example: - * - * - * Input: 10 - * Output: 4 - * Explanation: There are 4 prime numbers less than 10, they are 2, 3, 5, 7. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/count-primes/ -// discuss: https://leetcode.com/problems/count-primes/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn count_primes(n: i32) -> i32 { - if n <= 2 { - return 0; - } - let mut is_prime = vec![true; n as usize]; - is_prime[0] = false; - is_prime[1] = false; - let mut i = 2; - while i * i < n { - if !is_prime[i as usize] { - i += 1; - continue; - } - let mut j = i * i; - while j < n { - is_prime[j as usize] = false; - j += i; - } - i += 1; - } - let mut count = 0; - for &v in is_prime.iter() { - if v { - count += 1 - } - } - count - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_204() { - assert_eq!(Solution::count_primes(10), 4); - assert_eq!(Solution::count_primes(2), 0); - assert_eq!(Solution::count_primes(3), 1); - assert_eq!(Solution::count_primes(5), 2); - assert_eq!(Solution::count_primes(1), 0); - assert_eq!(Solution::count_primes(120), 30); - } -} diff --git a/src/solution/s0205_isomorphic_strings.rs b/src/solution/s0205_isomorphic_strings.rs deleted file mode 100644 index df697ebb..00000000 --- a/src/solution/s0205_isomorphic_strings.rs +++ /dev/null @@ -1,84 +0,0 @@ -/** - * [205] Isomorphic Strings - * - * Given two strings s and t, determine if they are isomorphic. - * - * Two strings are isomorphic if the characters in s can be replaced to get t. - * - * All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character but a character may map to itself. - * - * Example 1: - * - * - * Input: s = "egg", t = "add" - * Output: true - * - * - * Example 2: - * - * - * Input: s = "foo", t = "bar" - * Output: false - * - * Example 3: - * - * - * Input: s = "paper", t = "title" - * Output: true - * - * Note:
- * You may assume both s and t have the same length. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/isomorphic-strings/ -// discuss: https://leetcode.com/problems/isomorphic-strings/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::char; -use std::collections::hash_map::Entry; -use std::collections::HashMap; -impl Solution { - pub fn is_isomorphic(s: String, t: String) -> bool { - Solution::code(s) == Solution::code(t) - } - - fn code(s: String) -> String { - let mut map = HashMap::new(); - let mut start: char = '0'; - let mut res = String::new(); - for ch in s.chars() { - let v = map.entry(ch).or_insert_with(|| { - start = ((start as u8) + 1) as char; - start - }); - res.push(*v) - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_205() { - assert_eq!( - Solution::is_isomorphic("egg".to_owned(), "app".to_owned()), - true - ); - assert_eq!( - Solution::is_isomorphic("pecil".to_owned(), "this".to_owned()), - false - ); - assert_eq!( - Solution::is_isomorphic("paper".to_owned(), "title".to_owned()), - true - ); - } -} diff --git a/src/solution/s0206_reverse_linked_list.rs b/src/solution/s0206_reverse_linked_list.rs deleted file mode 100644 index b62aced8..00000000 --- a/src/solution/s0206_reverse_linked_list.rs +++ /dev/null @@ -1,52 +0,0 @@ -/** - * [206] Reverse Linked List - * - * Reverse a singly linked list. - * - * Example: - * - * - * Input: 1->2->3->4->5->NULL - * Output: 5->4->3->2->1->NULL - * - * - * Follow up: - * - * A linked list can be reversed either iteratively or recursively. Could you implement both? - * - */ -pub struct Solution {} -use crate::util::linked_list::{to_list, ListNode}; - -// problem: https://leetcode.com/problems/reverse-linked-list/ -// discuss: https://leetcode.com/problems/reverse-linked-list/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn reverse_list(head: Option>) -> Option> { - let mut curr = head; - let mut next = None; - while let Some(mut inner) = curr { - curr = inner.next.take(); - inner.next = next; - next = Some(inner); - } - next - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_206() { - assert_eq!( - Solution::reverse_list(linked![1, 2, 3, 4, 5]), - linked![5, 4, 3, 2, 1] - ); - } -} diff --git a/src/solution/s0207_course_schedule.rs b/src/solution/s0207_course_schedule.rs deleted file mode 100644 index 2a793683..00000000 --- a/src/solution/s0207_course_schedule.rs +++ /dev/null @@ -1,105 +0,0 @@ -/** - * [207] Course Schedule - * - * There are a total of n courses you have to take, labeled from 0 to n-1. - * - * Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1] - * - * Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses? - * - * Example 1: - * - * - * Input: 2, [[1,0]] - * Output: true - * Explanation: There are a total of 2 courses to take. - * To take course 1 you should have finished course 0. So it is possible. - * - * Example 2: - * - * - * Input: 2, [[1,0],[0,1]] - * Output: false - * Explanation: There are a total of 2 courses to take. - * To take course 1 you should have finished course 0, and to take course 0 you should - * also have finished course 1. So it is impossible. - * - * - * Note: - * - *
    - * The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented. - * You may assume that there are no duplicate edges in the input prerequisites. - *
- * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/course-schedule/ -// discuss: https://leetcode.com/problems/course-schedule/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// topology sort, BFS -use std::collections::VecDeque; -impl Solution { - pub fn can_finish(num_courses: i32, prerequisites: Vec>) -> bool { - let num = num_courses as usize; - let mut matrix = vec![vec![false; num]; num]; - let mut in_degree = vec![0; num]; - // collects node in degree - for pre in prerequisites.iter() { - if !matrix[pre[1] as usize][pre[0] as usize] { - in_degree[pre[0] as usize] += 1; - } - matrix[pre[1] as usize][pre[0] as usize] = true; - } - let mut deq = VecDeque::new(); - // BFS starts with nodes with 0 in degree - for (node, &v) in in_degree.iter().enumerate() { - if v == 0 { - deq.push_back(node); - } - } - let mut cnt = 0; - while let Some(node) = deq.pop_front() { - cnt += 1; - for (i, &connect) in matrix[node].iter().enumerate() { - if connect { - in_degree[i] -= 1; - if in_degree[i] == 0 { - deq.push_back(i); - } - } - } - } - cnt == num_courses - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_207() { - assert_eq!(Solution::can_finish(2, vec![vec![1, 0]]), true); - assert_eq!(Solution::can_finish(2, vec![vec![1, 0], vec![0, 1]]), false); - assert_eq!( - Solution::can_finish( - 8, - vec![ - vec![1, 0], - vec![2, 6], - vec![1, 7], - vec![6, 4], - vec![7, 0], - vec![0, 5] - ] - ), - true - ); - } -} diff --git a/src/solution/s0208_implement_trie_prefix_tree.rs b/src/solution/s0208_implement_trie_prefix_tree.rs deleted file mode 100644 index 9ac8e470..00000000 --- a/src/solution/s0208_implement_trie_prefix_tree.rs +++ /dev/null @@ -1,95 +0,0 @@ -/** - * [208] Implement Trie (Prefix Tree) - * - * Implement a trie with insert, search, and startsWith methods. - * - * Example: - * - * - * Trie trie = new Trie(); - * - * trie.insert("apple"); - * trie.search("apple"); // returns true - * trie.search("app"); // returns false - * trie.startsWith("app"); // returns true - * trie.insert("app"); - * trie.search("app"); // returns true - * - * - * Note: - * - * - * You may assume that all inputs are consist of lowercase letters a-z. - * All inputs are guaranteed to be non-empty strings. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/implement-trie-prefix-tree/ -// discuss: https://leetcode.com/problems/implement-trie-prefix-tree/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -#[derive(Default)] -struct Trie { - is_end: bool, - nodes: [Option>; 26], -} - -/** - * `&self` means the method takes an immutable reference. - * If you need a mutable reference, change it to `&mut self` instead. - */ -impl Trie { - /** Initialize your data structure here. */ - fn new() -> Self { - Default::default() - } - - /** insert a word into the trie. */ - fn insert(&mut self, word: String) { - let mut curr = self; - - for i in word.chars().map(|ch| (ch as u8 - 'a' as u8) as usize) { - curr = curr.nodes[i].get_or_insert_with(|| Box::new(Trie::new())); - } - curr.is_end = true; - } - - /** Returns if the word is in the trie. */ - fn search(&self, word: String) -> bool { - self.find(word).map_or(false, |t| t.is_end) - } - - /** Returns if there is any word in the trie that starts with the given prefix. */ - fn starts_with(&self, prefix: String) -> bool { - self.find(prefix).is_some() - } - - fn find(&self, word: String) -> Option<&Trie> { - let mut curr = self; - for i in word.chars().map(|ch| (ch as u8 - 'a' as u8) as usize) { - curr = curr.nodes[i].as_ref()?; - } - Some(curr) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_208() { - let mut trie = Trie::new(); - trie.insert("apple".to_owned()); - assert_eq!(trie.search("apple".to_owned()), true); // returns true - assert_eq!(trie.search("app".to_owned()), false); - assert_eq!(trie.starts_with("app".to_owned()), true); // returns true - trie.insert("app".to_owned()); - assert_eq!(trie.search("app".to_owned()), true); // returns true - } -} diff --git a/src/solution/s0209_minimum_size_subarray_sum.rs b/src/solution/s0209_minimum_size_subarray_sum.rs deleted file mode 100644 index b6a692d7..00000000 --- a/src/solution/s0209_minimum_size_subarray_sum.rs +++ /dev/null @@ -1,65 +0,0 @@ -/** - * [209] Minimum Size Subarray Sum - * - * Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn't one, return 0 instead. - * - * Example: - * - * - * Input: s = 7, nums = [2,3,1,2,4,3] - * Output: 2 - * Explanation: the subarray [4,3] has the minimal length under the problem constraint. - * - *
Follow up:
- * - *
If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n).
- * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/minimum-size-subarray-sum/ -// discuss: https://leetcode.com/problems/minimum-size-subarray-sum/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn min_sub_array_len(s: i32, nums: Vec) -> i32 { - let (mut i, mut j) = (0_usize, 0_usize); - let mut min = i32::max_value(); - let mut found = false; - let mut sum = 0; - while j < nums.len() { - sum += nums[j]; - if sum >= s { - found = true; - while i <= j { - sum -= nums[i]; - i += 1; - if sum < s { - min = i32::min(min, j as i32 - i as i32 + 2); - break; - } - } - } - j += 1; - } - if found { - min - } else { - 0 - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_209() { - assert_eq!(Solution::min_sub_array_len(7, vec![2, 3, 1, 2, 4, 3]), 2); - assert_eq!(Solution::min_sub_array_len(4, vec![1, 4, 4]), 1); - } -} diff --git a/src/solution/s0210_course_schedule_ii.rs b/src/solution/s0210_course_schedule_ii.rs deleted file mode 100644 index dd3a1b03..00000000 --- a/src/solution/s0210_course_schedule_ii.rs +++ /dev/null @@ -1,98 +0,0 @@ -/** - * [210] Course Schedule II - * - * There are a total of n courses you have to take, labeled from 0 to n-1. - * - * Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1] - * - * Given the total number of courses and a list of prerequisite pairs, return the ordering of courses you should take to finish all courses. - * - * There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array. - * - * Example 1: - * - * - * Input: 2, [[1,0]] - * Output: [0,1] - * Explanation: There are a total of 2 courses to take. To take course 1 you should have finished - * course 0. So the correct course order is [0,1] . - * - * Example 2: - * - * - * Input: 4, [[1,0],[2,0],[3,1],[3,2]] - * Output: [0,1,2,3] or [0,2,1,3] - * Explanation: There are a total of 4 courses to take. To take course 3 you should have finished both - * courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0. - * So one correct course order is [0,1,2,3]. Another correct ordering is [0,2,1,3] . - * - * Note: - * - *
    - * The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented. - * You may assume that there are no duplicate edges in the input prerequisites. - *
- * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/course-schedule-ii/ -// discuss: https://leetcode.com/problems/course-schedule-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::collections::VecDeque; -impl Solution { - pub fn find_order(num_courses: i32, prerequisites: Vec>) -> Vec { - let num = num_courses as usize; - let mut matrix = vec![vec![false; num]; num]; - let mut in_degree = vec![0; num]; - // collects node in degree - for pre in prerequisites.iter() { - if !matrix[pre[1] as usize][pre[0] as usize] { - in_degree[pre[0] as usize] += 1; - } - matrix[pre[1] as usize][pre[0] as usize] = true; - } - let mut deq = VecDeque::new(); - // BFS starts with nodes with 0 in degree - for (node, &v) in in_degree.iter().enumerate() { - if v == 0 { - deq.push_back(node); - } - } - let mut res = Vec::with_capacity(num); - while let Some(node) = deq.pop_front() { - res.push(node as i32); - for (i, &connect) in matrix[node].iter().enumerate() { - if connect { - in_degree[i] -= 1; - if in_degree[i] == 0 { - deq.push_back(i); - } - } - } - } - if res.len() == num { - res - } else { - vec![] - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_210() { - assert_eq!(Solution::find_order(2, vec![vec![1, 0]]), vec![0, 1]); - assert_eq!( - Solution::find_order(4, vec![vec![1, 0], vec![2, 0], vec![3, 1], vec![3, 2]]), - vec![0, 1, 2, 3] - ); - } -} diff --git a/src/solution/s0211_add_and_search_word_data_structure_design.rs b/src/solution/s0211_add_and_search_word_data_structure_design.rs deleted file mode 100644 index 0652f951..00000000 --- a/src/solution/s0211_add_and_search_word_data_structure_design.rs +++ /dev/null @@ -1,129 +0,0 @@ -/** - * [211] Add and Search Word - Data structure design - * - * Design a data structure that supports the following two operations: - * - * - * void addWord(word) - * bool search(word) - * - * - * search(word) can search a literal word or a regular expression string containing only letters a-z or .. A . means it can represent any one letter. - * - * Example: - * - * - * addWord("bad") - * addWord("dad") - * addWord("mad") - * search("pad") -> false - * search("bad") -> true - * search(".ad") -> true - * search("b..") -> true - * - * - * Note:
- * You may assume that all words are consist of lowercase letters a-z. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/add-and-search-word-data-structure-design/ -// discuss: https://leetcode.com/problems/add-and-search-word-data-structure-design/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -struct WordDictionary { - root: Option>, -} - -#[derive(Default)] -struct Trie { - is_end: bool, - marked: Vec, - nodes: [Option>; 26], -} - -impl Trie { - fn new() -> Self { - Default::default() - } -} - -/** - * `&self` means the method takes an immutable reference. - * If you need a mutable reference, change it to `&mut self` instead. - */ -impl WordDictionary { - // /** Initialize your data structure here. */ - // fn new() -> Self { - // WordDictionary{ - // root: Some(Box::new(Trie::new())), - // } - // } - - // /** Adds a word into the data structure. */ - // fn add_word(&mut self, word: String) { - // let mut curr = self.root; - - // for i in word.chars().map(|ch| (ch as u8 - 'a' as u8) as usize) { - // curr = curr.as_ref().unwrap().nodes[i]; - // } - // curr.as_mut().unwrap().is_end = true; - // } - - // /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */ - // fn search(&self, word: String) -> bool { - // let mut chs: Vec = word.chars().collect(); - // WordDictionary::search_from(self.root.as_ref(), &mut chs) - // } - - // fn search_from(node: Option<&Box>, chs: &mut [char]) -> bool { - // if node.is_none() { - // return false - // } - // let node = node.unwrap(); - // if chs.len() < 1 { - // return node.is_end - // } - // if chs[0] == '.' { - // // backtracking - // let mut sliced = &mut chs[1..]; - // for &idx in node.marked.iter() { - // if WordDictionary::search_from(node.nodes[idx].as_ref(), sliced) { - // return true - // } - // } - // false - // } else { - // let next = node.nodes[(chs[0] as u8 - 'a' as u8) as usize].as_ref(); - // WordDictionary::search_from(next, &mut chs[1..]) - // } - // } -} - -/** - * Your WordDictionary object will be instantiated and called as such: - * let obj = WordDictionary::new(); - * obj.add_word(word); - * let ret_2: bool = obj.search(word); - */ - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_211() { - // let mut dict = WordDictionary::new(); - // dict.add_word("bad".to_owned()); - // dict.add_word("dad".to_owned()); - // dict.add_word("mad".to_owned()); - // assert_eq!(dict.search("pad".to_owned()), false); - // assert_eq!(dict.search("bad".to_owned()), true); - // assert_eq!(dict.search(".ad".to_owned()), true); - // assert_eq!(dict.search("da.".to_owned()), true); - } -} diff --git a/src/solution/s0212_word_search_ii.rs b/src/solution/s0212_word_search_ii.rs deleted file mode 100644 index ada034c8..00000000 --- a/src/solution/s0212_word_search_ii.rs +++ /dev/null @@ -1,57 +0,0 @@ -/** - * [212] Word Search II - * - * Given a 2D board and a list of words from the dictionary, find all words in the board. - * - * Each word must be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word. - * - * - * - * Example: - * - * - * Input: - * board = [ - * ['o','a','a','n'], - * ['e','t','a','e'], - * ['i','h','k','r'], - * ['i','f','l','v'] - * ] - * words = ["oath","pea","eat","rain"] - * - * Output: ["eat","oath"] - * - * - * - * - * Note: - * - *
    - * All inputs are consist of lowercase letters a-z. - * The values of words are distinct. - *
- * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/word-search-ii/ -// discuss: https://leetcode.com/problems/word-search-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here -// TODO - -impl Solution { - pub fn find_words(board: Vec>, words: Vec) -> Vec { - vec![] - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_212() {} -} diff --git a/src/solution/s0213_house_robber_ii.rs b/src/solution/s0213_house_robber_ii.rs deleted file mode 100644 index fbe55040..00000000 --- a/src/solution/s0213_house_robber_ii.rs +++ /dev/null @@ -1,69 +0,0 @@ -/** - * [213] House Robber II - * - * You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night. - * - * Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police. - * - * Example 1: - * - * - * Input: [2,3,2] - * Output: 3 - * Explanation: You cannot rob house 1 (money = 2) and then rob house 3 (money = 2), - * because they are adjacent houses. - * - * - * Example 2: - * - * - * Input: [1,2,3,1] - * Output: 4 - * Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3). - * Total amount you can rob = 1 + 3 = 4. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/house-robber-ii/ -// discuss: https://leetcode.com/problems/house-robber-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// DP twice: rob first one || not rob first one -// F[i] = max(F[i-2] + num[i], F[i-1]) -impl Solution { - pub fn rob(nums: Vec) -> i32 { - let mut max = i32::min_value(); - for &rob_first in vec![true, false].iter() { - let (mut prev, mut curr) = (0, 0); - for (k, &num) in nums.iter().enumerate() { - if k == 0 && !rob_first { - continue; - } - // k is last element but not the first element - if k != 0 && k == (nums.len() - 1) && rob_first { - continue; - } - let next = i32::max(prev + num, curr); - prev = curr; - curr = next; - } - max = i32::max(max, curr) - } - max - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_213() { - assert_eq!(Solution::rob(vec![2, 3, 2]), 3); - assert_eq!(Solution::rob(vec![1, 2, 3, 1]), 4); - } -} diff --git a/src/solution/s0214_shortest_palindrome.rs b/src/solution/s0214_shortest_palindrome.rs deleted file mode 100644 index 425eec95..00000000 --- a/src/solution/s0214_shortest_palindrome.rs +++ /dev/null @@ -1,40 +0,0 @@ -/** - * [214] Shortest Palindrome - * - * Given a string s, you are allowed to convert it to a palindrome by adding characters in front of it. Find and return the shortest palindrome you can find by performing this transformation. - * - * Example 1: - * - * - * Input: "aacecaaa" - * Output: "aaacecaaa" - * - * - * Example 2: - * - * - * Input: "abcd" - * Output: "dcbabcd" - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/shortest-palindrome/ -// discuss: https://leetcode.com/problems/shortest-palindrome/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn shortest_palindrome(s: String) -> String { - "".to_owned() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_214() {} -} diff --git a/src/solution/s0215_kth_largest_element_in_an_array.rs b/src/solution/s0215_kth_largest_element_in_an_array.rs deleted file mode 100644 index 159e7af6..00000000 --- a/src/solution/s0215_kth_largest_element_in_an_array.rs +++ /dev/null @@ -1,62 +0,0 @@ -/** - * [215] Kth Largest Element in an Array - * - * Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element. - * - * Example 1: - * - * - * Input: [3,2,1,5,6,4] and k = 2 - * Output: 5 - * - * - * Example 2: - * - * - * Input: [3,2,3,1,2,4,5,5,6] and k = 4 - * Output: 4 - * - * Note:
- * You may assume k is always valid, 1 ≤ k ≤ array's length. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/kth-largest-element-in-an-array/ -// discuss: https://leetcode.com/problems/kth-largest-element-in-an-array/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cmp::Reverse; -use std::collections::BinaryHeap; -impl Solution { - pub fn find_kth_largest(nums: Vec, k: i32) -> i32 { - let k = k as usize; - let mut heap = BinaryHeap::with_capacity(k); - for &num in nums.iter() { - if heap.len() < k as usize { - heap.push(Reverse(num)) - } else if num >= heap.peek().unwrap().0 { - heap.pop(); - heap.push(Reverse(num)); - } - } - heap.peek().unwrap().0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_215() { - assert_eq!( - Solution::find_kth_largest(vec![3, 2, 3, 1, 2, 4, 5, 5, 6], 4), - 4 - ); - assert_eq!(Solution::find_kth_largest(vec![3, 2, 1, 5, 6, 4], 2), 5); - } -} diff --git a/src/solution/s0216_combination_sum_iii.rs b/src/solution/s0216_combination_sum_iii.rs deleted file mode 100644 index 0f714e01..00000000 --- a/src/solution/s0216_combination_sum_iii.rs +++ /dev/null @@ -1,83 +0,0 @@ -/** - * [216] Combination Sum III - * - *
- * Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers. - * - * Note: - * - * - * All numbers will be positive integers. - * The solution set must not contain duplicate combinations. - * - * - * Example 1: - * - * - * Input: k = 3, n = 7 - * Output: [[1,2,4]] - * - * - * Example 2: - * - * - * Input: k = 3, n = 9 - * Output: [[1,2,6], [1,3,5], [2,3,4]] - * - *
- */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/combination-sum-iii/ -// discuss: https://leetcode.com/problems/combination-sum-iii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn combination_sum3(k: i32, n: i32) -> Vec> { - if k > 9 || k < 1 { - return vec![]; - } - let max = (0..k).fold(0, |acc, t| acc + 9 - t); - let min = (0..k).fold(0, |acc, t| acc + t); - if n < min || n > max { - return vec![]; - } - let mut res = Vec::new(); - let mut seed = Vec::new(); - Solution::helper(n, 0, k, seed, &mut res); - res - } - - fn helper(distance: i32, prev: i32, remain: i32, mut curr: Vec, res: &mut Vec>) { - if remain == 0 { - if distance == 0 { - res.push(curr); - } - return; - } - for i in (prev + 1..=9) { - if distance - i < 0 { - break; - } - let mut new_vec = curr.clone(); - new_vec.push(i); - Solution::helper(distance - i, i, remain - 1, new_vec, res); - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_216() { - assert_eq!( - Solution::combination_sum3(3, 9), - vec![vec![1, 2, 6], vec![1, 3, 5], vec![2, 3, 4]] - ); - } -} diff --git a/src/solution/s0217_contains_duplicate.rs b/src/solution/s0217_contains_duplicate.rs deleted file mode 100644 index 0d2e5e12..00000000 --- a/src/solution/s0217_contains_duplicate.rs +++ /dev/null @@ -1,65 +0,0 @@ -/** - * [217] Contains Duplicate - * - * Given an array of integers, find if the array contains any duplicates. - * - * Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct. - * - * Example 1: - * - * - * Input: [1,2,3,1] - * Output: true - * - * Example 2: - * - * - * Input: [1,2,3,4] - * Output: false - * - * Example 3: - * - * - * Input: [1,1,1,3,3,4,3,2,4,2] - * Output: true - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/contains-duplicate/ -// discuss: https://leetcode.com/problems/contains-duplicate/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn contains_duplicate(nums: Vec) -> bool { - if nums.is_empty() { - return false; - } - let mut nums = nums; - nums.sort_unstable(); - let mut prev = nums[0]; - for i in 1..nums.len() { - if nums[i] == prev { - return true; - } - prev = nums[i] - } - false - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_217() { - assert_eq!(Solution::contains_duplicate(vec![1]), false); - assert_eq!(Solution::contains_duplicate(vec![]), false); - assert_eq!(Solution::contains_duplicate(vec![1, 2, 3, 4]), false); - assert_eq!(Solution::contains_duplicate(vec![1, 2, 3, 1]), true); - } -} diff --git a/src/solution/s0218_the_skyline_problem.rs b/src/solution/s0218_the_skyline_problem.rs deleted file mode 100644 index 7f0ba3c1..00000000 --- a/src/solution/s0218_the_skyline_problem.rs +++ /dev/null @@ -1,46 +0,0 @@ -/** - * [218] The Skyline Problem - * - * A city's skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Now suppose you are given the locations and height of all the buildings as shown on a cityscape photo (Figure A), write a program to output the skyline formed by these buildings collectively (Figure B). - * Buildings Skyline Contour - * - * The geometric information of each building is represented by a triplet of integers [Li, Ri, Hi], where Li and Ri are the x coordinates of the left and right edge of the ith building, respectively, and Hi is its height. It is guaranteed that 0 ≤ Li, Ri ≤ INT_MAX, 0 < Hi ≤ INT_MAX, and Ri - Li > 0. You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0. - * - * For instance, the dimensions of all buildings in Figure A are recorded as: [ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ] . - * - * The output is a list of "key points" (red dots in Figure B) in the format of [ [x1,y1], [x2, y2], [x3, y3], ... ] that uniquely defines a skyline. A key point is the left endpoint of a horizontal line segment. Note that the last key point, where the rightmost building ends, is merely used to mark the termination of the skyline, and always has zero height. Also, the ground in between any two adjacent buildings should be considered part of the skyline contour. - * - * For instance, the skyline in Figure B should be represented as:[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ]. - * - * Notes: - * - * - * The number of buildings in any input list is guaranteed to be in the range [0, 10000]. - * The input list is already sorted in ascending order by the left x position Li. - * The output list must be sorted by the x position. - * There must be no consecutive horizontal lines of equal height in the output skyline. For instance, [...[2 3], [4 5], [7 5], [11 5], [12 7]...] is not acceptable; the three lines of height 5 should be merged into one in the final output as such: [...[2 3], [4 5], [12 7], ...] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/the-skyline-problem/ -// discuss: https://leetcode.com/problems/the-skyline-problem/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn get_skyline(buildings: Vec>) -> Vec> { - vec![] - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_218() {} -} diff --git a/src/solution/s0219_contains_duplicate_ii.rs b/src/solution/s0219_contains_duplicate_ii.rs deleted file mode 100644 index da446dae..00000000 --- a/src/solution/s0219_contains_duplicate_ii.rs +++ /dev/null @@ -1,79 +0,0 @@ -/** - * [219] Contains Duplicate II - * - * Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k. - * - *
- * Example 1: - * - * - * Input: nums = [1,2,3,1], k = 3 - * Output: true - * - * - *
- * Example 2: - * - * - * Input: nums = [1,0,1,1], k = 1 - * Output: true - * - * - *
- * Example 3: - * - * - * Input: nums = [1,2,3,1,2,3], k = 2 - * Output: false - * - *
- *
- *
- * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/contains-duplicate-ii/ -// discuss: https://leetcode.com/problems/contains-duplicate-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::collections::HashMap; -impl Solution { - pub fn contains_nearby_duplicate(nums: Vec, k: i32) -> bool { - let mut map = HashMap::new(); - for (idx, &num) in nums.iter().enumerate() { - match map.get(&num) { - Some(v) => { - if idx - v <= k as usize { - return true; - } - map.insert(num, idx); - } - None => { - map.insert(num, idx); - } - } - } - false - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_219() { - assert_eq!( - Solution::contains_nearby_duplicate(vec![1, 2, 3, 1, 2, 3], 2), - false - ); - assert_eq!( - Solution::contains_nearby_duplicate(vec![1, 2, 3, 1, 2, 3], 3), - true - ); - } -} diff --git a/src/solution/s0220_contains_duplicate_iii.rs b/src/solution/s0220_contains_duplicate_iii.rs deleted file mode 100644 index 0677b1d3..00000000 --- a/src/solution/s0220_contains_duplicate_iii.rs +++ /dev/null @@ -1,87 +0,0 @@ -/** - * [220] Contains Duplicate III - * - * Given an array of integers, find out whether there are two distinct indices i and j in the array such that the absolute difference between nums[i] and nums[j] is at most t and the absolute difference between i and j is at most k. - * - *
- * Example 1: - * - * - * Input: nums = [1,2,3,1], k = 3, t = 0 - * Output: true - * - * - *
- * Example 2: - * - * - * Input: nums = [1,0,1,1], k = 1, t = 2 - * Output: true - * - * - *
- * Example 3: - * - * - * Input: nums = [1,5,9,1,5,9], k = 2, t = 3 - * Output: false - * - *
- *
- *
- * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/contains-duplicate-iii/ -// discuss: https://leetcode.com/problems/contains-duplicate-iii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here -use std::collections::HashMap; -impl Solution { - pub fn contains_nearby_almost_duplicate(nums: Vec, k: i32, t: i32) -> bool { - if k < 1 || t < 0 { - return false; - } - let mut map = HashMap::new(); - for i in 0..nums.len() { - let remap = nums[i] as i64 - i32::min_value() as i64; - let bucket = remap / (t as i64 + 1); - println!("{} {}", remap, bucket); - if map.contains_key(&bucket) - || map - .get(&(bucket - 1)) - .map_or(false, |v| remap - v <= t as i64) - || map - .get(&(bucket + 1)) - .map_or(false, |v| v - remap <= t as i64) - { - return true; - } - if i >= k as usize { - let last_bucket = - (nums[i - k as usize] as i64 - i32::min_value() as i64) / (t as i64 + 1); - map.remove(&last_bucket); - } - map.insert(bucket, remap); - } - false - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_220() { - // assert_eq!(Solution::contains_nearby_almost_duplicate(vec![1,5,9,1,5,9], 2, 3), false); - // assert_eq!(Solution::contains_nearby_almost_duplicate(vec![1,2,3,1], 3, 0), true); - assert_eq!( - Solution::contains_nearby_almost_duplicate(vec![-1, 2147483647], 1, 2147483647), - false - ); - } -} diff --git a/src/solution/s0221_maximal_square.rs b/src/solution/s0221_maximal_square.rs deleted file mode 100644 index 34f793ac..00000000 --- a/src/solution/s0221_maximal_square.rs +++ /dev/null @@ -1,84 +0,0 @@ -/** - * [221] Maximal Square - * - * Given a 2D binary matrix filled with 0's and 1's, find the largest square containing only 1's and return its area. - * - * Example: - * - * - * Input: - * - * 1 0 1 0 0 - * 1 0 1 1 1 - * 1 1 1 1 1 - * 1 0 0 1 0 - * - * Output: 4 - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/maximal-square/ -// discuss: https://leetcode.com/problems/maximal-square/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -DP, f(i, j) to represent the max square of matrix that end with (i, j) (right bottom corener), then: - -f(0, 0) = matrix[0][0] -f(i, j) = if matrix[0][0] { min(f(i-1,j), f(i,j-1), f(i-1)(j-1)) + 1 } else { 0 } - -The equation explained: - -matrix: dp: -1 1 1 1 1 1 -1 1 1 -> 1 2 2 -1 1 1 1 2 3 -*/ -impl Solution { - pub fn maximal_square(matrix: Vec>) -> i32 { - if matrix.is_empty() || matrix[0].is_empty() { - return 0; - } - let (height, width) = (matrix.len(), matrix[0].len()); - let mut dp = vec![vec![0; width]; height]; - let mut max = 0; - for i in 0..height { - for j in 0..width { - if matrix[i][j] == '0' { - continue; - } - dp[i][j] = i32::min( - i32::min( - if i < 1 { 0 } else { dp[i - 1][j] }, - if j < 1 { 0 } else { dp[i][j - 1] }, - ), - if i < 1 || j < 1 { 0 } else { dp[i - 1][j - 1] }, - ) + 1; - max = i32::max(max, dp[i][j]) - } - } - max * max - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_221() { - assert_eq!( - Solution::maximal_square(vec![ - vec!['1', '0', '1', '0', '0'], - vec!['1', '0', '1', '1', '1'], - vec!['1', '1', '1', '1', '1'], - vec!['1', '0', '0', '1', '0'], - ]), - 4 - ) - } -} diff --git a/src/solution/s0222_count_complete_tree_nodes.rs b/src/solution/s0222_count_complete_tree_nodes.rs deleted file mode 100644 index ae0d410b..00000000 --- a/src/solution/s0222_count_complete_tree_nodes.rs +++ /dev/null @@ -1,88 +0,0 @@ -/** - * [222] Count Complete Tree Nodes - * - * Given a complete binary tree, count the number of nodes. - * - * Note: - * - * Definition of a complete binary tree from Wikipedia:
- * In a complete binary tree every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between 1 and 2^h nodes inclusive at the last level h. - * - * Example: - * - * - * Input: - * 1 - * / \ - * 2 3 - * / \ / - * 4 5 6 - * - * Output: 6 - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/count-complete-tree-nodes/ -// discuss: https://leetcode.com/problems/count-complete-tree-nodes/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn count_nodes(root: Option>>) -> i32 { - // 0. get the hight of full nodes - let mut height = 0; - let mut curr = root.clone(); - let mut result = 0; - while let Some(inner) = curr { - height += 1; - result += 2_i32.pow(height - 1); - curr = inner.borrow().right.clone(); - } - if height == 0 { - return result; - } - // 1. 'binary search' to find the node number of the lowest level - // the lowest level may have 0~2^H-1 node - let mut curr_root = root.clone(); - while height > 1 { - // see if left tree is full - let mut node = curr_root.clone().unwrap().borrow().left.clone(); - let mut level = 2; - while level < height { - node = node.unwrap().borrow().right.clone(); - level += 1; - } - if node.unwrap().borrow().right.is_some() { - curr_root = curr_root.unwrap().borrow().right.clone(); - result += 2_i32.pow(height - 1); - } else { - curr_root = curr_root.unwrap().borrow().left.clone(); - } - height -= 1; - } - if curr_root.as_ref().unwrap().borrow().left.is_some() { - result += 1; - } - result - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_222() { - assert_eq!(Solution::count_nodes(tree![1, 1, 1, 1, 1, 1, 1]), 7); - assert_eq!(Solution::count_nodes(tree![]), 0); - assert_eq!(Solution::count_nodes(tree![1, 1]), 2); - assert_eq!(Solution::count_nodes(tree![1]), 1); - assert_eq!(Solution::count_nodes(tree![1, 1, 1]), 3); - } -} diff --git a/src/solution/s0223_rectangle_area.rs b/src/solution/s0223_rectangle_area.rs deleted file mode 100644 index 647b6b2a..00000000 --- a/src/solution/s0223_rectangle_area.rs +++ /dev/null @@ -1,62 +0,0 @@ -/** - * [223] Rectangle Area - * - * Find the total area covered by two rectilinear rectangles in a 2D plane. - * - * Each rectangle is defined by its bottom left corner and top right corner as shown in the figure. - * - * Rectangle Area - * - * Example: - * - * - * Input: A = -3, B = 0, C = 3, D = 4, E = 0, F = -1, G = 9, H = 2 - * Output: 45 - * - * Note: - * - * Assume that the total area is never beyond the maximum possible value of int. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/rectangle-area/ -// discuss: https://leetcode.com/problems/rectangle-area/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// mention the integer divition -impl Solution { - pub fn compute_area(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32, h: i32) -> i32 { - let center1 = ((a + c), (b + d)); - let center2 = ((e + g), (f + h)); - let rect1 = (c - a, d - b); - let rect2 = (g - e, h - f); - let x_intersect = i32::min( - (rect1.0 + rect2.0 - (center1.0 - center2.0).abs()), - i32::min(2 * rect1.0, 2 * rect2.0), - ) / 2; - let x_intersect = if x_intersect < 0 { 0 } else { x_intersect }; - let y_intersect = i32::min( - (rect1.1 + rect2.1 - (center1.1 - center2.1).abs()), - i32::min(2 * rect1.1, 2 * rect2.1), - ) / 2; - let y_intersect = if y_intersect < 0 { 0 } else { y_intersect }; - rect1.0 * rect1.1 - x_intersect * y_intersect + rect2.0 * rect2.1 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_223() { - assert_eq!(Solution::compute_area(0, 0, 0, 0, 0, 0, 0, 0), 0); - assert_eq!(Solution::compute_area(-3, 0, 3, 4, 0, -1, 9, 2), 45); - assert_eq!(Solution::compute_area(-2, -2, 2, 2, -2, -2, 2, 2), 16); - assert_eq!(Solution::compute_area(-2, -2, 2, 2, -1, 4, 1, 6), 20); - } -} diff --git a/src/solution/s0224_basic_calculator.rs b/src/solution/s0224_basic_calculator.rs deleted file mode 100644 index 5d917661..00000000 --- a/src/solution/s0224_basic_calculator.rs +++ /dev/null @@ -1,156 +0,0 @@ -/** - * [224] Basic Calculator - * - * Implement a basic calculator to evaluate a simple expression string. - * - * The expression string may contain open ( and closing parentheses ), the plus + or minus sign -, non-negative integers and empty spaces . - * - * Example 1: - * - * - * Input: "1 + 1" - * Output: 2 - * - * - * Example 2: - * - * - * Input: " 2-1 + 2 " - * Output: 3 - * - * Example 3: - * - * - * Input: "(1+(4+5+2)-3)+(6+8)" - * Output: 23 - * Note: - * - * - * You may assume that the given expression is always valid. - * Do not use the eval built-in library function. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/basic-calculator/ -// discuss: https://leetcode.com/problems/basic-calculator/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -#[derive(PartialEq, Copy, Clone, Debug)] -enum Token { - LeftBracket, - RightBracket, - PlusSign, - MinusSign, - Number(i64), -} - -impl Solution { - pub fn calculate(s: String) -> i32 { - // lexer - let mut token_stream = Vec::new(); - let mut num = 0_i64; - let mut in_num = false; - for ch in s.chars() { - match ch { - '0'..='9' => { - in_num = true; - num = 10 * num + (ch as u8 - '0' as u8) as i64; - } - _ => { - if in_num { - token_stream.push(Token::Number(num)); - num = 0; - in_num = false; - } - match ch { - '(' => { - token_stream.push(Token::LeftBracket); - } - ')' => { - token_stream.push(Token::RightBracket); - } - '+' => { - token_stream.push(Token::PlusSign); - } - '-' => { - token_stream.push(Token::MinusSign); - } - _ => {} - }; - } - } - } - if in_num { - token_stream.push(Token::Number(num)); - } - - // parser - let mut stack = Vec::new(); - let mut iter = token_stream.into_iter(); - let mut pause = false; - let mut token = Token::LeftBracket; - loop { - if !pause { - token = if let Some(token) = iter.next() { - token - } else { - break; - } - } else { - pause = false; - } - match token { - Token::LeftBracket => { - stack.push(token); - } - Token::RightBracket => { - if let Token::Number(right_hand) = stack.pop().unwrap() { - stack.pop(); - pause = true; - token = Token::Number(right_hand); - } - } - Token::PlusSign => { - stack.push(token); - } - Token::MinusSign => { - stack.push(token); - } - Token::Number(num) => { - if stack.is_empty() || Token::LeftBracket == *stack.last().unwrap() { - stack.push(Token::Number(num)); - } else { - let sign = stack.pop().unwrap(); - if let Token::Number(left_hand) = stack.pop().unwrap() { - let res = - left_hand + num * if Token::PlusSign == sign { 1 } else { -1 }; - stack.push(Token::Number(res)); - } - } - } - } - } - if let Token::Number(num) = stack.pop().unwrap() { - return num as i32; - } - 0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_224() { - assert_eq!(Solution::calculate("(1+(4+5+2)-3)+(6+8)".to_owned()), 23); - assert_eq!(Solution::calculate("1+1".to_owned()), 2); - assert_eq!(Solution::calculate("0".to_owned()), 0); - assert_eq!(Solution::calculate("2147483647".to_owned()), 2147483647); - } -} diff --git a/src/solution/s0225_implement_stack_using_queues.rs b/src/solution/s0225_implement_stack_using_queues.rs deleted file mode 100644 index f162e9a6..00000000 --- a/src/solution/s0225_implement_stack_using_queues.rs +++ /dev/null @@ -1,125 +0,0 @@ -/** - * [225] Implement Stack using Queues - * - * Implement the following operations of a stack using queues. - * - * - * push(x) -- Push element x onto stack. - * pop() -- Removes the element on top of the stack. - * top() -- Get the top element. - * empty() -- Return whether the stack is empty. - * - * - * Example: - * - * - * MyStack stack = new MyStack(); - * - * stack.push(1); - * stack.push(2); - * stack.top(); // returns 2 - * stack.pop(); // returns 2 - * stack.empty(); // returns false - * - * Notes: - * - * - * You must use only standard operations of a queue -- which means only push to back, peek/pop from front, size, and is empty operations are valid. - * Depending on your language, queue may not be supported natively. You may simulate a queue by using a list or deque (double-ended queue), as long as you use only standard operations of a queue. - * You may assume that all operations are valid (for example, no pop or top operations will be called on an empty stack). - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/implement-stack-using-queues/ -// discuss: https://leetcode.com/problems/implement-stack-using-queues/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -struct MyStack { - q1: VecDeque, - q2: VecDeque, -} - -/** - * `&self` means the method takes an immutable reference. - * If you need a mutable reference, change it to `&mut self` instead. - */ -use std::collections::VecDeque; -impl MyStack { - /** Initialize your data structure here. */ - fn new() -> Self { - MyStack { - q1: VecDeque::new(), - q2: VecDeque::new(), - } - } - - /** Push element x onto stack. */ - fn push(&mut self, x: i32) { - if self.q1.is_empty() { - self.q1.push_back(x); - while let Some(v) = self.q2.pop_front() { - self.q1.push_back(v); - } - } else { - self.q2.push_back(x); - while let Some(v) = self.q1.pop_front() { - self.q2.push_back(v); - } - } - } - - /** Removes the element on top of the stack and returns that element. */ - fn pop(&mut self) -> i32 { - if self.q1.is_empty() { - self.q2.pop_front().unwrap() - } else { - self.q1.pop_front().unwrap() - } - } - - /** Get the top element. */ - fn top(&self) -> i32 { - if self.q1.is_empty() { - *self.q2.front().unwrap() - } else { - *self.q1.front().unwrap() - } - } - - /** Returns whether the stack is empty. */ - fn empty(&self) -> bool { - self.q1.is_empty() && self.q2.is_empty() - } -} - -/** - * Your MyStack object will be instantiated and called as such: - * let obj = MyStack::new(); - * obj.push(x); - * let ret_2: i32 = obj.pop(); - * let ret_3: i32 = obj.top(); - * let ret_4: bool = obj.empty(); - */ - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_225() { - let mut stack = MyStack::new(); - - stack.push(1); - stack.push(2); - assert_eq!(stack.top(), 2); // returns 2 - assert_eq!(stack.pop(), 2); // returns 2 - assert_eq!(stack.empty(), false); // returns false - assert_eq!(stack.pop(), 1); - assert_eq!(stack.empty(), true); - } -} diff --git a/src/solution/s0226_invert_binary_tree.rs b/src/solution/s0226_invert_binary_tree.rs deleted file mode 100644 index 1a1b6115..00000000 --- a/src/solution/s0226_invert_binary_tree.rs +++ /dev/null @@ -1,69 +0,0 @@ -/** - * [226] Invert Binary Tree - * - * Invert a binary tree. - * - * Example: - * - * Input: - * - * - * 4 - * / \ - * 2 7 - * / \ / \ - * 1 3 6 9 - * - * Output: - * - * - * 4 - * / \ - * 7 2 - * / \ / \ - * 9 6 3 1 - * - * Trivia:
- * This problem was inspired by this original tweet by Max Howell: - * - *
Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so f*** off.
- * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/invert-binary-tree/ -// discuss: https://leetcode.com/problems/invert-binary-tree/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn invert_tree(root: Option>>) -> Option>> { - if let Some(node) = root.clone() { - Solution::invert_tree(node.borrow().right.clone()); - Solution::invert_tree(node.borrow().left.clone()); - let left = node.borrow().left.clone(); - let right = node.borrow().right.clone(); - node.borrow_mut().left = right; - node.borrow_mut().right = left; - } - root - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_226() { - assert_eq!( - Solution::invert_tree(tree![4, 2, 7, 1, 3, 6, 9]), - tree![4, 7, 2, 9, 6, 3, 1] - ); - } -} diff --git a/src/solution/s0227_basic_calculator_ii.rs b/src/solution/s0227_basic_calculator_ii.rs deleted file mode 100644 index 07e349dd..00000000 --- a/src/solution/s0227_basic_calculator_ii.rs +++ /dev/null @@ -1,107 +0,0 @@ -/** - * [227] Basic Calculator II - * - * Implement a basic calculator to evaluate a simple expression string. - * - * The expression string contains only non-negative integers, +, -, *, / operators and empty spaces . The integer division should truncate toward zero. - * - * Example 1: - * - * - * Input: "3+2*2" - * Output: 7 - * - * - * Example 2: - * - * - * Input: " 3/2 " - * Output: 1 - * - * Example 3: - * - * - * Input: " 3+5 / 2 " - * Output: 5 - * - * - * Note: - * - * - * You may assume that the given expression is always valid. - * Do not use the eval built-in library function. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/basic-calculator-ii/ -// discuss: https://leetcode.com/problems/basic-calculator-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn calculate(s: String) -> i32 { - let mut acc = 0_i64; - let mut prev = 0_i64; - let mut curr = 0_i64; - let mut sign = 1; - let mut has_prev = false; - let mut multiple = true; - for ch in s.chars() { - match ch { - '0'..='9' => { - curr = 10 * curr + (ch as u8 - '0' as u8) as i64; - } - '+' | '-' => { - if has_prev { - if multiple { - curr = prev * curr; - } else { - curr = prev / curr; - } - has_prev = false; - } - acc += curr * sign; - curr = 0; - sign = if ch == '+' { 1 } else { -1 }; - } - '*' | '/' => { - if has_prev { - if multiple { - curr = prev * curr; - } else { - curr = prev / curr; - } - } - has_prev = true; - prev = curr; - curr = 0; - multiple = if ch == '*' { true } else { false }; - } - _ => {} - } - } - if has_prev { - if multiple { - curr = prev * curr; - } else { - curr = prev / curr; - } - } - acc += sign * curr; - acc as i32 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_227() { - assert_eq!(Solution::calculate("3+2*2".to_owned()), 7); - } -} diff --git a/src/solution/s0228_summary_ranges.rs b/src/solution/s0228_summary_ranges.rs deleted file mode 100644 index 63e8fe77..00000000 --- a/src/solution/s0228_summary_ranges.rs +++ /dev/null @@ -1,74 +0,0 @@ -/** - * [228] Summary Ranges - * - * Given a sorted integer array without duplicates, return the summary of its ranges. - * - * Example 1: - * - * - * Input: [0,1,2,4,5,7] - * Output: ["0->2","4->5","7"] - * Explanation: 0,1,2 form a continuous range; 4,5 form a continuous range. - * - * - * Example 2: - * - * - * Input: [0,2,3,4,6,8,9] - * Output: ["0","2->4","6","8->9"] - * Explanation: 2,3,4 form a continuous range; 8,9 form a continuous range. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/summary-ranges/ -// discuss: https://leetcode.com/problems/summary-ranges/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn summary_ranges(nums: Vec) -> Vec { - if nums.is_empty() { - return vec![]; - } - let mut res = Vec::new(); - let mut curr = nums[0]; - let mut start = nums[0]; - for num in nums.into_iter().skip(1) { - if num == curr + 1 { - curr = num; - } else { - // seq done - Solution::record(&mut res, start, curr); - start = num; - curr = num; - } - } - Solution::record(&mut res, start, curr); - res - } - - pub fn record(vec: &mut Vec, start: i32, end: i32) { - if start == end { - vec.push(format!("{}", start)) - } else { - vec.push(format!("{}->{}", start, end)) - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_228() { - assert_eq!( - Solution::summary_ranges(vec![0, 1, 2, 3, 4, 5, 6]), - vec_string!["0->6"] - ); - } -} diff --git a/src/solution/s0229_majority_element_ii.rs b/src/solution/s0229_majority_element_ii.rs deleted file mode 100644 index fab987ba..00000000 --- a/src/solution/s0229_majority_element_ii.rs +++ /dev/null @@ -1,87 +0,0 @@ -/** - * [229] Majority Element II - * - * Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. - * - * Note: The algorithm should run in linear time and in O(1) space. - * - * Example 1: - * - * - * Input: [3,2,3] - * Output: [3] - * - * Example 2: - * - * - * Input: [1,1,1,3,3,2,2,2] - * Output: [1,2] - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/majority-element-ii/ -// discuss: https://leetcode.com/problems/majority-element-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn majority_element(nums: Vec) -> Vec { - if nums.is_empty() { - return vec![]; - } - let (mut vote0, mut vote1, mut candidate0, mut candidate1) = (0, 0, -1, -2); - for &num in nums.iter() { - if num == candidate0 { - vote0 += 1; - } else if num == candidate1 { - vote1 += 1; - } else if vote0 == 0 { - candidate0 = num; - vote0 = 1; - } else if vote1 == 0 { - candidate1 = num; - vote1 = 1; - } else { - vote0 -= 1; - vote1 -= 1; - } - } - // the presents of majority element is not guaranteed, we have to do a double check - let mut res = Vec::new(); - for &v in vec![candidate0, candidate1].iter() { - let mut count = 0; - for &num in nums.iter() { - if v == num { - count += 1; - } - } - if count > (nums.len() / 3) as i32 { - res.push(v); - } - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_229() { - assert_eq!( - Solution::majority_element(vec![1, 1, 1, 2, 2, 2, 3, 3, 3]), - vec![] - ); - assert_eq!( - Solution::majority_element(vec![1, 1, 1, 2, 2, 3, 3, 3]), - vec![1, 3] - ); - assert_eq!(Solution::majority_element(vec![1]), vec![1]); - assert_eq!(Solution::majority_element(vec![5, 6, 6]), vec![6]); - assert_eq!(Solution::majority_element(vec![1, 2, 3, 4]), vec![]); - } -} diff --git a/src/solution/s0230_kth_smallest_element_in_a_bst.rs b/src/solution/s0230_kth_smallest_element_in_a_bst.rs deleted file mode 100644 index 0533f705..00000000 --- a/src/solution/s0230_kth_smallest_element_in_a_bst.rs +++ /dev/null @@ -1,84 +0,0 @@ -/** - * [230] Kth Smallest Element in a BST - * - * Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. - * - * Note:
- * You may assume k is always valid, 1 ≤ k ≤ BST's total elements. - * - * Example 1: - * - * - * Input: root = [3,1,4,null,2], k = 1 - * 3 - * / \ - * 1 4 - * \ - * 2 - * Output: 1 - * - * Example 2: - * - * - * Input: root = [5,3,6,2,4,null,null,1], k = 3 - * 5 - * / \ - * 3 6 - * / \ - * 2 4 - * / - * 1 - * Output: 3 - * - * - * Follow up:
- * What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine? - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/kth-smallest-element-in-a-bst/ -// discuss: https://leetcode.com/problems/kth-smallest-element-in-a-bst/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn kth_smallest(root: Option>>, k: i32) -> i32 { - let mut res = 0; - Solution::helper(root, k, &mut res); - res - } - - pub fn helper(root: Option>>, k: i32, res: &mut i32) -> i32 { - if k <= 0 { - return 0; - } - if let Some(node) = root { - let left = Solution::helper(node.borrow().left.clone(), k, res); - if left == 1 { - *res = node.borrow().val; - } - let right = Solution::helper(node.borrow().right.clone(), left - 1, res); - right - } else { - k - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_230() { - assert_eq!(Solution::kth_smallest(tree![3, 1, 4, null, 2], 1), 1); - assert_eq!(Solution::kth_smallest(tree![3, 1, 4, null, 2], 2), 2); - assert_eq!(Solution::kth_smallest(tree![3, 1, 4, null, 2], 3), 3); - } -} diff --git a/src/solution/s0231_power_of_two.rs b/src/solution/s0231_power_of_two.rs deleted file mode 100644 index 334fc314..00000000 --- a/src/solution/s0231_power_of_two.rs +++ /dev/null @@ -1,54 +0,0 @@ -/** - * [231] Power of Two - * - * Given an integer, write a function to determine if it is a power of two. - * - * Example 1: - * - * - * Input: 1 - * Output: true - * Explanation: 2^0 = 1 - * - * - * Example 2: - * - * - * Input: 16 - * Output: true - * Explanation: 2^4 = 16 - * - * Example 3: - * - * - * Input: 218 - * Output: false - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/power-of-two/ -// discuss: https://leetcode.com/problems/power-of-two/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn is_power_of_two(n: i32) -> bool { - let results: Vec = (0..31).map(|x| 2_i32.pow(x)).collect(); - results.binary_search(&n).is_ok() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_231() { - assert_eq!(Solution::is_power_of_two(-1), false); - assert_eq!(Solution::is_power_of_two(1), true); - assert_eq!(Solution::is_power_of_two(1024), true); - } -} diff --git a/src/solution/s0232_implement_queue_using_stacks.rs b/src/solution/s0232_implement_queue_using_stacks.rs deleted file mode 100644 index 70bf3735..00000000 --- a/src/solution/s0232_implement_queue_using_stacks.rs +++ /dev/null @@ -1,110 +0,0 @@ -/** - * [232] Implement Queue using Stacks - * - * Implement the following operations of a queue using stacks. - * - * - * push(x) -- Push element x to the back of queue. - * pop() -- Removes the element from in front of queue. - * peek() -- Get the front element. - * empty() -- Return whether the queue is empty. - * - * - * Example: - * - * - * MyQueue queue = new MyQueue(); - * - * queue.push(1); - * queue.push(2); - * queue.peek(); // returns 1 - * queue.pop(); // returns 1 - * queue.empty(); // returns false - * - * Notes: - * - * - * You must use only standard operations of a stack -- which means only push to top, peek/pop from top, size, and is empty operations are valid. - * Depending on your language, stack may not be supported natively. You may simulate a stack by using a list or deque (double-ended queue), as long as you use only standard operations of a stack. - * You may assume that all operations are valid (for example, no pop or peek operations will be called on an empty queue). - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/implement-queue-using-stacks/ -// discuss: https://leetcode.com/problems/implement-queue-using-stacks/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -struct MyQueue { - vec1: Vec, - vec2: Vec, -} - -/** - * `&self` means the method takes an immutable reference. - * If you need a mutable reference, change it to `&mut self` instead. - */ -impl MyQueue { - /** Initialize your data structure here. */ - fn new() -> Self { - MyQueue { - vec1: Vec::new(), - vec2: Vec::new(), - } - } - - /** Push element x to the back of queue. */ - fn push(&mut self, x: i32) { - while let Some(v) = self.vec1.pop() { - self.vec2.push(v); - } - self.vec2.push(x); - while let Some(v) = self.vec2.pop() { - self.vec1.push(v); - } - } - - /** Removes the element from in front of queue and returns that element. */ - fn pop(&mut self) -> i32 { - self.vec1.pop().unwrap() - } - - /** Get the front element. */ - fn peek(&self) -> i32 { - *self.vec1.last().unwrap() - } - - /** Returns whether the queue is empty. */ - fn empty(&self) -> bool { - self.vec1.is_empty() - } -} - -/** - * Your MyQueue object will be instantiated and called as such: - * let obj = MyQueue::new(); - * obj.push(x); - * let ret_2: i32 = obj.pop(); - * let ret_3: i32 = obj.peek(); - * let ret_4: bool = obj.empty(); - */ - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_232() { - let mut queue = MyQueue::new(); - - queue.push(1); - queue.push(2); - assert_eq!(queue.peek(), 1); // returns 1 - assert_eq!(queue.pop(), 1); // returns 1 - assert_eq!(queue.empty(), false); // returns false - } -} diff --git a/src/solution/s0233_number_of_digit_one.rs b/src/solution/s0233_number_of_digit_one.rs deleted file mode 100644 index 60097ed0..00000000 --- a/src/solution/s0233_number_of_digit_one.rs +++ /dev/null @@ -1,36 +0,0 @@ -/** - * [233] Number of Digit One - * - * Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n. - * - * Example: - * - * - * Input: 13 - * Output: 6 - * Explanation: Digit 1 occurred in the following numbers: 1, 10, 11, 12, 13. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/number-of-digit-one/ -// discuss: https://leetcode.com/problems/number-of-digit-one/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn count_digit_one(n: i32) -> i32 { - 0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_233() {} -} diff --git a/src/solution/s0238_product_of_array_except_self.rs b/src/solution/s0238_product_of_array_except_self.rs deleted file mode 100644 index ef5683c4..00000000 --- a/src/solution/s0238_product_of_array_except_self.rs +++ /dev/null @@ -1,65 +0,0 @@ -/** - * [238] Product of Array Except Self - * - * Given an array nums of n integers where n > 1, return an array output such that output[i] is equal to the product of all the elements of nums except nums[i]. - * - * Example: - * - * - * Input: [1,2,3,4] - * Output: [24,12,8,6] - * - * - * Note: Please solve it without division and in O(n). - * - * Follow up:
- * Could you solve it with constant space complexity? (The output array does not count as extra space for the purpose of space complexity analysis.) - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/product-of-array-except-self/ -// discuss: https://leetcode.com/problems/product-of-array-except-self/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -x 2 3 4 = 24 -1 x 3 4 = 12 -1 2 x 4 = 8 -1 2 3 x = 6 - */ -impl Solution { - pub fn product_except_self(nums: Vec) -> Vec { - if nums.len() < 2 { - return vec![]; - } - let mut res = vec![1; nums.len()]; - let mut n = 1; - for i in (0..nums.len() - 1).rev() { - n *= nums[i + 1]; - res[i] = n; - } - n = 1; - for i in 1..nums.len() { - n *= nums[i - 1]; - res[i] *= n; - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_238() { - assert_eq!( - Solution::product_except_self(vec![1, 2, 3, 4]), - vec![24, 12, 8, 6] - ); - } -} diff --git a/src/solution/s0239_sliding_window_maximum.rs b/src/solution/s0239_sliding_window_maximum.rs deleted file mode 100644 index f7509cb9..00000000 --- a/src/solution/s0239_sliding_window_maximum.rs +++ /dev/null @@ -1,95 +0,0 @@ -/** - * [239] Sliding Window Maximum - * - * Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Return the max sliding window. - * - * Example: - * - * - * Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3 - * Output: [3,3,5,5,6,7] - * Explanation: - * - * Window position Max - * --------------- ----- - * [1 3 -1] -3 5 3 6 7 3 - * 1 [3 -1 -3] 5 3 6 7 3 - * 1 3 [-1 -3 5] 3 6 7 5 - * 1 3 -1 [-3 5 3] 6 7 5 - * 1 3 -1 -3 [5 3 6] 7 6 - * 1 3 -1 -3 5 [3 6 7] 7 - * - * - * Note:
- * You may assume k is always valid, 1 ≤ k ≤ input array's size for non-empty array. - * - * Follow up:
- * Could you solve it in linear time? - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/sliding-window-maximum/ -// discuss: https://leetcode.com/problems/sliding-window-maximum/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::collections::VecDeque; -impl Solution { - pub fn max_sliding_window(nums: Vec, k: i32) -> Vec { - let mut deq: VecDeque<(usize, i32)> = VecDeque::new(); - let mut res = Vec::new(); - for i in 0..nums.len() { - // maintain sliding window - if !deq.is_empty() && (*deq.front().unwrap()).0 as i32 <= (i as i32) - k { - deq.pop_front(); - let mut max = i32::min_value(); - let mut count = 0_usize; - for (j, &v) in deq.iter().enumerate() { - if v.1 >= max { - max = v.1; - count = j; - } - } - for _ in 0..count { - deq.pop_front(); - } - } - let num = nums[i]; - if !deq.is_empty() && (*deq.front().unwrap()).1 <= num { - while !deq.is_empty() { - deq.pop_front(); - } - } - deq.push_back((i, num)); - if i + 1 >= k as usize { - res.push((*deq.front().unwrap()).1); - } - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_239() { - assert_eq!( - Solution::max_sliding_window(vec![9, 10, 9, -7, -4, -8, 2, -6], 5), - vec![10, 10, 9, 2] - ); - assert_eq!( - Solution::max_sliding_window(vec![1, 3, 1, 2, 0, 5], 3), - vec![3, 3, 2, 5] - ); - assert_eq!(Solution::max_sliding_window(vec![7, 2, 4], 2), vec![7, 4]); - assert_eq!(Solution::max_sliding_window(vec![1, -1], 1), vec![1, -1]); - assert_eq!( - Solution::max_sliding_window(vec![1, 3, -1, -3, 5, 3, 6, 7], 3), - vec![3, 3, 5, 5, 6, 7] - ); - } -} diff --git a/src/solution/s0241_different_ways_to_add_parentheses.rs b/src/solution/s0241_different_ways_to_add_parentheses.rs deleted file mode 100644 index a76bfa6a..00000000 --- a/src/solution/s0241_different_ways_to_add_parentheses.rs +++ /dev/null @@ -1,81 +0,0 @@ -/** - * [241] Different Ways to Add Parentheses - * - * Given a string of numbers and operators, return all possible results from computing all the different possible ways to group numbers and operators. The valid operators are +, - and *. - * - * Example 1: - * - * - * Input: "2-1-1" - * Output: [0, 2] - * Explanation: - * ((2-1)-1) = 0 - * (2-(1-1)) = 2 - * - * Example 2: - * - * - * Input: "2*3-4*5" - * Output: [-34, -14, -10, -10, 10] - * Explanation: - * (2*(3-(4*5))) = -34 - * ((2*3)-(4*5)) = -14 - * ((2*(3-4))*5) = -10 - * (2*((3-4)*5)) = -10 - * (((2*3)-4)*5) = 10 - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/different-ways-to-add-parentheses/ -// discuss: https://leetcode.com/problems/different-ways-to-add-parentheses/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn diff_ways_to_compute(input: String) -> Vec { - Solution::helper(&input) - } - - pub fn helper(input: &str) -> Vec { - if input.is_empty() { - return vec![]; - } - if let Ok(digit) = input.parse::() { - return vec![digit]; - } - let mut res: Vec = Vec::new(); - for (i, ch) in input.chars().enumerate() { - if ch == '+' || ch == '-' || ch == '*' { - let left = Solution::helper(&input[..i]); - let right = Solution::helper(&input[i + 1..]); - for &a in left.iter() { - for &b in right.iter() { - res.push(match ch { - '+' => a + b, - '-' => a - b, - '*' => a * b, - _ => unreachable!(), - }) - } - } - } - } - res - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_241() { - assert_eq!( - Solution::diff_ways_to_compute("2*3-4*5".to_owned()), - vec![-34, -10, -14, -10, 10] - ); - } -} diff --git a/src/solution/s0242_valid_anagram.rs b/src/solution/s0242_valid_anagram.rs deleted file mode 100644 index ba7a58ae..00000000 --- a/src/solution/s0242_valid_anagram.rs +++ /dev/null @@ -1,61 +0,0 @@ -/** - * [242] Valid Anagram - * - * Given two strings s and t , write a function to determine if t is an anagram of s. - * - * Example 1: - * - * - * Input: s = "anagram", t = "nagaram" - * Output: true - * - * - * Example 2: - * - * - * Input: s = "rat", t = "car" - * Output: false - * - * - * Note:
- * You may assume the string contains only lowercase alphabets. - * - * Follow up:
- * What if the inputs contain unicode characters? How would you adapt your solution to such case? - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/valid-anagram/ -// discuss: https://leetcode.com/problems/valid-anagram/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn is_anagram(s: String, t: String) -> bool { - Solution::hit(s) == Solution::hit(t) - } - - fn hit(s: String) -> Vec { - let mut hit = vec![0; 27]; - for ch in s.chars() { - hit[(ch as u8 - 'a' as u8) as usize] += 1; - } - hit - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_242() { - assert_eq!( - Solution::is_anagram("anagram".to_owned(), "nagaram".to_owned()), - true - ); - } -} diff --git a/src/solution/s0257_binary_tree_paths.rs b/src/solution/s0257_binary_tree_paths.rs deleted file mode 100644 index 6c7833e2..00000000 --- a/src/solution/s0257_binary_tree_paths.rs +++ /dev/null @@ -1,85 +0,0 @@ -/** - * [257] Binary Tree Paths - * - * Given a binary tree, return all root-to-leaf paths. - * - * Note: A leaf is a node with no children. - * - * Example: - * - * - * Input: - * - * 1 - * / \ - * 2 3 - * \ - * 5 - * - * Output: ["1->2->5", "1->3"] - * - * Explanation: All root-to-leaf paths are: 1->2->5, 1->3 - * - */ -pub struct Solution {} -use crate::util::tree::{to_tree, TreeNode}; - -// problem: https://leetcode.com/problems/binary-tree-paths/ -// discuss: https://leetcode.com/problems/binary-tree-paths/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// Definition for a binary tree node. -// #[derive(Debug, PartialEq, Eq)] -// pub struct TreeNode { -// pub val: i32, -// pub left: Option>>, -// pub right: Option>>, -// } -// -// impl TreeNode { -// #[inline] -// pub fn new(val: i32) -> Self { -// TreeNode { -// val, -// left: None, -// right: None -// } -// } -// } -use std::cell::RefCell; -use std::rc::Rc; -impl Solution { - pub fn binary_tree_paths(root: Option>>) -> Vec { - let mut res = Vec::new(); - Solution::helper(root, "".to_owned(), &mut res); - res - } - - fn helper(root: Option>>, path: String, res: &mut Vec) { - if let Some(inner) = root { - if inner.borrow().left.is_none() && inner.borrow().right.is_none() { - res.push(format!("{}{}", path, inner.borrow().val)); - } else { - let path = format!("{}{}->", path, inner.borrow().val); - Solution::helper(inner.borrow().left.clone(), path.clone(), res); - Solution::helper(inner.borrow().right.clone(), path, res); - } - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_257() { - assert_eq!( - Solution::binary_tree_paths(tree![1, 2, 3, null, 5]), - vec_string!["1->2->5", "1->3"] - ); - } -} diff --git a/src/solution/s0258_add_digits.rs b/src/solution/s0258_add_digits.rs deleted file mode 100644 index 2248be1d..00000000 --- a/src/solution/s0258_add_digits.rs +++ /dev/null @@ -1,41 +0,0 @@ -/** - * [258] Add Digits - * - * Given a non-negative integer num, repeatedly add all its digits until the result has only one digit. - * - * Example: - * - * - * Input: 38 - * Output: 2 - * Explanation: The process is like: 3 + 8 = 11, 1 + 1 = 2. - * Since 2 has only one digit, return it. - * - * - * Follow up:
- * Could you do it without any loop/recursion in O(1) runtime? - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/add-digits/ -// discuss: https://leetcode.com/problems/add-digits/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn add_digits(num: i32) -> i32 { - 1 + ((num - 1) % 9) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_258() { - assert_eq!(Solution::add_digits(1234), 1); - } -} diff --git a/src/solution/s0260_single_number_iii.rs b/src/solution/s0260_single_number_iii.rs deleted file mode 100644 index 09d7a920..00000000 --- a/src/solution/s0260_single_number_iii.rs +++ /dev/null @@ -1,57 +0,0 @@ -/** - * [260] Single Number III - * - * Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once. - * - * Example: - * - * - * Input: [1,2,1,3,2,5] - * Output: [3,5] - * - * Note: - * - *
    - * The order of the result is not important. So in the above example, [5, 3] is also correct. - * Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity? - *
- */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/single-number-iii/ -// discuss: https://leetcode.com/problems/single-number-iii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn single_number(nums: Vec) -> Vec { - let mut res = 0; - for &num in nums.iter() { - res = res ^ num; - } - let right_most_set_bit = res & !(res - 1); - let mut bit_set = 0; - let mut bit_unset = 0; - for &num in nums.iter() { - if num & right_most_set_bit == 0 { - bit_unset = bit_unset ^ num; - } else { - bit_set = bit_set ^ num; - } - } - return vec![bit_set, bit_unset]; - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_260() { - assert_eq!(Solution::single_number(vec![1, 2, 1, 2, 3, 4]), vec![3, 4]); - assert_eq!(Solution::single_number(vec![1, 2, 1, 3, 2, 5]), vec![3, 5]); - } -} diff --git a/src/solution/s0263_ugly_number.rs b/src/solution/s0263_ugly_number.rs deleted file mode 100644 index 9ef3bf57..00000000 --- a/src/solution/s0263_ugly_number.rs +++ /dev/null @@ -1,73 +0,0 @@ -/** - * [263] Ugly Number - * - * Write a program to check whether a given number is an ugly number. - * - * Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. - * - * Example 1: - * - * - * Input: 6 - * Output: true - * Explanation: 6 = 2 × 3 - * - * Example 2: - * - * - * Input: 8 - * Output: true - * Explanation: 8 = 2 × 2 × 2 - * - * - * Example 3: - * - * - * Input: 14 - * Output: false - * Explanation: 14 is not ugly since it includes another prime factor 7. - * - * - * Note: - * - *
    - * 1 is typically treated as an ugly number. - * Input is within the 32-bit signed integer range: [-2^31, 2^31 - 1]. - *
- */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/ugly-number/ -// discuss: https://leetcode.com/problems/ugly-number/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn is_ugly(num: i32) -> bool { - if num <= 0 { - false - } else if num == 1 { - true - } else if num % 5 == 0 { - Solution::is_ugly(num / 5) - } else if num % 3 == 0 { - Solution::is_ugly(num / 3) - } else if num % 2 == 0 { - Solution::is_ugly(num / 2) - } else { - false - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_263() { - assert_eq!(Solution::is_ugly(25), true); - } -} diff --git a/src/solution/s0264_ugly_number_ii.rs b/src/solution/s0264_ugly_number_ii.rs deleted file mode 100644 index 8dda4f01..00000000 --- a/src/solution/s0264_ugly_number_ii.rs +++ /dev/null @@ -1,66 +0,0 @@ -/** - * [264] Ugly Number II - * - * Write a program to find the n-th ugly number. - * - * Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. - * - * Example: - * - * - * Input: n = 10 - * Output: 12 - * Explanation: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers. - * - * Note: - * - *
    - * 1 is typically treated as an ugly number. - * n does not exceed 1690. - *
- */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/ugly-number-ii/ -// discuss: https://leetcode.com/problems/ugly-number-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn nth_ugly_number(n: i32) -> i32 { - let mut base2 = 0; - let mut base3 = 0; - let mut base5 = 0; - let mut ugly = vec![1; 1]; - for _ in 1..n { - let next2 = ugly[base2] * 2; - let next3 = ugly[base3] * 3; - let next5 = ugly[base5] * 5; - let next = i32::min(next2, i32::min(next3, next5)); - if next2 == next { - base2 += 1 - } - if next3 == next { - base3 += 1 - } - if next5 == next { - base5 += 1 - } - ugly.push(next) - } - *ugly.last().unwrap() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_264() { - assert_eq!(Solution::nth_ugly_number(1), 1); - assert_eq!(Solution::nth_ugly_number(10), 12); - } -} diff --git a/src/solution/s0268_missing_number.rs b/src/solution/s0268_missing_number.rs deleted file mode 100644 index 63291ee0..00000000 --- a/src/solution/s0268_missing_number.rs +++ /dev/null @@ -1,46 +0,0 @@ -/** - * [268] Missing Number - * - * Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array. - * - * Example 1: - * - * - * Input: [3,0,1] - * Output: 2 - * - * - * Example 2: - * - * - * Input: [9,6,4,2,3,5,7,0,1] - * Output: 8 - * - * - * Note:
- * Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity? - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/missing-number/ -// discuss: https://leetcode.com/problems/missing-number/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn missing_number(nums: Vec) -> i32 { - ((nums.len() + 1) * nums.len()) as i32 / 2 - nums.into_iter().fold(0, |acc, v| acc + v) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_268() { - assert_eq!(Solution::missing_number(vec![3, 0, 1]), 2); - } -} diff --git a/src/solution/s0273_integer_to_english_words.rs b/src/solution/s0273_integer_to_english_words.rs deleted file mode 100644 index 123a1f9d..00000000 --- a/src/solution/s0273_integer_to_english_words.rs +++ /dev/null @@ -1,61 +0,0 @@ -/** - * [273] Integer to English Words - * - * Convert a non-negative integer to its english words representation. Given input is guaranteed to be less than 2^31 - 1. - * - * Example 1: - * - * - * Input: 123 - * Output: "One Hundred Twenty Three" - * - * - * Example 2: - * - * - * Input: 12345 - * Output: "Twelve Thousand Three Hundred Forty Five" - * - * Example 3: - * - * - * Input: 1234567 - * Output: "One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven" - * - * - * Example 4: - * - * - * Input: 1234567891 - * Output: "One Billion Two Hundred Thirty Four Million Five Hundred Sixty Seven Thousand Eight Hundred Ninety One" - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/integer-to-english-words/ -// discuss: https://leetcode.com/problems/integer-to-english-words/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// static digits: Vec<&str> = vec!["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"]; -// static xteens: Vec<&str> = vec!["Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventenn", "Eighteen", "Nineteen"]; -// static xtys: Vec<&str> = vec!["Twenty", "Thirty", "Fourty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"]; -// static hunderd: &str = "Hunderd"; -// static thousands: Vec<&str> = vec!["Thousand", "Million", "Billion"]; - -impl Solution { - pub fn number_to_words(num: i32) -> String { - "".to_owned() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_273() {} -} diff --git a/src/solution/s0274_h_index.rs b/src/solution/s0274_h_index.rs deleted file mode 100644 index b36f65a3..00000000 --- a/src/solution/s0274_h_index.rs +++ /dev/null @@ -1,53 +0,0 @@ -/** - * [274] H-Index - * - * Given an array of citations (each citation is a non-negative integer) of a researcher, write a function to compute the researcher's h-index. - * - * According to the definition of h-index on Wikipedia: "A scientist has index h if h of his/her N papers have at least h citations each, and the other N - h papers have no more than h citations each." - * - * Example: - * - * - * Input: citations = [3,0,6,1,5] - * Output: 3 - * Explanation: [3,0,6,1,5] means the researcher has 5 papers in total and each of them had - * received 3, 0, 6, 1, 5 citations respectively. - * Since the researcher has 3 papers with at least 3 citations each and the remaining - * two with no more than 3 citations each, her h-index is 3. - * - * Note: If there are several possible values for h, the maximum one is taken as the h-index. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/h-index/ -// discuss: https://leetcode.com/problems/h-index/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn h_index(mut citations: Vec) -> i32 { - citations.sort_unstable(); - let mut hidx = 0; - for &v in citations.iter().rev() { - if v >= hidx + 1 { - hidx += 1; - } else { - break; - } - } - hidx - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_274() { - assert_eq!(Solution::h_index(vec![3, 0, 6, 1, 5]), 3); - } -} diff --git a/src/solution/s0275_h_index_ii.rs b/src/solution/s0275_h_index_ii.rs deleted file mode 100644 index 027ad02a..00000000 --- a/src/solution/s0275_h_index_ii.rs +++ /dev/null @@ -1,74 +0,0 @@ -/** - * [275] H-Index II - * - * Given an array of citations sorted in ascending order (each citation is a non-negative integer) of a researcher, write a function to compute the researcher's h-index. - * - * According to the definition of h-index on Wikipedia: "A scientist has index h if h of his/her N papers have at least h citations each, and the other N - h papers have no more than h citations each." - * - * Example: - * - * - * Input: citations = [0,1,3,5,6] - * Output: 3 - * Explanation: [0,1,3,5,6] means the researcher has 5 papers in total and each of them had - * received 0, 1, 3, 5, 6 citations respectively. - * Since the researcher has 3 papers with at least 3 citations each and the remaining - * two with no more than 3 citations each, her h-index is 3. - * - * Note: - * - * If there are several possible values for h, the maximum one is taken as the h-index. - * - * Follow up: - * - * - * This is a follow up problem to H-Index, where citations is now guaranteed to be sorted in ascending order. - * Could you solve it in logarithmic time complexity? - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/h-index-ii/ -// discuss: https://leetcode.com/problems/h-index-ii/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn h_index(citations: Vec) -> i32 { - if citations.is_empty() { - return 0; - } - let len = citations.len(); - let (mut low, mut high) = (0_usize, len - 1); - while low <= high { - let mid = low + (high - low) / 2; - if citations[mid] >= (len - mid) as i32 { - if mid == 0 { - break; - } - high = mid - 1; - } else { - low = mid + 1; - } - } - (len - low) as i32 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_275() { - assert_eq!(Solution::h_index(vec![]), 0); - assert_eq!(Solution::h_index(vec![0]), 0); - assert_eq!(Solution::h_index(vec![11, 15]), 2); - assert_eq!(Solution::h_index(vec![1]), 1); - assert_eq!(Solution::h_index(vec![0, 1, 3, 5, 6]), 3); - assert_eq!(Solution::h_index(vec![0, 4, 4, 5, 6]), 4); - } -} diff --git a/src/solution/s0279_perfect_squares.rs b/src/solution/s0279_perfect_squares.rs deleted file mode 100644 index fe5f0a01..00000000 --- a/src/solution/s0279_perfect_squares.rs +++ /dev/null @@ -1,61 +0,0 @@ -/** - * [279] Perfect Squares - * - * Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n. - * - * Example 1: - * - * - * Input: n = 12 - * Output: 3 - * Explanation: 12 = 4 + 4 + 4. - * - * Example 2: - * - * - * Input: n = 13 - * Output: 2 - * Explanation: 13 = 4 + 9. - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/perfect-squares/ -// discuss: https://leetcode.com/problems/perfect-squares/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// BFS -use std::collections::VecDeque; -impl Solution { - pub fn num_squares(n: i32) -> i32 { - if n < 1 { - return 0; - } - let mut deq = VecDeque::new(); - deq.push_back((1, n)); - while let Some((level, num)) = deq.pop_front() { - let mut base = 1; - while base * base <= num { - if base * base == num { - return level; - } - deq.push_back((level + 1, num - base * base)); - base += 1; - } - } - 0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_279() { - assert_eq!(Solution::num_squares(13), 2); - assert_eq!(Solution::num_squares(12), 3); - } -} diff --git a/src/solution/s0282_expression_add_operators.rs b/src/solution/s0282_expression_add_operators.rs deleted file mode 100644 index 1c41367b..00000000 --- a/src/solution/s0282_expression_add_operators.rs +++ /dev/null @@ -1,61 +0,0 @@ -/** - * [282] Expression Add Operators - * - * Given a string that contains only digits 0-9 and a target value, return all possibilities to add binary operators (not unary) +, -, or * between the digits so they evaluate to the target value. - * - * Example 1: - * - * - * Input: num = "123", target = 6 - * Output: ["1+2+3", "1*2*3"] - * - * - * Example 2: - * - * - * Input: num = "232", target = 8 - * Output: ["2*3+2", "2+3*2"] - * - * Example 3: - * - * - * Input: num = "105", target = 5 - * Output: ["1*0+5","10-5"] - * - * Example 4: - * - * - * Input: num = "00", target = 0 - * Output: ["0+0", "0-0", "0*0"] - * - * - * Example 5: - * - * - * Input: num = "3456237490", target = 9191 - * Output: [] - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/expression-add-operators/ -// discuss: https://leetcode.com/problems/expression-add-operators/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn add_operators(num: String, target: i32) -> Vec { - vec![] - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_282() {} -} diff --git a/src/solution/s0283_move_zeroes.rs b/src/solution/s0283_move_zeroes.rs deleted file mode 100644 index 6581bcaf..00000000 --- a/src/solution/s0283_move_zeroes.rs +++ /dev/null @@ -1,50 +0,0 @@ -/** - * [283] Move Zeroes - * - * Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements. - * - * Example: - * - * - * Input: [0,1,0,3,12] - * Output: [1,3,12,0,0] - * - * Note: - * - *
    - * You must do this in-place without making a copy of the array. - * Minimize the total number of operations. - *
- */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/move-zeroes/ -// discuss: https://leetcode.com/problems/move-zeroes/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn move_zeroes(nums: &mut Vec) { - let mut last_none_zero = 0_usize; - for i in 0..nums.len() { - if nums[i] != 0 { - nums.swap(last_none_zero, i); - last_none_zero += 1; - } - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_283() { - let mut vec = vec![0, 1, 0, 3, 12]; - Solution::move_zeroes(&mut vec); - assert_eq!(vec, vec![1, 3, 12, 0, 0]); - } -} diff --git a/src/solution/s0287_find_the_duplicate_number.rs b/src/solution/s0287_find_the_duplicate_number.rs deleted file mode 100644 index cea65001..00000000 --- a/src/solution/s0287_find_the_duplicate_number.rs +++ /dev/null @@ -1,74 +0,0 @@ -/** - * [287] Find the Duplicate Number - * - * Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one. - * - * Example 1: - * - * - * Input: [1,3,4,2,2] - * Output: 2 - * - * - * Example 2: - * - * - * Input: [3,1,3,4,2] - * Output: 3 - * - * Note: - * - *
    - * You must not modify the array (assume the array is read only). - * You must use only constant, O(1) extra space. - * Your runtime complexity should be less than O(n^2). - * There is only one duplicate number in the array, but it could be repeated more than once. - *
- * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/find-the-duplicate-number/ -// discuss: https://leetcode.com/problems/find-the-duplicate-number/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// 假如把值看做 next node 的下标, 那么: -// 从 0 出发不会回到 0 -// 一定有环, 因为 1-n 全部落在下标范围 [0, n] 中 -// 从 0 遍历经过的环中, 一定存在重复数字 x, 且 x 就是入环点的下标: -// 1.从 0 走到入环点, 入环点的前驱值为 x; 2.入环点在环上的前驱值也是 x -// 由于我们不可能回到 0, 因此这两个节点下标不同, x 即为要找的重复数字 -impl Solution { - pub fn find_duplicate(nums: Vec) -> i32 { - let mut slow: usize = nums[0] as usize; - let mut fast: usize = nums[nums[0] as usize] as usize; - // util slow meet fast - while slow != fast { - slow = nums[slow] as usize; - fast = nums[nums[fast] as usize] as usize; - } - - fast = 0_usize; - while slow != fast { - fast = nums[fast] as usize; - slow = nums[slow] as usize; - } - slow as i32 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_287() { - assert_eq!(Solution::find_duplicate(vec![1, 3, 4, 2, 2]), 2); - assert_eq!(Solution::find_duplicate(vec![3, 1, 3, 4, 2]), 3); - assert_eq!(Solution::find_duplicate(vec![1, 2, 3, 4, 5, 5]), 5); - assert_eq!(Solution::find_duplicate(vec![5, 1, 2, 3, 4, 5]), 5); - } -} diff --git a/src/solution/s0289_game_of_life.rs b/src/solution/s0289_game_of_life.rs deleted file mode 100644 index 53d34623..00000000 --- a/src/solution/s0289_game_of_life.rs +++ /dev/null @@ -1,118 +0,0 @@ -/** - * [289] Game of Life - * - * According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970." - * - * Given a board with m by n cells, each cell has an initial state live (1) or dead (0). Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article): - * - *
    - * Any live cell with fewer than two live neighbors dies, as if caused by under-population. - * Any live cell with two or three live neighbors lives on to the next generation. - * Any live cell with more than three live neighbors dies, as if by over-population.. - * Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction. - *
- * - * Write a function to compute the next state (after one update) of the board given its current state. The next state is created by applying the above rules simultaneously to every cell in the current state, where births and deaths occur simultaneously. - * - * Example: - * - * - * Input: - * [ - * [0,1,0], - * [0,0,1], - * [1,1,1], - * [0,0,0] - * ] - * Output: - * [ - * [0,0,0], - * [1,0,1], - * [0,1,1], - * [0,1,0] - * ] - * - * - * Follow up: - * - *
    - * Could you solve it in-place? Remember that the board needs to be updated at the same time: You cannot update some cells first and then use their updated values to update other cells. - * In this question, we represent the board using a 2D array. In principle, the board is infinite, which would cause problems when the active area encroaches the border of the array. How would you address these problems? - *
- * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/game-of-life/ -// discuss: https://leetcode.com/problems/game-of-life/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// in-place: 1: live->live, 0: die->die, 2: die->live, 3: live->die -impl Solution { - pub fn game_of_life(board: &mut Vec>) { - let (height, width) = (board.len(), board[0].len()); - let neighbors = vec![ - (-1, -1), - (-1, 0), - (-1, 1), - (0, -1), - (0, 1), - (1, -1), - (1, 0), - (1, 1), - ]; - for i in 0..height { - for j in 0..width { - let mut live = 0; - for offset in neighbors.iter() { - if (offset.0 < 0 && i == 0) - || (offset.0 > 0 && i == height - 1) - || (offset.1 < 0 && j == 0) - || (offset.1 > 0 && j == width - 1) - { - continue; - } - let v = board[(i as i32 + offset.0) as usize][(j as i32 + offset.1) as usize]; - if v == 1 || v == 3 { - live += 1; - } - } - if board[i][j] == 1 && (live < 2 || live > 3) { - // go die - board[i][j] = 3; - } else if board[i][j] == 0 && live == 3 { - // go live - board[i][j] = 2; - } - } - } - - for i in 0..height { - for j in 0..width { - if board[i][j] == 2 { - board[i][j] = 1; - } else if board[i][j] == 3 { - board[i][j] = 0; - } - } - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_289() { - let mut test = vec![vec![0, 1, 0], vec![0, 0, 1], vec![1, 1, 1], vec![0, 0, 0]]; - Solution::game_of_life(&mut test); - assert_eq!( - test, - vec![vec![0, 0, 0], vec![1, 0, 1], vec![0, 1, 1], vec![0, 1, 0],] - ); - } -} diff --git a/src/solution/s0290_word_pattern.rs b/src/solution/s0290_word_pattern.rs deleted file mode 100644 index c758f352..00000000 --- a/src/solution/s0290_word_pattern.rs +++ /dev/null @@ -1,86 +0,0 @@ -/** - * [290] Word Pattern - * - * Given a pattern and a string str, find if str follows the same pattern. - * - * Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty word in str. - * - * Example 1: - * - * - * Input: pattern = "abba", str = "dog cat cat dog" - * Output: true - * - * Example 2: - * - * - * Input:pattern = "abba", str = "dog cat cat fish" - * Output: false - * - * Example 3: - * - * - * Input: pattern = "aaaa", str = "dog cat cat dog" - * Output: false - * - * Example 4: - * - * - * Input: pattern = "abba", str = "dog dog dog dog" - * Output: false - * - * Notes:
- * You may assume pattern contains only lowercase letters, and str contains lowercase letters that may be separated by a single space. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/word-pattern/ -// discuss: https://leetcode.com/problems/word-pattern/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::collections::HashMap; -impl Solution { - pub fn word_pattern(pattern: String, s: String) -> bool { - let mut p2s = HashMap::new(); - let mut s2p = HashMap::new(); - let mut s_iter = s.split(" "); - let mut p_iter = pattern.chars(); - loop { - match (s_iter.next(), p_iter.next()) { - (Some(sub), Some(ch)) => { - if *p2s.entry(ch).or_insert(sub) != sub || *s2p.entry(sub).or_insert(ch) != ch { - return false; - } - } - (None, None) => break, - _ => return false, - } - } - true - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_290() { - assert_eq!( - Solution::word_pattern("abba".to_owned(), "dog cat cat dog".to_owned()), - true - ); - assert_eq!( - Solution::word_pattern("aaaa".to_owned(), "dog cat cat dog".to_owned()), - false - ); - assert_eq!( - Solution::word_pattern("abba".to_owned(), "dog cat cat fish".to_owned()), - false - ); - } -} diff --git a/src/solution/s0292_nim_game.rs b/src/solution/s0292_nim_game.rs deleted file mode 100644 index 4c46505c..00000000 --- a/src/solution/s0292_nim_game.rs +++ /dev/null @@ -1,40 +0,0 @@ -/** - * [292] Nim Game - * - * You are playing the following Nim Game with your friend: There is a heap of stones on the table, each time one of you take turns to remove 1 to 3 stones. The one who removes the last stone will be the winner. You will take the first turn to remove the stones. - * - * Both of you are very clever and have optimal strategies for the game. Write a function to determine whether you can win the game given the number of stones in the heap. - * - * Example: - * - * - * Input: 4 - * Output: false - * Explanation: If there are 4 stones in the heap, then you will never win the game; - * No matter 1, 2, or 3 stones you remove, the last stone will always be - * removed by your friend. - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/nim-game/ -// discuss: https://leetcode.com/problems/nim-game/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn can_win_nim(n: i32) -> bool { - n % 4 != 0 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_292() { - assert_eq!(Solution::can_win_nim(4), false); - } -} diff --git a/src/solution/s0295_find_median_from_data_stream.rs b/src/solution/s0295_find_median_from_data_stream.rs deleted file mode 100644 index 02dc5331..00000000 --- a/src/solution/s0295_find_median_from_data_stream.rs +++ /dev/null @@ -1,136 +0,0 @@ -/** - * [295] Find Median from Data Stream - * - * Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value. - * For example, - * - * [2,3,4], the median is 3 - * - * [2,3], the median is (2 + 3) / 2 = 2.5 - * - * Design a data structure that supports the following two operations: - * - * - * void addNum(int num) - Add a integer number from the data stream to the data structure. - * double findMedian() - Return the median of all elements so far. - * - * - * - * - * Example: - * - * - * addNum(1) - * addNum(2) - * findMedian() -> 1.5 - * addNum(3) - * findMedian() -> 2 - * - * - * - * - * Follow up: - * - *
    - * If all integer numbers from the stream are between 0 and 100, how would you optimize it? - * If 99% of all integer numbers from the stream are between 0 and 100, how would you optimize it? - *
- * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/find-median-from-data-stream/ -// discuss: https://leetcode.com/problems/find-median-from-data-stream/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cmp::Ordering; -use std::collections::BinaryHeap; -#[derive(Eq, PartialEq)] -struct Invert { - value: i32, -} - -impl Ord for Invert { - fn cmp(&self, other: &Invert) -> Ordering { - other.value.cmp(&self.value) - } -} - -impl PartialOrd for Invert { - fn partial_cmp(&self, other: &Invert) -> Option { - Some(self.cmp(other)) - } -} - -struct MedianFinder { - head: BinaryHeap, - tail: BinaryHeap, - count: i32, -} - -/** - * `&self` means the method takes an immutable reference. - * If you need a mutable reference, change it to `&mut self` instead. - */ -impl MedianFinder { - /** initialize your data structure here. */ - fn new() -> Self { - MedianFinder { - head: BinaryHeap::new(), - tail: BinaryHeap::new(), - count: 0, - } - } - - fn add_num(&mut self, num: i32) { - self.count += 1; - if self.head.is_empty() || num > self.head.peek().unwrap().value { - self.head.push(Invert { value: num }); - } else { - self.tail.push(num); - } - // balance - if self.head.len() > self.tail.len() + 1 { - self.tail.push(self.head.pop().unwrap().value); - } else if self.head.len() + 1 < self.tail.len() { - self.head.push(Invert { - value: self.tail.pop().unwrap(), - }); - } - } - - fn find_median(&self) -> f64 { - if self.head.len() > self.tail.len() { - self.head.peek().unwrap().value as f64 - } else if self.head.len() < self.tail.len() { - *self.tail.peek().unwrap() as f64 - } else { - (self.head.peek().unwrap().value as f64 + *self.tail.peek().unwrap() as f64) / 2.0 - } - } -} - -/** - * Your MedianFinder object will be instantiated and called as such: - * let obj = MedianFinder::new(); - * obj.add_num(num); - * let ret_2: f64 = obj.find_median(); - */ - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_295() { - let mut obj = MedianFinder::new(); - obj.add_num(1); - obj.add_num(2); - assert_eq!(obj.find_median(), 1.5); - obj.add_num(3); - assert_eq!(obj.find_median(), 2_f64); - } -} diff --git a/src/solution/s0299_bulls_and_cows.rs b/src/solution/s0299_bulls_and_cows.rs deleted file mode 100644 index 08525c71..00000000 --- a/src/solution/s0299_bulls_and_cows.rs +++ /dev/null @@ -1,80 +0,0 @@ -/** - * [299] Bulls and Cows - * - * You are playing the following Bulls and Cows game with your friend: You write down a number and ask your friend to guess what the number is. Each time your friend makes a guess, you provide a hint that indicates how many digits in said guess match your secret number exactly in both digit and position (called "bulls") and how many digits match the secret number but locate in the wrong position (called "cows"). Your friend will use successive guesses and hints to eventually derive the secret number. - * - * Write a function to return a hint according to the secret number and friend's guess, use A to indicate the bulls and B to indicate the cows. - * - * Please note that both secret number and friend's guess may contain duplicate digits. - * - * Example 1: - * - * - * Input: secret = "1807", guess = "7810" - * - * Output: "1A3B" - * - * Explanation: 1 bull and 3 cows. The bull is 8, the cows are 0, 1 and 7. - * - * Example 2: - * - * - * Input: secret = "1123", guess = "0111" - * - * Output: "1A1B" - * - * Explanation: The 1st 1 in friend's guess is a bull, the 2nd or 3rd 1 is a cow. - * - * Note: You may assume that the secret number and your friend's guess only contain digits, and their lengths are always equal. - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/bulls-and-cows/ -// discuss: https://leetcode.com/problems/bulls-and-cows/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn get_hint(secret: String, guess: String) -> String { - let mut bulls = 0; - let mut cows = 0; - let mut s_iter = secret.chars(); - let mut g_iter = guess.chars(); - let mut bucket = vec![0; 10]; - let mut non_match = vec![]; - while let (Some(s), Some(g)) = (s_iter.next(), g_iter.next()) { - if s == g { - bulls += 1; - } else { - bucket[s.to_digit(10).unwrap() as usize] += 1; - non_match.push(g.to_digit(10).unwrap() as usize); - } - } - for &idx in non_match.iter() { - if bucket[idx] > 0 { - cows += 1; - bucket[idx] -= 1; - } - } - format!("{}A{}B", bulls, cows) - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_299() { - assert_eq!( - Solution::get_hint("1807".to_owned(), "7810".to_owned()), - "1A3B".to_owned() - ); - assert_eq!( - Solution::get_hint("1123".to_owned(), "0111".to_owned()), - "1A1B".to_owned() - ); - } -} diff --git a/src/solution/s0300_longest_increasing_subsequence.rs b/src/solution/s0300_longest_increasing_subsequence.rs deleted file mode 100644 index c0b7eb27..00000000 --- a/src/solution/s0300_longest_increasing_subsequence.rs +++ /dev/null @@ -1,57 +0,0 @@ -/** - * [300] Longest Increasing Subsequence - * - * Given an unsorted array of integers, find the length of longest increasing subsequence. - * - * Example: - * - * - * Input: [10,9,2,5,3,7,101,18] - * Output: 4 - * Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4. - * - * Note: - * - * - * There may be more than one LIS combination, it is only necessary for you to return the length. - * Your algorithm should run in O(n^2) complexity. - * - * - * Follow up: Could you improve it to O(n log n) time complexity? - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/longest-increasing-subsequence/ -// discuss: https://leetcode.com/problems/longest-increasing-subsequence/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here -// N^2, DP: L[i] = max(1 + L[j]) for j in [0, i) and nums[j] < nums[i] -// N * logN, kick out strategy, maintain an increasing array, new elements kick out a formal one larger than it, if the new element is largest, expand the array -impl Solution { - pub fn length_of_lis(nums: Vec) -> i32 { - let mut incr = Vec::new(); - for &num in nums.iter() { - if let Err(idx) = incr.binary_search(&num) { - if idx >= incr.len() { - incr.push(num); - } else { - incr[idx] = num; - } - } - } - incr.len() as i32 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_300() { - assert_eq!(Solution::length_of_lis(vec![10, 9, 2, 5, 3, 7, 101, 18]), 4); - } -} diff --git a/src/solution/s0301_remove_invalid_parentheses.rs b/src/solution/s0301_remove_invalid_parentheses.rs deleted file mode 100644 index 2cec757c..00000000 --- a/src/solution/s0301_remove_invalid_parentheses.rs +++ /dev/null @@ -1,131 +0,0 @@ -/** - * [301] Remove Invalid Parentheses - * - * Remove the minimum number of invalid parentheses in order to make the input string valid. Return all possible results. - * - * Note: The input string may contain letters other than the parentheses ( and ). - * - * Example 1: - * - * - * Input: "()())()" - * Output: ["()()()", "(())()"] - * - * - * Example 2: - * - * - * Input: "(a)())()" - * Output: ["(a)()()", "(a())()"] - * - * - * Example 3: - * - * - * Input: ")(" - * Output: [""] - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/remove-invalid-parentheses/ -// discuss: https://leetcode.com/problems/remove-invalid-parentheses/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// 1. Calculate the number of misplaced left parenthese and right parenthese -// 2. DFS the string to find the all possible removing policy -use std::collections::HashSet; -impl Solution { - pub fn remove_invalid_parentheses(s: String) -> Vec { - let (mut left, mut right) = (0, 0); - let mut chs: Vec = s.chars().collect(); - for &c in chs.iter() { - if c == '(' { - left += 1; - } else if c == ')' { - if left > 0 { - left -= 1; - } else { - right += 1; - } - } - } - - // Now, the number of left and right parentheses are 'left' and 'right' - let mut res: HashSet = HashSet::new(); - let mut seed: Vec = Vec::new(); - Solution::helper(&chs, 0, 0, left, right, &mut seed, &mut res); - res.into_iter().collect() - } - - fn helper( - chs: &Vec, - idx: usize, - left: i32, - l_remain: i32, - r_remain: i32, - exp: &mut Vec, - res: &mut HashSet, - ) { - if idx >= chs.len() { - if left == 0 { - res.insert(exp.iter().collect()); - } - return; - } - if chs[idx] == '(' { - if l_remain > 0 { - Solution::helper( - chs, - idx + 1, - left, - l_remain - 1, - r_remain, - &mut exp.clone(), - res, - ); - } - exp.push('('); - Solution::helper(chs, idx + 1, left + 1, l_remain, r_remain, exp, res); - } else if chs[idx] == ')' { - if r_remain > 0 { - Solution::helper( - chs, - idx + 1, - left, - l_remain, - r_remain - 1, - &mut exp.clone(), - res, - ); - } - if left > 0 { - exp.push(')'); - Solution::helper(chs, idx + 1, left - 1, l_remain, r_remain, exp, res); - } - } else { - exp.push(chs[idx]); - Solution::helper(chs, idx + 1, left, l_remain, r_remain, exp, res); - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_301() { - assert_eq!( - Solution::remove_invalid_parentheses("()())()".to_owned()), - vec_string!["(())()", "()()()"] - ); - assert_eq!( - Solution::remove_invalid_parentheses("(a)())()".to_owned()), - vec_string!["(a)()()", "(a())()"] - ); - } -} diff --git a/src/solution/s0303_range_sum_query_immutable.rs b/src/solution/s0303_range_sum_query_immutable.rs deleted file mode 100644 index c56f8ae9..00000000 --- a/src/solution/s0303_range_sum_query_immutable.rs +++ /dev/null @@ -1,74 +0,0 @@ -/** - * [303] Range Sum Query - Immutable - * - * Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive. - * - * Example:
- * - * Given nums = [-2, 0, 3, -5, 2, -1] - * - * sumRange(0, 2) -> 1 - * sumRange(2, 5) -> -1 - * sumRange(0, 5) -> -3 - * - * - * - * Note:
- *
    - * You may assume that the array does not change. - * There are many calls to sumRange function. - *
- * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/range-sum-query-immutable/ -// discuss: https://leetcode.com/problems/range-sum-query-immutable/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -struct NumArray { - nums: Vec, -} - -/** - * `&self` means the method takes an immutable reference. - * If you need a mutable reference, change it to `&mut self` instead. - */ -impl NumArray { - fn new(nums: Vec) -> Self { - let mut res = 0; - let mut vec = Vec::with_capacity(nums.len()); - for &num in nums.iter() { - res += num; - vec.push(res); - } - NumArray { nums: vec } - } - - fn sum_range(&self, i: i32, j: i32) -> i32 { - let (i, j) = (i as usize, j as usize); - self.nums[j] - if i > 0 { self.nums[i - 1] } else { 0 } - } -} - -/** - * Your NumArray object will be instantiated and called as such: - * let obj = NumArray::new(nums); - * let ret_1: i32 = obj.sum_range(i, j); - */ - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_303() { - let mut nums = NumArray::new(vec![-2, 0, 3, -5, 2, -1]); - assert_eq!(nums.sum_range(0, 2), 1); - assert_eq!(nums.sum_range(2, 5), -1); - assert_eq!(nums.sum_range(0, 5), -3); - } -} diff --git a/src/solution/s0304_range_sum_query_2d_immutable.rs b/src/solution/s0304_range_sum_query_2d_immutable.rs deleted file mode 100644 index 42a0f41f..00000000 --- a/src/solution/s0304_range_sum_query_2d_immutable.rs +++ /dev/null @@ -1,124 +0,0 @@ -/** - * [304] Range Sum Query 2D - Immutable - * - * Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2). - * - * - * Range Sum Query 2D
- * The above rectangle (with the red border) is defined by (row1, col1) = (2, 1) and (row2, col2) = (4, 3), which contains sum = 8. - * - * - * Example:
- * - * Given matrix = [ - * [3, 0, 1, 4, 2], - * [5, 6, 3, 2, 1], - * [1, 2, 0, 1, 5], - * [4, 1, 0, 1, 7], - * [1, 0, 3, 0, 5] - * ] - * - * sumRegion(2, 1, 4, 3) -> 8 - * sumRegion(1, 1, 2, 2) -> 11 - * sumRegion(1, 2, 2, 4) -> 12 - * - * - * - * Note:
- *
    - * You may assume that the matrix does not change. - * There are many calls to sumRegion function. - * You may assume that row1 ≤ row2 and col1 ≤ col2. - *
- * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/range-sum-query-2d-immutable/ -// discuss: https://leetcode.com/problems/range-sum-query-2d-immutable/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -struct NumMatrix { - cache: Vec>, -} - -/** region[2, 2, 3, 4] = - * x x \ \ \ . square[3,4] - square[1,4] - square[3,1] + square[1,1] - * x x \ \ \ . - * / / o o o . - * / / o o o . - * . . . . . . - * . . . . . . - */ -impl NumMatrix { - fn new(matrix: Vec>) -> Self { - if matrix.is_empty() || matrix[0].is_empty() { - return NumMatrix { - cache: vec![vec![]], - }; - } - let (x_max, y_max) = (matrix.len(), matrix[0].len()); - let mut cache = vec![vec![0; y_max]; x_max]; - for x in 0..x_max { - for y in 0..y_max { - cache[x][y] = matrix[x][y] - + if y > 0 { cache[x][y - 1] } else { 0 } - + if x > 0 { cache[x - 1][y] } else { 0 } - - if x > 0 && y > 0 { - cache[x - 1][y - 1] - } else { - 0 - } - } - } - NumMatrix { cache: cache } - } - - fn sum_region(&self, row1: i32, col1: i32, row2: i32, col2: i32) -> i32 { - let (row1, col1, row2, col2) = (row1 as usize, col1 as usize, row2 as usize, col2 as usize); - self.cache[row2][col2] - - if row1 > 0 { - self.cache[row1 - 1][col2] - } else { - 0 - } - - if col1 > 0 { - self.cache[row2][col1 - 1] - } else { - 0 - } - + if row1 > 0 && col1 > 0 { - self.cache[row1 - 1][col1 - 1] - } else { - 0 - } - } -} - -/** - * Your NumMatrix object will be instantiated and called as such: - * let obj = NumMatrix::new(matrix); - * let ret_1: i32 = obj.sum_region(row1, col1, row2, col2); - */ - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_304() { - let matrix = NumMatrix::new(vec![ - vec![3, 0, 1, 4, 2], - vec![5, 6, 3, 2, 1], - vec![1, 2, 0, 1, 5], - vec![4, 1, 0, 1, 7], - vec![1, 0, 3, 0, 5], - ]); - assert_eq!(matrix.sum_region(1, 1, 2, 2), 11); - assert_eq!(matrix.sum_region(2, 1, 4, 3), 8); - assert_eq!(matrix.sum_region(1, 2, 2, 4), 12); - } -} diff --git a/src/solution/s0306_additive_number.rs b/src/solution/s0306_additive_number.rs deleted file mode 100644 index 38f6c0b2..00000000 --- a/src/solution/s0306_additive_number.rs +++ /dev/null @@ -1,113 +0,0 @@ -/** - * [306] Additive Number - * - * Additive number is a string whose digits can form additive sequence. - * - * A valid additive sequence should contain at least three numbers. Except for the first two numbers, each subsequent number in the sequence must be the sum of the preceding two. - * - * Given a string containing only digits '0'-'9', write a function to determine if it's an additive number. - * - * Note: Numbers in the additive sequence cannot have leading zeros, so sequence 1, 2, 03 or 1, 02, 3 is invalid. - * - * Example 1: - * - * - * Input: "112358" - * Output: true - * Explanation: The digits can form an additive sequence: 1, 1, 2, 3, 5, 8. - * 1 + 1 = 2, 1 + 2 = 3, 2 + 3 = 5, 3 + 5 = 8 - * - * - * Example 2: - * - * - * Input: "199100199" - * Output: true - * Explanation: The additive sequence is: 1, 99, 100, 199. - * 1 + 99 = 100, 99 + 100 = 199 - * - * Follow up:
- * How would you handle overflow for very large input integers? - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/additive-number/ -// discuss: https://leetcode.com/problems/additive-number/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -// first_cut second_cut third_cut -// V V V -// 1 99 100 199 -impl Solution { - pub fn is_additive_number(num: String) -> bool { - let mut chs: Vec = num.chars().map(|c| c.to_digit(10).unwrap()).collect(); - let mut num1 = 0; - let len = chs.len(); - // first cut - for i in 0..(len / 2 + 1) { - num1 = num1 * 10 + chs[i]; - if Solution::second_cut(i + 1, len, num1, &chs) { - return true; - } - if num1 == 0 { - break; - } - } - false - } - - fn second_cut(from: usize, len: usize, num1: u32, chs: &Vec) -> bool { - let mut num2 = 0; - for i in from..len { - num2 = num2 * 10 + chs[i]; - if Solution::third_cut(i + 1, len, num1, num2, chs, false) { - return true; - } - if num2 == 0 { - break; - } - } - false - } - - fn third_cut( - from: usize, - len: usize, - num1: u32, - num2: u32, - chs: &Vec, - found: bool, - ) -> bool { - if found && from >= len { - return true; - } - let mut num3 = 0; - for i in from..len { - num3 = num3 * 10 + chs[i]; - if num3 == num2 + num1 { - if Solution::third_cut(i + 1, len, num2, num3, chs, true) { - return true; - } - } else if num3 == 0 || num3 > num1 + num2 { - break; - } - } - false - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_306() { - assert_eq!(Solution::is_additive_number("112358".to_owned()), true); - assert_eq!(Solution::is_additive_number("199100199".to_owned()), true); - assert_eq!(Solution::is_additive_number("1991001990".to_owned()), false); - assert_eq!(Solution::is_additive_number("1023".to_owned()), false); - } -} diff --git a/src/solution/s0307_range_sum_query_mutable.rs b/src/solution/s0307_range_sum_query_mutable.rs deleted file mode 100644 index bbaac119..00000000 --- a/src/solution/s0307_range_sum_query_mutable.rs +++ /dev/null @@ -1,151 +0,0 @@ -/** - * [307] Range Sum Query - Mutable - * - * Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive. - * - * The update(i, val) function modifies nums by updating the element at index i to val. - * - * Example: - * - * - * Given nums = [1, 3, 5] - * - * sumRange(0, 2) -> 9 - * update(1, 2) - * sumRange(0, 2) -> 8 - * - * - * Note: - * - *
    - * The array is only modifiable by the update function. - * You may assume the number of calls to update and sumRange function is distributed evenly. - *
- * - */ -pub struct Solution {} - -// Segement Tree -// -// N[0:6] -// / \ -// / \ -// N[0:3] N[4:6] -// / \ / \ -// N[0:1] N[2:3] N[4:5] N[6] -// / \ / \ / \ -// N[0] N[1] N[2] N[3] N[4] N[5] -// -// problem: https://leetcode.com/problems/range-sum-query-mutable/ -// discuss: https://leetcode.com/problems/range-sum-query-mutable/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -struct NumArray { - tree: Vec, - n: usize, -} - -/** - * `&self` means the method takes an immutable reference. - * If you need a mutable reference, change it to `&mut self` instead. - */ -impl NumArray { - fn new(nums: Vec) -> Self { - let n = nums.len(); - let mut tree = vec![0; 4 * n]; - if n > 0 { - NumArray::build(1, 0, n - 1, &mut tree, &nums); - } - NumArray { tree: tree, n: n } - } - - fn update(&mut self, i: i32, val: i32) { - NumArray::update_internal(i as usize, val, 1, 0, self.n - 1, &mut self.tree); - } - - fn sum_range(&self, i: i32, j: i32) -> i32 { - NumArray::sum(1, 0, self.n - 1, i as usize, j as usize, &self.tree) - } - - fn build(node: usize, start: usize, end: usize, tree: &mut Vec, nums: &Vec) { - if start == end { - tree[node] = nums[start]; - } else { - let mid = (start + end) / 2; - NumArray::build(2 * node, start, mid, tree, nums); - NumArray::build(2 * node + 1, mid + 1, end, tree, nums); - tree[node] = tree[2 * node] + tree[2 * node + 1]; - } - } - - fn update_internal( - i: usize, - val: i32, - node: usize, - start: usize, - end: usize, - tree: &mut Vec, - ) { - if start == end { - tree[node] = val; - } else { - let mid = (start + end) / 2; - if i <= mid { - NumArray::update_internal(i, val, 2 * node, start, mid, tree); - } else { - NumArray::update_internal(i, val, 2 * node + 1, mid + 1, end, tree); - } - tree[node] = tree[2 * node] + tree[2 * node + 1]; - } - } - - fn sum( - node: usize, - start: usize, - end: usize, - left: usize, - right: usize, - tree: &Vec, - ) -> i32 { - if right < start || left > end { - // not in range - 0 - } else if left <= start && end <= right { - // completely in range - tree[node] - } else { - // partially in range - let mid = (start + end) / 2; - NumArray::sum(2 * node, start, mid, left, right, tree) - + NumArray::sum(2 * node + 1, mid + 1, end, left, right, tree) - } - } -} - -/** - * Your NumArray object will be instantiated and called as such: - * let obj = NumArray::new(nums); - * obj.update(i, val); - * let ret_2: i32 = obj.sum_range(i, j); - */ - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_307() { - let _empty = NumArray::new(vec![]); - let mut tree = NumArray::new(vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); - assert_eq!(tree.sum_range(0, 6), 7); - tree.update(0, 2); - assert_eq!(tree.sum_range(0, 6), 8); - tree.update(1, 2); - assert_eq!(tree.sum_range(0, 2), 5); - tree.update(6, 10); - assert_eq!(tree.sum_range(6, 6), 10); - } -} diff --git a/src/solution/s0309_best_time_to_buy_and_sell_stock_with_cooldown.rs b/src/solution/s0309_best_time_to_buy_and_sell_stock_with_cooldown.rs deleted file mode 100644 index 6f3e911d..00000000 --- a/src/solution/s0309_best_time_to_buy_and_sell_stock_with_cooldown.rs +++ /dev/null @@ -1,79 +0,0 @@ -/** - * [309] Best Time to Buy and Sell Stock with Cooldown - * - * Say you have an array for which the i^th element is the price of a given stock on day i. - * - * Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times) with the following restrictions: - * - * - * You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again). - * After you sell your stock, you cannot buy stock on next day. (ie, cooldown 1 day) - * - * - * Example: - * - * - * Input: [1,2,3,0,2] - * Output: 3 - * Explanation: transactions = [buy, sell, cooldown, buy, sell] - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/ -// discuss: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -dp[i]: max profit with selling at day i -dp2[i]: max profit till day i - -dp[i] = max(dp[i-1] + p[i] - p[i-1], dp2[i-2], dp2[i-3] + p[i] - p[i-1]) -*/ -impl Solution { - pub fn max_profit(prices: Vec) -> i32 { - if prices.len() < 2 { - return 0; - } - if prices.len() == 2 { - return i32::max(0, prices[1] - prices[0]); - } - let mut dp = vec![0; prices.len()]; - let mut dp2 = vec![0; prices.len()]; - let mut max = 0; - dp[0] = 0; - dp2[0] = 0; - dp[1] = prices[1] - prices[0]; - dp2[1] = i32::max(dp2[0], dp[1]); - dp[2] = i32::max(prices[2] - prices[1], prices[2] - prices[0]); - dp2[2] = i32::max(dp2[1], dp[2]); - for i in 3..prices.len() { - dp[i] = i32::max( - dp[i - 1] + prices[i] - prices[i - 1], - i32::max(dp2[i - 2], dp2[i - 3] + prices[i] - prices[i - 1]), - ); - dp2[i] = i32::max(dp2[i - 1], dp[i]); - } - let mut temp = 0; - for &m in dp.iter() { - if m > temp { - temp = m; - } - } - temp - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_309() { - assert_eq!(Solution::max_profit(vec![1, 2, 3, 0, 2]), 3); - assert_eq!(Solution::max_profit(vec![4, 2, 7, 1, 11]), 10); - } -} diff --git a/src/solution/s0310_minimum_height_trees.rs b/src/solution/s0310_minimum_height_trees.rs deleted file mode 100644 index 4141273c..00000000 --- a/src/solution/s0310_minimum_height_trees.rs +++ /dev/null @@ -1,110 +0,0 @@ -/** - * [310] Minimum Height Trees - * - * For an undirected graph with tree characteristics, we can choose any node as the root. The result graph is then a rooted tree. Among all possible rooted trees, those with minimum height are called minimum height trees (MHTs). Given such a graph, write a function to find all the MHTs and return a list of their root labels. - * - * Format
- * The graph contains n nodes which are labeled from 0 to n - 1. You will be given the number n and a list of undirected edges (each edge is a pair of labels). - * - * You can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges. - * - * Example 1 : - * - * - * Input: n = 4, edges = [[1, 0], [1, 2], [1, 3]] - * - * 0 - * | - * 1 - * / \ - * 2 3 - * - * Output: [1] - * - * - * Example 2 : - * - * - * Input: n = 6, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]] - * - * 0 1 2 - * \ | / - * 3 - * | - * 4 - * | - * 5 - * - * Output: [3, 4] - * - * Note: - * - * - * According to the definition of tree on Wikipedia: “a tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.” - * The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/minimum-height-trees/ -// discuss: https://leetcode.com/problems/minimum-height-trees/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::mem; -impl Solution { - pub fn find_min_height_trees(n: i32, edges: Vec>) -> Vec { - let n = n as usize; - let mut matrix: Vec> = vec![vec![]; n]; - for edge in edges.iter() { - matrix[edge[0] as usize].push(edge[1] as usize); - matrix[edge[1] as usize].push(edge[0] as usize); - } - let mut count = n; - let mut la: Vec = vec![]; - let mut lb: Vec = vec![]; - for i in 0..n { - if matrix[i].len() <= 1 { - la.push(i); - } - } - while count > 2 { - count -= la.len(); - for &i in la.iter() { - let j = matrix[i][0]; - let idx = matrix[j].iter().position(|&r| r == i).unwrap(); - matrix[j].remove(idx); - if matrix[j].len() == 1 { - lb.push(j); - } - } - la.clear(); - mem::swap(&mut la, &mut lb); - } - la.into_iter().map(|i| i as i32).collect() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_310() { - assert_eq!( - Solution::find_min_height_trees(4, vec![vec![1, 0], vec![1, 2], vec![1, 3]]), - vec![1] - ); - assert_eq!( - Solution::find_min_height_trees( - 6, - vec![vec![0, 3], vec![1, 3], vec![2, 3], vec![4, 3], vec![5, 4]] - ), - vec![3, 4] - ); - assert_eq!(Solution::find_min_height_trees(1, vec![]), vec![0]); - } -} diff --git a/src/solution/s0312_burst_balloons.rs b/src/solution/s0312_burst_balloons.rs deleted file mode 100644 index f8833b5e..00000000 --- a/src/solution/s0312_burst_balloons.rs +++ /dev/null @@ -1,108 +0,0 @@ -/** - * [312] Burst Balloons - * - * Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by array nums. You are asked to burst all the balloons. If the you burst balloon i you will get nums[left] * nums[i] * nums[right] coins. Here left and right are adjacent indices of i. After the burst, the left and right then becomes adjacent. - * - * Find the maximum coins you can collect by bursting the balloons wisely. - * - * Note: - * - * - * You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can not burst them. - * 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100 - * - * - * Example: - * - * - * Input: [3,1,5,8] - * Output: 167 - * Explanation: nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> [] - * coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167 - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/burst-balloons/ -// discuss: https://leetcode.com/problems/burst-balloons/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -/* -The key idea is, for a sequence of balloon, select a balloon to be the last one to be bursted: - -max of [1 . a b c d e f . 1] - - ^ say we select 'c' as the last balloon to burst, then: - -= - max of [1 . a b . c] + - - max of [c . d e f . 1] + - - 1 * c * 1 - -Then we can use memorize to record the max of every sub sequence -*/ -impl Solution { - pub fn max_coins(nums: Vec) -> i32 { - if nums.is_empty() { - return 0; - } - let mut coins = vec![0; nums.len() + 2]; - let mut len = 0_usize; - // filter out zeros - for &num in nums.iter() { - if num != 0 { - len += 1; - coins[len] = num; - } - } - coins[0] = 1; - coins[len + 1] = 1; - - let mut memo = vec![vec![0; len + 1]; len + 1]; - Solution::max_subrange(&coins, 1, len, &mut memo) - } - - fn max_subrange(coins: &Vec, start: usize, end: usize, memo: &mut Vec>) -> i32 { - if memo[start][end] != 0 { - return memo[start][end]; - } - if start == end { - memo[start][end] = coins[start - 1] * coins[start] * coins[start + 1]; - return memo[start][end]; - } - let mut max = 0; - for i in start..end + 1 { - let left_max = if i > start { - Solution::max_subrange(coins, start, i - 1, memo) - } else { - 0 - }; - let right_max = if i < end { - Solution::max_subrange(coins, i + 1, end, memo) - } else { - 0 - }; - max = i32::max( - max, - left_max + right_max + coins[i] * coins[start - 1] * coins[end + 1], - ); - } - memo[start][end] = max; - return memo[start][end]; - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_312() { - assert_eq!(Solution::max_coins(vec![3, 1, 5, 8]), 167); - } -} diff --git a/src/solution/s0313_super_ugly_number.rs b/src/solution/s0313_super_ugly_number.rs deleted file mode 100644 index bf99bcc8..00000000 --- a/src/solution/s0313_super_ugly_number.rs +++ /dev/null @@ -1,94 +0,0 @@ -/** - * [313] Super Ugly Number - * - * Write a program to find the n^th super ugly number. - * - * Super ugly numbers are positive numbers whose all prime factors are in the given prime list primes of size k. - * - * Example: - * - * - * Input: n = 12, primes = [2,7,13,19] - * Output: 32 - * Explanation: [1,2,4,7,8,13,14,16,19,26,28,32] is the sequence of the first 12 - * super ugly numbers given primes = [2,7,13,19] of size 4. - * - * Note: - * - * - * 1 is a super ugly number for any given primes. - * The given numbers in primes are in ascending order. - * 0 < k ≤ 100, 0 < n ≤ 10^6, 0 < primes[i] < 1000. - * The n^th super ugly number is guaranteed to fit in a 32-bit signed integer. - * - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/super-ugly-number/ -// discuss: https://leetcode.com/problems/super-ugly-number/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::cmp::Ordering; -use std::collections::BinaryHeap; -#[derive(Eq, PartialEq)] -struct Invert { - base: i32, - idx: usize, - value: i32, -} - -impl Ord for Invert { - fn cmp(&self, other: &Invert) -> Ordering { - other.value.cmp(&self.value) - } -} - -impl PartialOrd for Invert { - fn partial_cmp(&self, other: &Invert) -> Option { - Some(self.cmp(other)) - } -} - -impl Solution { - pub fn nth_super_ugly_number(n: i32, primes: Vec) -> i32 { - let mut vec = vec![1; 1]; - let mut heap: BinaryHeap = BinaryHeap::new(); - for &prime in primes.iter() { - heap.push(Invert { - base: prime, - idx: 0, - value: prime, - }); - } - for _ in 0..n - 1 { - let mut min = 0; - if let Some(num) = heap.peek() { - min = num.value; - } - vec.push(min); - while heap.peek().unwrap().value == min { - let p = heap.pop().unwrap(); - heap.push(Invert { - base: p.base, - idx: p.idx + 1, - value: p.base * vec[p.idx + 1], - }); - } - } - *vec.last().unwrap() - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_313() { - assert_eq!(Solution::nth_super_ugly_number(12, vec![2, 7, 13, 19]), 32); - } -} diff --git a/src/solution/s0509_fibonacci_number.rs b/src/solution/s0509_fibonacci_number.rs deleted file mode 100644 index 47a9b420..00000000 --- a/src/solution/s0509_fibonacci_number.rs +++ /dev/null @@ -1,78 +0,0 @@ -/** - * [1013] Fibonacci Number - * - * The Fibonacci numbers, commonly denoted F(n) form a sequence, called the Fibonacci sequence, such that each number is the sum of the two preceding ones, starting from 0 and 1. That is, - * - * - * F(0) = 0, F(1) = 1 - * F(N) = F(N - 1) + F(N - 2), for N > 1. - * - * - * Given N, calculate F(N). - * - * - * - * Example 1: - * - * - * Input: 2 - * Output: 1 - * Explanation: F(2) = F(1) + F(0) = 1 + 0 = 1. - * - * - * Example 2: - * - * - * Input: 3 - * Output: 2 - * Explanation: F(3) = F(2) + F(1) = 1 + 1 = 2. - * - * - * Example 3: - * - * - * Input: 4 - * Output: 3 - * Explanation: F(4) = F(3) + F(2) = 2 + 1 = 3. - * - * - * - * - * Note: - * - * 0 ≤ N ≤ 30. - * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/fibonacci-number/ -// discuss: https://leetcode.com/problems/fibonacci-number/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn fib(n: i32) -> i32 { - if n == 0 { - return 0; - } - let mut f = (0, 1); - for _ in 1..n { - f = (f.1, f.0 + f.1); - } - return f.1; - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_1013() { - assert_eq!(Solution::fib(2), 1); - assert_eq!(Solution::fib(3), 2); - assert_eq!(Solution::fib(4), 3); - } -} diff --git a/src/solution/s0704_binary_search.rs b/src/solution/s0704_binary_search.rs deleted file mode 100644 index 26ed0c8d..00000000 --- a/src/solution/s0704_binary_search.rs +++ /dev/null @@ -1,83 +0,0 @@ -/** - * [792] Binary Search - * - * Given a sorted (in ascending order) integer array nums of n elements and a target value, write a function to search target in nums. If target exists, then return its index, otherwise return -1. - * - *
- * Example 1: - * - * - * Input: nums = [-1,0,3,5,9,12], target = 9 - * Output: 4 - * Explanation: 9 exists in nums and its index is 4 - * - * - * - * Example 2: - * - * - * Input: nums = [-1,0,3,5,9,12], target = 2 - * Output: -1 - * Explanation: 2 does not exist in nums so return -1 - * - * - * - * - * Note: - * - *
    - * You may assume that all elements in nums are unique. - * n will be in the range [1, 10000]. - * The value of each element in nums will be in the range [-9999, 9999]. - *
- * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/binary-search/ -// discuss: https://leetcode.com/problems/binary-search/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here -use std::cmp::Ordering; - -impl Solution { - pub fn search(nums: Vec, target: i32) -> i32 { - let mut lo = 0i32; - let mut hi = (nums.len() as i32) - 1; - while lo <= hi { - let mid = lo + (hi - lo) / 2; - match nums[mid as usize].cmp(&target) { - Ordering::Less => { - lo = mid + 1; - } - Ordering::Greater => { - hi = mid - 1; - } - Ordering::Equal => { - return mid; - } - } - } - -1 - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_792() { - assert_eq!(Solution::search(vec![-1, 0, 3, 5, 9, 12], 9), 4); - assert_eq!(Solution::search(vec![-1, 0, 3, 5, 9, 12], 2), -1); - assert_eq!(Solution::search(vec![1], 1), 0); - assert_eq!(Solution::search(vec![5], -5), -1); - assert_eq!(Solution::search(vec![5], 6), -1); - assert_eq!(Solution::search(vec![1, 2], 0), -1); - assert_eq!(Solution::search(vec![1, 2], 1), 0); - assert_eq!(Solution::search(vec![1, 2], 2), 1); - assert_eq!(Solution::search(vec![1, 2], 3), -1); - } -} diff --git a/src/solution/s0969_pancake_sorting.rs b/src/solution/s0969_pancake_sorting.rs deleted file mode 100644 index 541ae423..00000000 --- a/src/solution/s0969_pancake_sorting.rs +++ /dev/null @@ -1,148 +0,0 @@ -/** - * [1009] Pancake Sorting - * - * Given an array A, we can perform a pancake flip: We choose some positive integer k <= A.length, then reverse the order of the first k elements of A. We want to perform zero or more pancake flips (doing them one after another in succession) to sort the array A. - * - * Return the k-values corresponding to a sequence of pancake flips that sort A. Any valid answer that sorts the array within 10 * A.length flips will be judged as correct. - * - * - * - * Example 1: - * - * - * Input: [3,2,4,1] - * Output: [4,2,4,3] - * Explanation: - * We perform 4 pancake flips, with k values 4, 2, 4, and 3. - * Starting state: A = [3, 2, 4, 1] - * After 1st flip (k=4): A = [1, 4, 2, 3] - * After 2nd flip (k=2): A = [4, 1, 2, 3] - * After 3rd flip (k=4): A = [3, 2, 1, 4] - * After 4th flip (k=3): A = [1, 2, 3, 4], which is sorted. - * - * - *
- * Example 2: - * - * - * Input: [1,2,3] - * Output: [] - * Explanation: The input is already sorted, so there is no need to flip anything. - * Note that other answers, such as [3, 3], would also be accepted. - * - * - * - *
- * - * Note: - * - *
    - * 1 <= A.length <= 100 - * A[i] is a permutation of [1, 2, ..., A.length] - *
- * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/pancake-sorting/ -// discuss: https://leetcode.com/problems/pancake-sorting/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn pancake_sort(a: Vec) -> Vec { - let len = a.len(); - if len <= 1 { - return Vec::new(); - } - let mut b = a.clone(); - let mut res: Vec = Vec::new(); - for i in 0..len { - if i == (len - 1) { - break; - } - let k = (len - i) as i32; - let index = Solution::find_k(&b, k); - if index == (k - 1) as usize { - continue; - } - if index != 0usize { - Solution::pancake_oper(&mut b, index, &mut res); - } - Solution::pancake_oper(&mut b, (k - 1) as usize, &mut res); - } - // println!("{:?}", b); - res - } - - fn find_k(a: &Vec, k: i32) -> usize { - for i in 0..(k - 1) { - if a[i as usize] == k { - return i as usize; - } - } - (k - 1) as usize - } - - pub fn pancake_oper(a: &mut Vec, index: usize, res: &mut Vec) { - let mut helper = Vec::new(); - for i in 0..(index + 1) { - helper.push(a[index - i]); - } - for i in 0..(index + 1) { - a[i] = helper[i]; - } - res.push((index + 1) as i32); - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - use rand::seq::SliceRandom; - use rand::{thread_rng, Rng}; - - #[test] - fn test_1009() { - for _i in 0..20 { - let mut rng = rand::thread_rng(); - let size = rng.gen_range(0, 1000); - let sorted_vector = make_sorted_vector(size); - let mut shuffled_vector = make_shuffled_vector(&sorted_vector); - let res = Solution::pancake_sort(shuffled_vector.clone()); - let oper_num = res.len(); - apply_pancake_sort_res(&mut shuffled_vector, res); - assert_eq!(shuffled_vector, sorted_vector); - assert!(oper_num < (size * 10) as usize); - } - } - - fn make_sorted_vector(i: i32) -> Vec { - (1..i + 1).collect() - } - - fn make_shuffled_vector(a: &Vec) -> Vec { - let mut rng = thread_rng(); - let mut res = a.clone(); - res.shuffle(&mut rng); - res - } - - fn apply_pancake_sort_res(shuffled_vecter: &mut Vec, oper: Vec) { - for i in oper { - pancake_oper(shuffled_vecter, (i - 1) as usize); - } - } - - pub fn pancake_oper(a: &mut Vec, index: usize) { - let mut helper = Vec::new(); - for i in 0..(index + 1) { - helper.push(a[index - i]); - } - for i in 0..(index + 1) { - a[i] = helper[i]; - } - } -} diff --git a/src/solution/s1018_binary_prefix_divisible_by_5.rs b/src/solution/s1018_binary_prefix_divisible_by_5.rs deleted file mode 100644 index b2bb1839..00000000 --- a/src/solution/s1018_binary_prefix_divisible_by_5.rs +++ /dev/null @@ -1,106 +0,0 @@ -/** - * [1071] Binary Prefix Divisible By 5 - * - * Given an array A of 0s and 1s, consider N_i: the i-th subarray from A[0] to A[i] interpreted as a binary number (from most-significant-bit to least-significant-bit.) - * - * Return a list of booleans answer, where answer[i] is true if and only if N_i is divisible by 5. - * - * Example 1: - * - * - * Input: [0,1,1] - * Output: [true,false,false] - * Explanation: - * The input numbers in binary are 0, 01, 011; which are 0, 1, and 3 in base-10. Only the first number is divisible by 5, so answer[0] is true. - * - * - * Example 2: - * - * - * Input: [1,1,1] - * Output: [false,false,false] - * - * - * Example 3: - * - * - * Input: [0,1,1,1,1,1] - * Output: [true,false,false,false,true,false] - * - * - * Example 4: - * - * - * Input: [1,1,1,0,1] - * Output: [false,false,false,false,false] - * - * - * - * - * Note: - * - *
    - * 1 <= A.length <= 30000 - * A[i] is 0 or 1 - *
- * - */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/binary-prefix-divisible-by-5/ -// discuss: https://leetcode.com/problems/binary-prefix-divisible-by-5/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -impl Solution { - pub fn prefixes_div_by5(a: Vec) -> Vec { - let mut ret = vec![]; - let mut n = 0; - for i in a { - let remain = (n * 2 + i) % 5; - ret.push(remain == 0); - n = remain; - } - - ret - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_1071() { - assert_eq!( - Solution::prefixes_div_by5(vec![0, 1, 1]), - vec![true, false, false] - ); - assert_eq!( - Solution::prefixes_div_by5(vec![1, 1, 1]), - vec![false, false, false] - ); - assert_eq!( - Solution::prefixes_div_by5(vec![0, 1, 1, 1, 1, 1]), - vec![true, false, false, false, true, false] - ); - assert_eq!( - Solution::prefixes_div_by5(vec![1, 1, 1, 0, 1]), - vec![false, false, false, false, false] - ); - assert_eq!( - Solution::prefixes_div_by5(vec![ - 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, - 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1 - ]), - vec![ - false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, true, false, false, true, true, - true, true, false - ] - ); - } -} diff --git a/src/solution/s1046_last_stone_weight.rs b/src/solution/s1046_last_stone_weight.rs deleted file mode 100644 index 871b4eb4..00000000 --- a/src/solution/s1046_last_stone_weight.rs +++ /dev/null @@ -1,78 +0,0 @@ -/** - * [1127] Last Stone Weight - * - * We have a collection of rocks, each rock has a positive integer weight. - * - * Each turn, we choose the two heaviest rocks and smash them together. Suppose the stones have weights x and y with x <= y. The result of this smash is: - * - * - * If x == y, both stones are totally destroyed; - * If x != y, the stone of weight x is totally destroyed, and the stone of weight y has new weight y-x. - * - * - * At the end, there is at most 1 stone left. Return the weight of this stone (or 0 if there are no stones left.) - * - * - * - * Example 1: - * - * - * Input: [2,7,4,1,8,1] - * Output: 1 - * Explanation: - * We combine 7 and 8 to get 1 so the array converts to [2,4,1,1,1] then, - * we combine 2 and 4 to get 2 so the array converts to [2,1,1,1] then, - * we combine 2 and 1 to get 1 so the array converts to [1,1,1] then, - * we combine 1 and 1 to get 0 so the array converts to [1] then that's the value of last stone. - * - * - * - * Note: - * - *
    - * 1 <= stones.length <= 30 - * 1 <= stones[i] <= 1000 - *
- */ -pub struct Solution {} - -// problem: https://leetcode.com/problems/last-stone-weight/ -// discuss: https://leetcode.com/problems/last-stone-weight/discuss/?currentPage=1&orderBy=most_votes&query= - -// submission codes start here - -use std::collections::BinaryHeap; -impl Solution { - pub fn last_stone_weight(stones: Vec) -> i32 { - let mut heap = BinaryHeap::new(); - heap.extend(stones); - loop { - if let Some(rock1) = heap.pop() { - if let Some(rock2) = heap.pop() { - if rock1 > rock2 { - heap.push(rock1 - rock2); - } - } else { - return rock1; - } - } else { - return 0; - } - } - } -} - -// submission codes end - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_1127() { - assert_eq!(Solution::last_stone_weight(vec![2, 7, 4, 1, 8, 1]), 1); - assert_eq!(Solution::last_stone_weight(vec![2]), 2); - assert_eq!(Solution::last_stone_weight(vec![2, 2]), 0); - assert_eq!(Solution::last_stone_weight(vec![1, 2, 2]), 1); - } -} diff --git a/src/util/linked_list.rs b/src/util/linked_list.rs index 37b18e3d..13d9b3c9 100644 --- a/src/util/linked_list.rs +++ b/src/util/linked_list.rs @@ -1,4 +1,6 @@ -#[derive(PartialEq, Eq, Debug)] +use std::cmp::Ordering; + +#[derive(PartialEq, Eq, Debug, Clone)] pub struct ListNode { pub val: i32, pub next: Option>, @@ -11,6 +13,19 @@ impl ListNode { } } +impl Ord for ListNode { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.val.cmp(&other.val) + } +} + +impl PartialOrd for ListNode { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + // helper function for test pub fn to_list(vec: Vec) -> Option> { let mut current = None; @@ -27,3 +42,22 @@ macro_rules! linked { ($($e:expr),*) => {to_list(vec![$($e.to_owned()), *])}; ($($e:expr,)*) => {to_list(vec![$($e.to_owned()), *])}; } + +#[macro_export] +macro_rules! list { + () => { + None::> + }; + ($x:expr$(,)?)=> { + Some(Box::new(ListNode::new($x))) + }; + ($x:expr$(,$y:expr)+$(,)?) => {{ + let mut head = Some(Box::new(ListNode::new($x))); + let mut next = &mut head; + $( + next = &mut next.as_mut().unwrap().next; + *next = Some(Box::new(ListNode::new($y))); + )* + head + }}; +} diff --git a/src/util/tree.rs b/src/util/tree.rs index dacda57d..093a6534 100644 --- a/src/util/tree.rs +++ b/src/util/tree.rs @@ -1,5 +1,4 @@ -use std::cell::RefCell; -use std::rc::Rc; +use std::{cell::RefCell, rc::Rc}; #[derive(Debug, PartialEq, Eq)] pub struct TreeNode {