행렬과 연산
문제 풀이 시간 : 1시간
문제 요약
- 주어진 행렬
rc에 대해 두 가지 연산을 수행해야 한다. - 여러 번의 연산을 순서대로 수행한 후의 행렬을 반환해야 한다.
- 시간 효율을 고려해야 함 — 단순 배열 기반으로 회전시키면 시간초과 발생
문제 풀이
이 문제는 처음보자마자 배열로 행렬을 만들어서 하면 절대 안될거라고 생각했다.
그래서 생각한게 Deque를 사용해서 계산하면 앞뒤로 넣고, 뺄 수 있으니 더 빠르게 계산이 가능할 것이라고 생각했다.
그래서 처음에는 단순하게 ArrayList<ArrayDeque> 를 이용해 각 행을 deque로 저장하고, Rotate 연산 시 두 번의 for문으로 직접 앞뒤 원소를 하나씩 밀고 당기는 방식을 사용했다.
for(int j=0;j<r;j++){
if(j!=0)
a.get(j).removeFirst();
if(j==r-1)
break;
a.get(j).addFirst(a.get(j+1).getFirst());
}
for(int j=r-1;j>=0;j--){
if(j!=r-1)
a.get(j).removeLast();
if(j==0)
break;
a.get(j).addLast(a.get(j-1).getLast());
}하지만 이렇게 하면 각 회전마다 의 시간이 들고,
연산 수가 많을 때 시간초과가 발생한다.
실패 코드
핵심 아이디어
이 문제는 “행렬의 전체를 움직이지 않고, 경계선만 빠르게 회전시킬 수 있느냐”가 포인트다.
그래서 행렬을 세 부분으로 분리했다.
[왼쪽 열] [가운데 중간 행들] [오른쪽 열]이렇게 세 부분을 각각 Deque으로 관리하면 다음과 같은 장점이 생긴다.
ShiftRow→ 세 deque 각각을 맨 앞/뒤에서 한 칸씩 옮기면 끝 ()Rotate→ 경계 네 구역만 한 칸씩 옮기면 끝 ()
즉, 한 번의 연산을 상수 시간에 처리할 수 있다.
세부 구현
- 분리
- ShiftRow 연산
- Rotate 연산
- 결과 조립
최종 코드
import java.util.*;
class Solution {
public int[][] solution(int[][] rc, String[] operations) {
int r = rc.length;
int c = rc[0].length;
int[][] answer = new int[r][c];
ArrayDeque<Integer> left = new ArrayDeque<>();
ArrayDeque<Integer> right = new ArrayDeque<>();
ArrayDeque<ArrayDeque<Integer>> middle = new ArrayDeque<>();
for(int i=0;i<r;i++){
left.add(rc[i][0]);
right.add(rc[i][c-1]);
ArrayDeque<Integer> mid = new ArrayDeque<>();
for(int j=1;j<c-1;j++){
mid.add(rc[i][j]);
}
middle.add(mid);
}
for(int i=0;i<operations.length;i++){
String op = operations[i];
if(op.equals("Rotate")){
middle.getFirst().addFirst(left.removeFirst());
right.addFirst(middle.getFirst().removeLast());
middle.getLast().addLast(right.removeLast());
left.addLast(middle.getLast().removeFirst());
}
else{
left.addFirst(left.removeLast());
middle.addFirst(middle.removeLast());
right.addFirst(right.removeLast());
}
}
for(int i=0;i<r;i++){
answer[i][0] = left.removeFirst();
int idx = 1;
for(int val : middle.removeFirst()){
answer[i][idx++] = val;
}
answer[i][c-1] = right.removeFirst();
}
return answer;
}
}함께 읽으면 좋은 글
택배상자
order 배열은 택배 기사님이 원하는 상자 적재 순서다 기존 컨테이너 벨트는 1번부터 순서대로만 꺼낼 수 있다 보조 벨트는 스택처럼 마지막에 넣은 것부터 꺼낼 수 있다 원하는 순서대로 최대한 실을 수 있는 상자 개수를 구하는 문제다 처음에는 기존 벨트를 실제 리스트로 만들어…
롤케이크 자르기
topping 배열은 롤케이크에 일렬로 올라간 토핑 번호다 한 지점을 잘라 두 조각으로 나눴을 때, 양쪽 토핑 종류 수가 같아야 공평하게 나눈 것이다 공평하게 자를 수 있는 방법의 수를 구하는 문제다 처음에는 자르는 위치마다 왼쪽과 오른쪽 배열을 나눠서 각각 서로 다른 토핑…
할인 행사
want, number 배열로 정현이가 원하는 제품과 수량을 표현한다 discount 배열은 XYZ 마트가 매일 할인하는 제품 목록이다 연속된 10일 동안 할인 제품 종류와 수량이 want, number와 정확히 일치해야 회원가입할 수 있다 그런 시작일이 총 몇 번 있는지…
숫자 변환하기
자연수 x를 y로 바꾸는 데 x+n, x2, x3 세 가지 연산을 쓸 수 있다 x를 y로 바꾸는 최소 연산 횟수를 구하는 문제다 만들 수 없으면 -1을 반환한다 처음에는 x에서 시작해서 세 가지 연산을 재귀적으로 다 시도해보고 y에 도달하는 경로 중 가장 짧은 걸 고르면…