코드 훔쳐보는 변태 코더
춤 좋아하는 백엔드 개발자(였으면 좋겠다)
Algorithm (34)
프로그래머스 - 신고 결과 받기 (lv1, 카카오, 자바)

https://school.programmers.co.kr/learn/courses/30/lessons/92334

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제 설명

신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다. 무지가 개발하려는 시스템은 다음과 같습니다.

  • 각 유저는 한 번에 한 명의 유저를 신고할 수 있습니다.
    • 신고 횟수에 제한은 없습니다. 서로 다른 유저를 계속해서 신고할 수 있습니다.
    • 한 유저를 여러 번 신고할 수도 있지만, 동일한 유저에 대한 신고 횟수는 1회로 처리됩니다.
  • k번 이상 신고된 유저는 게시판 이용이 정지되며, 해당 유저를 신고한 모든 유저에게 정지 사실을 메일로 발송합니다.
    • 유저가 신고한 모든 내용을 취합하여 마지막에 한꺼번에 게시판 이용 정지를 시키면서 정지 메일을 발송합니다.

다음은 전체 유저 목록이 ["muzi", "frodo", "apeach", "neo"]이고, k = 2(즉, 2번 이상 신고당하면 이용 정지)인 경우의 예시입니다.

유저 ID 유저가 신고한 ID 설명

"muzi" "frodo" "muzi"가 "frodo"를 신고했습니다.
"apeach" "frodo" "apeach"가 "frodo"를 신고했습니다.
"frodo" "neo" "frodo"가 "neo"를 신고했습니다.
"muzi" "neo" "muzi"가 "neo"를 신고했습니다.
"apeach" "muzi" "apeach"가 "muzi"를 신고했습니다.

각 유저별로 신고당한 횟수는 다음과 같습니다.

유저 ID 신고당한 횟수

"muzi" 1
"frodo" 2
"apeach" 0
"neo" 2

위 예시에서는 2번 이상 신고당한 "frodo"와 "neo"의 게시판 이용이 정지됩니다. 이때, 각 유저별로 신고한 아이디와 정지된 아이디를 정리하면 다음과 같습니다.

유저 ID 유저가 신고한 ID 정지된 ID

"muzi" ["frodo", "neo"] ["frodo", "neo"]
"frodo" ["neo"] ["neo"]
"apeach" ["muzi", "frodo"] ["frodo"]
"neo" 없음 없음

따라서 "muzi"는 처리 결과 메일을 2회, "frodo"와 "apeach"는 각각 처리 결과 메일을 1회 받게 됩니다.

이용자의 ID가 담긴 문자열 배열 id_list, 각 이용자가 신고한 이용자의 ID 정보가 담긴 문자열 배열 report, 정지 기준이 되는 신고 횟수 k가 매개변수로 주어질 때, 각 유저별로 처리 결과 메일을 받은 횟수를 배열에 담아 return 하도록 solution 함수를 완성해주세요.


제한사항

  • 2 ≤ id_list의 길이 ≤ 1,000
    • 1 ≤ id_list의 원소 길이 ≤ 10
    • id_list의 원소는 이용자의 id를 나타내는 문자열이며 알파벳 소문자로만 이루어져 있습니다.
    • id_list에는 같은 아이디가 중복해서 들어있지 않습니다.
  • 1 ≤ report의 길이 ≤ 200,000
    • 3 ≤ report의 원소 길이 ≤ 21
    • report의 원소는 "이용자id 신고한id"형태의 문자열입니다.
    • 예를 들어 "muzi frodo"의 경우 "muzi"가 "frodo"를 신고했다는 의미입니다.
    • id는 알파벳 소문자로만 이루어져 있습니다.
    • 이용자id와 신고한id는 공백(스페이스)하나로 구분되어 있습니다.
    • 자기 자신을 신고하는 경우는 없습니다.
  • 1 ≤ k ≤ 200, k는 자연수입니다.
  • return 하는 배열은 id_list에 담긴 id 순서대로 각 유저가 받은 결과 메일 수를 담으면 됩니다.

입출력 예

id_list report k result

["muzi", "frodo", "apeach", "neo"] ["muzi frodo","apeach frodo","frodo neo","muzi neo","apeach muzi"] 2 [2,1,1,0]
["con", "ryan"] ["ryan con", "ryan con", "ryan con", "ryan con"] 3 [0,0]

 

 

풀이

 

해당 문제는 적절한 자료구조와 문자열 관련 메소드의 활용으로 풀이하면 될 것 같았다.

 

1차적으로는 해당 회원의 인덱스를 갖고있는 배열이 필요해보였고, 신고 상황을 저장할 배열, 신고 누적 횟수를 저장할 배열, 그리고 이메일 송신 횟수를 갖는 배열 이렇게 4개의 배열을 선언할까 생각했었고,

 

