From aace3dd127df8922ff14f17ef04e8d974ed2997f Mon Sep 17 00:00:00 2001 From: ryo <34418898+ryoooooory@users.noreply.github.com> Date: Mon, 8 Jul 2024 22:48:03 +0900 Subject: [PATCH 01/15] Create step1.java --- .../step1.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 373. Find K Pairs with Smallest Sums/step1.java diff --git a/373. Find K Pairs with Smallest Sums/step1.java b/373. Find K Pairs with Smallest Sums/step1.java new file mode 100644 index 0000000..6225ae4 --- /dev/null +++ b/373. Find K Pairs with Smallest Sums/step1.java @@ -0,0 +1,28 @@ +class Solution { + public List> kSmallestPairs(int[] nums1, int[] nums2, int k) { + int length1 = nums1.length; + int length2 = nums2.length; + List> kSmallestPairs = new ArrayList<>(); + Set> visited = new HashSet<>(); + + PriorityQueue minSums = new PriorityQueue<>((a, b) -> a[0] - b[0]); + minSums.add(new int[] {nums1[0] + nums2[0], 0, 0}); + visited.add(new Pair(0, 0)); + + while(kSmallestPairs.size() < k && !minSums.isEmpty()) { + int[] currentMinPair = minSums.poll(); + int index1 = currentMinPair[1]; + int index2 = currentMinPair[2]; + kSmallestPairs.add(List.of(nums1[index1], nums2[index2])); + if (index1 + 1 < length1 && !visited.contains(new Pair(index1 + 1, index2))) { + minSums.add(new int[] {nums1[index1 + 1] + nums2[index2], index1 + 1, index2}); + visited.add(new Pair(index1 + 1, index2)); + } + if (index2 + 1 < length2 && !visited.contains(new Pair(index1, index2 + 1))) { + minSums.add(new int[] {nums1[index1] + nums2[index2 + 1], index1, index2 + 1}); + visited.add(new Pair(index1, index2 + 1)); + } + } + return kSmallestPairs; + } +} From 3cde1213fccf61236d2f3e94e65a5b6a267f90a5 Mon Sep 17 00:00:00 2001 From: ryo <34418898+ryoooooory@users.noreply.github.com> Date: Mon, 8 Jul 2024 23:06:38 +0900 Subject: [PATCH 02/15] Create note.md --- 373. Find K Pairs with Smallest Sums/note.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 373. Find K Pairs with Smallest Sums/note.md diff --git a/373. Find K Pairs with Smallest Sums/note.md b/373. Find K Pairs with Smallest Sums/note.md new file mode 100644 index 0000000..5e2fe59 --- /dev/null +++ b/373. Find K Pairs with Smallest Sums/note.md @@ -0,0 +1,6 @@ +# step1 +時間計算量: O(klogk), 空間計算量: O(k) +全探索しか思い浮かばず、ACできなかった。 +回答をみて理解してその通りに実装(変数名のリネームはおこなった。) + +# step2 From 998ec1c54b7aaca4e0bffba0fb8880dcd8dac82f Mon Sep 17 00:00:00 2001 From: ryo <34418898+ryoooooory@users.noreply.github.com> Date: Mon, 8 Jul 2024 23:10:40 +0900 Subject: [PATCH 03/15] Create step2.java --- 373. Find K Pairs with Smallest Sums/step2.java | 1 + 1 file changed, 1 insertion(+) create mode 100644 373. Find K Pairs with Smallest Sums/step2.java diff --git a/373. Find K Pairs with Smallest Sums/step2.java b/373. Find K Pairs with Smallest Sums/step2.java new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/373. Find K Pairs with Smallest Sums/step2.java @@ -0,0 +1 @@ + From d62e36a8c6f2cbedceb0d2f9566218e727bfcc93 Mon Sep 17 00:00:00 2001 From: ryo <34418898+ryoooooory@users.noreply.github.com> Date: Mon, 8 Jul 2024 23:12:53 +0900 Subject: [PATCH 04/15] Update step1.java --- 373. Find K Pairs with Smallest Sums/step1.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/373. Find K Pairs with Smallest Sums/step1.java b/373. Find K Pairs with Smallest Sums/step1.java index 6225ae4..4eda67a 100644 --- a/373. Find K Pairs with Smallest Sums/step1.java +++ b/373. Find K Pairs with Smallest Sums/step1.java @@ -9,7 +9,7 @@ public List> kSmallestPairs(int[] nums1, int[] nums2, int k) { minSums.add(new int[] {nums1[0] + nums2[0], 0, 0}); visited.add(new Pair(0, 0)); - while(kSmallestPairs.size() < k && !minSums.isEmpty()) { + while(kSmallestPairs.size() < k) { int[] currentMinPair = minSums.poll(); int index1 = currentMinPair[1]; int index2 = currentMinPair[2]; From 32ccdcdd69b496e043f5d010d9e58dfae5011639 Mon Sep 17 00:00:00 2001 From: ryo <34418898+ryoooooory@users.noreply.github.com> Date: Mon, 8 Jul 2024 23:13:31 +0900 Subject: [PATCH 05/15] Update and rename step2.java to step2-1.java --- .../step2-1.java | 28 +++++++++++++++++++ .../step2.java | 1 - 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 373. Find K Pairs with Smallest Sums/step2-1.java delete mode 100644 373. Find K Pairs with Smallest Sums/step2.java diff --git a/373. Find K Pairs with Smallest Sums/step2-1.java b/373. Find K Pairs with Smallest Sums/step2-1.java new file mode 100644 index 0000000..a0c51d9 --- /dev/null +++ b/373. Find K Pairs with Smallest Sums/step2-1.java @@ -0,0 +1,28 @@ +class Solution { + public List> kSmallestPairs(int[] nums1, int[] nums2, int k) { + int length1 = nums1.length; + int length2 = nums2.length; + List> kSmallestPairs = new ArrayList<>(); + Set> visited = new HashSet<>(); + + PriorityQueue minSortedPairs = new PriorityQueue<>((a, b) -> (nums1[a[0]] + nums2[a[1]]) - (nums1[b[0]] + nums2[b[1]])); + minSortedPairs.add(new int[] {0, 0}); + visited.add(new Pair(0, 0)); + + while(kSmallestPairs.size() < k) { + int[] currentMinPair = minSortedPairs.poll(); + int index1 = currentMinPair[0]; + int index2 = currentMinPair[1]; + kSmallestPairs.add(List.of(nums1[index1], nums2[index2])); + if (index1 + 1 < length1 && !visited.contains(new Pair(index1 + 1, index2))) { + minSortedPairs.add(new int[] {index1 + 1, index2}); + visited.add(new Pair(index1 + 1, index2)); + } + if (index2 + 1 < length2 && !visited.contains(new Pair(index1, index2 + 1))) { + minSortedPairs.add(new int[] {index1, index2 + 1}); + visited.add(new Pair(index1, index2 + 1)); + } + } + return kSmallestPairs; + } +} diff --git a/373. Find K Pairs with Smallest Sums/step2.java b/373. Find K Pairs with Smallest Sums/step2.java deleted file mode 100644 index 8b13789..0000000 --- a/373. Find K Pairs with Smallest Sums/step2.java +++ /dev/null @@ -1 +0,0 @@ - From 3592ed30d43156096d3128a8f39730ae5ffd8622 Mon Sep 17 00:00:00 2001 From: ryo <34418898+ryoooooory@users.noreply.github.com> Date: Mon, 8 Jul 2024 23:44:32 +0900 Subject: [PATCH 06/15] Update note.md --- 373. Find K Pairs with Smallest Sums/note.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/373. Find K Pairs with Smallest Sums/note.md b/373. Find K Pairs with Smallest Sums/note.md index 5e2fe59..6dbe623 100644 --- a/373. Find K Pairs with Smallest Sums/note.md +++ b/373. Find K Pairs with Smallest Sums/note.md @@ -1,6 +1,16 @@ -# step1 +# 373. Find K Pairs with Smallest Sums + +## step1 時間計算量: O(klogk), 空間計算量: O(k) 全探索しか思い浮かばず、ACできなかった。 回答をみて理解してその通りに実装(変数名のリネームはおこなった。) -# step2 +## step2 +他の人の実装を参考に実装した。 +### step2-1 +参考:https://github.com/seal-azarashi/leetcode/pull/10/files +根本的な解法はstep1と同じだが、PriorityQueueにいれる中身を変えて、変数を少なくしたタイプ。変数宣言での記述量は増えるものの、繰り返しの部分は余計な合計などもなくわかりやすいかなとおもった。 + +### step2-2 +参考:[https://github.com/seal-azarashi/leetcode/pull/10/files](https://github.com/kazukiii/leetcode/pull/11/files) +実装していて、Pairを使わない場合は独自で定義したほうが見やすいなあとおもっていて同様のコメントが上記のPRでもあったので、独自定義する方針でも実装してみた。 From 16916311b5afcd422853bade1301cbce4dc4e2e8 Mon Sep 17 00:00:00 2001 From: ryo <34418898+ryoooooory@users.noreply.github.com> Date: Mon, 8 Jul 2024 23:44:56 +0900 Subject: [PATCH 07/15] Create step2-2.java --- .../step2-2.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 373. Find K Pairs with Smallest Sums/step2-2.java diff --git a/373. Find K Pairs with Smallest Sums/step2-2.java b/373. Find K Pairs with Smallest Sums/step2-2.java new file mode 100644 index 0000000..e64f497 --- /dev/null +++ b/373. Find K Pairs with Smallest Sums/step2-2.java @@ -0,0 +1,40 @@ +class Solution { + public List> kSmallestPairs(int[] nums1, int[] nums2, int k) { + int length1 = nums1.length; + int length2 = nums2.length; + List> kSmallestPairs = new ArrayList<>(); + Set> visited = new HashSet<>(); + + PriorityQueue minSortedPairs = new PriorityQueue<>((a, b) -> (a.sum - b.sum)); + minSortedPairs.add(new SumPair(nums1, 0, nums2, 0)); + visited.add(new Pair(0, 0)); + + for(int i = 0; i < k; i++) { + SumPair currentMinPair = minSortedPairs.poll(); + int index1 = currentMinPair.indice.getKey(); + int index2 = currentMinPair.indice.getValue(); + kSmallestPairs.add(List.of(currentMinPair.elements.getKey(), currentMinPair.elements.getValue())); + if (index1 + 1 < length1 && !visited.contains(new Pair(index1 + 1, index2))) { + minSortedPairs.add(new SumPair(nums1, index1 + 1, nums2, index2)); + visited.add(new Pair(index1 + 1, index2)); + } + if (index2 + 1 < length2 && !visited.contains(new Pair(index1, index2 + 1))) { + minSortedPairs.add(new SumPair(nums1, index1, nums2, index2 + 1)); + visited.add(new Pair(index1, index2 + 1)); + } + } + return kSmallestPairs; + } +} + +class SumPair { + int sum; + Pair elements; + Pair indice; + + SumPair(int[] nums1, int index1, int[] nums2, int index2) { + this.sum = nums1[index1] + nums2[index2]; + this.elements = new Pair(nums1[index1], nums2[index2]); + this.indice = new Pair(index1, index2); + } +} From d4777c96b427b38ded87e9f3b1d914176188652b Mon Sep 17 00:00:00 2001 From: ryo <34418898+ryoooooory@users.noreply.github.com> Date: Tue, 9 Jul 2024 00:08:53 +0900 Subject: [PATCH 08/15] Update note.md --- 373. Find K Pairs with Smallest Sums/note.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/373. Find K Pairs with Smallest Sums/note.md b/373. Find K Pairs with Smallest Sums/note.md index 6dbe623..9ba6a44 100644 --- a/373. Find K Pairs with Smallest Sums/note.md +++ b/373. Find K Pairs with Smallest Sums/note.md @@ -13,4 +13,10 @@ ### step2-2 参考:[https://github.com/seal-azarashi/leetcode/pull/10/files](https://github.com/kazukiii/leetcode/pull/11/files) -実装していて、Pairを使わない場合は独自で定義したほうが見やすいなあとおもっていて同様のコメントが上記のPRでもあったので、独自定義する方針でも実装してみた。 +実装していて、indexまわりをまとめて独自で定義したほうが見やすいなあとおもっていて同様のコメントが上記のPRでもあったので、独自定義する方針でも実装してみた。 + +## メモ +Loopの表現についてfor, whileの議論が他のPRのコメントでもあったが、宣言的か手続的のどちらがいいかというものがあり、今回の問題だと個人的にはどちらでもそこまで変わらないかなと思ったが問題や条件によってはどちらが自然かというのを常に意識したい。 +また問題文の制約次第ではループのなかでエラーとなる可能性があることも意識したい。 +https://github.com/sakupan102/arai60-practice/pull/11#discussion_r1622031840 +https://github.com/fhiyo/leetcode/pull/13/files From 3ecf75eeb4655a2c5025401edd8040a043672a4e Mon Sep 17 00:00:00 2001 From: ryo <34418898+ryoooooory@users.noreply.github.com> Date: Tue, 9 Jul 2024 00:19:03 +0900 Subject: [PATCH 09/15] Update note.md --- 373. Find K Pairs with Smallest Sums/note.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/373. Find K Pairs with Smallest Sums/note.md b/373. Find K Pairs with Smallest Sums/note.md index 9ba6a44..e548250 100644 --- a/373. Find K Pairs with Smallest Sums/note.md +++ b/373. Find K Pairs with Smallest Sums/note.md @@ -4,6 +4,11 @@ 時間計算量: O(klogk), 空間計算量: O(k) 全探索しか思い浮かばず、ACできなかった。 回答をみて理解してその通りに実装(変数名のリネームはおこなった。) +大まかな思考の流れは以下の通り +1, 単純に全探索→ソートすると計算量がよくないので、改善のためにどのように比較をするかを考える +2, 実際に比較をするのは、最小のペア(nums1[index1], nums2[index2])を基準に考えると、次の最小値は(nums1[index1 + 1], nums2[index2], nums1[index1], nums2[index2 + 1])かもしくは、この以前のステップでのこったもののどれかとなる。 +3, 上記で以前のステップでのこったものを実現すること、常にソートされた状態でいることを考慮してHeapを使うという流れとなる。 +4, あとは追加の際に重複をさけるため、Setを用意して重複のIndexペアは弾くようにする。 ## step2 他の人の実装を参考に実装した。 From 23db7ca49519250d3eb892e881e684582003c6b0 Mon Sep 17 00:00:00 2001 From: ryo <34418898+ryoooooory@users.noreply.github.com> Date: Sun, 28 Jul 2024 21:04:55 +0900 Subject: [PATCH 10/15] Create step3-1.java --- .../step3-1.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 373. Find K Pairs with Smallest Sums/step3-1.java diff --git a/373. Find K Pairs with Smallest Sums/step3-1.java b/373. Find K Pairs with Smallest Sums/step3-1.java new file mode 100644 index 0000000..d87a924 --- /dev/null +++ b/373. Find K Pairs with Smallest Sums/step3-1.java @@ -0,0 +1,25 @@ +class Solution { + public List> kSmallestPairs(int[] nums1, int[] nums2, int k) { + int length1 = nums1.length; + int length2 = nums2.length; + List> kSmallestPairs = new ArrayList<>(); + Set> visited = new HashSet<>(); + + PriorityQueue minSums = new PriorityQueue<>((a, b) -> a[0] - b[0]); + minSums.add(new int[] { nums1[0] + nums2[0], 0, 0 }); + + while (kSmallestPairs.size() < k) { + int[] totalAndIndexes = minSums.poll(); + int index1 = totalAndIndexes[1]; + int index2 = totalAndIndexes[2]; + kSmallestPairs.add(List.of(nums1[index1], nums2[index2])); + if (index2 == 0 && index1 + 1 < length1) { + minSums.add(new int[] { nums1[index1 + 1] + nums2[index2], index1 + 1, index2 }); + } + if (index2 + 1 < length2) { + minSums.add(new int[] { nums1[index1] + nums2[index2 + 1], index1, index2 + 1 }); + } + } + return kSmallestPairs; + } +} From 02666d13547fe9108e218c3f56da659b2d860df1 Mon Sep 17 00:00:00 2001 From: ryo <34418898+ryoooooory@users.noreply.github.com> Date: Thu, 22 Aug 2024 22:44:04 +0900 Subject: [PATCH 11/15] Update note.md --- 373. Find K Pairs with Smallest Sums/note.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/373. Find K Pairs with Smallest Sums/note.md b/373. Find K Pairs with Smallest Sums/note.md index e548250..1dc0c89 100644 --- a/373. Find K Pairs with Smallest Sums/note.md +++ b/373. Find K Pairs with Smallest Sums/note.md @@ -25,3 +25,13 @@ Loopの表現についてfor, whileの議論が他のPRのコメントでもあ また問題文の制約次第ではループのなかでエラーとなる可能性があることも意識したい。 https://github.com/sakupan102/arai60-practice/pull/11#discussion_r1622031840 https://github.com/fhiyo/leetcode/pull/13/files + +## step3 +いただいたコメントを元にアルゴリズムを修正した。 +### step3-1 +具体的には、 +・2つの配列について片方の配列のIndexしか動かさない +・動かす方のindex = 0の時のみもう片方の配列のについてその配列のIndex+1の要素をQueueに追加 +することで重複がないようにおこなうことができる。 + +### step3-2 From ce12c50d84fdfc42b03015a56d000ef2d2b2fad9 Mon Sep 17 00:00:00 2001 From: ryo <34418898+ryoooooory@users.noreply.github.com> Date: Thu, 22 Aug 2024 23:01:06 +0900 Subject: [PATCH 12/15] Update step3-1.java --- 373. Find K Pairs with Smallest Sums/step3-1.java | 1 - 1 file changed, 1 deletion(-) diff --git a/373. Find K Pairs with Smallest Sums/step3-1.java b/373. Find K Pairs with Smallest Sums/step3-1.java index d87a924..b4d6bb2 100644 --- a/373. Find K Pairs with Smallest Sums/step3-1.java +++ b/373. Find K Pairs with Smallest Sums/step3-1.java @@ -3,7 +3,6 @@ public List> kSmallestPairs(int[] nums1, int[] nums2, int k) { int length1 = nums1.length; int length2 = nums2.length; List> kSmallestPairs = new ArrayList<>(); - Set> visited = new HashSet<>(); PriorityQueue minSums = new PriorityQueue<>((a, b) -> a[0] - b[0]); minSums.add(new int[] { nums1[0] + nums2[0], 0, 0 }); From 71568b70f34b53e38181d6bc1e0114012a311445 Mon Sep 17 00:00:00 2001 From: ryo <34418898+ryoooooory@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:41:07 +0900 Subject: [PATCH 13/15] Create step3-2.java --- .../step3-2.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 373. Find K Pairs with Smallest Sums/step3-2.java diff --git a/373. Find K Pairs with Smallest Sums/step3-2.java b/373. Find K Pairs with Smallest Sums/step3-2.java new file mode 100644 index 0000000..ee74b4f --- /dev/null +++ b/373. Find K Pairs with Smallest Sums/step3-2.java @@ -0,0 +1,64 @@ +class Solution { + int[] nums1; + int[] nums2; + + public List> kSmallestPairs(int[] nums1, int[] nums2, int k) { + this.nums1 = nums1; + this.nums2 = nums2; + List> kSmallestPairs = new ArrayList<>(); + Set visited = new HashSet<>(); + PriorityQueue minSortedPairs = new PriorityQueue<>((a, b) -> (a.sum - b.sum)); + IndexPair firstPair = new IndexPair(0, 0, nums1[0] + nums2[0]); + minSortedPairs.add(firstPair); + visited.add(firstPair); + + for(int i = 0; i < k; i++) { + IndexPair currentMinPair = minSortedPairs.poll(); + int index1 = currentMinPair.index1; + int index2 = currentMinPair.index2; + kSmallestPairs.add(List.of(nums1[index1], nums2[index2])); + insertPairIfNeeded(minSortedPairs, visited, index1 + 1, index2); + insertPairIfNeeded(minSortedPairs, visited, index1, index2 + 1); + } + return kSmallestPairs; + } + + private void insertPairIfNeeded(PriorityQueue queue, Set visited, int pos1, int pos2) { + int len1 = nums1.length; + int len2 = nums2.length; + if (len1 <= pos1 || len2 <= pos2) { + return; + } + IndexPair newPair = new IndexPair(pos1, pos2, nums1[pos1] + nums2[pos2]); + if (visited.contains(newPair)) { + return; + } + queue.add(newPair); + visited.add(newPair); + } +} + +class IndexPair { + int sum; + int index1; + int index2; + + IndexPair(int index1, int index2, int sum) { + this.index1 = index1; + this.index2 = index2; + this.sum = sum; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + IndexPair other = (IndexPair) o; + return other.index1 == index1 && other.index2 == index2; + } + + @Override + public int hashCode() { + return Objects.hash(index1, index2); + } +} From a64480b6d6c09eb36671937c84767f56b37b4a24 Mon Sep 17 00:00:00 2001 From: ryo <34418898+ryoooooory@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:45:07 +0900 Subject: [PATCH 14/15] Update note.md --- 373. Find K Pairs with Smallest Sums/note.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/373. Find K Pairs with Smallest Sums/note.md b/373. Find K Pairs with Smallest Sums/note.md index 1dc0c89..f028cbf 100644 --- a/373. Find K Pairs with Smallest Sums/note.md +++ b/373. Find K Pairs with Smallest Sums/note.md @@ -27,11 +27,13 @@ https://github.com/sakupan102/arai60-practice/pull/11#discussion_r1622031840 https://github.com/fhiyo/leetcode/pull/13/files ## step3 -いただいたコメントを元にアルゴリズムを修正した。 +いただいたコメントを元に修正した。 ### step3-1 -具体的には、 +アルゴリズムの修正を行なった。 ・2つの配列について片方の配列のIndexしか動かさない ・動かす方のindex = 0の時のみもう片方の配列のについてその配列のIndex+1の要素をQueueに追加 することで重複がないようにおこなうことができる。 ### step3-2 +独自クラスの定義のし直し、および共通ロジックを関数として外出しした。 +修正を行うと途端にどこが共通化されているのか、どこが無駄な処理になるのかがぼやけるので、全体の処理を頭に置きながら共通化部分をしっかり頭で描いてからコードにうつるように癖づけないといけないと思った。 From 8f11027d1468ed1bc14a72da04777b50ae296ebe Mon Sep 17 00:00:00 2001 From: ryo <34418898+ryoooooory@users.noreply.github.com> Date: Fri, 23 Aug 2024 12:11:24 +0900 Subject: [PATCH 15/15] Update note.md --- 373. Find K Pairs with Smallest Sums/note.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/373. Find K Pairs with Smallest Sums/note.md b/373. Find K Pairs with Smallest Sums/note.md index f028cbf..ea17d0b 100644 --- a/373. Find K Pairs with Smallest Sums/note.md +++ b/373. Find K Pairs with Smallest Sums/note.md @@ -37,3 +37,8 @@ https://github.com/fhiyo/leetcode/pull/13/files ### step3-2 独自クラスの定義のし直し、および共通ロジックを関数として外出しした。 修正を行うと途端にどこが共通化されているのか、どこが無駄な処理になるのかがぼやけるので、全体の処理を頭に置きながら共通化部分をしっかり頭で描いてからコードにうつるように癖づけないといけないと思った。 +また、HashSetに独自クラスのオブジェクトをいれるときに、仕組みとしてどのように一致判定を行なっているかについて気になったので以下にまとめる。 + +・HashSetではAbstractSetをimplementしており、equalsとhashCodeを使ってObjectの一致判定をしている。 +・classは暗黙的にObjectクラスを継承しているのでequalsとhashCodeは必ずもっている。 +・独自クラスでかつ一致判定をカスタムしたい時は上記をOverrideする必要がある。