Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions 01-15/4.First-Unique-Character-in-a-String/1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#if __has_include("../debug.hpp")
#include "../debug.hpp"
#endif
// ここまでローカルでのデバッグ用なので気にしないでください --------------------

#include <bits/stdc++.h>

using namespace std;

// <時間>
// 18分
// <感想>
// 一周回って変なことしてしまったと思う
// 原因があるとすれば、O(2N)=O(N)を体で理解していないこと?
// それでも実行時間は早いかなと思ったら全然早くなかった
// 可能性があるとすればO(N)かかる方のif文の分岐かな
// 反省のために残しておく

// なお以下で出てくるコメントはプロダクト版にも書くつもりのコメント
class Solution {
public:
int firstUniqChar(string s) {
vector<int> indexes(26, -1);
vector<bool> is_repeated(26);
for (int i = 0; i < s.size(); ++i) {
auto alpha = s[i] - 'a';
if (indexes[alpha] == -1) {
indexes[alpha] = i;
} else {
is_repeated[alpha] = true;
}
}

int min_index = s.size();
for (int alpha = 0; alpha < 26; ++alpha) {
if (indexes[alpha] != -1 && !is_repeated[alpha]) {
min_index = min(min_index, indexes[alpha]);
}
}

return min_index != s.size() ? min_index : -1;
}
};
29 changes: 29 additions & 0 deletions 01-15/4.First-Unique-Character-in-a-String/2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#if __has_include("../debug.hpp")
#include "../debug.hpp"
#endif
// ここまでローカルでのデバッグ用なので気にしないでください --------------------

#include <bits/stdc++.h>

using namespace std;

// <時間>
// 1分
// <疑問・不安点(・個人的な感想、違う意見があれば教えてほしいもの)>
// - s[i] - 'a'が初見で伝わるのか問題
// - countsの他の命名候補としてalpha_countsがあった

// なお以下で出てくるコメントはプロダクト版にも書くつもりのコメント
class Solution {
public:
int firstUniqChar(string s) {
vector<int> counts(26);
for (int i = 0; i < s.size(); ++i) {
++counts[s[i] - 'a'];
}
for (int i = 0; i < s.size(); ++i) {
if (counts[s[i] - 'a'] == 1) return i;
}
return -1;
}
};
26 changes: 26 additions & 0 deletions 01-15/4.First-Unique-Character-in-a-String/3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#if __has_include("../../debug.hpp")
#include "../../debug.hpp"
#endif
// ここまでローカルでのデバッグ用なので気にしないでください --------------------

#include <algorithm>

using namespace std;

// <時間>
// 1分
// <疑問・不安点(・個人的な感想、違う意見があれば教えてほしいもの)>
class Solution {
public:
int firstUniqChar(string s) {
int alphabet_to_count[26];
fill(alphabet_to_count, alphabet_to_count + 26, 0);
for (auto c : s) {
++alphabet_to_count[c - 'a'];
}
for (int i = 0; i < s.size(); ++i) {
if (alphabet_to_count[s[i] - 'a'] == 1) return i;
}
return -1;
}
};
75 changes: 75 additions & 0 deletions 01-15/4.First-Unique-Character-in-a-String/Ex1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <algorithm>
#if __has_include("../debug.hpp")
#include "../debug.hpp"
#endif
// ここまでローカルでのデバッグ用なので気にしないでください --------------------

#include <bits/stdc++.h>

using namespace std;

// こちらは番外編です。入力がstreamだったときです。
// <時間>
// Ex2も併せて13分
// <疑問・不安点(・個人的な感想、違う意見があれば教えてほしいもの)>
// - 2バージョン作っている。
// Ex2の方がメモリもコード量も少なくて好きなのだが、アクロバティックなので
// 可読性大丈夫かな…と思って無印の方も残している。
// なお、intの代わりにsize_tを使えばフラグと値の範囲が実際被ることはない。
// string::nposだってstatic_cast<size_t>(-1)である。