2차적으로는 인덱스를 해시맵으로 구현, 신고상황은 한 회원이 여러번 같은 회원을 신고할 , 다른 회원을 신고한 기록도 저장해야 하니 해시맵이 아닌 리포트배열은 2차원으로 , 그리고 신고 누적 횟수는 해시맵, 그리고 이메일 배열은 마찬가지로 2차원 배열로 구현하였다 (?)

 

제출 이후인 3차적으로 생각하면 인덱스와 누적 신고 횟수를 합쳐서 정수 리스트를 같는 해시맵과 신고누적 횟수 해시맵 이렇게 2개만 선언해도 됐을 것 같다.

 

class Solution {
 public List<Integer> solution(String[] id_list, String[] report, int k) {
    List<Integer> answer = new ArrayList<>();
        HashMap<String,Integer> idxMap = new HashMap<>();
        HashMap<String,Integer> reportedMap = new HashMap<>();
        int[][] reportArr = new int[id_list.length][id_list.length];
        int[][] emailArr = new int[id_list.length][1];
        int idx = 0;
        for(String id : id_list){
            reportedMap.put(id,0);
            idxMap.put(id,idx);
            for(int j=0; j<id_list.length;j++){
                reportArr[idx][j]=0;
            }
            idx++;
        }
        for(String detail:report){
            int spaceIdx = detail.indexOf(" ");
            String reportFrom = detail.substring(0,spaceIdx);
            String reportTo = detail.substring(spaceIdx+1,detail.length());
            int fromIdx = idxMap.get(reportFrom);
            int toIdx = idxMap.get(reportTo);
            if(reportArr[toIdx][fromIdx]!=1){
                reportArr[toIdx][fromIdx]=1;
                reportedMap.put(reportTo,reportedMap.get(reportTo)+1);
            }
        }
        reportedMap.forEach((key,value)->{
            if(value>=k){
                int toIdx = idxMap.get(key);
                for(int i=0; i<id_list.length;i++){
                    if(reportArr[toIdx][i]==1){
                        emailArr[i][0]++;
                    }
                }
            }
        });
        for(int i=0; i<id_list.length;i++){
            answer.add(emailArr[i][0]);
        }
        return answer;
    }
}

 

  Comments,     Trackbacks
프로그래머스 - 바탕화면 정리 (lv1,자바)

https://school.programmers.co.kr/learn/courses/30/lessons/161990

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

문제 설명

코딩테스트를 준비하는 머쓱이는 프로그래머스에서 문제를 풀고 나중에 다시 코드를 보면서 공부하려고 작성한 코드를 컴퓨터 바탕화면에 아무 위치에나 저장해 둡니다. 저장한 코드가 많아지면서 머쓱이는 본인의 컴퓨터 바탕화면이 너무 지저분하다고 생각했습니다. 프로그래머스에서 작성했던 코드는 그 문제에 가서 다시 볼 수 있기 때문에 저장해 둔 파일들을 전부 삭제하기로 했습니다.

컴퓨터 바탕화면은 각 칸이 정사각형인 격자판입니다. 이때 컴퓨터 바탕화면의 상태를 나타낸 문자열 배열 wallpaper가 주어집니다. 파일들은 바탕화면의 격자칸에 위치하고 바탕화면의 격자점들은 바탕화면의 가장 왼쪽 위를 (0, 0)으로 시작해 (세로 좌표, 가로 좌표)로 표현합니다. 빈칸은 ".", 파일이 있는 칸은 "#"의 값을 가집니다. 드래그를 하면 파일들을 선택할 수 있고, 선택된 파일들을 삭제할 수 있습니다. 머쓱이는 최소한의 이동거리를 갖는 한 번의 드래그로 모든 파일을 선택해서 한 번에 지우려고 하며 드래그로 파일들을 선택하는 방법은 다음과 같습니다.

  • 드래그는 바탕화면의 격자점 S(lux, luy)를 마우스 왼쪽 버튼으로 클릭한 상태로 격자점 E(rdx, rdy)로 이동한 뒤 마우스 왼쪽 버튼을 떼는 행동입니다. 이때, "점 S에서 점 E로 드래그한다"고 표현하고 점 S와 점 E를 각각 드래그의 시작점, 끝점이라고 표현합니다.
  • 점 S(lux, luy)에서 점 E(rdx, rdy)로 드래그를 할 때, "드래그 한 거리"는 |rdx - lux| + |rdy - luy|로 정의합니다.
  • 점 S에서 점 E로 드래그를 하면 바탕화면에서 두 격자점을 각각 왼쪽 위, 오른쪽 아래로 하는 직사각형 내부에 있는 모든 파일이 선택됩니다.

예를 들어

wallpaper

= [".#...", "..#..", "...#."]인 바탕화면을 그림으로 나타내면 다음과 같습니다.

이러한 바탕화면에서 다음 그림과 같이 S(0, 1)에서 E(3, 4)로 드래그하면 세 개의 파일이 모두 선택되므로 드래그 한 거리 (3 - 0) + (4 - 1) = 6을 최솟값으로 모든 파일을 선택 가능합니다.

