알고리즘 [2024 KAKAO WINTER INTERNSHIP]가장 많이 받은 선물

이명진·2024년 7월 23일
0

코드카타

목록 보기
71/74

정말 오래간만에 문제를 풀었다. 레벨 1인데 kakao 문제라서 그런지 시간이 좀 소요 되었다.
문제를 쭉 읽다가 설계를 잘못해서 문제를 다시 풀었던게 컸다. 문제를 이해하는것이 진짜 진짜 중요하다.

문제 정리

일단 문제는 친구들 배열, 친구들이 선물을 준 목록이 배열로 준비되어 있다.
선물을 주고 받았는데 만약 선물을 더 많이 주었을 경우 다음달에 선물을 하나 받는다.
(이 부분에서 그냥 그렇구나 하고 넘어갔는데 , 선물을 교류한 경험이 둘다 없을 경우 지수를 구해서 계산해줘야 한다.ㅎ.. 그냥 넘어가서 코드가 꼬이고 답이 안나왔다)
만약 선물을 주고 받은 갯수가 같다면 선물 지수를 구해서 선물 지수가 높으면 선물을 받을수 있다.
선물 지수는 내가 총 받은 선물 갯수 - 내가 준 총 선물의 갯수 의 값으로 구할수 있다.
이를 구하여서 선물을 가장 많는 사람의 선물 갯수를 리턴해라.

내가 푼 풀이

function solution(friends, gifts) {
    var answer = 0;
  const friendsMap = new Map();
  const jisoMap = new Map();
  
  for(let i=0; i<friends.length;i++){
    const key = friends[i];
    jisoMap.set(key,{give:0,recive:0})
    for(let j=0; j<friends.length;j++){
      const friend = friends[j];
      if(key===friend){
        continue;
      }
      const propsKey = friendsMap.get(key);
      friendsMap.set(key,{...propsKey,[friend]:0})
    }   
  }
  
  gifts.map((list)=>{
    const[giver,reciever] = list.split(' ');
    const friendsMapProps = friendsMap.get(giver);
    const jisoMapProps = jisoMap.get(giver);
    const jisoReceiverProps = jisoMap.get(reciever);
    friendsMap.set(giver,{...friendsMapProps,[reciever]:friendsMapProps[reciever]+1})
    jisoMap.set(giver,{...jisoMapProps,give:jisoMapProps.give+1});
    jisoMap.set(reciever,{...jisoReceiverProps,recive:jisoReceiverProps.recive+1})
  })
  console.log(friendsMap,jisoMap)
  for(let i=0; i<friends.length;i++){
    const me = friends[i];
    const meJisu = jisoMap.get(me).give-jisoMap.get(me).recive;
    const meGive = friendsMap.get(me)
    let nextGive = 0;
    console.log(me,meJisu,meGive)
    for(let j=0;j<friends.length;j++){
      const you = friends[j];
      const youJisu = jisoMap.get(you).give-jisoMap.get(you).recive;
      const youGiveMe = friendsMap.get(you)[me];
      const meGiveYou = meGive[you];
      if(meGiveYou>youGiveMe){
        nextGive++
      }else if(meGiveYou===youGiveMe){
        if(meJisu>youJisu){
          nextGive++
        }
      }
    }
    console.log(me,nextGive)
    if(nextGive>answer){
      answer=nextGive;
    }
  }
  
    return answer;
}


이전 알고리즘 문제를 풀면서 new Map 이라는 Map객체가 성능이 좋다 라고해서 적용해봤다.
for문, 이중포문이 여러개 있어서 성능상 문제가 될거라고 생각해서 map객체를 선택했다.

문제를 풀면서 for문이 이렇게 많이 나와 ? 라고 생각하면서 이렇게 푸는게 맞나? 하고 생각하게 되었다.
(like 수능,중간,기말 시험 때 답으로 고른 번호가 같은 번호가 여러개 나오면 이게 답맞나? 라고 의심하는 것처럼..)

처음 Map객체를 만들때 이중 포문을 썼는데 이를 어떻게 잘 적용하면 포문을줄일수 있을것 같다는 생각이 드는데 나중에 다시 한번 봐야 겠다. ㅎㅎ 이렇게 풀었고 문제를 해결 완료 하게 되었다.

시간은 준수하게 잘 나온건지 모르겠다. 아무튼 문제 해결완료했다.
level1 문제라서 쉽게 봤더니 애를 먹었던 문제이다. 그래도 Map객체에 대해서 공부할수 있는 시간이 되었다.

다른사람 풀이

다른사람들은 어떻게 풀었을까 쭉 보다가 몇개 배울점, 인상깊은 코드를 가져왔다.
대부분 객체, new array 를 이용해서 배열로 푼것같다.

그중 두개를 가져왔다.

