문제 설명
과일 장수가 사과 상자를 포장하고 있습니다. 사과는 상태에 따라 1점부터 k점까지의 점수로 분류하며, k점이 최상품의 사과이고 1점이 최하품의 사과입니다. 사과 한 상자의 가격은 다음과 같이 결정됩니다.

한 상자에 사과를 m개씩 담아 포장합니다.
상자에 담긴 사과 중 가장 낮은 점수가 p (1 ≤ p ≤ k)점인 경우, 사과 한 상자의 가격은 p * m 입니다.
과일 장수가 가능한 많은 사과를 팔았을 때, 얻을 수 있는 최대 이익을 계산하고자 합니다.(사과는 상자 단위로만 판매하며, 남는 사과는 버립니다)

예를 들어, k = 3, m = 4, 사과 7개의 점수가 [1, 2, 3, 1, 2, 3, 1]이라면, 다음과 같이 [2, 3, 2, 3]으로 구성된 사과 상자 1개를 만들어 판매하여 최대 이익을 얻을 수 있습니다.

(최저 사과 점수) x (한 상자에 담긴 사과 개수) x (상자의 개수) = 2 x 4 x 1 = 8
사과의 최대 점수 k, 한 상자에 들어가는 사과의 수 m, 사과들의 점수 score가 주어졌을 때, 과일 장수가 얻을 수 있는 최대 이익을 return하는 solution 함수를 완성해주세요.

제한사항
3 ≤ k ≤ 9
3 ≤ m ≤ 10
7 ≤ score의 길이 ≤ 1,000,000
1 ≤ score[i] ≤ k
이익이 발생하지 않는 경우에는 0을 return 해주세요.

 


 

 

function solution(k, m, score) {
    var answer = 0;
    let arr = score.sort((a, b) => b - a); // 내림차순 정렬
    let box = [];
   
    arr.forEach((item,i) =>{
        box.push(arr[i])  
        
        // 박스에 사과가 m개 담겼다면 점수계산
        if(box.length === m){
            answer += Math.min(...box) * box.length;
            box=[];
        }
    })
    
    return answer;
}

중간에 발생한 문제점

처음에는 splice로 꺼내는 작업을 했더니 forEach가 멈춰버리는 일이 생겼습니다.
알아보니 forEach는 처음에 시작할때 배열의 길이와 요소를 고정된 상태로 순회한다는걸 몰랐습니다.

 

 


혹시 문제가 남은 사과까지 계산한다면..?

 

문제에서는 남은 사과는 계산하지 않습니다.

 

혹시라도 남은 사과를 계산을 했었다면

 

for문이나 while문으로짜고 splice로 잘라서 넣고 남은 arr.length가 m보다 작다면 arr의 요소를 더해서 계산하면 될 듯 싶습니다.

 

 

 

function solution(k, m, score) {
    let answer = 0;
    let arr = score.sort((a, b) => b - a);  

    // 상자 단위로 처리 (m개씩 꺼내서 상자 구성)
    while (arr.length >= m) {
        let box = arr.splice(0, m);  // m개씩 꺼내서 상자에 담기
        answer += Math.min(...box) * m;  // 최소 점수 * m (상자의 가격)
    }

    // 남은 사과가 있으면 마지막 상자에 대해 처리
    if (arr.length > 0) {
        let box = arr.splice(0, arr.length);  // 남은 사과들
        answer += Math.min(...box) * arr.length;  // 남은 사과들 가격 계산
    }

    return answer;
}

'개발공부 > 알고리즘' 카테고리의 다른 글

[Algorithm] 2차원 배열 최대합 구하기  (0) 2023.04.30
[Algorithm] 점수계산하기  (0) 2023.04.27
[Algorithm] 가위바위보  (0) 2023.04.27
[Algotithm] 큰 수 출력하기  (0) 2023.04.26
[Algorithm] 보이는 학생  (0) 2023.04.26
<html>

<head>
  <meta charset="UTF-8">
  <title>출력결과</title>
