https://programmers.co.kr/learn/courses/30/lessons/49993?language=java


소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public int solution(String skill, String[] skill_trees) {
char[] ch = skill.toCharArray();

List<ArrayList<Skill>> l = new ArrayList<ArrayList<Skill>>();
for (String element : skill_trees) {
ArrayList<Skill> list = new ArrayList<Skill>();

for (int i = 0; i < ch.length; i++) {
Skill s = new Skill();
s.skill = ch[i];
s.index = element.indexOf(ch[i]);

if (s.index != -1) {
list.add(s);
}
}

l.add(list);
}

int answer = 0;
for (ArrayList<Skill> list : l) {
Collections.sort(list, new Comparator<Skill>() {
@Override
public int compare(Skill o1, Skill o2) {
return o1.getIndex().compareTo(o2.getIndex());
}
});

StringBuilder sb = new StringBuilder();
for (Skill s : list) {
sb.append(s.getSkill());
}

if (skill.startsWith(sb.toString())) {
answer++;
}
}

return answer;
}

public class Skill {
private int index;
private char skill;

public Integer getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public char getSkill() {
return skill;
}
public void setSkill(char skill) {
this.skill = skill;
}
}

흐름

  1. 스킬트리에 있는 스킬들을 선행스킬 만큼 반복한다.

  2. 돌면서 스킬들에서 선행스킬의 index와 선행스킬명을 저장하는 클래스(Skill)에 저장하고 그 클래스를 List에 저장한다.

    • ex) List = [{index = 1, skill = A}, {index = 7, skill = Q}, …]
  3. 선행스킬명을 저장한 List를 다른 List(AllSkillList)에 저장한다.

    • 전체 스킬을 저장해야 하므로
    • ex) AllSkillList = [List1, List2, List3, …]
  4. 전체 스킬이 저장된 List(AllSkillList)를 돌면서 저장된 List의 Skill의 Index 순으로 정렬 시킨다.

  5. 정렬된 List를 돌면서 StringBuilder에 스킬명을 담는다.

  6. 입력받은 선행스킬과 비교하여 일치하면 answer을 증가 시킨다.


다른 분의 소스

1
2
3
4
5
6
7
8
9
10
11
12
13
public int solution(String skill, String[] skill_trees) {
int answer = 0;
ArrayList<String> skillTrees = new ArrayList<String>(Arrays.asList(skill_trees));
Iterator<String> it = skillTrees.iterator();

while (it.hasNext()) {
if (skill.indexOf(it.next().replaceAll("[^" + skill + "]", "")) != 0) {
it.remove();
}
}
answer = skillTrees.size();
return answer;
}

로직

  • 스킬트리에 있는 스킬들 중 선행스킬이 아닌 녀석들을 없애버리고 선행스킬과 일치하는 지 확인해서 일치하지 않으면 List에서 삭제하고 List의 갯수를 return 하는 것으로 끝을 낸다.

  • ex) “CBD” 인 경우 “BACDE”에서 “C”, “B”, “D”가 아닌 녀석들은 삭제되서 “BCD”가 남지만 “CBD”.indexOf(“BCD”) 할 경우 “CBD”에 “BCD”가 존재 하지 않으므로 1을 return 하고 -1은 0이 아니므로 List에서 삭제된다.

  • “BDA” 인 경우엔 “CBD”.indexOf(“BD”) 할 경우 “CBD”에 존재하지만 1 번째 index에 존재하므로 1을 return 하고 List에서 삭제된다.

  • 직관적이고 가독성이 좋다.

  • 정규표현식 활용도 굿


결과

1 번