(0, 0)에서 (3, 5)로 드래그해도 모든 파일을 선택할 수 있지만 이때 드래그 한 거리는 (3 - 0) + (5 - 0) = 8이고 이전의 방법보다 거리가 늘어납니다.

머쓱이의 컴퓨터 바탕화면의 상태를 나타내는 문자열 배열 wallpaper가 매개변수로 주어질 때 바탕화면의 파일들을 한 번에 삭제하기 위해 최소한의 이동거리를 갖는 드래그의 시작점과 끝점을 담은 정수 배열을 return하는 solution 함수를 작성해 주세요. 드래그의 시작점이 (lux, luy), 끝점이 (rdx, rdy)라면 정수 배열 [lux, luy, rdx, rdy]를 return하면 됩니다.


제한사항

  • 1 ≤ wallpaper의 길이 ≤ 50
  • 1 ≤ wallpaper[i]의 길이 ≤ 50
    • wallpaper의 모든 원소의 길이는 동일합니다.
  • wallpaper[i][j]는 바탕화면에서 i + 1행 j + 1열에 해당하는 칸의 상태를 나타냅니다.
  • wallpaper[i][j]는 "#" 또는 "."의 값만 가집니다.
  • 바탕화면에는 적어도 하나의 파일이 있습니다.
  • 드래그 시작점 (lux, luy)와 끝점 (rdx, rdy)는 lux < rdx, luy < rdy를 만족해야 합니다.

입출력 예

wallpaper result

[".#...", "..#..", "...#."] [0, 1, 3, 4]
["..........", ".....#....", "......##..", "...##.....", "....#....."] [1, 3, 5, 8]
[".##...##.", "#..#.#..#", "#...#...#", ".#.....#.", "..#...#..", "...#.#...", "....#...."] [0, 0, 7, 9]
["..", "#."] [1, 0, 2, 1]

 

 

풀이

해당 문제는 1차적인 생각으로는 2차원 배열로 풀이하면 됐었고, 2차적인 생각으로는 가장 큰 x,y 좌표값을 저장하는 변수와 가장 작은 x,y 좌표값을 저장하는 변수를 선언 해 마지막으로 가장 큰 x,y 좌표값에 +1를 하면 되겠다는 생각을 하게 되었다.

 

정답률이 35퍼센트라 겁먹고 들어갔으나 생각보다 너무 빨리 오류도 없이 쉽게 풀어서 당황..

 

3차적인 생각으로는 반례를 살펴보게 되었는데 파일이 하나일경우가 반례가 될까? 했지만 출력이 정답과 다르지 않아서 그냥 제출했더니 맞았다.

 

class Solution {
    public int[] solution(String[] wallpaper) {
        int leastX = wallpaper[0].length();
        int leastY = wallpaper.length;
        int maxX = 0;
        int maxY = 0;
        for(int i=0; i<wallpaper.length;i++){
            for(int j=0; j<wallpaper[0].length();j++){
                int nowX = j;
                int nowY = i;
                if(wallpaper[i].charAt(j)=='#'){
                    if(leastX>nowX){
                        leastX=nowX;
                    }
                    if(leastY>nowY){
                        leastY=nowY;
                    }
                    if(maxX<nowX){
                        maxX=nowX;
                    }
                    if(maxY<nowY){
                        maxY=nowY;
                    }
                }
            }
        }

        return new int[]{leastY, leastX, maxY + 1, maxX + 1};
    }
}

읽기 쉬운 코드를 작성하려고 하니 딱히 코드가 엄청 짧지 않아도 이해하기 쉽게 구현이 가능한거 같다. 실력도 늘은거 같고 뿌듯 ><

  Comments,     Trackbacks
프로그래머스 - 개인정보 수집 유효기간 (카카오, lv1,자바)

https://school.programmers.co.kr/learn/courses/30/lessons/150370

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

문제 설명

고객의 약관 동의를 얻어서 수집된 1~n번으로 분류되는 개인정보 n개가 있습니다. 약관 종류는 여러 가지 있으며 각 약관마다 개인정보 보관 유효기간이 정해져 있습니다. 당신은 각 개인정보가 어떤 약관으로 수집됐는지 알고 있습니다. 수집된 개인정보는 유효기간 전까지만 보관 가능하며, 유효기간이 지났다면 반드시 파기해야 합니다.

예를 들어, A라는 약관의 유효기간이 12 달이고, 2021년 1월 5일에 수집된 개인정보가 A약관으로 수집되었다면 해당 개인정보는 2022년 1월 4일까지 보관 가능하며 2022년 1월 5일부터 파기해야 할 개인정보입니다.당신은 오늘 날짜로 파기해야 할 개인정보 번호들을 구하려 합니다.

모든 달은 28일까지 있다고 가정합니다.

다음은 오늘 날짜가 2022.05.19일 때의 예시입니다.

약관 종류 유효기간

