-
Notifications
You must be signed in to change notification settings - Fork 0
387. First Unique Character in a String #28
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
hayashi-ay
wants to merge
4
commits into
main
Choose a base branch
from
hayashi-ay-patch-17
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
Show all changes
4 commits
Select commit
Hold shift + click to select a range
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 |
---|---|---|
@@ -0,0 +1,107 @@ | ||
愚直にやるなら前から1文字ずつ見ていってそれぞれ重複がないかを調べる。計算量は $O(n^2)$ で問題の設定上nは最大10^5になるので10^10になりTLEしそうなので別の解法を考える必要がある。 | ||
あらかじめユニークな文字を求めたあとで前から見ていけば $O(n)$ でいける。ユニークを求める方法は、各文字の登場回数をカウンティングしたりする感じで良さそう。 | ||
ただ上記の方法では2周する必要がある。後ろから見ていって、最後に初めて登場した文字を覚えていれば1回文字列を後ろからなめるだけで解けそう。← と思ったけどそんなことはなくて結構大変そう。 | ||
|
||
|
||
1st | ||
|
||
文字の登場回数をあらかじめカウントする。 | ||
英アルファベット小文字をインデックス値に変換する処理は関数に切り出しても良いがtoo muchか。 | ||
|
||
```python | ||
class Solution: | ||
def firstUniqChar(self, s: str) -> int: | ||
freq = [0] * 26 | ||
for c in s: | ||
freq[ord(c) - ord('a')] += 1 | ||
for i, c in enumerate(s): | ||
if freq[ord(c) - ord('a')] == 1: | ||
return i | ||
return -1 | ||
``` | ||
|
||
2nd | ||
|
||
1stでは課題の制約で英アルファベット小文字のみだったので配列で管理したがdictを使う版でも解いた。Counterを使っても良い。 | ||
|
||
```python | ||
class Solution: | ||
def firstUniqChar(self, s: str) -> int: | ||
freq = defaultdict(int) | ||
for c in s: | ||
freq[c] += 1 | ||
for i, c in enumerate(s): | ||
if freq[c] == 1: | ||
return i | ||
return -1 | ||
``` | ||
|
||
Counterを使った版 | ||
|
||
```python | ||
class Solution: | ||
def firstUniqChar(self, s: str) -> int: | ||
freq = Counter(s) | ||
for i, c in enumerate(s): | ||
if freq[c] == 1: | ||
return i | ||
return -1 | ||
``` | ||
|
||
3rd | ||
|
||
1stと同じ。 | ||
|
||
```python | ||
class Solution: | ||
def firstUniqChar(self, s: str) -> int: | ||
freq = [0] * 26 | ||
for c in s: | ||
freq[ord(c) - ord('a')] += 1 | ||
for i, c in enumerate(s): | ||
if freq[ord(c) - ord('a')] == 1: | ||
return i | ||
return -1 | ||
``` | ||
|
||
4th | ||
|
||
1から3と違いsを1回だけなめる。登場したindexの位置と2回以上登場したかどうかは別に管理しても良いが一旦infが2回以上登場したと扱って1つで管理するようにした。 | ||
minを使っている部分は、Python3.7からdictへの追加順が仕様として保証されるようになったので他に書きようがある。 | ||
1から3だと`aaaaaaaaaa ... b`みたいな文字だと2周する必要があったのでこちらの方が1周で済む分良い。 | ||
|
||
```python | ||
class Solution: | ||
def firstUniqChar(self, s: str) -> int: | ||
char_to_first_appear_index = {} | ||
for index, c in enumerate(s): | ||
if c in char_to_first_appear_index: | ||
char_to_first_appear_index[c] = inf | ||
else: | ||
char_to_first_appear_index[c] = index | ||
min_index = min(char_to_first_appear_index.values()) | ||
if min_index == inf: | ||
return -1 | ||
return min_index | ||
``` | ||
|
||
4-1をベースに書き直し。登場したindexの位置と重複しているかを別で管理するように。Pythonのdictの追加順が保存されていることを利用するように。 | ||
https://docs.python.org/3/library/stdtypes.html#dictionary-view-objects | ||
|
||
```python | ||
class Solution: | ||
def firstUniqChar(self, s: str) -> int: | ||
char_to_first_appear_index = {} | ||
duplicated = set() | ||
for index, c in enumerate(s): | ||
if c in duplicated: | ||
continue | ||
if c in char_to_first_appear_index: | ||
del char_to_first_appear_index[c] | ||
duplicated.add(c) | ||
continue | ||
char_to_first_appear_index[c] = index | ||
if not char_to_first_appear_index: | ||
return -1 | ||
return next(iter(char_to_first_appear_index.values())) | ||
``` |
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 |
---|---|---|
@@ -0,0 +1,20 @@ | ||
1st | ||
|
||
```java | ||
class Solution { | ||
public int firstUniqChar(String s) { | ||
HashMap<Character, Integer> charToFreq = new HashMap<>(); | ||
|
||
for (char c: s.toCharArray()) { | ||
int prevFreq = charToFreq.getOrDefault(c, 0); | ||
charToFreq.put(c, prevFreq + 1); | ||
} | ||
for (int i = 0; i < s.length(); i++) { | ||
if (charToFreq.get(s.charAt(i)) == 1) { | ||
return i; | ||
} | ||
} | ||
return -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.
listを使った解法にしたんですね。
想定外の文字列が入ってたらエラーになるので、dictのほうが安全かつ分かりやすいと思いました。
今回は英アルファベット小文字のみの制約があるので、気にし過ぎたコメントかもしれません。
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.
コメントありがとうございます。
まあ何を想定するかですかねー。英アルファベット小文字が来ることが担保できる状況ならハッシュ処理が入らない固定長のlistを使った方が早いと思ったのでlistの解法にしました。アルファベットをインデックス値に変換する処理が入るのでその分複雑にはなりますね。
dictは前提条件が変わって文字種が増えた際などにそのまま使い回せるので良いと思います。
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.
まあでもとりあえず書くならdictの方が良い気がしてきました。そのうえで入力値の制約下でパフォーマンスを向上させたいなどの要件があった際にlistを使った方を書く方がいいですね。