번호 속도
테스트 1 통과 (1.40ms, 52.1MB)
테스트 2 통과 (1.37ms, 50.1MB)
테스트 3 통과 (1.29ms, 52.7MB)
테스트 4 통과 (1.11ms, 52.3MB)
테스트 5 통과 (1.42ms, 50.6MB)
테스트 6 통과 (1.33ms, 52.4MB)
테스트 7 통과 (1.38ms, 50.5MB)
테스트 8 통과 (1.38ms, 50.8MB)
테스트 9 통과 (1.46ms, 52MB)
테스트 10 통과 (1.26ms, 52.4MB)
테스트 11 통과 (1.36ms, 54.3MB)
테스트 12 통과 (1.72ms, 52.5MB)
테스트 13 통과 (1.27ms, 52.3MB)
테스트 14 통과 (1.31ms, 52.2MB)

2 번

번호 속도
테스트 1 통과 (17.73ms, 54.5MB)
테스트 2 통과 (18.75ms, 52.2MB)
테스트 3 통과 (17.83ms, 52.4MB)
테스트 4 통과 (19.98ms, 54.3MB)
테스트 5 통과 (20.10ms, 52.3MB)
테스트 6 통과 (20.89ms, 52.5MB)
테스트 7 통과 (20.94ms, 54.3MB)
테스트 8 통과 (18.68ms, 52.2MB)
테스트 9 통과 (19.60ms, 52.8MB)
테스트 10 통과 (20.75ms, 54.4MB)
테스트 11 통과 (18.02ms, 52.3MB)
테스트 12 통과 (18.70ms, 54.3MB)
테스트 13 통과 (18.79ms, 52.5MB)
테스트 14 통과 (19.85ms, 54.8MB)
  • 2 번의 경우 Arrays.asList(skill_trees) 와 replace 때문에 속도가 살짝 느려진 것으로 판단된다.

테스트 케이스

1
2
3
4
5
6
assertEquals(3, test.solution("CBD", new String[] {"BACDE", "CBADF", "AECB", "BDA", "ASF", "BDF","CEFD"}));
assertEquals(4, test.solution("C", new String[] {"BACDE", "CBADF", "AECB", "BDA"}));
assertEquals(2, test.solution("CBD", new String[] {"C", "D", "CB", "BDA"}));
assertEquals(2, test.solution("AC", new String[] {"ABC", "CA", "ATEW", "SFCQTA"}));
assertEquals(2, test.solution("ACHQ", new String[] {"TWER", "FGCHQEA", "ATEW", "SFCQTA"}));
assertEquals(4, test.solution("CBDK", new String[] {"CB", "CXYB", "BD", "AECD", "ABC", "AEX", "CDB", "CBKD", "IJCB", "LMDK"}));
  • 임의로 만든 테스트 케이스 이므로 위 테스트 케이스를 통과해도 시험에서 통과하지 못할 가능성이 있다.

댓글 공유

https://programmers.co.kr/learn/courses/30/lessons/17682?language=java


소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public int solution(String dartResult) {
char[] charArray = dartResult.toCharArray();

int[] scores = new int[3];
int i = 0;
StringBuilder sb = new StringBuilder();
for (char ch : charArray) {
switch (ch) {
case 'S':
scores[i++] = Integer.parseInt(sb.toString());

sb.setLength(0);
break;
case 'D':
int a = Integer.parseInt(sb.toString());
scores[i++] = a * a;

sb.setLength(0);
break;
case 'T':
int b = Integer.parseInt(sb.toString());
scores[i++] = b * b * b;

sb.setLength(0);
break;
case '*':
if (i > 1) {
scores[i-2] = scores[i-2] * 2;
}
scores[i-1] = scores[i-1] * 2;
break;
case '#':
scores[i-1] = scores[i-1] * -1;
break;
default:
sb.append(ch);
break;
}
}

int answer = scores[0] + scores[1] + scores[2];
return answer;
}

흐름

  1. 문자열을 charArray로 치환하고 loop 돈다.

  2. char를 비교하여 각 문자별로 맞게 계산을 실행하고, index를 증가 시킨 후 다음 점수 저장을 위해 StringBuilder를 초기화 한다.

  3. *‘ 일 경우 이전 점수와 현재 점수 모두 2 배씩 해야 하므로 2 번 던진 경우엔 이전 점수도 2를 곱 해준다.

  4. 계산된 세 점수 모두 더해서 return 한다.