// なお以下で出てくるコメントはプロダクト版にも書くつもりのコメント
class SolutionStream {
public:
SolutionStream() : is_repeated(26), last_indexes(26, -1), index(0) {}

int firstUniqChar(char c) {
int alpha = c - 'a';
if (last_indexes[alpha] == -1) {
last_indexes[alpha] = index;
} else {
is_repeated[alpha] = true;
}

int min_index = INT_MAX;
for (int alpha = 0; alpha < 26; ++alpha) {
if (last_indexes[alpha] != -1 && !is_repeated[alpha]) {
min_index = min(min_index, last_indexes[alpha]);
}
}

return min_index != INT_MAX ? min_index : -1;
}

private:
vector<int> is_repeated;
vector<int> last_indexes;
int index;
};

class SolutionStream2 {
public:
SolutionStream2() : first_index_or_repeated(26, kNotUsed), index(0) {}

int firstUniqChar(char c) {
int alpha = c - 'a';
if (first_index_or_repeated[alpha] == kNotUsed) {
first_index_or_repeated[alpha] = index;
} else {
first_index_or_repeated[alpha] = kRepeated;
}
++index;

auto first_index = *min_element(
first_index_or_repeated.begin(), first_index_or_repeated.end()
);

return first_index < index ? first_index : -1;
}

private:
static constexpr int kNotUsed = INT_MAX;
static constexpr int kRepeated = INT_MAX - 1;
vector<int> first_index_or_repeated;
int index;
};
75 changes: 75 additions & 0 deletions 01-15/4.First-Unique-Character-in-a-String/Ex2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#if __has_include("../../debug.hpp")
#include "../../debug.hpp"
#endif
// ここまでローカルでのデバッグ用なので気にしないでください --------------------

#include <queue>
#include <set>
#include <stdexcept>

using namespace std;

// こちらは番外編です。入力がintのstreamだったときです。
// <時間>
// 15分
// <疑問・不安点(・個人的な感想、違う意見があれば教えてほしいもの)>
// - 若干分かりにくかったが、もう一度書き直したらわかりやすくなった
class SolutionStream {
public:
int firstUniqueNum(int num) {
if (duplicated_numbers.contains(num)) {
if (numbers.empty()) throw new range_error("No unique number was found");
return numbers.front();
}

if (auto it = unique_numbers.find(num); it != unique_numbers.end()) {
unique_numbers.erase(it);
duplicated_numbers.insert(num);
} else {
unique_numbers.insert(num);
numbers.push(num);
}

while (!numbers.empty() && duplicated_numbers.contains(numbers.front())) {
numbers.pop();
}

if (numbers.empty()) throw new range_error("No unique number was found");
return numbers.front();
}

private:
queue<int> numbers;
set<int> unique_numbers;
set<int> duplicated_numbers;
};

// <時間>
// 不明
// <疑問・不安点(・個人的な感想、違う意見があれば教えてほしいもの)>
class SolutionStream2 {
public:
int firstUniqueNum(int num) {
if (duplicated_numbers.contains(num)) {
if (numbers.empty()) throw new range_error("No unique number was found");
return numbers.front();
}
if (auto it = unique_numbers.find(num); it != unique_numbers.end()) {
unique_numbers.erase(it);
duplicated_numbers.insert(num);
while (!numbers.empty() && duplicated_numbers.contains(numbers.front())) {
numbers.pop();
}
if (numbers.empty()) throw new range_error("No unique number was found");
} else {
unique_numbers.insert(num);
numbers.push(num);
}
return numbers.front();
}

private:
queue<int> numbers;
set<int> unique_numbers;
set<int> duplicated_numbers;
};
3 changes: 3 additions & 0 deletions 01-15/4.First-Unique-Character-in-a-String/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 387. First Unique Character in a String

<https://leetcode.com/problems/first-unique-character-in-a-string/description/>