A 6 달
B 12 달
C 3 달

번호 개인정보 수집 일자 약관 종류

1 2021.05.02 A
2 2021.07.01 B
3 2022.02.19 C
4 2022.02.20 C
  • 첫 번째 개인정보는 A약관에 의해 2021년 11월 1일까지 보관 가능하며, 유효기간이 지났으므로 파기해야 할 개인정보입니다.
  • 두 번째 개인정보는 B약관에 의해 2022년 6월 28일까지 보관 가능하며, 유효기간이 지나지 않았으므로 아직 보관 가능합니다.
  • 세 번째 개인정보는 C약관에 의해 2022년 5월 18일까지 보관 가능하며, 유효기간이 지났으므로 파기해야 할 개인정보입니다.
  • 네 번째 개인정보는 C약관에 의해 2022년 5월 19일까지 보관 가능하며, 유효기간이 지나지 않았으므로 아직 보관 가능합니다.

따라서 파기해야 할 개인정보 번호는 [1, 3]입니다.

오늘 날짜를 의미하는 문자열 today, 약관의 유효기간을 담은 1차원 문자열 배열 terms와 수집된 개인정보의 정보를 담은 1차원 문자열 배열 privacies가 매개변수로 주어집니다. 이때 파기해야 할 개인정보의 번호를 오름차순으로 1차원 정수 배열에 담아 return 하도록 solution 함수를 완성해 주세요.

제한사항

  • today는 "YYYY.MM.DD" 형태로 오늘 날짜를 나타냅니다.
  • 1 ≤ terms의 길이 ≤ 20
    • terms의 원소는 "약관 종류 유효기간" 형태의 약관 종류와 유효기간을 공백 하나로 구분한 문자열입니다.
    • 약관 종류는 A~Z중 알파벳 대문자 하나이며, terms 배열에서 약관 종류는 중복되지 않습니다.
    • 유효기간은 개인정보를 보관할 수 있는 달 수를 나타내는 정수이며, 1 이상 100 이하입니다.
  • 1 ≤ privacies의 길이 ≤ 100
    • privacies[i]는 i+1번 개인정보의 수집 일자와 약관 종류를 나타냅니다.
    • privacies의 원소는 "날짜 약관 종류" 형태의 날짜와 약관 종류를 공백 하나로 구분한 문자열입니다.
    • 날짜는 "YYYY.MM.DD" 형태의 개인정보가 수집된 날짜를 나타내며, today 이전의 날짜만 주어집니다.
    • privacies의 약관 종류는 항상 terms에 나타난 약관 종류만 주어집니다.
  • today와 privacies에 등장하는 날짜의 YYYY는 연도, MM은 월, DD는 일을 나타내며 점(.) 하나로 구분되어 있습니다.
    • 2000 ≤ YYYY ≤ 2022
    • 1 ≤ MM ≤ 12
    • MM이 한 자릿수인 경우 앞에 0이 붙습니다.
    • 1 ≤ DD ≤ 28
    • DD가 한 자릿수인 경우 앞에 0이 붙습니다.
  • 파기해야 할 개인정보가 하나 이상 존재하는 입력만 주어집니다.

입출력 예

today terms privacies result

"2022.05.19" ["A 6", "B 12", "C 3"] ["2021.05.02 A", "2021.07.01 B", "2022.02.19 C", "2022.02.20 C"] [1, 3]
"2020.01.01" ["Z 3", "D 5"] ["2019.01.01 D", "2019.11.15 Z", "2019.08.02 D", "2019.07.01 D", "2018.12.28 Z"] [1, 4, 5]

 

 

 

풀이

 

해당 문제 같은 경우는 설명만 길고 단순히 생각의 흐름대로 풀이해보면 되는 문제같다.

전체적으로 문자열 관련 메소드를 잘 활용하면 되는 문제였다.

가장 좋았던건 한 달이 28일이라고 지정해둔 덕에 어렵지 않게 풀 수 있었다.

 

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

class Solution {
    public List<Integer> solution(String today, String[] terms, String[] privacies) {
        int dayForM = 28;
        int todayY = Integer.parseInt(today.substring(0,4));
        int todayM = Integer.parseInt(today.substring(5,7));
        int todayD = Integer.parseInt(today.substring(8,10));

        int totalD = (todayY*dayForM*12) + (todayM*28) + todayD;
        List<Integer> answerArr = new ArrayList<>();
        HashMap<Character,Integer> termsMap = new HashMap<>();
        for(String term : terms){
            char termO = term.charAt(0);
            int termM = Integer.parseInt(term.substring(2));
            termsMap.put(termO,termM);
        }
        for(int i=0; i<privacies.length; i++){
            char privacyO = privacies[i].charAt(11);
            int privacyY = Integer.parseInt(privacies[i].substring(0,4));
            int privacyM = Integer.parseInt(privacies[i].substring(5,7));
            int privacyD = Integer.parseInt(privacies[i].substring(8,10));
            int totalPrivacyD = (privacyY*12*dayForM) + (privacyM*dayForM) + privacyD;
            int termM = termsMap.get(privacyO);
            int termDay = termM * dayForM;
            if(totalPrivacyD+termDay <=totalD){
                answerArr.add(i+1);
            }
        }

        return answerArr;
    }
}

 