1

function solution(friends, gifts) {
  var answer = 0;
  const map = new Map();

  for (let i = 0; i < friends.length; i++) {
    for (let j = 0; j < friends.length; j++) {
      if (i === j) continue;

      map.set(friends[i], {
        ...map.get(friends[i]),
        giveCount: 0,
        receiveCount: 0,
        willPresent: 0,
        [friends[j]]: 0,
      });
    }
  }

  for (let i = 0; i < gifts.length; i++) {
    const [giver, receiver] = gifts[i].split(" ");
    map.set(giver, {
      ...map.get(giver),
      [receiver]: map.get(giver)[receiver] + 1,
    });
  }

  for (let i = 0; i < friends.length; i++) {
    const giver = friends[i];
    const friendsExceptGiver = map.get(giver);

    let giveCount = 0;
    Object.entries(friendsExceptGiver).forEach(([receiver, count]) => {
      if (map.get(receiver)) {
        giveCount += count;
        map.get(receiver).receiveCount += count;
      }
    });

    map.set(giver, {
      ...map.get(giver),
      giveCount,
    });
  }

  for (let i = 0; i < friends.length; i++) {
    for (let j = i; j < friends.length; j++) {
      if (i === j) continue;

      const giver = friends[i];
      const receiver = friends[j];

      if (map.get(giver)[receiver] > map.get(receiver)[giver]) {
        map.set(giver, {
          ...map.get(giver),
          willPresent: ++map.get(giver).willPresent,
        });
      } else if (map.get(giver)[receiver] < map.get(receiver)[giver]) {
        map.set(receiver, {
          ...map.get(receiver),
          willPresent: ++map.get(receiver).willPresent,
        });
      } else {
        const giverPoint =
          map.get(giver).giveCount - map.get(giver).receiveCount;
        const receiverPoint =
          map.get(receiver).giveCount - map.get(receiver).receiveCount;

        if (giverPoint > receiverPoint) {
          map.set(giver, {
            ...map.get(giver),
            willPresent: ++map.get(giver).willPresent,
          });
        } else if (giverPoint < receiverPoint) {
          map.set(receiver, {
            ...map.get(receiver),
            willPresent: ++map.get(receiver).willPresent,
          });
        }
      }
    }
  }

  for (let i = 0; i < friends.length; i++) {
    answer = Math.max(answer, map.get(friends[i]).willPresent);
  }

  return answer;
}

이분은 나와 같이 Map 객체를 이용해서 풀었다.
쭉 보니 나는 props 변수를 가지고 map.get을 가져와서 스프레드 연산자로 이전 데이터 값을 이어주었는데
바로 …map.get() 으로 바로 이어줄수 있다는 점을 깨닫게 되었다.
다른 변수를 선언안해도 되서 깔끔하긴 하지만 문제를 풀다가 헷갈리는 부분이 많았는데 변수로 저장해서 까먹지 않고 바로 대입하는것도 나쁘지않다고 생각이 든다.

성능상 이슈가 된다면 바꿔야 겠지만.. ㅎㅎ

2

function solution(friends, gifts) {
    //친구들의 선물 지수 구하기
    const obj = friends.reduce((acc,cur) => {
        acc[cur] = 0
        return acc;
    }  ,{})

    const answer = friends.reduce((acc,cur) => {
        acc[cur] = 0
        return acc;
    }  ,{})

    gifts.forEach((gift) => {
        const [giver,receiver] = gift.split(' ');
        obj[giver] = obj[giver] + 1
        obj[receiver] = obj[receiver] - 1
    })
    let arr = [];
    for(let i = 0; i < friends.length ; i++){
        for(let j = i + 1 ; j < friends.length; j++){
            const iGiveStr =  [friends[i],friends[j]].join(' ');
            const jGiveStr = [friends[j],friends[i]].join(' ');
            const iGiveNum = gifts.filter((gift) => gift === iGiveStr).length;
            const jGiveNum = gifts.filter((gift) => gift === jGiveStr).length;
            if((!iGiveNum && !jGiveNum) || (iGiveNum == jGiveNum)){
                if(obj[friends[i]] > obj[friends[j]]){
                  answer[friends[i]]++;
                }else if(obj[friends[i]] < obj[friends[j]]){
              answer[friends[j]]++;
                }else{}
            }else{
                if(iGiveNum > jGiveNum){
                  answer[friends[i]]++;
                }else{
                 answer[friends[j]]++;
                }           
            }
        }
    }
    return Math.max(...Object.values(answer));
}

그다음분은 reduce를 가져와 푼것이 인상깊다. 코드를 확실히 많이 줄일수 있는 방법인것 같다.

profile
프론트엔드 개발자 초보에서 고수까지!

0개의 댓글

관련 채용 정보