괄호가 바르게 짝지어졌다는 것은 '(' 문자로 열렸으면 반드시 짝지어서 ')' 문자로 닫혀야 한다는 뜻입니다. 예를 들어
"()()" 또는 "(())()" 는 올바른 괄호입니다.
")()(" 또는 "(()(" 는 올바르지 않은 괄호입니다.
'(' 또는 ')' 로만 이루어진 문자열 s가 주어졌을 때, 문자열 s가 올바른 괄호이면 true를 return 하고, 올바르지 않은 괄호이면 false를 return 하는 solution 함수를 완성해 주세요.
제한사항
문자열 s의 길이 : 100,000 이하의 자연수
문자열 s는 '(' 또는 ')' 로만 이루어져 있습니다.
코드
import java.util.Stack;
class Solution {
boolean solution(String s) {
Stack<Character> stack = new Stack<Character>();
try {
for (char cha : s.toCharArray()) {
if (cha == '(')
stack.add(cha);
else { //문자열은 '(' , ')' 밖에 없기 때문에 이 조건식
stack.pop();
}
}
} catch (Exception e) {
return false; // 예외발생은 pop()에서 날 것 즉, 짝이 안맞는다.
}
return stack.empty() ? true : false;
}
}
결과
정확성 테스트
테스트 1 〉 통과 (0.17ms, 76.7MB)
테스트 2 〉 통과 (0.20ms, 81.6MB)
테스트 3 〉 통과 (0.19ms, 79MB)
테스트 4 〉 통과 (0.22ms, 79MB)
테스트 5 〉 통과 (0.27ms, 76.4MB)
테스트 6 〉 통과 (0.14ms, 77.1MB)
테스트 7 〉 통과 (0.24ms, 78.2MB)
테스트 8 〉 통과 (0.20ms, 75.6MB)
테스트 9 〉 통과 (0.25ms, 72.8MB)
테스트 10 〉 통과 (0.25ms, 75MB)
테스트 11 〉 통과 (0.20ms, 72.4MB)
테스트 12 〉 통과 (0.22ms, 75.1MB)
테스트 13 〉 통과 (0.30ms, 75.5MB)
테스트 14 〉 통과 (0.24ms, 73.4MB)
테스트 15 〉 통과 (0.21ms, 75.4MB)
테스트 16 〉 통과 (0.22ms, 99.7MB)
테스트 17 〉 통과 (0.21ms, 74.8MB)
테스트 18 〉 통과 (0.25ms, 68MB)
효율성 테스트
테스트 1 〉 통과 (15.83ms, 53.8MB)
테스트 2 〉 통과 (14.89ms, 53.1MB)
채점 결과
정확성: 69.5
효율성: 30.5
합계: 100.0 / 100.0
스트리밍 사이트에서 장르 별로 가장 많이 재생된 노래를 두 개씩 모아 베스트 앨범을 출시하려 합니다. 노래는 고유 번호로 구분하며, 노래를 수록하는 기준은 다음과 같습니다.
속한 노래가 많이 재생된 장르를 먼저 수록합니다.
장르 내에서 많이 재생된 노래를 먼저 수록합니다.
장르 내에서 재생 횟수가 같은 노래 중에서는 고유 번호가 낮은 노래를 먼저 수록합니다.
노래의 장르를 나타내는 문자열 배열 genres와 노래별 재생 횟수를 나타내는 정수 배열 plays가 주어질 때, 베스트 앨범에 들어갈 노래의 고유 번호를 순서대로 return 하도록 solution 함수를 완성하세요.
제한사항
genres[i]는 고유번호가 i인 노래의 장르입니다.
plays[i]는 고유번호가 i인 노래가 재생된 횟수입니다.
genres와 plays의 길이는 같으며, 이는 1 이상 10,000 이하입니다.
장르 종류는 100개 미만입니다.
장르에 속한 곡이 하나라면, 하나의 곡만 선택합니다.
모든 장르는 재생된 횟수가 다릅니다.
입출력 예
genres
plays
return
["classic", "pop", "classic", "classic", "pop"]
[500, 600, 150, 800, 2500]
[4, 1, 3, 0]
입출력 예 설명
classic 장르는 1,450회 재생되었으며, classic 노래는 다음과 같습니다.
고유 번호 3: 800회 재생
고유 번호 0: 500회 재생
고유 번호 2: 150회 재생
pop 장르는 3,100회 재생되었으며, pop 노래는 다음과 같습니다.
고유 번호 4: 2,500회 재생
고유 번호 1: 600회 재생
따라서 pop 장르의 [4, 1]번 노래를 먼저, classic 장르의 [3, 0]번 노래를 그다음에 수록합니다.
장르 별로 가장 많이 재생된 노래를 최대 두 개까지 모아 베스트 앨범을 출시하므로 2번 노래는 수록되지 않습니다.
코드
import java.util.*;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import static java.util.stream.Collectors.*;
class Solution {
static int i = 0;
public int[] solution(String[] genres, int[] plays) {
return IntStream.range(0, genres.length) // intStream
.mapToObj(i-> new TopGenrePlay(i, genres[i], plays[i])) // 기본형에서 참조형으로
.collect(groupingBy( TopGenrePlay::getGenre)) // key는 genres[i] 객체 그대로 Map<String, List<TopGenrePlay>>
.entrySet().stream() // Stream<Entry<String, List<TopGenrePlay>>>
.sorted( (a,b)-> { // 스트림 안에서 총 Play집계 값으로 내림차순
int sum1 = a.getValue().stream().mapToInt(TopGenrePlay::getPlay).sum();
int sum2 = b.getValue().stream().mapToInt(TopGenrePlay::getPlay).sum();
return Integer.compare(sum2, sum1);}) //내림차순
.map( entry -> { //<Entry<String, List<TopGenrePlay>>>
List tgpList = entry.getValue().stream().sorted()//정렬은 객체에 구현된 Comparable에 의존한다.
.limit(2)//정렬된 결과에서 2개만 가져온다.
.map( TopGenrePlay::getId ).collect(toList());//식별값만 필요하다.
entry.setValue(tgpList);
return entry; } )
.flatMap( entry-> Stream.of(entry.getValue().toArray(new Integer[] {}))) // 하나의 스트림으로 만든다.
.mapToInt( Integer::intValue ) //기본형 스트림으로 IntStream
.toArray()
;
}
public static void main(String[] args) {
Solution s = new Solution();
System.out.println(Arrays.toString(s.solution(
new String[] { "classic", "pop", "classic", "classic", "pop", "trot", "trot", "trot", "pop" },
new int[] { 1000, 600, 2000, 1000, 2500, 6000, 200, 200, 600 })));
}
class TopGenrePlay implements Comparable<TopGenrePlay> {
int id;
String genre;
int play;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getGenre() {
return genre;
}
public void setGenre(String genre) {
this.genre = genre;
}
public int getPlay() {
return play;
}
public void setPlay(int play) {
this.play = play;
}
public TopGenrePlay(int id, String genre, int play) {
super();
this.id = id;
this.genre = genre;
this.play = play;
}
@Override
public String toString() {
return "[id="+ id + ", genre=" + genre + ", play=" + play + "]";
}
@Override
public int compareTo(TopGenrePlay o) {
int result = Integer.compare(o.play, this.play);
if (result == 0) {
return Integer.compare(this.id, o.id);
}
return result;
}
}
}
결과
정확성 테스트
테스트 1 〉 통과 (17.71ms, 82.3MB)
테스트 2 〉 통과 (13.47ms, 77.6MB)
테스트 3 〉 통과 (15.14ms, 81.7MB)
테스트 4 〉 통과 (15.90ms, 73.1MB)
테스트 5 〉 통과 (9.80ms, 81.5MB)
테스트 6 〉 통과 (15.30ms, 73.7MB)
테스트 7 〉 통과 (10.73ms, 72.7MB)
테스트 8 〉 통과 (9.44ms, 73.7MB)
테스트 9 〉 통과 (9.91ms, 73.8MB)
테스트 10 〉 통과 (16.23ms, 80.8MB)
테스트 11 〉 통과 (8.91ms, 75MB)
테스트 12 〉 통과 (8.83ms, 75.1MB)
테스트 13 〉 통과 (14.77ms, 81.3MB)
테스트 14 〉 통과 (10.05ms, 78.5MB)
테스트 15 〉 통과 (8.19ms, 75.4MB)
퇴근하고 이틀 동안 계속 붙잡았다... 컬렉션으로만 해결하려 했던게 오히려 나에겐 독이였다.
될듯..?말듯...
그러다 문득, 내가 자바를 하는데 너무 함수형으로 생각한 게 아닌가 라는 생각이 들었다.
갑자기 Class를 활용할 생각을 안하고 컬렉션만 쓰려했는지...참...
그래도 이 교훈은 오래 남을 듯 하다.
누군가 봐서 조금이라도 도움이 됐으면하는 마음으로 중간중간에 데이터 형을 입력했다.
위 코드의 개략적인 구도는 play, id 순 정렬은 객체의 Comparable 구현에 의존한다.
첫째 줄에 (A+B)%C, 둘째 줄에 ((A%C) + (B%C))%C, 셋째 줄에 (A×B)%C, 넷째 줄에 ((A%C) × (B%C))%C를 출력한다.
예시
입력 : 5 8 4
출력
1
1
0
0
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.function.Function;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<Integer> intList = new ArrayList<Integer>();
intList.add(scanner.nextInt());
intList.add(scanner.nextInt());
intList.add(scanner.nextInt());
System.out.println(calc(intList, (list) -> {
int A = list.get(0);
int B = list.get(1);
int C = list.get(2);
return (A + B) % C;
}));
System.out.println(calc(intList, (list) -> {
int A = list.get(0);
int B = list.get(1);
int C = list.get(2);
return ((A%C) + (B%C))%C;
}));
System.out.println(calc(intList, (list) -> {
int A = list.get(0);
int B = list.get(1);
int C = list.get(2);
return (A*B)%C;
}));
System.out.println(calc(intList, (list) -> {
int A = list.get(0);
int B = list.get(1);
int C = list.get(2);
return ((A%C) * (B%C))%C;
}));
}
public static int calc(List<Integer> intList, Function<List<Integer>, Integer> func) {
return func.apply(intList);
}
}
ICPC Bangkok Regional에 참가하기 위해 수완나품 국제공항에 막 도착한 팀 레드시프트 일행은 눈을 믿을 수 없었다. 공항의 대형 스크린에 올해가 2562년이라고 적혀 있던 것이었다.
불교 국가인 태국은 불멸기원(佛滅紀元), 즉 석가모니가 열반한 해를 기준으로 연도를 세는 불기를 사용한다. 반면, 우리나라는 서기 연도를 사용하고 있다. 불기 연도가 주어질 때 이를 서기 연도로 바꿔 주는 프로그램을 작성하시오.
입력
서기 연도를 알아보고 싶은 불기 연도y가 주어진다. (1000 ≤y≤ 3000)
출력
불기 연도를 서기 연도로 변환한 결과를 출력한다.
예시
입력 : 2541
출력 : 1998
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println(scanner.nextInt()-543);
}
}
준하는 사이트에 회원가입을 하다가 joonas라는 아이디가 이미 존재하는 것을 보고 놀랐다. 준하는 놀람을 ??!로 표현한다. 준하가 가입하려고 하는 사이트에 이미 존재하는 아이디가 주어졌을 때, 놀람을 표현하는 프로그램을 작성하시오.
입력
첫째 줄에 준하가 가입하려고 하는 사이트에 이미 존재하는 아이디가 주어진다. 아이디는 알파벳 소문자로만 이루어져 있으며, 길이는 50자를 넘지 않는다.
출력
첫째 줄에 준하의 놀람을 출력한다. 놀람은 아이디 뒤에 ??!를 붙여서 나타낸다.
예시
입력값 : wow
출력값 : wow??!
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String id1 = scanner.next();
System.out.println(appendString(id1));
}
public static String appendString(String str) {
return new StringBuffer(str).append("??!").toString();
}
}
핵심
문자열 결합은 StringBuffer를 사용하는 것이 좋다. String은 변경불가능한 상수로 매번 새로운 객체가 생성되지만, StringBuffer는 문자 그대로 내부에 Buffer가 있어 불필요한 새로운 객체 생성이 없다.