[알고리즘]배열탐색:점수 계산,등수구하기,격자판 최대합

chaewon Im·2022년 1월 19일
0
post-thumbnail

4.점수 계산


📃 문제

여러 개의 OX문제로 만들어진 시험에서 연속적으로 답을 맞히는 경우에는 가산점을 주기 위해서 다음과 같이 점수 계산을
하기로 하였다. 1번 문제가 맞는 경우에는 1점으로 계산한다. 앞의 문제에 대해서는 답을 틀리다가 답이 맞는 첫 문제는 1점으로 계산한다.
또한 연속으로 문제의 답이 맞는 경우에서 두번째 문제는 2점, 3번째 문제는 3점..K번째 문제는 K점으로 계산한다. 틀린 문제는 0점으로 계산한다.

[입력 설명]
첫줄에 문제의 개수가 주어진다.
두번째 줄에 N개의 문제의 채점 결과를 나타내는 0 혹은 1이 주어진다. 0은 문제의 답이 틀린 경우, 1은 문제의 답이 맞는 경우이다.

[출력 설명]
채점 결과에 대하여 가산점을 고려한 총 점수를 출력


✏️ 내 풀이

가산점을 고려한 점수를 카운팅할 bonus라는 변수를 만들어서 문제가 맞을때마다 +1시키고 틀리면 0으로 초기화한다.
계속 문제를 맞는다면 가산점이 1,2,3..순으로 올라갈 것이고, 틀리면 0으로 초기화된다. 초기화 후에 맞춘 문제가 나타나면 다시 1,2..순으로 카운팅될 것이다.
이 bonus를 answer에 계속 더하면 총점이 된다.

function solution(arr){
    let answer = 0;
    let bonus = 0;
    for(let i=0;i<=arr.length;i++){
        if(arr[i] === 1){
            bonus++
            answer += bonus
        }else{
            bonus = 0
        }
    }
    return answer
}

let arr = [1,0,1,1,1,0,0,1,1,0]
console.log(solution(arr))

5.등수 구하기

📃 문제

N(1<=K<=100)명의 학생의 국어 점수가 입력되면 각 학생의 등수를 입력된 순서대로 출력하는 프로그램을 작성하시오

[입력 설명]
첫줄에 문제의 개수가 주어진다.
두번째 줄에 국어점수를 의미하는 N개의 정수가 입력된다.같은 점수가 입력될 경우 높은 등수로 동일 처리한다.
즉 가장 높은 점수가 92점인데 92점이 3명 존재하면 1등이 3명이고 그 다음 학생은 4등이 된다.

[출력 설명]
입력된 순서대로 등수를 출력한다.


✏️ 풀이

내 풀이📚) 이중 for문을 피할 수 없을 까 생각하다가 중복을 해결 못함..

처음 생각한 풀이: 배열에서 가장 큰 수를 구하고,
indexOf로 해당 수의 index를 구한다음 answer에서 그 위치에 등수 i를 입력한다.
비교를 위해 이미 등수를 구한 값은 0으로 만들어 최소값으로 만들어버린다.
그러나 중복 해결이 어려워서 결국 해설을 보았다.

function mySolution(arr){
    let answer = [];
    for(let i=0;i<arr.length;i++){
        max = Math.max.apply(null,arr)
        maxPos = arr.indexOf(max)
        answer[maxPos] = i+1
        arr[maxPos] = 0
    }

    return answer
}

let arr = [87,89,92,92,100,76]
console.log(mySolution(arr))

해설📚)

answer를 arr와 동일한 길이로 초기화 한다.
이중 for문을 돌면서 현재 위치의 값보다 큰 값이 존재하는지 검사하고, 만약 더 큰 값이 있다면 있을 때마다 현재 위치의 값 등수를 내린다(+1)

function solution(arr){
    let n = arr.length
    let answer = Array.from({length:n},()=>1) 
    //배열 초기화(길이:n만큼,초기값=1)

    for(let i=0;i<n;i++){
        for(j=0;j<n;j++){
            if(arr[j]>arr[i]) answer[i]++ 
        }
    }
    return answer
}

let arr = [87,89,92,92,100,76]
console.log(solution(arr))

다른 분의 또 다른 풀이📚)

✨map과 filter를 이용한 풀이✨