해당 문제풀이들을 살펴보니 객체지향으로 풀이하신분도 계셨다.

 

  Comments,     Trackbacks
백준 11497 통나무 건너뛰기 (자바) 풀이
시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초 256 MB 6971 3993 3265 59.635%

문제

남규는 통나무를 세워 놓고 건너뛰기를 좋아한다. 그래서 N개의 통나무를 원형으로 세워 놓고 뛰어놀려고 한다. 남규는 원형으로 인접한 옆 통나무로 건너뛰는데, 이때 각 인접한 통나무의 높이 차가 최소가 되게 하려 한다.

통나무 건너뛰기의 난이도는 인접한 두 통나무 간의 높이의 차의 최댓값으로 결정된다. 높이가 {2, 4, 5, 7, 9}인 통나무들을 세우려 한다고 가정하자. 이를 [2, 9, 7, 4, 5]의 순서로 세웠다면, 가장 첫 통나무와 가장 마지막 통나무 역시 인접해 있다. 즉, 높이가 2인 것과 높이가 5인 것도 서로 인접해 있다. 배열 [2, 9, 7, 4, 5]의 난이도는 |2-9| = 7이다. 우리는 더 나은 배열 [2, 5, 9, 7, 4]를 만들 수 있으며 이 배열의 난이도는 |5-9| = 4이다. 이 배열보다 난이도가 낮은 배열은 만들 수 없으므로 이 배열이 남규가 찾는 답이 된다.

입력

입력은 T개의 테스트 케이스로 이루어져 있다. 첫 줄에 T가 주어진다.

이어지는 각 줄마다 첫 줄에 통나무의 개수를 나타내는 정수 N(5 ≤ N ≤ 10,000), 둘째 줄에 각 통나무의 높이를 나타내는 정수 Li가 주어진다. (1 ≤ Li ≤ 100,000)

출력

각 테스트 케이스마다 한 줄에 주어진 통나무들로 만들 수 있는 최소 난이도를 출력하시오.

예제 입력 1 복사

3
7
13 10 12 11 10 11 12
5
2 4 5 7 9
8
6 6 6 6 6 6 6 6

예제 출력 1 복사

1
4
0

풀이

문제를 읽다보면 힌트가 나와있다.

2 4 5 7 9 로 입력받을때

2 5 9 7 4 에서 9-5 를 해서 난이도가 4가 나온다고 굉장히 친절하게 알려주고있다.

단순히 이것을 응용해서 입력받은 배열을 가장 큰 수가 중앙에 오고 그 다음으로 큰수가 중앙의 오른쪽, 그다음으로 큰수가 왼쪽으로 오게 만들면된다.

 

우선순위 큐를 활용해서 가장 큰 순서대로 정렬받은 배열을 먼저 만들고,

 

새로 정렬할 배열을 생성해준 후 왼쪽과 오른쪽 인덱스를 만들어주고 while 문으로 2개씩 poll해서 삽입해주면 된다.

그러면 배열의 순서상으론 맨 처음값과 맨 끝 값이 원래의 오름차순으로 데이터가 들어가있을건데,

 

이 두개를 뺀 값의 절대값을 max 변수에 대입해주고 배열을 처음부터 비교해서 더 큰 값이 나온다면 max를 바꿔주는 식으로 풀이하면 된다. (통나무 높이를 뺐을때 가장 큰 값이 난이도가 된다고 문제에 나와있다.)

 

package baekjoon.a11497;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class a11497 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int T = Integer.parseInt(br.readLine());
        for(int i=0; i<T;i++){
            int N = Integer.parseInt(br.readLine());
            StringTokenizer st = new StringTokenizer(br.readLine());
            PriorityQueue<Integer> queue = new PriorityQueue<>((o1, o2) -> o2-o1);
            int[] arr = new int[N];
            for(int j=0; j<N;j++){
                queue.add(Integer.valueOf(st.nextToken()));
            }
            arr[N/2]=queue.poll();
            int left = N/2-1;
            int right = N/2+1;
            while(!queue.isEmpty()){
                if(right<N){
                arr[right++]=queue.poll();}
                if(!queue.isEmpty()){
                arr[left--]=queue.poll();}
            }
            int max = Math.abs(arr[0]-arr[N-1]);
            for(int j=1; j<N;j++){
               max = Math.max(max,Math.abs(arr[j]-arr[j-1]));
            }
            System.out.println(max);
        }
    }

}

 

 

 

  Comments,     Trackbacks
백준 1431번 시리얼 번호 (자바) 풀이
시간 제한메모리 제한제출정답맞힌 사람정답 비율
2 초 128 MB 11139 6005 4941 55.133%

