코딩테스트 준비
JAVA로 코딩테스트를 준비하기로 하였다.
- JAVA만 코딩테스트를 보는 회사가 많다. 내 시장성 가치를 올리기 위해 수요가 많은 시장을 선택한다.
- 추후 안드로이드 개발도 관심이 있는데 코틀린이 자바와 완전한 상호운용이 가능하고 구문 전환이 용이하므로 자바 개발자에게 매력적이라고 한다.
공부는 인터넷 강의에 나와있는 백준 문제대로 풀이를 하고 하루에 한 번씩 같이 코딩테스트를 공부하는 스터디원분과 손코딩으로 작성하며 문제풀이를 설명하는 방식이다.
[2744] 대소문자 바꾸기
문제
영어 소문자와 대문자로 이루어진 단어를 입력받은 뒤, 대문자는 소문자로, 소문자는 대문자로 바꾸어 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 영어 소문자와 대문자로만 이루어진 단어가 주어진다. 단어의 길이는 최대 100이다.
출력
첫째 줄에 입력으로 주어진 단어에서 대문자는 소문자로, 소문자는 대문자로 바꾼 단어를 출력한다.
예제 입력 1 복사
WrongAnswer
예제 출력 1 복사
wRONGaNSWER
제일 처음 문제 풀이
먼저 답안과 문제를 풀기전에 정리해보자.
- 문자열(영어)를 입력 받아야 한다.
- 입력받은 문자열을 소문자와 대문자로 구별을 해야 한다.
- 구별한 소문자와 대문자를 반대로 변경해야 한다.(소문자 → 대문자 & 대문자 → 소문자)
- 변경된 문자열을 출력하자.
문자열(영어)를 입력 받아야 한다.
- 일단 나는 JAVA 기초를 공부하며 코딩테스트를 준비해야 한다. JAVA에서 문자열의 특징을 알아보자.
- JAVA에서 문자열을 입력받는 방식
- Scanner 클래스를 사용해서 입력받는 문자열을 받아보자.
import java.util.Scanner // 스캐너 클래스 임포트 Scanner sc = new Scanner(System.in); // 스캐너 객체 생성 String input = sc.next(); // 스캐너 클래스의 메소드 중 next() 메서드 사용
입력 받은 문자열을 소문자와 대문자로 구별 해야 한다.
- 방법은 두가지의 방식이 있다.
- isUpperCase() 메서드, isLowerCase() 메서드 사용하기
- Character 클래스에서 제공하는 메서드가 문자가 대문자인지 소문자인지 확인할 수 있다.
- isUpperCase() 대문자일 경우 true 반대로 isLowerCase()는 소문자일 경우 true
- // 대문자만 출력 for(int i=0; i<input.length(); i++) { if (Character.isUpperCase(input.charAt(i))) { System.out.println("대문자:" + input.charAt(i)); } }
- ASCII 코드 이용하기
- ASCII 코드표를 보면 대문자는 65부터 소문자는 97부터 시작하는 것을 알 수 있다. 이 숫자를 이용하면 대문자와 소문자를 구분할 수 있다.
for (int i =0; i<str.length(); i++) { // 대문자일 경우 if (str.charAt(i) < 'a') { System.out.print((char)(str.charAt(i))); } else { System.out.print((char)(str.charAt(i))); } }
- ASCII 코드표를 보면 대문자는 65부터 소문자는 97부터 시작하는 것을 알 수 있다. 이 숫자를 이용하면 대문자와 소문자를 구분할 수 있다.
- isUpperCase() 메서드, isLowerCase() 메서드 사용하기
구별한 소문자와 대문자를 반대로 변경해야 한다.(소문자 → 대문자 & 대문자 → 소문자)
- ASCII 코드를 사용해서 더 해주는 코드
import java.util.Scanner;
public class Solution {
public static void main(String[] args) {
// 1. 문자열 입력 받기
Scanner input = new Scanner(System.in);
String str = input.nextLine();
// 2. 소문자와 대문자의 차이 구하기
// 3. 입력받은 값의 문자를 숫자로 변경하여 대소문자 변경하기
for (int i =0; i<str.length(); i++) {
// 대문자일 경우
if (str.charAt(i) < 'a') {
System.out.print((char) (str.charAt(i) + 'a' - 'A'));
} else {
System.out.print((char) (str.charAt(i) + 'A' - 'a'));
}
}
}
}
[1919]애너그램 만들기
문제
두 영어 단어가 철자의 순서를 뒤바꾸어 같아질 수 있을 때, 그러한 두 단어를 서로 애너그램 관계에 있다고 한다. 예를 들면 occurs 라는 영어 단어와 succor 는 서로 애너그램 관계에 있는데, occurs의 각 문자들의 순서를 잘 바꾸면 succor이 되기 때문이다.
한 편, dared와 bread는 서로 애너그램 관계에 있지 않다. 하지만 dared에서 맨 앞의 d를 제거하고, bread에서 제일 앞의 b를 제거하면, ared와 read라는 서로 애너그램 관계에 있는 단어가 남게 된다.
두 개의 영어 단어가 주어졌을 때, 두 단어가 서로 애너그램 관계에 있도록 만들기 위해서 제거해야 하는 최소 개수의 문자 수를 구하는 프로그램을 작성하시오. 문자를 제거할 때에는 아무 위치에 있는 문자든지 제거할 수 있다.
입력
첫째 줄과 둘째 줄에 영어 단어가 소문자로 주어진다. 각각의 길이는 1,000자를 넘지 않으며, 적어도 한 글자로 이루어진 단어가 주어진다.
출력
첫째 줄에 답을 출력한다.
예제 입력 1 복사
aabbcc
xxyybb
예제 출력 1 복사
8
문제 풀이
문자열 입력받기
- 대소문자 변경하기 문제를 풀 때 학습했던 Scanner클래스를 이용
- 문자열 두 개를 입력 받을 것이다.
- import java.util.Scanner public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String a = sc.next(); String b = sc.next(); } }
중복된 문자찾기
- 중복된 문자를 찾으려면 문자열끼리 비교를 해야한다.
- 문제를 풀다가 보니 equals로 한다면 문자열끼리 비교이기 때문에 Character가 포함되어 있는지 확인하는 여부로 변경해봤다.
- 하지만 하나씩 모든 요소를 비교하면 시간복잡도가 O(n^2)이 나올것같다.
- int 배열을 활용해서 문제를 풀 것이다
- count 배열은 a~z까지 순서대로 몇개가 있는지 저장이 된다. 아래 사진처럼 aabbcc는 a가 2개, b가 2개, c가2개 이기 때문에 [2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]가 저장이 된다.
- 문자열 만큼 반복문을 돌려 count배열 i번째 요소가 있을때 마다 추가해준다. ASCII코드를 이용하여 어떤 문자인지 확인할 수 있다.
public static int[] getAlphabetCountArray(String str) {
int[] count = new int[26];
for (int i = 0; i < str.length(); i++)
count[str.charAt(i) - 'a']++; // ASCII 코드 사용
return count;
}
중복된 문자 이외의 문자 개수 구하기
- countA와 countB의 몇번째 요소가 몇개있는지 저장하였다.
- 이제 반복문을 사용해서 countA의 i번째요소와 countB의 i번째 요소를 빼준다음 Math.abs메서드를 사용하여 절대값으로 더해주면 된다!
int[] countA = getAlphabetCountArray(a);
int[] countB = getAlphabetCountArray(b);
int ans = 0;
for (int i = 0; i <26; i++)
ans += Math.abs(countA[i] - countB[i]);
System.out.println(ans);
기타
JAVA String의 특징
- JAVA에서 String은 기본형이 아닌 참조형이다. 즉, stack영역이 아닌 heap에 문자열 변수 데이터가 생성되고 다뤄진다.
- String은 불변이다. 기본적으로 JAVA에서 String 객체의 값은 변경할 수 없다. hashCode() 메소드를 이용해 실제로 변수가 가지고 있는 주소값을 찍어보면 알 수 있다.
String a = "Hello";
a = a + " World";
System.out.println(a); // Hello World
String a = "Hello";
System.out.println(a.hashCode()); // 69609650
a = a + " World";
System.out.println(a.hashCode()); // -862545276
- 불변으로 설계된 이유
- JVM에서 String Constant Pool이라는 독립적인 영역을 만들고 문자열들을 Constant화 하여 다른 변수 혹은 객체들과 고유하게 되는데 이 과정에서 데이터 캐싱이 일어나고 그만큼 성능적 이득을 취할 수 있음.
- 데이터가 불변하다면 Multi-Table 환경에서 동기화 문제가 발생하지 않음
- 보안, 해커가 참조값을 변경하여 애플리케이션에 보안 문제를 일으킬 수 있음.
- 리터럴을 이용한 방식, new 연산자를 이용한 방식 아래 문자열은 JVM 메모리에 내부적인 측면에서 큰 차이가 존재함.
- String str1 = "Hello"; // 문자열 리터럴을 이용한 방식 String str2 = "Hello"; String str3 = new String("Hello"); // new 연산자를 이용한 방식 String str4 = new String("Hello");
String Constant Pool
문자열 리터럴을 변수에 저장하게 되면 이 값은string constant pool이라는 영역에 존재하게 되고,new를 통해 String을 생성하면 이 값은 Heap 영역에 존재하게 된다.
중요한 점은 str1, str2 가 같은 메모리 주소를 가리킨다는 점 String 은 한번 사용이 되면 또다시 재사용될 확률이 높기 때문에, 이에 대한 적절한 대처 방법으로 Heap 영역 내에 문자열 상수의 Pool 을 유지하고 해당 Pool 로 사용자가 정의한 변수가 가지고 있는 value 들을 담고 같은 주소를 참조하도록 연결해주었기 때문이다.
만약 new String() 방식을 사용하면 메모리를 더 사용하는 것이다.
JAVA에서 문자열을 입력받는 방식
- Scanner 클래스를 사용하여 값을 입력 받을 수 있다. 스캐너 클래스 호출
**import** java.util.Scanner;
- 스캐너의 객체 생성 sc라는 객체를 생성하여 System.in으로 입력한 값을 바이트 단위로 읽음.
Scanner sc = new Scanner(System.in);
- 각 메소드
next + {자료형}()
예시에서는 대표적으로 nextInt()와 nextDouble() 을 사용하였다.
뒤에 사용한 자료형에 맞는 값을 받을 수 있다.
nextLine()
한 줄을 통째로 받아온다. 근데 nextLine()은 개행문자까지 받을 수 있다.
next()
화이트 스페이스를 기준으로 한 단어를 받아온다.
문자열 비교하는 방법
- equals()으로 문자열 비교 주의점: str1이 Null이라면 NullPointerExecption 발생
str1.equals(str2) : false str2.equals(str1) : false str1.equals(str3) : true
- String str1 = "Hello"; String str2 = "World"; String str3 = "Hello"; System.out.println("str1.equals(str2) : " + str1.equals(str2)); System.out.println("str2.equals(str1) : " + str2.equals(str1)); System.out.println("str1.equals(str3) : " + str1.equals(str3));
- == 를 이용하여 문자열 비교하지 못함
- 그 이유는 JAVA에서 String은 참조형인데 ==는 주소값을 비교하기 때문에 같은 문자열을 갖더라도 주소값이 다름.
- 문자열 비교하는 방법
- equals()으로 문자열 비교 주의점: str1이 Null이라면 NullPointerExecption 발생
str1.equals(str2) : false str2.equals(str1) : false str1.equals(str3) : true
- String str1 = "Hello"; String str2 = "World"; String str3 = "Hello"; System.out.println("str1.equals(str2) : " + str1.equals(str2)); System.out.println("str2.equals(str1) : " + str2.equals(str1)); System.out.println("str1.equals(str3) : " + str1.equals(str3));
- equals()으로 문자열 비교 주의점: str1이 Null이라면 NullPointerExecption 발생
- == 를 이용하여 문자열 비교하지 못함
- 그 이유는 JAVA에서 String은 참조형인데 ==는 주소값을 비교하기 때문에 같은 문자열을 갖더라도 주소값이 다름.
'알고리즘 > 백준' 카테고리의 다른 글
[코딩테스트] [1157] 단어 공부 & [1543] 문서검색 (0) | 2024.11.26 |
---|---|
[백준/Gold IV] 오큰수 - 17298 (1) | 2024.06.25 |
[백준/Silver II] 쇠막대기 - 10799 (0) | 2024.05.28 |
[백준/Silver V] 셀프 넘버 - 4673 (0) | 2024.05.24 |
[백준/Silver III] 단어 뒤집기 2 - 17413 (0) | 2024.05.24 |