filter를 이용해 j가 i보다 큰지 확인해서 큰 값이 있다면 true를 뱉고, 더 큰 값만 모아둔 새로운 배열을 반환한다. 이 배열의 길이+1이 등수가 된다. 만약 더 높은 점수가 2개 있다면 배열의 길이는 2이므로 +1한 3등이 i의 등수가 된다. map은 i위치의 값을 이 등수로 치환한 새로운 배열을 return한다.

function solution2(arr){
    const answer = arr.map((i) => arr.filter((j) => i < j).length + 1);
    return answer
}

let arr = [87,89,92,92,100,76]
console.log(solution2(arr))

6.격자판 최대합(2차원 배열)

📃 문제

5*5 격자판에 아래와 같이 숫자가 적혀있습니다.

10,13,10,12,15
12,39,30,23,11
11,25,50,53,15
19,27,29,37,27
19,13,30,13,19

N*N의 격자판이 주어지면 각 행의 합, 각 열의 합, 두 대각선의 합 중 가장 큰 합을 출력합니다.

[입력 설명]
첫 줄에 자연수 N이 주어진다.
두 번째 줄부터 N줄에 걸쳐 각 줄에 N개의 자연수가 주어진다. 각 자연수는 100을 넘지 않는다.

[출력 설명]
최대 합을 출력합니다.

✏️ 풀이

문제 자체가 이해가 잘 가지 않아서 해설을 먼저 보고 문제를 풀었다. 처음에 각 행/열의 합을 더한 총합을 구하라는 줄 알고 그러면 그냥 다 더한거랑 차이가 없는데 뭔소린가 했음..행/열의 합 각각을 계속 비교하라는 의미였다.

  • 각 행의 합 구하기:arr[j][i]
    => i가 0일 때, 1,2,3,4,5 행(i)을 돌고 그 다음 열(j)로 넘어가는 방식으로 생각
  • 각 열의 합 구하기:arr[i][j]
    => i가 0일 때, 순차적으로 열(j)을 탐색하고 그다음 행(i)으로 넘어가는 식으로 생각
  • 대각선의 합 구하기:arr[i][i], arr[i][-1]...
    => 시작지점에서 끝지점 방향('\')은 i열에서 i값에 해당하므로 arr[i][i]로 순회하며 돌면 된다고 생각했고, 반대방향('/')은 arr[i]일 때 그 배열의 가장 뒷 순서부터 시작하면 되니까[-1][-2]...순서로 진행하면 될 것으로 생각했다.

여기에 더한 해설 내용📚)
위 내용까지는 맞았고, 각 합을 계속 비교하여 최대 합을 구하기 위해서는 반복문을 돌 때마다 이전값과 현재 값을 비교해야 했다.

이를 위해 2번째 for문이 종료될 때마다 answer에 최대값을 구해 저장하고, 첫번째 for문이 다시 실행될 때 sum1,2의 값을 0으로 다시 초기화시켜 계산하고, 또 다시 2번째 for문이 종료되면 이전에 저장된 answer와 비교해 새로운 값을 저장하도록 하는 로직으로 풀이하셨다.

열의 합과 행의 합은 이중for문이 필요해서 먼저 배열 전체를 순회하며 각 합중 최대 합을 발견해낸다. 그 다음으로 대각선 두 방향의 합을 구하여 앞에서 구한 최대 합과 비교해 가장 큰 수를 최종적으로 answer에 저장한다.

function solution(arr){
    let n = arr.length;
    let answer = Number.MIN_SAFE_INTEGER
    let sum1 = 0
    let sum2 = 0
    //합의 값을 저장할 변수

    for(let i=0;i<n;i++){
        sum1=sum2=0 //열의 합과 행의 합 이전 기록 초기화
        for(let j=0;j<n;j++){
            sum1 += arr[i][j] //열의 합
            sum2 += arr[j][i] //행의 합
        }
        answer = Math.max(answer,sum1,sum2) //열의 합과 행의 합 중 큰 것을 answer에 저장
    }

    sum1=sum2=0 //초기화
    for(let i=0;i<n;i++){
        sum1 += arr[i][i]
        sum2 += arr[i][n-i-1]
    }
    answer = Math.max(answer,sum1,sum2)
    return answer
}

let arr = [
    [10,13,10,12,15],
    [12,39,30,23,11],
    [11,25,50,53,15],
    [19,27,29,37,27],
    [19,13,30,13,19]]
    
console.log(solution(arr))
profile
빙글빙글 FE 개발자

0개의 댓글