결과

번호 속도
테스트 1 통과 (0.79ms, 52.4MB)
테스트 2 통과 (0.86ms, 52.2MB)
테스트 3 통과 (0.86ms, 52.4MB)
테스트 4 통과 (0.84ms, 52.3MB)
테스트 5 통과 (0.92ms, 54.5MB)
테스트 6 통과 (0.82ms, 52.5MB)
테스트 7 통과 (0.83ms, 52.1MB)
테스트 8 통과 (0.83ms, 52.2MB)
테스트 9 통과 (0.90ms, 50.8MB)
테스트 10 통과 (0.83ms, 52.7MB)
테스트 11 통과 (0.84ms, 52.9MB)
테스트 12 통과 (0.84ms, 52.5MB)
테스트 13 통과 (0.82ms, 50.4MB)
테스트 14 통과 (0.74ms, 52.6MB)
테스트 15 통과 (0.90ms, 52.1MB)
테스트 16 통과 (0.86ms, 52.9MB)
테스트 17 통과 (0.81ms, 52.7MB)
테스트 18 통과 (0.86ms, 52.4MB)
테스트 19 통과 (0.85ms, 50.1MB)
테스트 20 통과 (0.95ms, 52.4MB)
테스트 21 통과 (0.81ms, 50.4MB)
테스트 22 통과 (0.80ms, 51.9MB)
테스트 23 통과 (0.88ms, 52.3MB)
테스트 24 통과 (0.87ms, 51.9MB)
테스트 25 통과 (0.87ms, 50.4MB)
테스트 26 통과 (0.88ms, 52.1MB)
테스트 27 통과 (0.89ms, 52.4MB)
테스트 28 통과 (0.88ms, 52.2MB)
테스트 29 통과 (0.85ms, 52.7MB)
테스트 30 통과 (0.89ms, 51.8MB)
테스트 31 통과 (0.85ms, 50.2MB)
테스트 32 통과 (0.83ms, 52MB)

테스트 케이스

1
2
3
4
5
6
7
assertEquals(37, test.solution("1S2D*3T"));
assertEquals(9, test.solution("1D2S#10S"));
assertEquals(3, test.solution("1D2S0T"));
assertEquals(23, test.solution("1S*2T*3S"));
assertEquals(5, test.solution("1D#2S*3S"));
assertEquals(-4, test.solution("1T2D3D#"));
assertEquals(59, test.solution("1D2S3T*"));
  • 프로그래머스에서 제공한 예제 테스트 케이스이므로
    위 테스트케이스를 모두 통과하여도 실제 테스트에선 통과하지 못할 수 있음.

댓글 공유

문제

https://programmers.co.kr/learn/courses/30/lessons/42889


소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public int[] solution(int N, int[] stages) {
int[] failUsers = new int[N+2];
for (int stage : stages) {
failUsers[stage] += 1;
}

Map<Integer, Double> map = new HashMap<Integer, Double>();
double userCount = stages.length;
for (int i = 1; i <= N; i++) {
double value = 0.0;
if (failUsers[i] != 0 && userCount != 0) {
value = (failUsers[i] / userCount) * 100;
userCount -= failUsers[i];
}
map.put(i, value);
}

List<Integer> list = new ArrayList<Integer>(map.keySet());
Collections.sort(list, new Comparator<Integer>() {

@Override
public int compare(Integer o1, Integer o2) {
return map.get(o2).compareTo(map.get(o1));
}
});

int[] answer = list.stream().mapToInt(i -> i).toArray();
return answer;
}

