Notice
Recent Posts
Recent Comments
Link
개발자는 기록이 답이다
자바(Java) 알고리즘 문제풀이 입문: 코딩테스트 대비(Hash, sliding window : 시간복잡도 O(n)_모든 아나그램 찾기) 본문
알고리즘/인프런 - Java알고리즘 입문
자바(Java) 알고리즘 문제풀이 입문: 코딩테스트 대비(Hash, sliding window : 시간복잡도 O(n)_모든 아나그램 찾기)
slow-walker 2023. 9. 30. 00:49
4. 모든 아나그램 찾기(Hash, sliding window : 시간복잡도 O(n))
예시 입력 1
10 3
13 15 34 23 45 65 33 11 26 42
예시 출력 1
143
내가 푼 첫번째 틀린 풀이
맨 처음에는 map에서 equals함수가 된다는걸 모르고 엄청난 뻘짓을 했다,,
map.get(key)로 나온 value값이 서로 일치하는지로 해봤더니, 이전에 A부분에서 지나간건 체크를 못하더라.
import java.util.HashMap;
import java.util.Scanner;
public class Main {
public int solution(String str, String t) {
int answer = 0;
HashMap<Character, Integer> target = new HashMap<>();
for (Character x : t.toCharArray()) {
target.put(x, target.getOrDefault(x, 0) + 1);
}
HashMap<Character, Integer> HM = new HashMap<>();
int lt = 0;
for (int rt = 0; rt < str.length(); rt++) {
char key = str.charAt(rt);
HM.put(key, HM.getOrDefault(key, 0) + 1);
System.out.println(HM);
if (HM.get(key) == target.get(key)) {
System.out.println("---A를 찾아라---");
System.out.println(key);
System.out.println("HM.get(key) : " + HM.get(key));
System.out.println("target.get(key) : " + target.get(key));
System.out.println("key의 벨류가 같은지 검증 확인");
if (target.size() == HM.size()) {
System.out.println("answer추가됨");
answer++; // 미완성,,,
}
}
if (rt - lt + 1 == t.length()) {
HM.put(str.charAt(lt), HM.get(str.charAt(lt)) - 1);
if (HM.get(str.charAt(lt)) == 0) HM.remove(str.charAt(lt)); // 키 삭제
lt++;
}
}
return answer;
}
public static void main(String[] args) {
Main T = new Main();
Scanner kb = new Scanner(System.in);
String str = kb.next();
String t = kb.next();
System.out.println(T.solution(str, t));
}
}
내가 푼 두번째 풀이(Time: 179ms Memory: 28MB)
Map의 equals()를 사용했다.
나는 따로 str에 대한 map을 초반에 세팅해주진 않았는데, 강의에서는 세팅해줬다.
미리 세팅해놓고, 그 다음 조건부터 put을 하는게 더 좋은 것 같다.그리고 나는 설정 구간과 t의 길이가 일치하는 경우를 조건문으로 붙였는데, 강의처럼 그냥 바로 equals하면 편한것같다.
어차피 맵의 equals는 키와 벨류까지 다 일치하는지 확인해주기 때문이다.
import java.util.HashMap;
import java.util.Scanner;
public class Main {
public int solution(String str, String t) {
int answer = 0;
HashMap<Character, Integer> target = new HashMap<>();
for (Character x : t.toCharArray()) {
target.put(x, target.getOrDefault(x, 0) + 1);
}
HashMap<Character, Integer> HM = new HashMap<>();
int lt = 0;
for (int rt = 0; rt < str.length(); rt++) {
char key = str.charAt(rt);
HM.put(key, HM.getOrDefault(key, 0) + 1);
// 설정한 구간과 t의 길이가 일치하는 경우
if (rt - lt + 1 == t.length()) {
if (HM.equals(target)) { // HM과 target을 비교하여 모든 문자의 개수가 일치하는지 확인
answer++;
}
HM.put(str.charAt(lt), HM.get(str.charAt(lt)) - 1);
if (HM.get(str.charAt(lt)) == 0) HM.remove(str.charAt(lt)); // 키 삭제
lt++;
}
}
return answer;
}
public static void main(String[] args) {
Main T = new Main();
Scanner kb = new Scanner(System.in);
String str = kb.next();
String t = kb.next();
System.out.println(T.solution(str, t));
}
}
강의 풀이 (Time: 172ms Memory: 28MB)
b의 길이 하나 전까지 am을 다 세팅해준 다음에 rt를 움직이면서 업데이트 한다.
자바에는 두 객체(맵)을 비교하는 equals()라는 함수가 있는데, 키값 카운팅한 벨류값까지 다 봐준다.
HM : {a=1, b=1, c=1}
target : {a=1, b=1, c=1}
import java.util.HashMap;
import java.util.Scanner;
public class Main {
public int solution(String a, String b) {
int answer = 0;
HashMap<Character, Integer> am = new HashMap<>();
// 먼저 bm 세팅하기
HashMap<Character, Integer> bm = new HashMap<>();
for (char x : b.toCharArray()) bm.put(x, bm.getOrDefault(x, 0) + 1);
// am 세팅해놓기, b의 길이보다 하나 적게 세팅
int L = b.length()-1;
for (int i = 0; i < L; i++) am.put(a.charAt(i), am.getOrDefault(a.charAt(i), 0) + 1);
int lt = 0;
// 투포인터랑 슬라이딩 윈도우로 rt부터 쭈욱 am 업데이트하기
for (int rt = L; rt < a.length(); rt++) {
am.put(a.charAt(rt), am.getOrDefault(a.charAt(rt), 0) + 1);
// 해쉬맵의 equals를 할 줄 아는게 매우 중요!!!!
if (am.equals(bm)) answer++;
am.put(a.charAt(lt), am.get(a.charAt(lt))-1);
if (am.get(a.charAt(lt))==0) am.remove(a.charAt(lt));
lt++;
}
return answer;
}
public static void main(String[] args) {
Main T = new Main();
Scanner kb = new Scanner(System.in);
String a = kb.next();
String b = kb.next();
System.out.println(T.solution(a, b));
}
}