</head>
<!-- 각 행의 합, 각 열의 합
그리고 두 대각선의 합 중 가장 큰 합을 출력하시오 -->

<body>
  <script>
    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]
      ];
    function solution(arr) {
      let answer = Number.MIN_SAFE_INTEGER;
      let sum1 = sum2 = sum3 = sum4 = 0;
      for (let i = 0; i < arr.length; i++) {
        sum1 = sum2 = 0;
        for (let j = 0; j < arr.length; j++) {
          sum1 += arr[i][j];
          sum2 += arr[j][i];
        }
        sum3 += arr[i][i];
        sum4 += arr[(arr.length - 1) - i][i];
        answer = Math.max(answer, sum1, sum2, sum3, sum4);
        console.log(`${i + 1}번째 행의 합 : ${sum1},  ${i + 1}번째 열의 합 : ${sum2}`);
      }
      console.log(`대각선의 합 [0][0] ~[4][4] : ${sum3}`)
      console.log(`대각선의 합2 [0][4] ~ [4][0] : ${sum4}`);
      return `가장 큰 수 : ${answer} `;
    }

    function solution2(arr) {
      let answer = Number.MIN_SAFE_INTEGER;
      let sum1 = sum2 = sum3 = sum4 = 0;
      for (let i = 0; i < arr.length; i++) {
        sum1 = sum2 = 0;
        for (let j = 0; j < arr.length; j++) {
          sum1 += arr[i][j];
          sum2 += arr[j][i];
        }
        console.log(`${i + 1}번째 행의 합 : ${sum1},  ${i + 1}번째 열의 합 : ${sum2}`);
        answer = Math.max(answer, sum1, sum2);
      }
      for (let i = 0; i < arr.length; i++) {
        sum3 += arr[i][i];
        sum4 += arr[i][(arr.length - 1) - i];
        answer = Math.max(answer, sum3, sum4);
      }
      console.log(`대각선의 합 [0][0] ~[4][4] : ${sum3}`)
      console.log(`대각선의 합2 [0][4] ~ [4][0] : ${sum4}`);
      return `가장 큰 수 : ${answer} `;
    }
    console.log(solution2(arr));
  </script>
</body>

</html>

음... 억지로 for문 따로 안쓰게 만들어 봤는데..
저러면 sum3, sum4가 누적되기 전부터 Math.max가 들어가서.. 좀..

<html>

<head>
  <meta charset="UTF-8">
  <title>출력결과</title>
</head>
<!-- O 는 1점 , X 는 0점 
  연속해서 맞출경우 +1점
-->
<body>
  <script>
    function solution(arr) {
      let answer = 0;
      let count = 0;
      for(let i=0; i<arr.length; i++){
        if(arr[i] === 'O'){
          cnt++;
          answer += cnt
        }
        else cnt = 0;
      }
      return answer;
    }

    let arr = ['O', 'O', 'X', 'O', 'X', 'X', 'O', 'O', 'O', 'X'];
    console.log(solution(arr));
  </script>
</body>

</html>
<html>

<head>
    <meta charset="UTF-8">
    <title>출력결과</title>
</head>

<!-- 가위 = 1 , 바위 = 2 , 보 = 3 -->
<!-- 승리시 A or B, 비기는 경우 D -->