흐름

  1. 유저 수(stages.length) 만큼 loop 돌면서 각 stage 별로 실패한 유저 수를 array에 저장한다.
  2. 스테이지별로 틀린 인원 수를 저장히기 위한 Map 변수를 하나 생성하고,
  3. 스테이지 수(N) 만큼 loop 돌면서 해당 스테이지에 실패한 사람이 있으면서, 전체 시도한 사람이 0명이 아닌 경우,
  4. $$ 해당 스테이지에서 실패한 유저 수 / 해당 스테이지에 도전한 유저 수 * 100 $$ 해서 해당 스테이지의 실패율을 구한다.
    • 이 때 스테이지에 도전한 유저 수는 이전 스테이지를 성공한 사람들 만이다.
  5. 이번 스테이지에서 실패한 유저들은 다음 스테이지에 도전 할 수 없으므로, 총 유저 수에서 실패한 유저 수를 제한다.
  6. 위에서 선언한 Map 변수에 key를 스테이지 번호로, value를 실패율로 하여 put 한다.
  7. 실패율을 저장한 Map을 Value 기준으로 내림차순 정렬을 한다.
  8. ArrayList를 int[]로 변환한다.
    • stream에 경우 속도가 느리므로, loop를 돌면서 직접 int[]로 만드는 방법이 퍼포먼스에 더 이로울 듯 하다.

결과

번호 속도
테스트 1 통과 (7.39ms, 52.6MB)
테스트 2 통과 (6.26ms, 54.7MB)
테스트 3 통과 (11.14ms, 54.2MB)
테스트 4 통과 (12.53ms, 58.2MB)
테스트 5 통과 (13.17ms, 63.3MB)
테스트 6 통과 (12.28ms, 52.3MB)
테스트 7 통과 (9.12ms, 53.5MB)
테스트 8 통과 (11.79ms, 58.6MB)
테스트 9 통과 (13.39ms, 61.4MB)
테스트 10 통과 (11.68ms, 55.8MB)
테스트 11 통과 (12.76ms, 59.8MB)
테스트 12 통과 (11.43ms, 60MB)
테스트 13 통과 (12.27ms, 62.7MB)
테스트 14 통과 (5.77ms, 54.3MB)
테스트 15 통과 (10.07ms, 54MB)
테스트 16 통과 (9.50ms, 55.6MB)
테스트 17 통과 (7.79ms, 53.4MB)
테스트 18 통과 (9.16ms, 54.8MB)
테스트 19 통과 (6.27ms, 52.8MB)
테스트 20 통과 (7.16ms, 53.2MB)
테스트 21 통과 (8.94ms, 55.3MB)
테스트 22 통과 (12.98ms, 62.7MB)
테스트 23 통과 (11.22ms, 58MB)
테스트 24 통과 (17.40ms, 59.7MB)
테스트 25 통과 (6.25ms, 52.9MB)
테스트 26 통과 (6.00ms, 52.3MB)
테스트 27 통과 (5.83ms, 50.4MB)

테스트 케이스

1
2
3
4
5
6
assertArrayEquals(new int[] {3,4,2,1,5}, test.solution(5, new int[] {2, 1, 2, 6, 2, 4, 3, 3}));
assertArrayEquals(new int[] {4,1,2,3}, test.solution(4, new int[] {4,4,4,4,4}));
assertArrayEquals(new int[] {2,1,3,4}, test.solution(4, new int[] {1,1,1,1,2}));
assertArrayEquals(new int[] {4,2,3,1}, test.solution(4, new int[] {3,2,5,4,2}));
assertArrayEquals(new int[] {7,6,2,3,5,4,1}, test.solution(7, new int[] {2, 1, 2, 6, 2, 4, 3, 3,7,5}));
assertArrayEquals(new int[] {1,2,3,4,5}, test.solution(5, new int[] {}));
  • Junit5로 테스트 했음.

  • 프로그래머스에서 제공하는 모든 케이스에 대한 것이 아니라,
    필자가 마음대로 넣은 것 이므로 이 소스를 통과하여도 프로그래머스에선 통과되지 못할 수 있음.


다른 멋진 분들의 해결방법

댓글 공유

https://programmers.co.kr/learn/courses/30/lessons/64061


