Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1-SunYerim #5

Merged
merged 1 commit into from
Mar 23, 2024
Merged

1-SunYerim #5

merged 1 commit into from
Mar 23, 2024

Conversation

SunYerim
Copy link
Member

@SunYerim SunYerim commented Mar 18, 2024

BOJ17140. 이차원 배열과 연산

🔗 문제 링크

https://www.acmicpc.net/problem/17140

✔️ 소요된 시간

50분-1시간

✨ 수도 코드

1. 풀이 과정

해당 문제는 특정 알고리즘 적용이 필요하지 않은 구현 문제였습니다. 문제에서 요구하는 그대로 코드를 작성하면 됐었는데, 코드 구조와 같이 설명을 적어보겠습니다.

문제 코드를 크게 4가지 부분으로 쪼개어 볼 수 있을 것 같습니다.

1. solution()

private static int solution() {
        for (int time = 0; time <= 100; time++) {
            if (map2[r][c] == k) {
                return time;
            }
            calculate();
        }
        return -1;

    }
  • [r][c]에 들어있는 값이 k가 되었을때, 최소시간을 출력하도록 하였고, 100초가 넘어도 k가 되지 않으면 -1을 출력. 그리고 그 외 조건에 부합한다면 calculate() 메서드가 실행되도록 하였습니다.

2. calculate()

private static void calculate() {
        // 여기서 R연산과 C연산 기준을 나눈다.
        if (xLength >= yLength) {
            for (int i = 1; i <= xLength; i++) {
                calculateR(i);
            }
        } else {
            for (int i = 1; i <= yLength; i++) {
                calculateC(i);
            }
        }
    }
  • calculate() 메서드는 행 길이와 열 길이를 판단하여 기준에 따라 R연산과 C연산을 실행시켜주었습니다.
  • R연산은 행 개수 >= 열 개수, C연산은 행 개수 < 열 개수 일때 실행이 됩니다.

R연산과 L연산은 로직은 행을 대상으로 하느냐, 열을 대상으로 하느냐의 차이만 있기때문에 묶어서 설명해볼게요 -!

  • 숫자들의 갯수를 세아려서 Map<number, count>에 저장해주었습니다.
  • 우선순위를 적용한 Node클래스에 넣어 PriorityQueue에 넣어주었습니다.
  • PriorityQueue에서 순서대로 값을 꺼내 배열을 다시 갱신해주고 해당되지 않는 배열들은 0으로 초기화해주었습니다.

3. R연산

private static void calculateR(int num) {
        // 각 숫자들이 몇 번 나왔는지 갯수를 구해서 map에 담았다가 priorityqueue로 옮겨 정렬 기준에 맞춰 정렬
        PriorityQueue<Node> queue = new PriorityQueue<>();
        Map<Integer, Integer> map = new HashMap<>();

        // 행
        for (int i = 1; i <= yLength; i++) {
            if (map2[num][i] == 0) continue; // 0이면 무시하고
            map.compute(map2[num][i], (number, count) -> count == null ? 1 : count+1);
        }
        map.forEach((k, v) -> queue.add(new Node(k, v)));

        int i = 1;
        while (!queue.isEmpty()) {
            Node node = queue.poll();
            map2[num][i++] = node.number;
            map2[num][i++] = node.count;
        }

        yLength = Math.max(yLength, i);

        // 돌려놓기
        while (i <= 99) {
            map2[num][i++] = 0;
            map2[num][i++] = 0;
        }

    }

4. L연산

private static void calculateC(int num) {
        PriorityQueue<Node> queue = new PriorityQueue<>();
        Map<Integer, Integer> map = new HashMap<>(); // <number, count>

        for (int i = 1; i <= yLength; i++) {
            if (map2[i][num] == 0) continue;
            map.compute(map2[i][num], (number, count) -> count == null ? 1 : count+1);
        }

        map.forEach((k, v) -> queue.add(new Node(k, v)));

        int i = 1;
        while (!queue.isEmpty()) {
            Node node = queue.poll();
            map2[i++][num] = node.number;
            map2[i++][num] = node.count;
        }

        xLength = Math.max(xLength, i);

        // 돌려놓기
        while (i <= 99) {
            map2[i++][num] = 0;
            map2[i++][num] = 0;
        }
    }

Node 클래스

static class Node implements Comparable<Node>{
        private int number, count;
        public Node(int number, int count) {
            this.number = number;
            this.count = count;
        }