문제

다솜이는 기타를 많이 가지고 있다. 그리고 각각의 기타는 모두 다른 시리얼 번호를 가지고 있다. 다솜이는 기타를 빨리 찾아서 빨리 사람들에게 연주해주기 위해서 기타를 시리얼 번호 순서대로 정렬하고자 한다.

모든 시리얼 번호는 알파벳 대문자 (A-Z)와 숫자 (0-9)로 이루어져 있다.

시리얼번호 A가 시리얼번호 B의 앞에 오는 경우는 다음과 같다.

  1. A와 B의 길이가 다르면, 짧은 것이 먼저 온다.
  2. 만약 서로 길이가 같다면, A의 모든 자리수의 합과 B의 모든 자리수의 합을 비교해서 작은 합을 가지는 것이 먼저온다. (숫자인 것만 더한다)
  3. 만약 1,2번 둘 조건으로도 비교할 수 없으면, 사전순으로 비교한다. 숫자가 알파벳보다 사전순으로 작다.

시리얼이 주어졌을 때, 정렬해서 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 기타의 개수 N이 주어진다. N은 50보다 작거나 같다. 둘째 줄부터 N개의 줄에 시리얼 번호가 하나씩 주어진다. 시리얼 번호의 길이는 최대 50이고, 알파벳 대문자 또는 숫자로만 이루어져 있다. 시리얼 번호는 중복되지 않는다.

출력

첫째 줄부터 차례대로 N개의 줄에 한줄에 하나씩 시리얼 번호를 정렬한 결과를 출력한다.

예제 입력 1 복사

5
ABCD
145C
A
A910
Z321

예제 출력 1 복사

A
ABCD
Z321
145C
A910

예제 입력 2 복사

2
Z19
Z20

예제 출력 2 복사

Z20
Z19

예제 입력 3 복사

4
34H2BJS6N
PIM12MD7RCOLWW09
PYF1J14TF
FIPJOTEA5

예제 출력 3 복사

FIPJOTEA5
PYF1J14TF
34H2BJS6N
PIM12MD7RCOLWW09

예제 입력 4 복사

5
ABCDE
BCDEF
ABCDA
BAAAA
ACAAA

예제 출력 4 복사

ABCDA
ABCDE
ACAAA
BAAAA
BCDEF

 

 

풀이

 

굉장히 친절한 문제이다

 

문제에 어떻게 정렬을 하라고 다 알려주고 있다.

 

1 -> A와 B의 길이가 다르다면 짧은것이 먼저 온다.

단순히 조건문으로 A와 B의 길이를 비교해 정렬하면 된다.

2 -> A와 B의 길이가 같다면 문자열 내 모든 숫자의 합 순으로 정렬한다.

마찬가지로 조건문안에 반복문을 삽입하면 된다.

3 -> 두 방법으로도 정렬이 안된다면 단순 사전순으로 정렬한다.

 

3번째 방법이 문제이다.

두 방법으로도 정렬이 안된다면? 이 어떤 상황일까?

단순하다. A와 B의 길이도 같은데 문자열 내 모든 숫자의 합마저 같다면 이라는 조건이 되어버린다.

 

단순히 2번의 조건문 안에 숫자의 합을 비교하는 조건문을 추가해주면 된다.

 

package baekjoon.a1431;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class a1431 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        List<String> list = new ArrayList<>();
        for (int i = 0; i < N; i++) {
            list.add(br.readLine());
        }
        list.sort((o1, o2) -> {
            if (o1.length() != o2.length()) {
                return o1.length() - o2.length();
            } else {
                int a = 0;
                int b = 0;
                for (int i = 0; i < o1.length(); i++) {
                    int num1 = o1.charAt(i) - '0';
                    int num2 = o2.charAt(i) - '0';
                    if (num1 > 0 && num1 < 10) {
                        a += num1;
                    }
                    if (num2 > 0 && num2 < 10) {
                        b += num2;
                    }
                }
                if (a == b) {
                    return o1.compareToIgnoreCase(o2);
                }
                return a - b;
            }
        });
        list.forEach(System.out::println);
    }
}

  Comments,     Trackbacks
백준 1946번 신입사원 (자바) 풀이
시간 제한메모리 제한제출정답맞힌 사람정답 비율
2 초 256 MB 44813 14819 10815 32.065%

문제

언제나 최고만을 지향하는 굴지의 대기업 진영 주식회사가 신규 사원 채용을 실시한다. 인재 선발 시험은 1차 서류심사와 2차 면접시험으로 이루어진다. 최고만을 지향한다는 기업의 이념에 따라 그들은 최고의 인재들만을 사원으로 선발하고 싶어 한다.

그래서 진영 주식회사는, 다른 모든 지원자와 비교했을 때 서류심사 성적과 면접시험 성적 중 적어도 하나가 다른 지원자보다 떨어지지 않는 자만 선발한다는 원칙을 세웠다. 즉, 어떤 지원자 A의 성적이 다른 어떤 지원자 B의 성적에 비해 서류 심사 결과와 면접 성적이 모두 떨어진다면 A는 결코 선발되지 않는다.