소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public int solution(int[][] board, int[] moves) {
int[] tops = setTop(board);

Stack<Integer> stack = new Stack<Integer>();
int answer = 0;
for (int i = 0; i < moves.length; i++) {
int move = moves[i] - 1;
int top = tops[move];
if (top == 0) {
continue;
}

int height = board.length - top;
int value = board[height][move];
tops[move] = tops[move] - 1;

if (!stack.isEmpty() && (stack.peek() == value)) {
stack.pop();
answer += 2;
} else {
stack.push(value);
}
}

return answer;
}

private int[] setTop(int[][] board) {
int height = board.length;
int width = board[0].length;
int[] tops = new int[width];

for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
if (tops[j] == 0 && board[i][j] != 0) {
tops[j] = height - i;
}
}
}

return tops;
}

흐름

  1. 인형이 쌓여있는 상자에서 각 열마다 맨 위에 있는 인형의 위치를 배열에 저장함.

  2. 크레인이 뽑을 위치가 담긴 배열 크기(moves) 만큼 loop 돔.

  3. 배열이 0부터 시작하므로, 뽑을 위치(move) 에서 -1 함.

  4. 뽑을 위치에서 맨 위의 위치를 가져오는데 0이면 그 열에 있는 건 모두 뽑아 먹은 것이므로 아무 행동도 하지 않음.

  5. 총 높이에서 그 열에서 제일 위에 있는 인형의 위치를 뻄.

  6. 상자에서 인형을 꺼냄.(value = board[height][move])

  7. 그 열에 한 개 꺼냈으므로, top의 위치를 한 칸 내림.

  8. stack이 비어 있지 않으면서, stack의 top이 현재 뽑은 인형과 같으면 stack에 저장된 인형을 삭제하고, 삭제된 인형의 갯수를 더 함.

  9. 그렇지 않으면 stack에 인형을 추가.


결과

번호 속도
테스트 1 통과 (0.94ms, 50.1MB)
테스트 2 통과 (0.94ms, 52.4MB)
테스트 3 통과 (1.04ms, 52.6MB)
테스트 4 통과 (2.28ms, 50.6MB)
테스트 5 통과 (0.98ms, 50.9MB)
테스트 6 통과 (0.97ms, 50.6MB)
테스트 7 통과 (1.11ms, 52.4MB)
테스트 8 통과 (1.25ms, 52.1MB)
테스트 9 통과 (1.37ms, 54.4MB)
테스트 10 통과 (1.38ms, 52.5MB)
테스트 11 통과 (1.81ms, 52.7MB)

댓글 공유

https://programmers.co.kr/learn/courses/30/lessons/12940


소스

1
2
3
4
5
6
7
8
9
10
11
12
public int[] solution(int n, int m) {
int big = n > m ? n : m;
int small = n < m ? n : m;

while (m != 0) {
int r = n % m;
n = m;
m = r;
}

return new int[] {n, n * (big / n) * (small / n)};
}

흐름

  • 유클리드 호제법으로 처리

    두 양의 정수 $$ a, b (a > b) $$ 에 대하여 $$ a = bq + r(0 ≤ r < a) $$
    라 하면, a, b 의 최대공약수는 b, r의 최대공약수와 같다.

  1. 두 수를 중 큰 수와 작은 수 구분

  2. 큰 수 a의 최대공약수는 b와 r(a mod b)의 최대 공약수와 같으므로 작은 수 m이 0이 될 때 까지 반복

  3. 최소공배수는 최대공약수(G) * (a / G) * (m / G) 이므로 계산해서 배열에 할당한다.

    • $$ (a * b) / G $$ 로 하면 수가 큰 경우 overflow가 발생 할 가능성이 있음.

유클리드 호제법

두 양의 정수 $$ A, B (A > B) $$ 에 대하여 $$ A = Bq + R(0 ≤ R < a) $$
라 하면, A, B 의 최대공약수는 B, R의 최대공약수와 같다.