        @Override
        public int compareTo(Node o) {
            // 커지는 순으로 정렬
            if (this.count == o.count) {
                return this.number - o.number;
            }
            return this.count - o.count;
        }
    }
  • Node 클래스를 구현하여, 우선순위 큐에 넣을 때 문제에서 요구하는 정렬 조건에 맞춰지도록 하였습니다.

📚 새롭게 알게된 내용

문제 풀면서 map interface의 메서드에 대해 다시 공부할 수 있었습니다.
https://codingnojam.tistory.com/39

p.s. 이렇게 자세하게 글로 적으면서 푼 문제를 복기해본 적은 거의 없었던 것 같은데 혹시 좀 부족한 내용이나 이해가 힘든 부분이 있으면 마구마구 적어주세요 ~ 🙃🙂
그리고 항상 문제 풀 때마다 느끼는 거지만, 변수명을 뭐로 해야할지 생각해내는 게 쉽지않네요 ...

BOJ17140. 이차원 배열과 연산
@9kyo-hwang
Copy link
Contributor

선생님 하이퍼링크 2개 다 이상한 링크 걸려있는 것 같아요
image

@SunYerim
Copy link
Member Author

오마이갓 .. 다시 확인하고 오겠습니다

Copy link
Collaborator

@wjdheesp44 wjdheesp44 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우선순위 큐를 써서 이런 식으로 할 수 있군요!
저는 풀다가 A[r][c] == k가 맞는지 체크할 때, 예외 처리를 제대로 안 해서 헤맸습니다..
고생하셨습니다!

SunYerim/구현/BOJ17140.java Show resolved Hide resolved
@9kyo-hwang
Copy link
Contributor

허허 C++로 풀다가 화딱지나서 파이썬으로 바꿨네요...
�연산 한 번 할 때마다 새로운 리스트를 만들어서 갱신하는 식으로 해도 여유롭게 통과하네요.

input = open(0).readline

r, c, k = map(int, input().split())
r, c = r - 1, c - 1
A = [list(map(int, input().split())) for _ in range(3)]


def calculation(lst, d):
    sorted_list = []  # 연산이 완료된 새로운 리스트
    max_len = 0  # 가장 긴 행/열 길이를 기록하는 변수
    
    for row in lst:
        cnts = {col : row.count(col) for col in row if col != 0}  # 각 원소 별 개수 딕셔너리
        cnts_list = sorted(cnts.items(), key=lambda x: (x[1], x[0]))  # 원소 개수 -> 원소 크기 순으로 정렬
        flatten = [item for items in cnts_list for item in items]  # 원소, 원소 개수, ... 식으로 평탄화
        sorted_list.append(flatten)
        max_len = max(max_len, len(flatten))
    
    for row in sorted_list:  # 0 덧붙이는 과정
        row += [0] * (max_len - len(row))
        row = row[:100]
        
    return sorted_list if d == 'r' else list(zip(*sorted_list))  # 'r' 연산이면 그대로 반환, 'c' 연산이면 전치시켜서 반환
    

ans = -1
for tick in range(0, 101):
    if r < len(A) and c < len(A[0]):
        if A[r][c] == k:
            ans = tick
            break
    
    if len(A) >= len(A[0]):
        A = calculation(A, "r")
    else:
        A = calculation(list(zip(*A)), "c")  # 'c' 연산의 경우 전치시킨 리스트를 넘김
        
print(ans)

파이썬엔 약간의 트릭으로 전치시킬 수 있어서 편하게 했네요...

@erase-jeong
Copy link
Collaborator

자바를 안한지 오래되서그런지 코드 이해하는데 시간이 걸렸던 것 같습니다. 고생하셨습니다!

Copy link
Collaborator

@erase-jeong erase-jeong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

자바를 안한지 오래되서그런지 코드 이해하는데 시간이 걸렸던 것 같습니다. 고생하셨습니다!

PriorityQueue<Node> queue = new PriorityQueue<>();
Map<Integer, Integer> map = new HashMap<>(); // <number, count>

for (int i = 1; i <= yLength; i++) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for (int i = 1; i <= xLength; i++)

범위가 잘못된것 같은데 그래도 예제는 잘 돌아가네요
코드 다 봤는데 잘 짜신것같아요.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

엇 감사합니다 한 번 확인해볼게요 !!!

@SunYerim SunYerim merged commit 0de8509 into main Mar 23, 2024
1 check passed
@SunYerim SunYerim deleted the 1-SunYerim branch March 23, 2024 10:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants