TIL&WIL
2023-06-20 TIL (Spring, 알고리즘 문풀)
blues_jun
2023. 6. 20. 21:19
오늘 학습한 내용
- Spring (Spring Security, Validation)
- 알고리즘 문풀
문제상황
오늘 문제를 겪고 해결까지 했던 문제는
'교점에 별 만들기'이다.
프로그래머스 Lv.2에 있는 문제기 때문에 매우 어려웠고 여러번의 실패를 겪었다.
https://school.programmers.co.kr/learn/courses/30/lessons/87377
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
시도한 내용
우선 다음과 같이 문제 풀이를 구상하는데 긴 시간을 투자했다. 구상은 노트에 끄적이면서 했다.
구상했던 내용은 다음과 같다.
- 이중 for문을 사용하여 각 교점들의 좌표를 구한다.
for(int i=0; i<line.length-1; i++) {
for(int j=i; j<line.length; j++) {
if(!Arrays.equals(operate(line[i], line[j]), defaultArr)) {
long[] intArr = operate(line[i], line[j]);
list.add(new Coordinate(intArr[0], intArr[1]));
}
}
}
- 교점들의 좌표를 담을 수 있는 리스트를 만들기 위해 좌표를 저장하는 클래스를 만든다.
// 좌표를 담는 객체를 위한 클래스
class Coordinate {
private long x;
private long y;
public Coordinate(long x, long y) {
this.x = x;
this.y = y;
}
public long getX() {
return x;
}
public long getY() {
return y;
}
- 리스트를 생성한 뒤 각각의 좌표를 담는다.
- 그 후 새로운 배열을 만들어서 모든 원소에 .을 찍고, 리스트에 속한 좌표만 *을 찍는다.
- 각 row를 join을 사용하여 문자열로 바꾼 뒤 return한다.
문제를 해결하면서 겪었던 문제들을 나열하면
- 주어진 배열의 원소를 계산할 때 int의 범위를 넘어갈 수 있다. ( Integer Overflow 발생)
- 배열의 길이는 int형만 가능하다.
해결
해결한 코드는 다음과 같다.
import java.util.*;
class Solution {
public String[] solution(int[][] line) {
long[] defaultArr = {1001, 1001};
List<Coordinate> list = new ArrayList<>();
for(int i=0; i<line.length-1; i++) {
for(int j=i; j<line.length; j++) {
if(!Arrays.equals(operate(line[i], line[j]), defaultArr)) {
long[] intArr = operate(line[i], line[j]);
list.add(new Coordinate(intArr[0], intArr[1]));
}
}
}
//최댓값 구하기
long xMax = list.get(0).getX(), yMax = list.get(0).getY();
for(int i=0; i<list.size(); i++) {
if(xMax<list.get(i).getX()) {
xMax = list.get(i).getX();
}
if(yMax<list.get(i).getY()) {
yMax = list.get(i).getY();
}
}
//최솟값 구하기
long xMin = list.get(0).getX(), yMin = list.get(0).getY();
for(int i=0; i<list.size(); i++) {
if(xMin > list.get(i).getX()) {
xMin = list.get(i).getX();
}
if(yMin > list.get(i).getY()) {
yMin = list.get(i).getY();
}
}
//맞는 배열의 크기를 구하고
String[][] answer = new String[(int)(yMax-yMin)+1][(int)(xMax-xMin)+1];
for (String[] strings : answer) {
Arrays.fill(strings, ".");
}
// 교점이 있는 부분만 *로 바꾼다.
long a = -yMin;
long b = -xMin;
for (Coordinate coordinate : list) {
answer[(int)(coordinate.getY() + a)][(int)(coordinate.getX() + b)] = "*";
}
String[] answerArr = new String[answer.length];
for (int i = 0; i < answerArr.length; i++) {
answerArr[i] = String.join("",answer[i]);
}
String[] realAnswer = new String[answerArr.length];
for(int i = 0; i < realAnswer.length; i++) {
realAnswer[i] = answerArr[answerArr.length-1-i];
}
// System.out.println(Arrays.toString(realAnswer));
return realAnswer;
}
// 교점을 계산하는 메소드
private static long[] operate(int[] arr, int[] arr2) {
long[] result = {1001, 1001};
long a = (long)arr[1]*(long)arr2[2] - (long)arr[2]*(long)arr2[1]; //BF-ED
long b = (long)arr[2]*(long)arr2[0] - (long)arr[0]*(long)arr2[2]; //EC-AF
long c = (long)arr[0]*(long)arr2[1] - (long)arr[1]*(long)arr2[0]; //AD-BC
if( c != 0 && a % c == 0 && b % c == 0 ) {
result[0] = (a / c);
result[1] = (b / c);
return result;
}
return result;
}
}
// 좌표를 담는 객체를 위한 클래스
class Coordinate {
private long x;
private long y;
public Coordinate(long x, long y) {
this.x = x;
this.y = y;
}
public long getX() {
return x;
}
public long getY() {
return y;
}
}
알게된 내용
- 알고리즘 문제를 해결할 때는 항상 Overflow를 조심하자.
- 배열의 길이를 나타낼때는 int만 사용하자.
- 기본적인 형식을 담는 것이 생각나지 않을 때에는 객체를 생성하는 방향도 고려해보자.