10/26 백준
9093 단어 뒤집기
풀이 1(StringBuilder 이용)
이 풀이는 StringBuilder 객체의 reverse() 메소드를 이용해 간단하게 문장의 문자열을 뒤집는 역할을 한다.
StringBuilder
StringBuilder는 문자열을 더하거나 수정할 때 사용되는 클래스이다. String 객체는 immutable이기 때문에 문자열이 변경될 때마다 새로운 객체가 생성되지만 StringBuilder는 기존 객체를 수정한다는 특징이 있다.
- append(String str) : 문자열 끝에 새로운 문자열 추가
- insert(int offset, String str) : 특정 위치에 문자열을 삽입
- delete(int start, int end) : 지정한 범위의 문자열 삭제
- reverse() : 문자열 뒤집기
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
sc.nextLine();
for (int i = 0; i < T; i++) {
String sen = sc.nextLine();
String[] senToWord = sen.split(" ");
int wordNum = senToWord.length;
for (int j = 0; j < wordNum; j++) {
String reversedWord = new StringBuilder(senToWord[j]).reverse().toString();
System.out.print(reversedWord + " ");
}
System.out.println();
}
}
}
풀이 2(반복문 사용)
StringBuilder를 이용한 부분을 반복문을 사용했다는점 말고 동일하다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
sc.nextLine();
for (int i = 0; i < T; i++) {
String sen = sc.nextLine();
String[] senToWord = sen.split(" ");
int wordNum = senToWord.length;
for (int j = 0; j < wordNum; j++) {
String word = senToWord[j];
String reversedWord = "";
for (int k = word.length() - 1 ; k >= 0; k--) {
reversedWord += word.charAt(k);
}
System.out.print(reversedWord + " ");
}
System.out.println();
}
}
}
문자열을 뒤집는 부분에서 단어의 가장 마지막 인덱스부터 처음 인덱스까지 반복문을 돌린 후 문자열에 더해주면 된다.
여기서 주의할 점은 이제껏 사용했던 언어와 달리 문자열은 인덱스가 아닌 charAt으로 접근해야 한다.
놓치기 쉬운 부분
이 문제를 풀면서 컴파일 에러가 많이 났다.
-
케이스 수 T를 입력받은 뒤, 개행문자를 제거하는 코드가 필요하다.
sc.nextLine();
-
length vs length();
length는 배열의 길이를 구할 때, length()는 문자열의 길이를 구할 때 사용된다.
-
split()은 배열을 반환
선언을 할 때 String에 대괄호([])를 쓰는걸 깜빡하고 한참 오류를 찾았다.
그리고 파이썬에서는 split()만 호출해도 알아서 공백을 기준으로 분리해줘서 안에 아무것도 안써줬더니 컴파일 에러가 났다. 자바에서는 공백으로 분리하려면 매개변수에 “ “을 꼭 넣어줘야 한다는 점!!
9012 괄호
풀이
스택을 직접 구현해서 풀었다. 먼저 괄호에서 나올 수 있는 경우의 수는 3가지가 있다.
- 올바른 괄호
- 여는 괄호가 더 많음
- 닫는 괄호가 더 많음
우선 기본적인 스택 클래스를 만들어준다.
class Stack {
private int top = -1;
private char[] stack = new char[51];
public Stack() {
}
public void push(char x) {
stack[++top] = x;
}
public char pop() {
if (!empty()) {
return stack[top--];
} else {
return '\0';
}
}
public boolean empty() {
return top == -1;
}
}
괄호 문자열을 입력받은 뒤 charAt()을 이용해 괄호 하나씩 접근해서
여는 괄호일 때는 무조건 push를 해준다.
닫는 괄호가 등장했을 때는 두가지로 나뉜다. 스택에 여는괄호가 하나라도 있을때(empty())와 스택에 아무것도 없을떄(!empty())이다.
스택이 비어있지 않을 때는 스택에 있는 괄호 하나를 pop해주면 된다. 하지만 스택이 비어있을 때는 괄호의 쌍이 맞지 않으므로 boolean 변수 isBalanced를 false로 만들어준다.
isBalanced는 닫는 괄호가 더 많은 경우를 필터링 해주는 역할을 하므로 여는 괄호가 더 많은 경우를 커버하기 위해서는 괄호검사를 마쳤을 때 스택이 비어있는지 검사해야 한다. isBalanced가 true이고 스택이 비어있다면 올바른 괄호 쌍이 되고, 스택이 비어있지 않다면 여는 괄호가 많이 있다는 의미이기 때문에 NO를 출력하면 된다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
sc.nextLine();
for (int i = 0; i < T; i++) {
Stack stack = new Stack();
String parenthesis = sc.next();
int len = parenthesis.length();
boolean isBalanced = true;
for (int j = 0; j < len; j++) {
char p = parenthesis.charAt(j);
if (p == '(') {
stack.push(p);
} else if (p == ')') {
if (!stack.empty()) {
stack.pop();
} else {
isBalanced = false;
break;
}
}
}
if (isBalanced && stack.empty()) {
System.out.println("YES");
} else {
System.out.println("NO");
}
}
}
}
이코테 3-2
N : 배열의 길이
M : 숫자들이 총 더해지는 횟수
K : 한 숫자가 한번에 더해질 수 있는 횟수
입력 : 첫째줄에 N, M, K의 자연수, 둘째줄에 N개의 자연수가 주어지며, 공백으로 구분한다.
출력 : 나올 수 있는 최댓값
예를들어 N = 5, M = 8, K = 3이 주어지고 N = 5개의 자연수 2 4 5 4 6가 주어졌을 때
6 + 6 + 6 + 5 + 6 + 6 + 6 + 5 = 46이 정답이다.
풀이
package ch03Greedy;
import java.util.Arrays;
import java.util.Scanner;
//첫째줄에 배열 크기 N, 숫자가 총 더해지는 횟수 M, 한 숫자가 한번에 더해질 수 있는 횟수 K
//일 때 나올 수 있는 결과의 최댓값
public class ex02 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int M = sc.nextInt();
int K = sc.nextInt();
int[] numArr = new int[N];
for (int i = 0; i < N; i++) {
numArr[i] = sc.nextInt();
}
Arrays.sort(numArr);
int first = numArr[N - 1];
int second = numArr[N - 2];
int result = 0;
while (true) {
for (int i = 0; i < K; i++) {
if (M == 0) {
break;
}
result += first;
M--;
}
if (M == 0) {
break;
}
result += second;
M--;
}
System.out.println(result);
}
}
-
Arrays.sort()
매개변수 자리에 정렬하고싶은 배열을 넣으면 오름차순으로 정렬하게 된다.
이코테 3-3
카드들이 N행 M열로 나열되어 있을 때, 각 행에서 가장 작은 숫자카드를 뽑은 뒤, 뽑은 숫자들 중에 가장 큰 수를 구하는 문제이다.
풀이
package ch03Greedy;
import java.util.Scanner;
//각 행에서 가장 작은 숫자를 뽑은 뒤, 뽑은 숫자들 중에서 가장 큰 수를 뽑음
public class ex03 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(); // 행
int m = sc.nextInt(); // 열
int[] rowMinArr = new int[n];
for (int i = 0; i < n; i++) {
// int rowMin = 10001;
int rowMin = Integer.MAX_VALUE;
for (int j = 0; j < m; j++) {
int num = sc.nextInt();
if (rowMin > num) {
rowMin = num;
}
}
rowMinArr[i] = rowMin;
}
int result = rowMinArr[0];
for (int i = 0; i < n; i++) {
if (result < rowMinArr[i]) {
result = rowMinArr[i];
}
}
System.out.println(result);
}
}
- Integer.MAX_VALUE
문제에서 숫자카드에 줄 수 있는 최댓값이 10000이라고 주어져 있어서 rowMin 변수를 10001로 초기화 했지만, 조금 더 범용적으로 쓸 수 있는 방법은 Integer.MAX_VALUE이다. 이 표현은 정수 중에서 가장 큰 수 $2^{31} - 1$을 의미한다.
이코테 4-1-2
0시 0분 0초 ~ N시 59분 59초의 모든 시각에서 숫자 3이 포함된 경우의 수 구하기
풀이
package ch04Implement;
import java.util.Scanner;
//모든 시각 중에서 숫자 3이 포함되어있는 경우의 수를 구하기
public class ex1_2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int result = 0;
for (int i = 0; i <= n; i++) {
for (int j = 0; j < 60; j++) {
for (int k = 0; k < 60; k++) {
String timeStr = String.format("%02d%02d%02d", i, j, k);
if (timeStr.contains("3")) {
result++;
}
}
}
}
System.out.println(result);
}
}
이 문제에서 핵심은 숫자를 문자열로 포맷팅하는 것이다.
-
String.format(“HHmmss”, x, y, z)
String.format() 함수를 이용해 숫자를 시, 분, 초 문자열로 바꿔준다.
-
timeStr.contains(“3”)
contains() 메서드를 이용해 3이 포함된 경우 결과에 하나씩 더해준다.
댓글남기기