<body>
    <script>

        const HandType = {
            ROCK: 1,
            SCISSORS: 2,
            PAPER: 3
        };

        const Result = {
            DRAW: 'D',
            PLAYER_A: 'A',
            PLAYER_B: 'B'
        };

        let a = [2, 3, 3, 1, 3];
        let b = [1, 1, 2, 2, 3];

        function solution(a, b) {
            let answer = "";
            for (let i = 0; i < a.length; i++) {
                if (a[i] === b[i]) answer += Result.DRAW + " ";
                else if ((a[i] === 1) && (b[i] === 3)) answer += Result.PLAYER_A + " ";
                else if ((a[i] === 2) && (b[i] === 1)) answer += Result.PLAYER_A + " ";
                else if ((a[i] === 3) && (b[i] === 2)) answer += Result.PLAYER_A + " ";
                else answer += Result.PLAYER_B + ' ';
            }
            return answer;
        }



        function solution2(a, b) {
            const result = a.map((value, index) => {
                if (value === b[index]) {
                    return Result.DRAW;
                }
                switch (value) {
                    case HandType.ROCK:
                        switch (b[index]) {
                            case 3:
                                return Result.PLAYER_A;
                            case 2:
                                return Result.PLAYER_B;
                            default:
                                return '';
                        }
                    case HandType.SCISSORS:
                        switch (b[index]) {
                            case 3:
                                return Result.PLAYER_B;
                            case 1:
                                return Result.PLAYER_A;
                            default:
                                return '';
                        }
                    case HandType.PAPER:
                        switch (b[index]) {
                            case 1:
                                return Result.PLAYER_B;
                            case 2:
                                return Result.PLAYER_A;
                            default:
                                return '';
                        }
                    default:
                        return '';
                }
            });
            return result.join(' ');
        }


        console.log(solution(a, b));
    </script>
</body>

</html>

솔루션 2는 내가 뭘 한거지..

 

<html>

<head>
  <meta charset="UTF-8">
  <title>출력결과</title>
</head>

<!-- 자신의 앞 수보다 큰 수만 출력하기 -->

<body>
  <script>
      let arr = [7, 3, 9, 5, 6, 12];
      function solution(arr) {
        let answer = [arr[0]];
        for(let i=1; i<arr.length; i++){
          if(arr[i-1] < arr[i]) answer.push(arr[i]);
        }
        return answer;
      }

    console.log(solution(arr));
  </script>
</body>

</html>
<html>

<head>
  <meta charset="UTF-8">
  <title>출력결과</title>
</head>
<!-- 학생의 키가 주어질 때, 앞에 있는 사람들보다 크면 보이고 작거나 같으면 보이지 않습니다  -->

<body>
  <script>
    function solution(arr) {
      let answer = 0;
      let max = 0;
      for (let student of arr) {
        if (max < student) {
          max = student;
          answer++;
        }
      }
      return answer;
    }

    let arr = [130, 135, 148, 140, 145, 150, 150, 153];
    console.log(solution(arr));
  </script>
</body>

</html>
<html>

<head>
  <meta charset="UTF-8">
  <title>출력결과</title>
</head>

<!-- N개의 문자열이 입력되면 중복된 문자열은 제거. (원래의 입력순서를 유지). -->

<body>
  <script>
    let arr = ["good", "time", "good", "time", "student"];
    function solution(arr) {
      let set = new Set(arr)
      return [...set];
    }

    function solution2(arr) {
      const set = new Set();
      arr.forEach(el => set.add(el));
      return [...set];
    }

    function solution3(arr) {
      let answer = arr.filter((el, i) => arr.indexOf(el) === i)
      return answer;
    }
    console.log(solution(arr));
  </script>
</body>

</html>

solution과 solution2의 차이는
두번째의 방법이 메모리 소모가 더 적습니다.

 

solution 함수는

set 자체에는 중복이 제거된 상태의 Set 객체가 들어가있지만
new Set으로 객체를 생성할때 중복을 포함한 요소가 Set 객체에 추가가 되어

배열 전체를 사용하기 때문에, 중복 제거전부터 불필요한 메모리를 소모합니다.

('중복이 제거된 배열',  '중복 포함 배열' 두 가지의 배열이 메모리에 저장됩니다)

 

solution2의 경우는 빈 Set객체를 생성후 forEach를 통해 하나씩 추가합니다

이 경우 Set 객체 자체에는 할당된 배열이 없으며, 배열의 요소를 하나씩 Set에 추가하면서 Set 객채의 특성을 이용해

중복을 제거하는 함수입니다. 이 경우 배열의 중복 개수 크기에 상관없이 필요한 메모리만 사용합니다.

다만 forEach는 새로운 배열을 생성하지는 않지만, 반복문을 돌며 배열의 요소를 처리하는데 메모리를 사용합니다.