이러한 조건을 만족시키면서, 진영 주식회사가 이번 신규 사원 채용에서 선발할 수 있는 신입사원의 최대 인원수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에는 테스트 케이스의 개수 T(1 ≤ T ≤ 20)가 주어진다. 각 테스트 케이스의 첫째 줄에 지원자의 숫자 N(1 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 N개 줄에는 각각의 지원자의 서류심사 성적, 면접 성적의 순위가 공백을 사이에 두고 한 줄에 주어진다. 두 성적 순위는 모두 1위부터 N위까지 동석차 없이 결정된다고 가정한다.

출력

각 테스트 케이스에 대해서 진영 주식회사가 선발할 수 있는 신입사원의 최대 인원수를 한 줄에 하나씩 출력한다.

예제 입력 1 복사

2
5
3 2
1 4
4 1
2 3
5 5
7
3 6
7 3
4 2
1 4
5 7
2 5
6 1

 

풀이

해당 문제는 정렬과 그리디 알고리즘을 활용한 문제이다.

그리디 알고리즘은 배우지 않았지만 대충 탐욕 이라는 뜻을 가진다는걸 알고있기는 하다..

 

단순하다. 문제의 조건 자체가 다른 지원자보다 하나라도 점수가 낮다면 탈락이 되고, 최대의 합격자수를 가져와주길 바라고 있다.

 

최대 를 가지려면 일단 생각해봐야 할것이 남들보다 두 점수 모두가 높은 사람들을 탈락시키고 적절한 비율로 합격을 시킬것인지, 아닌지 를 생각해보면 좋다.

 

하지만 문제 자체는 정렬을 이용해 풀라고 알려주고 있다.

 

단순히 배열에 값을 입력받아서 서류심사 성적 순으로 정렬하고, 첫번째 지원자의 면접심사 점수보다 낮은 사람이 존재한다면 낮은 사람의 점수를 기억한후 카운트를 ++ 하는식으로 돌리면 된다.

 

package baekjoon.a1946;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class a1946 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int T = Integer.parseInt(br.readLine());
        for (int i = 0; i < T; i++) {
            List<int[]> list = new ArrayList<>();
            int N = Integer.parseInt(br.readLine());
            for (int j = 0; j < N; j++) {
                StringTokenizer st = new StringTokenizer(br.readLine());
                list.add(new int[]{Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())});
            }
            list.sort(Comparator.comparingInt(o -> o[0]));
            int count =1;
             int min = list.get(0)[1];
             for(int k=1; k<list.size();k++){
                 if(min>list.get(k)[1]){
                     min = list.get(k)[1];
                     count++;
                 }
             }
            System.out.println(count);
        }
    }
}

 

가장 일반적인 풀이방법이라 생각한다.

 

 

  Comments,     Trackbacks
22-12-30 TIL

오늘 진행한 것들 🤔

  • 토이프로젝트 설계
    • 외부 API를 활용한 커뮤니티 서비스를 클론코딩 하기로 맘을 먹었다.

  • 알고리즘 문제풀이
    • 동적 계획법, 해시테이블, 깊이우선탐색 (?) 프로그래머스 / 백준 문제풀이
 

프로그래머스 마법의 엘리베이터 (자바) 풀이

문제 설명 마법의 세계에 사는 민수는 아주 높은 탑에 살고 있습니다. 탑이 너무 높아서 걸어 다니기 힘든 민수는 마법의 엘리베이터를 만들었습니다. 마법의 엘리베이터의 버튼은 특별합니다.

codinghentai.tistory.com

 

 

프로그래머스 귤 고르기 (자바) 풀이

문제 설명 경화는 과수원에서 귤을 수확했습니다. 경화는 수확한 귤 중 'k'개를 골라 상자 하나에 담아 판매하려고 합니다. 그런데 수확한 귤의 크기가 일정하지 않아 보기에 좋지 않다고 생각한

codinghentai.tistory.com

