diff --git a/1/1. TWO SUM.md b/1/1. TWO SUM.md new file mode 100644 index 0000000..51dcdd8 --- /dev/null +++ b/1/1. TWO SUM.md @@ -0,0 +1,103 @@ +# [1. TWO SUM](https://leetcode.com/problems/two-sum/description/) + +## Step1 +### 問題意図の考察 + + - 整数配列 numsと整数 targetに対して、合計がtargetになる数のindexを返す + - 問題文にある条件の確認 + 1. 必ずちょうど一つの解が存在する + 2. 同じ要素を返してはいけない + 3. インデックスを返す順番はどちらでもいい + 4. 1.exactly one solution -> 「複数解をどう扱うか」を考えなくでOK、つまり即return + + - 制約の確認 + 1. 配列numsの長さ、要素数は、2 ~ 10,000 -> 最大要素数は10,000で単純ループだと1億回 + 2. 配列numsの各要素nums[i]は、-1,000,000,000 ~ +1,000,000,000 + -> 大きな数や小さな数が出てくることもあるから値に依存したアルゴリズムは不向きかな + -> C++ int(32bits)は、おおよそ-2,174,483,648 ~ -2,174,483,647、nums[i]は+-10^9なので合計もintの範囲内でintOK。オーバーフローはしない,問題文通り + 3. targetの値も、+-10^9の間、intOK + - ここでは「1億回の比較O(n^2)」くらいだと、0.05 ~ 0.3秒前後でそんなに時間が掛からないが、よりベターな方法を探したい。 + - ペアを探す。つまり、補数を探す。O(1)での探索 + -> nums[i] + nums[j] = target + -> nums[j] = target - nums[i] + - 値ではなく、indexで返せるか + +### 解法を考える。 + - 整数配列nums、整数targetで、nums[i] + nums[j] = targetとなるインデックスi, jを探す + - 問題文から補数を探す、今回はハッシュマップ unordered_mapで良さそう + - 整理すると、 + 1. 配列を左から順番に要素をみる + 2. nums[j] = target - nums[i] はあるか探索 + 3. ある時、あったよ + 4. ない時、nums[i]は見たよと記録して次 + + +初回の回答 +```cpp +#include +#include + + +class Solution { +public: + std::vector twoSum(std::vector& nums, int target) { + std::unordered_map num_to_index; + for (int i = 0; i < nums.size(); ++i) { + int complement = target - nums[i]; + if (num_to_index.count(complement)) { + return std::vector{num_to_index[complement], i}; + } + num_to_index[nums[i]] = i; + } + return std::vector{}; + } +}; + +``` + + +## Step2 + - 初回同じキーに対してハッシュを2回使用しているので、find()という書き方も + - find rerturn に対しては、{}を返せる + - 「符号付きと符号なしの比較」あたりの修正。気づかなかった。 + +```cpp +#include +#include + + +class Solution { +public: + std::vector twoSum(std::vector& nums, int target) { + std::unordered_map num_to_index; + for (int i = 0; i < static_cast(nums.size()); ++i) { + int complement = target - nums[i]; + auto it = num_to_index.find(complement); + if (it != num_to_index.end()) { + return std::vector{it->second, i}; + } + num_to_index[nums[i]] = i; + } + return {}; + } +}; + +``` + + - map&unordered_map復習(以下リンク) + - 選択の基準としては、要素の数・順序・セキュリティ・最悪計算量・小さいところでのメモリ使用量あたり + - https://github.com/ryosuketc/leetcode_grind75/pull/1/commits/2c5161514b4561a34193852a2a218603b35ca734#r2249075780 + - https://chromium.googlesource.com/chromium/src/+/master/base/containers/README.md#Map-and-set-selection-Usage-advice + - https://stackoverflow.com/questions/3902644/choosing-between-stdmap-and-stdunordered-map + +### 参考GitHub + - https://github.com/ryosuketc/leetcode_grind75/pull/1/commits/2c5161514b4561a34193852a2a218603b35ca734 + - https://github.com/Ryotaro25/leetcode_first60/pull/12/commits/9c80068466e83724dc9004bca374e26f2b130b95 + + +## Step3 +6min +7min +5min +5min +5min