(그래도 1번보다는 좋다!)

 

크기가 작은 배열의 중복제거의 경우, 두 함수는 큰 차이를 보이지 않지만, 배열의 크기가 커질경우 성능차이가 발생합니다.

(2번이 효율적)

 

solution3의 경우, filter 함수가 새로운 배열을 반환하기 때문에 메모리 양이 더 많아집니다.

중복이 포함된 배열과 같은 크기를 가지고있어 메모리 사용량이 증가합니다.

filter 함수 내에서 새로운 배열을 생성하기 때문에 중복을 제거한 새로운 배열과 원래의 배열 두 가지가 메모리에 할당됩니다.

(따라서 1번과 마찬가지로 메모리 사용량이 높습니다)

<html>

<head>
  <meta charset="UTF-8">
  <title>출력결과</title>
</head>

<body>
  <script>
    function solution(str) {
      let arr = str.split('');
      let set = new Set();
      arr.forEach(e => {
        if (!set.has(e)) {
          set.add(e);
        }
      })
      return Array.from(set).join('');
    }

    function solution2(str) {
      const obj = {};
      let result = '';

      for (let i = 0; i < str.length; i++) {
        const char = str[i];
        if (!obj[char]) {
          obj[char] = true;
          result += char;
        }
      }

      return result;
    }


    console.log(solution("apple"));
    console.log(solution("banana"));
    console.log(solution("asdasd"));
    console.log('----------------------')
    console.log(solution2("apple"));
    console.log(solution2("banana"));
    console.log(solution2("asdasd"));
  </script>
</body>

</html>

중복 제거를 위해 사용한다면 . 성능은 2번이 더 좋습니다.

timeEnd 사용시 평균적으로 성능은 2번이 더 좋습니다.

1번은  중복이 적은 경우입니다 중복이 적을때 좋은 중복제거 알고리즘..?

내가 이상한걸 만들어버린 것 같다.. 언제 쓰는걸까

중복이 발생하지 않는다는 가정이나, 중복이 발생하는 경우의 수가 매우 적은 경우에 사용하는걸까..?

 


생각해보니.. 1번 알고리즘

    function solution(str) {
      let arr = str.split('');
      let set = new Set(arr);
      return Array.from(set).join('');
    }​

이렇게 짜면 되는걸..

<html>

<head>
  <meta charset="UTF-8">
  <title>출력결과</title>
</head>

<!-- 문자열의 가운대 문자를 출력합니다.
짝수의 문자일경우 가운대 2개의 문자를 출력합니다. -->

<body>
  <script>
    function solution(str) {
      let answer = "";
      const len = str.length;
      const mid = Math.floor(len / 2);
      if (str.length === 0) {
        answer = "입력된 문자열이 없습니다.";
      } else if (len % 2 === 0) {
        answer = str[mid- 1] + str[mid];
      } else {
        answer = str[Math.floor(mid)];
      }
      return answer;
    }

    function solution2(str) {
      const len = str.length;
      const mid = Math.floor(len / 2);
      if (len % 2 === 0) {
        return str.slice(mid - 1, mid + 1);
      } else {
        return str[mid];
      }
    }

    console.log(solution("good"));
    console.log(solution("study"));

  </script>
</body>

</html>

 

<html>

<head>
  <meta charset="UTF-8">
  <title>출력결과</title>
</head>

<!-- 가장 긴 문자열 찾기 -->

<body>
  <script>
    let arr = ['apple', 'banana', 'cherry', 'durian', 'eggplant'];

    function solution(arr) {
      let max = arr[0];
      for (let a of arr) {
        if (max.length < a.length) { max = a;
        max = a; }
      }
      return max;
    }

    function solution2(arr) {
      let max = arr[0];
      for (let i = 0; i < arr.length; i++) {
        if (max.length < arr[i].length) max = arr[i];
      }
      return max;
    }
    console.log(solution(arr));
  </script>
</body>

</html>

 

+ Recent posts