오늘의 배운 점 🤔

  • 토이프로젝트를 설계했습니다.
    • 추억을 살려서 어렸을때 많이 플레이 했었던 던전앤 파이터의 API를 활용한 프로젝트를 진행해보기로 했습니다.
    • ERD를 설계하는데 왜이렇게 테이블이 적지,, 라고 생각했던 순간 외부 API를 쓰기때문에라는 생각이 스쳐지나갔습니다....
    • 이미 만들어져있는걸 얼마나 잘 활용하느냐도 능력이라고 생각하기때문에.. 어떻게 잘 찜쪄먹을지를 많이 고민해봐야겠습니다.
    • 요즘 헤이해지고있다고 생각했었는데 새로운 시작이라고 느껴집니다.
  • 알고리즘 문제풀이
    • 동적계획법 문제를 풀이했습니다.
      • 동적계획법은 풀어도 풀어도 어떠한 조건을 설정해서 풀어나가야할지가 가장 큰 고민거리인것 같습니다..
      • 이번에도 다른 유형의 문제를 맞닥트렸을때 매번 어떻게 조건을 설정할지를 못정해서 틀리기 일수였습니다.
      • 문제를 풀때 마음을 급하게 먹지 말아야하는데.. 그게 잘안되는것 같습니다 ㅜ.ㅠ
    • 프로그래머스 2레벨 문제를 풀이했습니다.
      • 처음으로 2레벨 문제들을 풀이를 안보고 풀어보았습니다..
      • 확실히 실력이 늘고있긴 한가봅니다.
      • 마찬가지로 여러 유형중에 학습하지 못했던 알고리즘문제들은 도전조차 못해보는게 아까웠습니다.
      • 이제 새로 프로젝트도 시작했으니 진짜 하루에 2문제만 풀어보아야겠습니다.
  Comments,     Trackbacks
프로그래머스 마법의 엘리베이터 (자바) 풀이

문제 설명

마법의 세계에 사는 민수는 아주 높은 탑에 살고 있습니다. 탑이 너무 높아서 걸어 다니기 힘든 민수는 마법의 엘리베이터를 만들었습니다. 마법의 엘리베이터의 버튼은 특별합니다. 마법의 엘리베이터에는 -1, +1, -10, +10, -100, +100 등과 같이 절댓값이 10c (c ≥ 0 인 정수) 형태인 정수들이 적힌 버튼이 있습니다. 마법의 엘리베이터의 버튼을 누르면 현재 층 수에 버튼에 적혀 있는 값을 더한 층으로 이동하게 됩니다. 단, 엘리베이터가 위치해 있는 층과 버튼의 값을 더한 결과가 0보다 작으면 엘리베이터는 움직이지 않습니다. 민수의 세계에서는 0층이 가장 아래층이며 엘리베이터는 현재 민수가 있는 층에 있습니다.

마법의 엘리베이터를 움직이기 위해서 버튼 한 번당 마법의 돌 한 개를 사용하게 됩니다.예를 들어, 16층에 있는 민수가 0층으로 가려면 -1이 적힌 버튼을 6번, -10이 적힌 버튼을 1번 눌러 마법의 돌 7개를 소모하여 0층으로 갈 수 있습니다. 하지만, +1이 적힌 버튼을 4번, -10이 적힌 버튼 2번을 누르면 마법의 돌 6개를 소모하여 0층으로 갈 수 있습니다.

마법의 돌을 아끼기 위해 민수는 항상 최소한의 버튼을 눌러서 이동하려고 합니다. 민수가 어떤 층에서 엘리베이터를 타고 0층으로 내려가는데 필요한 마법의 돌의 최소 개수를 알고 싶습니다. 민수와 마법의 엘리베이터가 있는 층을 나타내는 정수 storey 가 주어졌을 때, 0층으로 가기 위해 필요한 마법의 돌의 최소값을 return 하도록 solution 함수를 완성하세요.


제한사항
  • 1 ≤ storey ≤ 100,000,000

입출력 예storeyresult
16 6
2554 16

입출력 예 설명

입출력 예 #1

  • 문제 예시와 같습니다.

입출력 예 #2

  • -1, +100이 적힌 버튼을 4번, +10이 적힌 버튼을 5번, -1000이 적힌 버튼을 3번 누르면 0층에 도착 할 수 있습니다. 그러므로 16을 return 합니다.

 

풀이

해당 문제는 반례가 존재한다.

만약에 수가 555, 85 같은 경우에

일반적이라면 85-5, 80+20, 100-100

해서 8번이 걸릴수도 있겠다고 생각할 수 있지만

85+5,90+10,100-100 을 하면 7번인것처럼 예외도 생각해주어야한다.

 

따라서 조건문으로 해당 자릿수가 첫번째 자리가 아니고 해당 자리수의 숫자가 5이고 그 이전 자릿수의 숫자가 5보다 크거나 같다면 뺴주는게 아니라 숫자를 더해주는게 나을것이다.

 

    public static int solution(int storey) {
        int answer = 0;
        List<Integer> arr = Arrays.stream(String.valueOf(storey).split("")).map(Integer::parseInt).collect(Collectors.toList());
        int len = String.valueOf(storey).length();
        for (int i = len - 1; 0 <= i; i--) {
            int a = arr.get(i);
            if (5 < a) {
                if (i > 0) {
                    answer += 10 - a;
                    arr.set(i - 1, arr.get(i - 1) + 1);
                } else {
                    answer += 11 - a;
                }
            } else if (i > 0 && a == 5 && arr.get(i - 1) >= 5) {
                answer += 5;
                arr.set(i - 1, arr.get(i - 1) + 1);
            } else {
                answer += a;
            }
        }
        return answer;
    }

 

 

  Comments,     Trackbacks