-
Notifications
You must be signed in to change notification settings - Fork 0
1871. Jump Game VII #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
kitano-kazuki
wants to merge
1
commit into
main
Choose a base branch
from
1871-jump-game-7
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,91 @@ | ||
| # Step1 | ||
|
|
||
| ## Code1-1 | ||
|
|
||
| * O(N^2)になるので, TLEになった | ||
|
|
||
| ```python | ||
| import functools | ||
|
|
||
|
|
||
| class Solution: | ||
| def canReach(self, s: str, minJump: int, maxJump: int) -> bool: | ||
| @functools.cache | ||
| def can_reach_helper(i: int): | ||
| if i == len(s) - 1: | ||
| return s[i] == "0" | ||
|
|
||
| if s[i] == "1": | ||
| return False | ||
|
|
||
| for jump in range(minJump, maxJump + 1): | ||
| if i + jump >= len(s): | ||
| break | ||
| if can_reach_helper(i + jump): | ||
| return True | ||
|
|
||
| return False | ||
|
|
||
| return can_reach_helper(0) | ||
|
|
||
| ``` | ||
|
|
||
| ## Code1-2 | ||
|
|
||
| * O(N)でやりたい | ||
| * 各インデックスごとに, いける範囲を引き継ぐ | ||
| * `s = "011010", minJump = 2, maxJump = 3` | ||
| * `01[10]10` | ||
| * `01101[0` | ||
| * `s = "010010", minJump = 2, maxJump = 3` | ||
| * `01[00]10` | ||
| * `01[00](10)` | ||
| * 範囲の右端にきたら, その範囲はそれ以上残しておく必要はない | ||
| * 範囲の寿命は, その範囲の右端にくるまでだから, 範囲の長さ(最大でN) | ||
| * 各インデックスごとに, 対象の範囲をみるとすると, 結局最大でO(N^2)になる | ||
| * いける範囲に重なりがあるから, それをうまいこと対処できたら嬉しい気がする | ||
| * これが常に2区間に抑えられるならいいけど、飛び石上になっていたらめんどう | ||
| * `01110000000000, min=4, max=5` | ||
| * `0111[00]00000000` | ||
| * `0111[00]00(00)0000` | ||
| * `0111[00]00(0{0)0}000` | ||
| * `0111[00]00(0{0)0}0|00|` | ||
| * `0111[00]00(0{0)0}0|0"0|` | ||
| * 到達可能かどうかをTrue/Falseで保存しておく | ||
| * Trueとなっている0の値に到達するたびに, 配列を更新する | ||
| * すでにいけると更新をしたおしりは記録しておく | ||
| * `010010`, `TFFFFF` | ||
| * `0100|10`, `TFTTFF` | ||
| * `010010|`, `TFTTFT` | ||
| * ある時点iでいけない点j(s[j]=0)があったとき, i以降のs[k]=0となる点をもってしても, jには到達できない | ||
| * AC | ||
|
|
||
|
|
||
| ```python | ||
| class Solution: | ||
| def canReach(self, s: str, minJump: int, maxJump: int) -> bool: | ||
| if not s: | ||
| return True | ||
| if s[0] == "1": | ||
| return False | ||
|
|
||
| reachable = [False] * len(s) | ||
| reachable[0] = True | ||
|
|
||
| updated_tail = 0 | ||
| for i in range(len(s)): | ||
| if updated_tail >= len(s): | ||
| break | ||
| if s[i] == "1": | ||
| continue | ||
| if not reachable[i]: | ||
| continue | ||
| for j in range(max(updated_tail + 1, i + minJump), min(len(s), i + maxJump + 1)): | ||
| if s[j] == "0": | ||
| reachable[j] = True | ||
|
|
||
| updated_tail = i + maxJump | ||
|
|
||
| return reachable[-1] | ||
|
|
||
| ``` | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
自分でも解いてみまし。シンプルな解法が思いつかず、 range query を平方分割で実装して解きました。初めは Binary Indexed Tree を二次元配列で書き始めたのですが、更新部分が上手く書けず、平方分割に逃げました。
供養のために貼っておきます。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reached_sqrt_count[i]はバケットiのうち到達可能な個数を表しているのですか?この部分の更新は, バケット内すべてを到達可能とみなしているように思いましたが、バケット内のインデックスjで
s[j]=1なるjに対しても, 到達可能としていることになりませんか?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
その理解であっているように思います。
本来やりたいことは reached の [begin, end) の範囲を true にすることです。一方、これには O(N) かかります。これを避けるため、 reached を sqrt(reached.size()) 個のバケットに分け、 reached の [left, right) の範囲を true とする代わりに、対応する reached_sqrt_count を BASE に設定しています。これによりO(sqrt(N)) になります。
また、 get() する際に、 reached_sqrt_count が BASE となっている、つまりバケット内のすべての reached が true となっているか、 reached[index] のどちらがが true となっていれば、 true を返すようにしています。
ただ、 set() が間違っていることに気づきました。正しくは以下の通りです。
元のコードでも Accepted してしまっていました。 LeetCode のテストケースが弱かったためだと思います。
なお、平方分割はソフトウェアエンジニアの常識には含まれていないと思います。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
理解できました。平方分割は自分もよくわからなくて調べながら理解したのですが、解法として浮かんでいなかったので勉強になりました。