File tree Expand file tree Collapse file tree 8 files changed +298
-0
lines changed Expand file tree Collapse file tree 8 files changed +298
-0
lines changed Original file line number Diff line number Diff line change
1
+ /*
2
+ Solve Time: 4:20
3
+
4
+ Time: O(n)
5
+ Space: O(1)
6
+
7
+ 一回の走査で解けないかを軽く模索したが思いつかなかったので愚直にmapで記録し、二回ループする手法で解いた。
8
+ 一回の走査で解くことに固執しかけて時間を無駄に思想になっていたため、そこに気づけた点が個人的によかった
9
+ */
10
+ class Solution {
11
+ public:
12
+ int firstUniqChar (string s) {
13
+ map<char , int > character_to_count;
14
+ for (const auto & c : s) {
15
+ character_to_count[c]++;
16
+ }
17
+ for (int i = 0 ; i < s.size () ; i++) {
18
+ if (character_to_count[s[i]] == 1 ) {
19
+ return i;
20
+ }
21
+ }
22
+ return -1 ;
23
+ }
24
+ };
Original file line number Diff line number Diff line change
1
+ /*
2
+ Time: O(n)
3
+ Space: O(1)
4
+
5
+ step1の改良、マジックナンバーを定数にした
6
+ */
7
+ class Solution {
8
+ public:
9
+ int firstUniqChar (string s) {
10
+ map<char , int > character_to_count;
11
+ for (const auto & c : s) {
12
+ character_to_count[c]++;
13
+ }
14
+ for (int i = 0 ; i < s.size (); i++) {
15
+ if (character_to_count[s[i]] == 1 ) {
16
+ return i;
17
+ }
18
+ }
19
+
20
+ int const kNotFound = -1 ;
21
+ return kNotFound ;
22
+ }
23
+ };
Original file line number Diff line number Diff line change
1
+ /*
2
+ Time : O(N log N)
3
+ Space : O(N)
4
+
5
+ https://github.com/kazukiii/leetcode/pull/16/files#diff-f400dc0fa41a78f5b2a9ec5c2d5364dd8cf0da8dc9e8c39d15f52f98ea05394b
6
+ を参考にした解法。
7
+ 平衡木(mapのkey)を利用して文字の初出インデックスを管理。
8
+ 二度目の出現でインデックスを削除することで、平衡木の先頭には一度しか出現していない文字のインデックスが残る。
9
+ 3度以上の出現で削除した要素が復帰してしまうが、インデックスが大きいため結果に影響しない。
10
+ */
11
+ class Solution {
12
+ public:
13
+ int firstUniqChar (string s) {
14
+ map<char , int > character_to_first_index;
15
+ map<int , char > index_to_character;
16
+ for (int i = 0 ; i < s.size (); i++) {
17
+ char c = s[i];
18
+ if (character_to_first_index.contains (c)) {
19
+ int first_index = character_to_first_index[c];
20
+ index_to_character.erase (first_index);
21
+ continue ;
22
+ }
23
+ character_to_first_index[c] = i;
24
+ index_to_character[i] = c;
25
+ }
26
+ if (index_to_character.empty ()) {
27
+ const int kNotFound = -1 ;
28
+ return kNotFound ;
29
+ }
30
+ return index_to_character.begin ()->first ;
31
+ }
32
+ };
Original file line number Diff line number Diff line change
1
+ /*
2
+ https://github.com/colorbox/leetcode/pull/29#discussion_r1861430039
3
+ を見てそれを参考に自分で書いた解法、比較用
4
+ */
5
+ class Solution {
6
+ public:
7
+ int firstUniqChar (string s) {
8
+ queue<CharacterAndCount> queue;
9
+ map<char , int > character_to_count;
10
+ for (int i = 0 ; i < s.size (); i++) {
11
+ char c = s[i];
12
+ character_to_count[c]++;
13
+ queue.push ({c, i});
14
+ while (true ) {
15
+ char front_character = queue.front ().character ;
16
+ if (character_to_count[front_character] > 1 ) {
17
+ queue.pop ();
18
+ } else {
19
+ break ;
20
+ }
21
+ }
22
+ }
23
+ if (queue.empty ()) {
24
+ return -1 ;
25
+ }
26
+ return queue.front ().index ;
27
+ }
28
+
29
+ private:
30
+ struct CharacterAndCount {
31
+ char character;
32
+ int index;
33
+ };
34
+ };
Original file line number Diff line number Diff line change
1
+ /*
2
+ step2_2_suggested.cpp
3
+ を
4
+ https://github.com/colorbox/leetcode/pull/29#discussion_r1861430039
5
+ の書き方に沿って修正したコード、参照用
6
+ */
7
+ class Solution {
8
+ public:
9
+ int firstUniqChar (string s) {
10
+ queue<CharacterAndCount> characters;
11
+ map<char , int > character_to_count;
12
+ for (int i = 0 ; i < s.size (); ++i) {
13
+ char c = s[i];
14
+ ++character_to_count[c];
15
+ characters.push ({c, i});
16
+ while (character_to_count[characters.front ().character ] >= 2 ) {
17
+ characters.pop ();
18
+ }
19
+ }
20
+ if (characters.empty ()) {
21
+ return -1 ;
22
+ }
23
+ return characters.front ().index ;
24
+ }
25
+
26
+ private:
27
+ struct CharacterAndCount {
28
+ char character;
29
+ int index;
30
+ };
31
+ };
Original file line number Diff line number Diff line change
1
+ /*
2
+ Time : O(N log N)
3
+ Space : O(N)
4
+
5
+ https://github.com/kazukiii/leetcode/pull/16/files#diff-f5b3276a9df261ed1c1e70d5b6de00ca4544e1a1ae1de6a466add8df5cd3d1b0
6
+ を参考にした解法。
7
+ ソートで文字種ごとに隣接させ、二度以上出現したものを除外し、min比較で最小インデックスを求める。
8
+ */
9
+ class Solution {
10
+ public:
11
+ int firstUniqChar (string s) {
12
+ vector<CharacterIndex> character_indices;
13
+ for (int i = 0 ; i < s.size (); i++) {
14
+ character_indices.push_back ({s[i], i});
15
+ }
16
+ sort (character_indices.begin (), character_indices.end ());
17
+ int count = 1 ;
18
+ int first_unique_character_index = numeric_limits<int >::max ();
19
+ for (int i = 0 ; i < s.size (); i++) {
20
+ if (i < s.size () - 1 && character_indices[i].character == character_indices[i + 1 ].character ) {
21
+ count++;
22
+ continue ;
23
+ }
24
+ if (count == 1 ) {
25
+ first_unique_character_index = min (first_unique_character_index, character_indices[i].index );
26
+ }
27
+ count = 1 ;
28
+ }
29
+ if (first_unique_character_index == numeric_limits<int >::max ()) {
30
+ return -1 ;
31
+ }
32
+ return first_unique_character_index;
33
+ }
34
+
35
+ struct CharacterIndex {
36
+ char character;
37
+ int index;
38
+
39
+ bool operator <(const CharacterIndex& other) {
40
+ return character < other.character ;
41
+ }
42
+ };
43
+ };
Original file line number Diff line number Diff line change
1
+ /*
2
+ Time : O(N)
3
+ Space : O(1)
4
+
5
+ LRUを応用してできるとのことだったので実装。
6
+ https://www.geeksforgeeks.org/lru-cache-implementation-using-double-linked-lists/
7
+ 本質的に平衡木による解法と大差ない気がする。
8
+ */
9
+ struct Node {
10
+ int index;
11
+ int count;
12
+ Node* prev;
13
+ Node* next;
14
+
15
+ explicit Node (int i) {
16
+ index = i;
17
+ count = 1 ;
18
+ prev = nullptr ;
19
+ next = nullptr ;
20
+ }
21
+ };
22
+
23
+ class LRUCache {
24
+ public:
25
+ Node* head;
26
+ Node* tail;
27
+ map<char , Node*> character_to_node;
28
+
29
+ LRUCache () {
30
+ head = new Node (numeric_limits<int >::max ());
31
+ tail = new Node (numeric_limits<int >::max ());
32
+ head->next = tail;
33
+ tail->prev = head;
34
+ }
35
+
36
+ ~LRUCache () {
37
+ for (auto [_c, node] : character_to_node) {
38
+ delete node;
39
+ }
40
+ delete head;
41
+ delete tail;
42
+ }
43
+
44
+ void Put (char character, int index) {
45
+ if (character_to_node.contains (character)) {
46
+ Node *node = character_to_node[character];
47
+ Remove (node);
48
+ node->count ++;
49
+ return ;
50
+ }
51
+
52
+ Node *node = new Node (index);
53
+ character_to_node[character] = node;
54
+ PushBack (node);
55
+ }
56
+
57
+ bool Empty () {
58
+ return head->next ->index == tail->index ;
59
+ }
60
+
61
+ private:
62
+ void Remove (Node* node) {
63
+ if (node->prev == nullptr ) {
64
+ return ;
65
+ }
66
+ Node* prev = node->prev ;
67
+ Node* next = node->next ;
68
+ prev->next = next;
69
+ next->prev = prev;
70
+ node->prev = nullptr ;
71
+ node->next = nullptr ;
72
+ }
73
+
74
+ void PushBack (Node* node) {
75
+ Node* prev = tail->prev ;
76
+ prev->next = node;
77
+ node->prev = prev;
78
+ node->next = tail;
79
+ tail->prev = node;
80
+ }
81
+ };
82
+
83
+ class Solution {
84
+ public:
85
+ int firstUniqChar (string s) {
86
+ LRUCache cache = LRUCache ();
87
+ for (int i = 0 ; i < s.size (); i++) {
88
+ cache.Put (s[i], i);
89
+ }
90
+ if (cache.Empty () || cache.head ->next ->count > 1 ) {
91
+ return -1 ;
92
+ }
93
+ return cache.head ->next ->index ;
94
+ }
95
+ };
96
+
Original file line number Diff line number Diff line change
1
+ class Solution {
2
+ public:
3
+ int firstUniqChar (string s) {
4
+ map<char , int > character_to_count;
5
+ for (const char & c : s) {
6
+ character_to_count[c]++;
7
+ }
8
+ for (int i = 0 ; i < s.size (); i++) {
9
+ if (character_to_count[s[i]] == 1 ) {
10
+ return i;
11
+ }
12
+ }
13
+ return -1 ;
14
+ }
15
+ };
You can’t perform that action at this time.
0 commit comments