[백준] 12891번 DNA 비밀번호 - 슬라이딩 윈도우 / switch / 함수

2023. 8. 12. 23:36·Java
문제

 

 

 

로직

입력 받을 문자열의 길이 입력 받기 

부분 문자열의 길이 입력 받기

 

입력 받을 문자열을 담는 배열 선언 & 크기 설정(S로)

부분문자열에 포함되어야 할 {‘A’, ‘C’, ‘G’, ‘T’} 의 최소 개수를 담는 배열 선언 & 크기 설정

최소 개수를 입력한 문자열과 비교할 배열 선언 & 크기 설정

만들 수 있는 비밀번호 종류의 수를 담는 변수 선언 및 초기화

 

1. 반복문- 문자열 입력 받고 배열에 저장

 

2. 반복문- 최소 개수 입력 받고 배열에 저장

 

슬라이딩 윈도우를 실행할 수 있는 코드 작성

.

.

.

슬라이딩 윈도우를 하기 위해 부분 문자열마다 시작과 끝만 고치고 싶은데 그 부분이 어려웠다.

시간복잡도를 O(n)이 되도록 하려면 이중 반복문을 못 써서 이 부분에 고민이 많았다.

선형으로 반복하고 싶은데(ex - O(2n)) 그걸 어떻게 할 지 고민하던 중

참고 강의를 보며 공부하니 함수를 이용하면 된다는 걸 깨달았다.

 

 

My Code
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
int S = Integer.parseInt(bufferedReader.readLine());
int P = Integer.parseInt(bufferedReader.readLine());
String[] strArray = new String[S];
int[] numArray = new int[4];
int[] testNumArray = new int[4];
int count = 0;

for (int a = 0; a < S; a++){
strArray[a] = bufferedReader.readLine();
}

StringTokenizer stringTokenizer = new StringTokenizer(bufferedReader.readLine());
for (int b = 0; b < 4; b++){
numArray[b] = Integer.parseInt(stringTokenizer.nextToken());
}

int start_index = 0;
int end_index = S-1;
int partstart_index = 0;
int partend_index = P-1;
switch (strArray[partstart_index]){
case "A":
testNumArray[0] += 1;
partstart_index++;
break;
case "C":
testNumArray[1] += 1;
partstart_index++;
break;
case "G":
testNumArray[2] += 1;
partstart_index++;
break;
case "T":
testNumArray[3] += 1;
partstart_index++;
break;
}
if (partstart_index == partend_index){
start_index++;
partend_index++;
}
for (int c = 0; c < 4; c++){
if (testNumArray[c] >= numArray[c])
count++;
}


}
}

 

 

문제의 핵심 & 알게된 점

변수의 범위와 시간제한으로 인해 이중 반복문을 사용하면 안되고 시간복잡도가 O(n)이 나오게 해야한다.

그 방법은 함수를 만들어 반복시키는 방법이 있었다.

그래서 Add(), Remove()라는 함수를 만들어 시작부분을 앞으로 옮기면서 뒤를 없애고

끝부분을 앞으로 옮기면서 앞을 더하는 방식인 "슬라이딩 윈도우"를 실현할 수 있었다.

int j = i - p;로 두어 j는 시작 부분, i는 끝 부분으로 설정할 수 있었다.

 

여기서 슬라이딩 윈도우란?

2개의 포인터로 범위를 지정한 다음 범위를 유지한 채로 이동하며 문제를 해결한다.

슬라이딩 윈도우의 방식
문제 해결 논리

이렇게 슬라이딩 윈도우에 대해 이해할 수 있게 됐다.

 

또한 switch문의 if문에서 checkArray[0] == numArray[0]의 조건이 꼭 ==여야하는 이유는

같을 때로 정의해야 반복이 되지 않고 정확히 할 수 있기 때문이다.

 

이번 문제는 My Code는 실행도 제대로 안됐다.

슬라이딩 윈도우에 대해 무지했기에 어렵게 느꼈고 참고 Code를 보는게 좋을  것이다.

 

 

참고 Code
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
static int[] checkArray;
static int checkNum;
static int[] numArray;
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stringTokenizer = new StringTokenizer(bufferedReader.readLine());

int S = Integer.parseInt(stringTokenizer.nextToken());
int P = Integer.parseInt(stringTokenizer.nextToken());
char[] strArray = new char[S];
numArray = new int[4];
checkArray = new int[4];
checkNum = 0;
int result = 0;

strArray = bufferedReader.readLine().toCharArray();

stringTokenizer = new StringTokenizer(bufferedReader.readLine());
for (int i = 0; i<4; i++){
numArray[i] = Integer.parseInt(stringTokenizer.nextToken());
if (numArray[i]==0)checkNum++;
}

for (int i = 0; i<P; i++){
Add(strArray[i]);
}

if (checkNum == 4) result++;

