すっげー適当なHashMapに対するメモを昔に書いてました。。
この問題
で連想配列使ったほうがいいよとなってたのでチャレンジしてみました。
まーいつも通り小一時間悩んだんですが(ダブルループなんてしないでcontains()
をすぐに思い浮かべられたら..と悔いが残ります。)
自分のクソロジックで申し訳ないですが一応自分なりに解けたのでメモ
考えたこと
s
、t
、それぞれの配列でいくつ重複した値があるのかを与えられたStringをキーとしてHashMapをつくるt
で与えられた配列の中にs
とマッチする値があればs
の重複値 -t
の重複カウントを求めるt
で与えられた配列の中にs
とマッチしない値があれば、そのs
の値の重複カウントを求める- 最大値の重複カウントが答え
HashMap
宣言は基本的には下記でいいはず(String, intを格納する場合)
import java.util.Map; import java.util.HashMap; Map<String, Integer> map = new HashMap<>();
ランクBくらいであれば基礎的な使い方だけ知っていればいいと勝手に思っておきます。
https://style.potepan.com/articles/16280.html
この記事もタメになりました。
Mapではダメで どうしてもHashMapのメソッドを使わないといけない
あるいは使った方が実装が楽、という場合に限り
HashMap map = new HashMap()
と記述する。
リストに存在する重複値のカウント
これもぜひ覚えておきたいなーと思いました。基本はHashSet
とセットで使う気がしている。
import java.util.Collections; import java.util.Set; import java.util.HashSet; import java.util.ArrayList; ArrayList<String> arrayList = {"a", "a", "b", "c"}; Set<String> set = new HashSet<>(arrayList); for(String s: set) { map.put(s, Collections.frequency(arrayList, s)); }
今回は各String値をキーとして、HashMapにぶっ込みました。
Sample
import java.util.Scanner; import java.util.ArrayList; import java.util.Set; import java.util.HashSet; import java.util.Map; import java.util.HashMap; import java.util.Collections; public class Main45 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); sc.nextLine(); ArrayList<String> s = new ArrayList<>(); for(int i=0; i<n; i++) { s.add(sc.nextLine()); } int m = sc.nextInt(); sc.nextLine(); ArrayList<String> t = new ArrayList<>(); for(int j=0; j<m; j++) { t.add(sc.nextLine()); } Set<String> setS = new HashSet<>(s); Set<String> setT = new HashSet<>(t); Map<String,Integer> mapS = new HashMap<>(); for(String str: setS) { mapS.put(str, Collections.frequency(s, str)); } Map<String,Integer> mapT = new HashMap<>(); for(String str: setT) { mapT.put(str, Collections.frequency(t, str)); } int count = 0; int currentCount = 0; for(String str: setS) { if(setT.contains(str)) { count = mapS.get(str) - mapT.get(str); } else { count = mapS.get(str); } if(currentCount < count) { currentCount = count; } } System.out.println(currentCount); sc.close(); } }
追記 5/26
上記問題もおさらいしてて、長いコード書くのだるってなったのでもう少し簡潔にできないか探っていたところ...
Set/HashSet
のくだりをどうにか削れないかと調べました。
すると、いきなりInputからMapに放り込んでる人がいて、なるほどそうだよなと思ったので追記です。
containsKey()
でMapの中にキーがあるかどうか探せる
Map<String, Integer> s = new HashMap<>(); for(int i=0; i<n; i++) { String str = sc.nextLine(); if(s.containsKey(str)) { s.put(str, s.get(str)+1); } else { s.put(str, 1); } }
Mapのfor eachループのやり方
基本的には3通りあるらしい。
- entrySet() : オフィシャルっぽい。
(Map<String, Integer> entry: s.entrySet()){
- keySet() : ループさせるMapに含まれるkeyを元にループ、valueを取り出したいときにおすすめ?
- valueSet() : ループさせるMapに含まれるvalueを元にループ、keyを取り出したいときにおすすめ?(これは例があまりなかった)
for(String str: s.keySet()) { // }