이 때 R은 A mod B 한 값으로 식으로 나타내면 아래와 같다.

$$ G(A,B) = G(B,R) $$

A와 B에게 최대공약수 G가 있다면,

$$ A = aG, B = bG $$

과 같이 나타 낼수 있고 이 때 a와 b는 반드시 서로소 여야 한다.
위에서 A mod B 한 값이 R 이라고 정의했고 A와 B를 나눈 값을 q라고 한다면,

$$ A = Bq + R $$
$$ aG = bGq + R $$
$$ R = G(a-bq) $$

처럼 전개 될 수 있고, 이 경우 R과 B가 G 라는 최대 공약수를 갖기 떄문에 $$ a-bq $$ 와 b가 서로소 임을 증명하면 된다.

만약 $$ a-bq $$ 와 b가 서로소가 아니라면, 둘은 공약수가 존재 하기 떄문에 아래와 같이 표현 할 수 있다.

$$ a-bq = pm , b = pn $$
$$ a = bq + pm $$
$$ a = pnq + pm $$
$$ a = p(nq + m), b = pn $$

이 때 a와 b는 서로소인데 p 라는 공약수를 갖게 되므로
a와 b가 서로소라는 전제가 모순되어 $$ a-bq $$ 와 b는 서로소임이 증명되고 B와 R의 최대 공약수가 G 인 것이 된다.


참고 사이트

댓글 공유

https://programmers.co.kr/learn/courses/30/lessons/12932


소스

1
2
3
4
5
6
7
8
9
public int[] solution(long n) {
List<Long> list = new ArrayList<Long>();
while (n > 0) {
list.add(n % 10);
n /= 10;
}

return list.stream().mapToInt(i -> (int) (long) i).toArray();
}

흐름

  1. n은 10,000,000,000이하인 자연수이므로 몇 자리의 수가 올지 알 수 없으므로 배열이 아닌 ArrayList를 생성
  2. n mode 10한 값을 저장하고 n을 10 나눔
    • ex) 12345 mod 10 = 5, 12345 / 10 = 1234
  3. List를 stream()을 활용하여 int array로 변경함

다른 풀이

1
2
3
4
5
6
7
8
9
10
public int[] solution(long n) {
int[] arrays = new int[String.valueOf(n).length()];
int i = 0;
while (n > 0) {
arrays[i++] = (int) (n % 10);
n /= 10;
}

return arrays;
}
  1. n이 몇 자리의 수가 올지 알 수 없으므로 n을 String으로 변환 후 String의 length를 구해서 array의 크기를 구함
  2. 이하 상동

시간 비교

첫 번째 풀이

번호 속도
테스트 1 통과 (5.56ms, 50.8MB)
테스트 2 통과 (5.78ms, 50.2MB)
테스트 3 통과 (5.51ms, 50.9MB)
테스트 4 통과 (4.88ms, 52.9MB)
테스트 5 통과 (6.73ms, 52.3MB)
테스트 6 통과 (5.79ms, 52.6MB)
테스트 7 통과 (6.36ms, 50.7MB)
테스트 8 통과 (5.06ms, 50.7MB)
테스트 9 통과 (5.75ms, 52.5MB)
테스트 10 통과 (4.99ms, 50.6MB)
테스트 11 통과 (5.25ms, 52.7MB)
테스트 12 통과 (5.65ms, 52.4MB)
테스트 13 통과 (5.75ms, 55MB)

두 번째 풀이

번호 속도
테스트 1 통과 (1.34ms, 52.5MB)
테스트 2 통과 (1.57ms, 49.9MB)
테스트 3 통과 (1.52ms, 50.3MB)
테스트 4 통과 (1.36ms, 53.1MB)
테스트 5 통과 (1.52ms, 52.3MB)
테스트 6 통과 (1.42ms, 52.4MB)
테스트 7 통과 (1.52ms, 50.4MB)
테스트 8 통과 (1.43ms, 50.4MB)
테스트 9 통과 (1.37ms, 52.2MB)
테스트 10 통과 (1.50ms, 50.2MB)
테스트 11 통과 (1.42ms, 49.9MB)
테스트 12 통과 (1.72ms, 52.2MB)
테스트 13 통과 (1.73ms, 50.7MB)
  • Stream()이 생각보다 더 느리게 동작하는 듯 싶다.