for (int i = P; i<S; i++){
int j = i-P;
Add(strArray[i]);
Remove(strArray[j]);
if (checkNum == 4) result++;
}

System.out.println(result);
bufferedReader.close();
}

private static void Remove(char c) {
switch (c){
case 'A':
if (checkArray[0] == numArray[0]) checkNum--;
checkArray[0]--;
break;
case 'C':
if (checkArray[1] == numArray[1]) checkNum--;
checkArray[1]--;
break;
case 'G':
if (checkArray[2] == numArray[2]) checkNum--;
checkArray[2]--;
break;
case 'T':
if (checkArray[3] == numArray[3]) checkNum--;
checkArray[3]--;
break;
}
}

private static void Add(char c) {
switch (c){
case 'A':
checkArray[0]++;
if (checkArray[0] == numArray[0]) checkNum++;
break;
case 'C':
checkArray[1]++;
if (checkArray[1] == numArray[1]) checkNum++;
break;
case 'G':
checkArray[2]++;
if (checkArray[2] == numArray[2]) checkNum++;
break;
case 'T':
checkArray[3]++;
if (checkArray[3] == numArray[3]) checkNum++;
break;
}
}
}

 

 

참고_인프런의 Do it! 알고리즘 코딩 테스트 with JAVA

저작자표시 (새창열림)

'Java' 카테고리의 다른 글

[백준] 2164번 카드2 - 큐(Queue)/선입선출/스택을 이용한 방법/  (0) 2023.08.18
[백준] 1874번 스택 수열 - Stack / push() / pop() / 스택의 원리  (0) 2023.08.16
[백준] 1940번 주몽 - 투포인터 / 시간 제한 맞추기 / 배열 정렬 / BufferReader  (0) 2023.08.12
[백준] 2018번 수들의 합5 - 투포인터 / 배열 / if문 / while문  (0) 2023.08.11
[백준] 11659번 구간 합 구하기4 - 구간 합 / 배열 / BufferedReader / StringToken  (0) 2023.08.09
'Java' 카테고리의 다른 글
  • [백준] 2164번 카드2 - 큐(Queue)/선입선출/스택을 이용한 방법/
  • [백준] 1874번 스택 수열 - Stack / push() / pop() / 스택의 원리
  • [백준] 1940번 주몽 - 투포인터 / 시간 제한 맞추기 / 배열 정렬 / BufferReader
  • [백준] 2018번 수들의 합5 - 투포인터 / 배열 / if문 / while문
미우딩
미우딩
다양한 프로그래밍 언어를 공부하고 있는 공대생입니다! Python, Java, C언어를 주로 공부하고 있으며 Figma를 통한 디자인도 종종 올릴 예정입니다.
  • 미우딩
    미우의 코딩 기록
    미우딩
  • 전체
    오늘
    어제
    • 분류 전체보기 (60)
      • Java (47)
      • C언어 (0)
      • 대외활동 (5)
      • Spring (4)
      • 프로젝트 (2)
      • 앱개발 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    IT #코딩테스트 #알고리즘 #슬라이딩윈도우 #투포인터 #함수
    IT #알고리즘 #코딩테스트 #퀵정렬 #오름차순정렬
    IT #코딩테스트 #알고리즘 #스택 #
    IT #알고리즘 #코딩테스트 #선택정렬 #내림차순정렬 #최댓값
    IT #알고리즘 #그리디알고리즘 #탐욕알고리즘 #코테
    IT #백준 #코딩테스트 #알고리즘 #구간합 #반복문
    IT #알고리즘 #코딩테스트 #삽입정렬 #오름차순정렬
    IT #BFS #코딩테스트 #구현 #큐 #재귀함수
    IT #코딩테스트 #알고리즘 #버블정렬 #오름차순
    IT #백준 #알고리즘 #코딩테스트 #배열 #형변환 #아스키코드
    android #java #kotlin #compose
    IT #코딩테스트 #이진탐색 #알고리즘
    java #android #개발자
    push #pop #StringBuffer
    IT #코딩테스트 #알고리즘 #투포인터 #시간제한 #Scanner #BufferedReader #StringTokenizer
    Spring #정적컨텐츠 #MVC #템플릿엔진 #API #애너테이션
    IT #알고리즘 #코딩테스트 #우선순위큐 #힙 #절댓값 #오름차순 #정렬
    android #java #kotlin #상태관리
    IT #코딩테스트 #알고리즘 #DFS #재귀함수 #무방향그래프
    BufferedReader
    IT #큐 #알고리즘 #코딩테스트 #자바 #선입선출
    IT #코딩테스트 #알고리즘 #백준 #투포인터 #배열
    IT #백준 #알고리즘 #코딩테스트 #배열 #형변환 #평균구하기
    IT #알고리즘 #코딩테스트 #DFS
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
미우딩
[백준] 12891번 DNA 비밀번호 - 슬라이딩 윈도우 / switch / 함수
상단으로

티스토리툴바