[알고리즘] array.reduce / array.pop / while / for문 성능개선

seo young park·2022년 3월 12일
0

알고리즘

목록 보기
2/3
post-thumbnail

🤔 문제 : 예산

문제 설명

S사에서는 각 부서에 필요한 물품을 지원해 주기 위해 부서별로 물품을 구매하는데 필요한 금액을 조사했습니다. 그러나, 전체 예산이 정해져 있기 때문에 모든 부서의 물품을 구매해 줄 수는 없습니다. 그래서 최대한 많은 부서의 물품을 구매해 줄 수 있도록 하려고 합니다.

물품을 구매해 줄 때는 각 부서가 신청한 금액만큼을 모두 지원해 줘야 합니다. 예를 들어 1,000원을 신청한 부서에는 정확히 1,000원을 지원해야 하며, 1,000원보다 적은 금액을 지원해 줄 수는 없습니다.

부서별로 신청한 금액이 들어있는 배열 d와 예산 budget이 매개변수로 주어질 때, 최대 몇 개의 부서에 물품을 지원할 수 있는지 return 하도록 solution 함수를 완성해주세요.

제한 조건

  • d는 부서별로 신청한 금액이 들어있는 배열이며, 길이(전체 부서의 개수)는 1 이상 100 이하입니다.
  • d의 각 원소는 부서별로 신청한 금액을 나타내며, 부서별 신청 금액은 1 이상 100,000 이하의 자연수입니다.
  • budget은 예산을 나타내며, 1 이상 10,000,000 이하의 자연수입니다.

입출력 예

⏰ 문제풀이

1️⃣ 문제 이해

정확히 신청한 금액을 지원해줘야한다. 다만, 예산을 최대한 소비하거나 최대한 남긴다는 등의 조건은 없다.
따라서 부서의 예산을 오름차순으로 정렬하고, 물품구매비용을 적게 기입한 부서부터 분배하여 예산이 음수가 되면 카운트를 멈추도록 코드를 짰다.

2️⃣ 코드 구현

function solution(d, budget) {
    var answer = 0;
  	d.sort((a,b)=>(a-b));

  	for(i=0; i<d.length; i++) {
      if((budget-d[i]) < 0) {
        break;
      }
      else {
        budget -= d[i];
        answer += 1;
      }
    }
    return answer;
}

💡 정답 분석

function solution(d, budget) {
    d.sort((a, b) => a - b);
   // 예시 [1,3,2,5,4] -> [1,2,3,4,5];

    while (d.reduce((a, b) => (a + b), 0) > budget) d.pop();
  
  // 1+2+3+4+5 > 9(true) , 5를 뺀다.
  // 1+2+3+4 > 9(true), 4를 뺀다.
  // 1+2+3 > 9(false), while문을 중단한다.

    return d.length;
}

반복할 때마다 reduce함수와 pop함수를 호출해서 효율적이지 않다는 의견이 있다.

Array.prototype.reduce();

reduce() 메서드는 배열의 각 요소에 대해 주어진 리듀서(reducer) 함수를 실행하고, 하나의 결과값을 반환합니다.

arr.reduce(callback[, initialValue])

callback 함수는 다음 4가지 인자를 가진다.

  • accumulator

    • 콜백의 반환값 누적
    • 콜백의 첫 번째 호출
    • initialValue를 제공한 경우에는 initialValue의 값.
  • currentValue

    • 처리할 현재 요소
  • currentIndex (optional)

    • 처리할 현재 요소의 인덱스
    • initialValue를 제공한 경우 0, 아니면 1.
  • array (optional)

    • reduce()를 호출한 배열.
  • initialValue를 제공한 경우
    • accumulator는 initialValue, currentValue는 배열의 첫 번째 값
    • initialValue를 제공하지 않은 경우, accumulator는 배열의 첫 번째 값 currentValue는 배열의 두 번째 값

Array.prototype.pop()

pop() 메서드는 배열에서 마지막 요소를 제거하고 그 요소를 반환한다.

  • 예시
const plants = ['broccoli', 'cauliflower', 'cabbage', 'kale', 'tomato'];

console.log(plants.pop());
// expected output: "tomato"

console.log(plants);
// expected output: Array ["broccoli", "cauliflower", "cabbage", "kale"]

plants.pop();

console.log(plants);
// expected output: Array ["broccoli", "cauliflower", "cabbage"]

while문

while 문은 조건문이 참일 때 실행되는 반복문이다. 조건은 문장안이 실행되기 전에 참, 거짓을 판단한다.

문제출처: https://programmers.co.kr/learn/courses/30/lessons/12982
출처:mdn