댓글 공유

문제

https://programmers.co.kr/learn/courses/30/lessons/12921


코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public int solution(int n) {
boolean[] prime = new boolean[n+1];

prime[0] = true;
prime[1] = true;

for (int i = 2; (i * i) <= n; i++) {
if (!prime[i]) {
for (int j = i * 2; j <= n; j += i) {
prime[j] = true;
}
}
}

int answer = 0;
for (boolean is : prime) {
if (!is) {
answer++;
}
}

return answer;
}

흐름

  • 에라토스테네스의 체로 해결

Sieve_of_Eratosthenes_animation

  1. n까지의 숫자중 0과 1은 소수가 아니므로 true 할당
  2. 2부터 루트n 까지 반복하면서 배수들에 true 할당
  3. 소수 판별한 배열 prime을 loop 돌면서 false 인 경우에만 갯수 추가

부연 설명

1
for (int i = 2; (i * i) <= n; i++)

입력받은 수 n이 합성수 인 경우 $$n = a * b​$$ 로 나타낼 수 있다.
이 때 a와 b 중 큰거나 같은 수를 a, 작거나 같은 수를 b라고 가정하면 b가 a보다 작으므로 $$ a * a >= a * b $$ 이고
$$ n = a * b $$ 이므로, 큰 수 a의 제곱일 경우 $$ a^2>=n $$ 처럼 된다.
이를 치환하면 $$ a>=\sqrt{n} $$ 이 되므로 a의 최솟값은 $$ \sqrt{n} $$ 이 된다.
그리고 b는 $$ a >= b $$이므로 b의 최댓값은 $$ \sqrt{n} $$ 이 된다.
고로 n이 소수가 아닌 합성수라면 a의 와 b의 합성수로 이루어 짐을 알 수 있으므로, $$ \sqrt{n} $$ 까지만 반복하면 소수임을 판별할 수 있다.

  • ex) 입력받은 수 n이 50일 경우 $$ \sqrt{50} $$ = 7.071067811865475‬‬….이므로, 7.071067811865475‬‬… 을 기준으로 50의 약수 {1,2,5,10,25,50}을 나누면 b = {1, 2, 5}, a = {10, 25, 50} 이므로 b만 검사하면 50이 소수 인지 아닌지 알 수 있다.
1
for (int j = i * 2; j <= n; j += i)

원래는 i보다 작은 수인 경우 이미 이전에 작은 수 * i에서 삭제된 상태이므로 i * i인 게 맞으나,
i의 값이 너무 클 경우 문제가 될 수 있으므로 $$ i * 2 $$ 로 설정한다.
물론 이 문제에선 100만 까지로 한정되어 있으므로 $$ i * i $$ 를 해도 문제는 없다.


참고 사이트

댓글 공유

https://www.acmicpc.net/problem/11399


소스

1
2
3
4
5
6
7
8
9
10
11
12

public static int solution(int n, int[] times) {
Arrays.sort(times);

int answer = 0;
for (int i = 0; i < times.length; i++) {
answer += times[i] * (n-i);
}

return answer;
}


흐름

  1. 시간이 짧게 걸리는 사람이 앞에 올수록 전체 수행 시간이 짧아지므로 sorting부터 실행

  2. 앞에 사람이 걸리는 시간은 그 뒤 사람들도 그만큼 시간이 + 되는 것이므로 n-i 한 값을 곱함

    ex) 첫 번째 사람이 1분 걸리면 2, 3, 4, 5 번째 사람도 1분씩 더 걸리게 됨

  3. 다 더한 값을 출력하면 끝

댓글 공유

Junggu Ji

author.bio


author.job