알고리즘/프로그래머스 Level1

[프로그래머스,Java] Level1: 위클리챌린지 2주차

류창 2021. 8. 9. 14:25
반응형

문제분석: 

요점은, N명의 학생들이 서로 개인평가를한뒤  평가받은점수를 평균을구해 등급을 부여해주는문제다.

 

여기까지가 딱 Level1 수준인데 한술 더떠서 Level2급으로 바뀐다

 

하지만 특수한규칙이있는데, 자기자신이 평가한점수가 유일하고, 최저최대면 평가에 제외합니다.

 

이 규칙을 따라서 학생들의 등급을 문자열로 반환하는 문제다. 

 

문제풀이:

처음 이 문제를 풀엇을땐, 특수한규칙에 맞춰서 반복문을 최대로 줄이는(최적화)법을 오래 고민해봤다. 하지만 명쾌하게 생각나지않아, 일단 생각나는대로 풀기로 해보았다.

 

우선 메소드 3개를 구성했다.

1.등급을 구하는 GetGrade 

2.유일한지 구하는 IsUnique

3.최저최대인지 구하는 IsMaxMin

 

1.GetGrade: if else로 등급을 나눠서 구현했다.

 

2.IsUnique : 자기자신이 평가한점수를 unique로 저장해, unique가 다른점수와 같으면 false, 유일하면 true 반환

 

3.IsMaxMin:자기자신이 평가한점수를 maxmin으로 저장하고, list에 평가점수를 모두 넣어 정렬한다.

   정렬한 list에 maxmin이 첫번째와 마지막번째값과 같으면 true , 다르면 false를 반환

 

모든메소드를 구현했으니, 메인을 구현할차례다.

합을구할 sum, 평균을 구할 avg, 그리고 특수한규칙( IsUnique  IsMaxMin)이 성립한지 flag를 선언하다.

 

이 3 변수는 학생이바뀔때마다 초기화시켜야하니 반복문속에 선언한다.

 

flag에 따라 제외여부를 결정하고, flag에따라 평균을 나눠줘서 구현했다.

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import java.util.*;
class Solution {
    public String solution(int[][] scores) {
        String answer = "";
        StringBuilder sb =new StringBuilder();
        for(int i=0;i<scores.length;i++){
        //sum,avg,flag 3개의 변수는 번호가 바뀔때마다 초기화 해야한다.
           int sum=0;
           int avg=0;
           boolean flag =true;
          //유일하고, 최저 최고인지 검사 맞다면 flag를 false
          if(IsUnique(scores,i)&&IsMaxMin(scores,i)){
             flag=false;   
            }
 
           for(int j=0;j<scores.length;j++){
              if(!flag&&i==j){
                  continue;
              } 
               sum+=scores[j][i];
           }
 
        //flag가 false면 갯수만큼나누고, true면 갯수-1만큼 나누기 
            if(flag){
                avg=sum/scores.length;
            }
            else{
                avg=sum/(scores.length-1);
            }
            sb.append(GetGrade(avg));
        }
 
        return answer=sb.toString();
    }
 
    //등급 구하기
    public String GetGrade (int avg){
 
        if(avg>=90return "A";
        else if(avg>=80return "B";
        else if(avg>=70return "C";
        else if(avg>=50return "D";
 
        return "F";
    }
    // 유일한가?
    public boolean IsUnique (int[][] scores,int num){
 
        int unique =scores[num][num];
 
        for(int i=0;i<scores.length;i++){
            if(i!=num&&unique==scores[i][num]){
                return false;
            }
        }
 
        return true;
    }
 
    //최고점,최저점인가?
    public boolean IsMaxMin (int[][] scores,int num){
 
        int maxmin=scores[num][num];
 
        List<Integer> list = new ArrayList<>();
 
        for(int i=0;i<scores.length;i++){
            list.add(scores[i][num]);
        }
 
        Collections.sort(list);
 
        if(list.get(0)==maxmin||list.get(scores.length-1)==maxmin){
 
            return true;
 
        }
 
        return false;
    }
}
cs

 

그리고 String에다가 문자열을 +할거면 꼭 StringBuilder를 쓰는습관을들이자!

 

쓰거나 안쓰거나의 차이가 6~7배나 차이가난다.

다른사람 풀이:

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
import java.util.*;
class Solution {
    public String solution(int[][] scores) {
        String answer = "";
        StringBuilder sb = new StringBuilder();
        for(int j=0;j<scores[0].length;j++){
            int max = 0;
            int min = 100;
            int cnt = 0;
            int sum = 0;
            for(int i=0;i<scores.length;i++){
                sum += scores[i][j];
                if(scores[j][j] == scores[i][j]){
                    cnt++;
                }
                max = Math.max(max, scores[i][j]);
                min = Math.min(min, scores[i][j]);
            }
            int num = scores.length;
            if(cnt==1 && (scores[j][j] == max || scores[j][j] ==min )){
                sum -= scores[j][j];
                num--;
            }
            int score = sum/num;
            if(score>=90){
                sb.append('A');
            } else if(score>=80){
                sb.append('B');
            } else if(score>=70){
                sb.append('C');
            } else if(score>=50){
                sb.append('D');
            } else {
                sb.append('F');
            }
        }
        answer = sb.toString();
        return answer;
    }
}
cs

 

다른사람풀이를보며 배울점

 

내가 생각해내지못한 최적화방법을 적용시킨 코드다 이런 생각은 대체어떻게하는거야

 

최소한의반복(2차반복) 속에서, 유일성과 최대최소를 체크해나갔다.

 

일단 학생들에게 평가받은점수를 모두 더해나간다.

 

유일성은 cnt의 갯수로 체크했다. cnt가 1이면 유일하다라는뜻이다.

 

최대최소는 학생들의 점수를 순회할때마다 max와 min값을 갱신해나간다.

 

1명의학생이 순회가끝낫으면 cnt가 1 (유일) max와 min값인지를 체크하고, 성립하면

 

자기가 평가한점수를 빼고, 평균갯수를 저장한 num에서 -1을한다. 천잰가..?

 

 

P.s 매번 문제를 풀고나서 다른사람이 푼 창의적인 생각을보면 약간의 자괴감이든다

다른사람의풀이를 계속읽어보고 코드리뷰를한다보면 분명 이런생각에 도달할것이다.

 

반응형