🤔 문제 : 완주하지못한 선수

문제 설명

수많은 마라톤 선수들이 마라톤에 참여하였습니다. 단 한 명의 선수를 제외하고는 모든 선수가 마라톤을 완주하였습니다.

마라톤에 참여한 선수들의 이름이 담긴 배열 participant와 완주한 선수들의 이름이 담긴 배열 completion이 주어질 때, 완주하지 못한 선수의 이름을 return 하도록 solution 함수를 작성해주세요.

제한 조건

  • 마라톤 경기에 참여한 선수의 수는 1명 이상 100,000명 이하입니다.
  • completion의 길이는 participant의 길이보다 1 작습니다.
  • 참가자의 이름은 1개 이상 20개 이하의 알파벳 소문자로 이루어져 있습니다.
  • 참가자 중에는 동명이인이 있을 수 있습니다.

입출력 예

⏰ 문제풀이

1️⃣ 문제 이해

filter 함수를 사용하면 완주자와 미완주자가 동명이인인 경우를 잡아내지 못한다. 다만, 미완주자가 단 한 명이기 때문에 참가자와 완주자를 알파벳순으로 정렬하여, 일대일로 비교하고 일치하지 않는 경우 return 한다.

2️⃣ 코드 구현

function solution(participant, completion) {
  participant.sort(); // 참가자 알파벳순 정렬
  completion.sort(); // 완주자 알파벳순 정렬
  
  for (let i = 0; i < participant.length; i++) {
    if(participant[i] !== completion[i]) {
      return participant[i];
    }

// 참가자 : 민수, 병수, 병수, 철수
// 완주자 : 민수, 병수, 철수
// 참가자[0] === 완주자[0]; pass
// 참가자[1] === 완주자[1]; pass
// 참가자[2] !=== 완주자[2]; return 참가자[2];
}


solution(a, b);

💡 정답 분석

정답


function solution(participant, completion) {
    participant.sort();
    completion.sort();

    for(let i in participant) {
        if(participant[i] !== completion[i]) return participant[i];
    }
}

for문 성능 개선 : length 변수 지정

for문을 돌릴 때, length를 변수 지정해주면 속도가 빨라진다고 한다.

  • 예시
function solution(participant, completion) {
    participant.sort();
    completion.sort();
	const participant_length = participant.length
    for(let i = 0; i < participant_length; i++) {
        if(participant[i] !== completion[i]) return participant[i];
    }
}

문제출처: https://programmers.co.kr/learn/courses/30/lessons/42576

🤔 문제 : 두 개 뽑아서 더하기

문제 설명

정수 배열 numbers가 주어집니다. numbers에서 서로 다른 인덱스에 있는 두 개의 수를 뽑아 더해서 만들 수 있는 모든 수를 배열에 오름차순으로 담아 return 하도록 solution 함수를 완성해주세요.

제한 조건

  • numbers의 길이는 2 이상 100 이하입니다.
  • numbers의 모든 수는 0 이상 100 이하입니다.

입출력 예

⏰ 문제풀이

1️⃣ 문제 이해

서로 다른 인덱스에 있는 두 개의 수를 더해 만들 수 있는 모든 경우의 수를 구해야한다.
[3, 5, 6, 7, 8] 원소가 5개인 배열이 있다고 치면,

index 기준으로
0+1
0+2
0+3
0+4
1+2
1+3
1+4
2+3
2+4
3+4

왼쪽은 (0) ~ (length - 1)까지, 오른쪽은 (왼쪽+1) ~ (length)까지 줄세워서 더해준다.
더한 결과를 배열에 넣어주면,
set으로 중복을 잡아주고 sort를 이용해 오름차순으로 바꾼다.

2️⃣ 코드 구현

function solution(numbers) {
    var answer = [];
  	const numbers_length = numbers.length;
  	for(i=0; i<(numbers_length-1); i++){
      for(j=i+1; j<numbers_length; j++) {
        answer.push(numbers[i]+numbers[j]);
      }
    }
  	const newAnswer = [...new Set(answer)].sort(function(a,b){
      return a-b;
    });
  
    return newAnswer;
}

💡 정답 분석

function solution(numbers) {
    const temp = []

    for (let i = 0; i < numbers.length; i++) {
        for (let j = i + 1; j < numbers.length; j++) {
            temp.push(numbers[i] + numbers[j])
        }
    }

    const answer = [...new Set(temp)]

    return answer.sort((a, b) => a - b)
}

문제출처: https://programmers.co.kr/learn/courses/30/lessons/68644
출처:mdn

0개의 댓글