본 내용은 인프런 자바(Java) 알고리즘 문제풀이 : 입문 - 코딩테스트 대비 강의 문제를 기반으로 포스팅 한 내용입니다.
문제
- 문자거리
- 문자열 압축
- 암호(replace(), parseInt(string, 2))
문제 1. 문자거리
문제 설명과 예시, 그리고 내가 접근하고자 했던 방식
한 개의 문자열 s와 문자 t가 주어지면 문자열 s의 각 문자가 문자 t와 떨어진 최소거리를 출력하는 프로그램을 작성
ex) teachermode e -> 1 0 1 2 1 0 1 2 2 1 0
<접근방식> 고민해보기 정방향 -> 역방향 순으로 반복문을 통해 해당 요소가 있는지 확인하고, 값을 기준으로 최소거리를 저장하면 됐었음.
본 강의에서는 Math.min()을 이용해 기존에 있던 배열의 요소와 새로운 값을 비교해 더 작은 값을 넣는 방식 (더 간단함)
나는 이 부분을 직접 조건식을 통해 해결하려고 했었음
코드
public int[] solution(String s,char t){
int p = 1000;
int[] answer= new int[s.length()];
for(int i=0; i<s.length(); i++){
if(s.charAt(i)==t){
p=0;
answer[i]=p;
}else
p++;
answer[i]=p;
}
p=1000;
for(int i=s.length()-1; i>=0; i--){
if(s.charAt(i)==t)p=0;
else{
p++;
answer[i]=Math.min(answer[i],p);
}
}
return answer;
}
1. 파라미터로 전달받은 문자열(s)와 문자(t)를 이용한다.
2. 첫번째 반복문은 정방향, 두 번째 반복문은 역방향
반복문이 정방향 역뱡향이 있는 이유는, 전달받은 문자열에 중복된 문자가 있을 수 있는데, 문자의 위치에 따라 최소거리가 달라질 수 있기때문에 그것을 검출하기 위함
문제 2. 문자열 압축
문제 설명과 예시, 그리고 내가 접근하고자 했던 방식
설명 : 알파벳 대문자로 이루어진 문자열을 입력받아 -> 같은 문자가 연속으로 반복되는 경우 반복 문자 바로 오른쪽에 반복 횟수를 표기
ex) KKHSSSSSSSF -> K2H1S7F1 이런방식으로 -> 이렇게 하는 줄 알았는데, 1개인 부분은 1은 안찍고 그냥 알파벳만 찍음
고민해보기
우선 반복문 탐색(String 길이) -> 문자열 앞, 뒤 요소 비교하고 같으면 count 증가, 다르면 해당 문자열 요소와 count 저장
근데 이렇게 하면 StringboundaryException 발생 -> 당연함 요소가 없는데 어떻게 비교하냐? (이 부분에서 고민 많이 함)
이 부분에서 고민이 많아졌다. 그 이유는 인덱스 요소를 비교하는데, 마지막 요소를 비교할 수 있는 방법이 없었다.
해결책 : 그냥 문자열에 빈 여백을 하나 추가...
코드
public String solution(String a) {
String s = a + " ";
String answer = "";
int count = 1;
for (int i = 0; i < s.length() - 1; i++) {
if (s.charAt(i) == s.charAt(i + 1)) {
count++;
} else {
answer = answer + s.charAt(i);
if (count > 1) {
answer = answer + Integer.toString(count);
count = 1;
}
}
}
return answer;
1. 입력된 문자열에 빈 여백 하나 더해주기.
2. 여기서 count는 문자열에 해당 문자가 몇 개 있는지 check 하기 위해서 선언
3. 해당 인덱스와 다음 인덱스를 이용해 앞, 뒤 문자를 확인하고 같으면 cnt ++
다르면 비교중인 해당 인덱스를 answer에 추가하고, cnt가 1보다 크면 anwer 뒤에 저장(형변환까지), 그리고 cnt 1 초기
문제 3. 암호(replace(), parseInt(string, 2))
문제 설명과 예시, 그리고 내가 접근하고자 했던 방식
설명 : 알파벳 한 문자마다 # or *이 7개로 구성되어 있다 -> 입력된 # or * 일곱자리의 이진수(#->1, *->0)으로 변환 ->
이렇게 바뀐 이진수를 다시 10진수로 변환 -> 이 10진수를 아스키 코드로 변환 -> 그리고 출력
ex) 4 #****###**#####**#####**##** -> COOL
로직 순서 -> 입력받은 문자열을 이진수로 변환 -> 이 이진수를 쪼갬과 동시에 10진수로 변환하고, 그 요소를 배열에 저장
-> 배열의 인덱스엔 10진수가 저장되어있으니까 이 배열을 순회하면서 10진수를 아스키코드로 변환 -> 출력 끝!
고민해보기 <접근방식>
로직을 위의 설명처럼 구성했음. 과연 더욱 효율적인 방법이 있을까?
코드
위의 로직 순서대로 코드를 직접 작성하니 뭔가 코드가 엄청 길어지고 성능도 별로였다.
public void solution(int num, String p){
String a = "";
String answer = "";
int []arr = new int[num];
for(int i=0; i<p.length(); i++){
if(p.charAt(i)=='#'){
a=a+'1';
}else{
a=a+'0';
}
}
for(int i=0; i<num; i++){
String b=a.substring(i*7,((i*7)+7));
int c = Integer.parseInt(b,2);
arr[i]=c;
}
for(int i=0; i<num; i++){
char ch = (char) arr[i];
System.out.print(ch);
}
내가 구현한 코드는 윗 코드와 같다.
1. 첫 번째 반복문에서 전달받은 문자열을 이진수로 바꿔줄 것.
2. 다음 반복문에선 요소를 7개씩 자르고, 자른 요소를 10진수로 변환 후 배열에 저장
3. 마지막 반복문은 저장된 배열속 요소를 아스키 코드로 형변환
코드를 구현하고 해설강의를 보았는데, 해설강의의 코드는 다음과 같았다.
public String solution(int n, String s){
String answer="";
for(int i=0; i<n; i++){
String tmp=s.substring(0,7).replace('#','1').replace('*','0');
int num = Integer.parseInt(tmp,2);
answer += (char)num;
s=s.substring(7);
}
return answer;
}
너무 간결했다...
오늘 문자열 챕터의 마지막 3문제를 정복하며 어떻게 코드를 더욱 간결하게 짤 수있을까?
어떻게 로직에 접근할 수 있을가?
이 부분에는 어떻게 무엇을 사용하는게 좋을까? 라는 여러가지 생각을 하면서 직접 펜과 종이를 이용해 문제를 해결하는 시간을 가졌다.
'알고리즘 및 자료구조' 카테고리의 다른 글
chapter. String (숫자만 추출) (0) | 2022.11.30 |
---|---|
String(문자열)문제에서 찾은 StringBuilder (0) | 2022.01.20 |