728x90

최솟값 만들기

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

스크린샷 2022-09-22 오후 5 55 22


문제 설명

길이가 같은 배열 A, B 두개가 있습니다. 각 배열은 자연수로 이루어져 있습니다.
배열 A, B에서 각각 한 개의 숫자를 뽑아 두 수를 곱합니다. 이러한 과정을 배열의 길이만큼 반복하며, 두 수를 곱한 값을 누적하여 더합니다. 이때 최종적으로 누적된 값이 최소가 되도록 만드는 것이 목표입니다. (단, 각 배열에서 k번째 숫자를 뽑았다면 다음에 k번째 숫자는 다시 뽑을 수 없습니다.)

예를 들어 A = [1, 4, 2] , B = [5, 4, 4] 라면

  • A에서 첫번째첫 번째 숫자인 1, B에서 첫 번째 숫자인 5를 뽑아 곱하여 더합니다. (누적된 값 : 0 + 5(1x5) = 5)
  • A에서 두번째 숫자인 4, B에서 세 번째 숫자인 4를 뽑아 곱하여 더합니다. (누적된 값 : 5 + 16(4x4) = 21)
  • A에서 세번째 숫자인 2, B에서 두 번째 숫자인 4를 뽑아 곱하여 더합니다. (누적된 값 : 21 + 8(2x4) = 29)

즉, 이 경우가 최소가 되므로 29를 return 합니다.

배열 A, B가 주어질 때 최종적으로 누적된 최솟값을 return 하는 solution 함수를 완성해 주세요.


제한사항

  • 배열 A, B의 크기 : 1,000 이하의 자연수
  • 배열 A, B의 원소의 크기 : 1,000 이하의 자연수

입출력 예

A B answer
[1, 4, 2] [5, 4, 4] 29
[1,2] [3,4] 10

풀이

길이가 같은 두개의 배열이 주어지고 두 배열의 원소를 서로 곱해서 answer이라는 변수에 누적 저장해서 answer 값이 최소가 되는 값을 구하면 되는 문제이다. A, B를 오름차순으로 정렬하면 A는 1, 2, 4가 되고 B는 4, 4, 5가 된다. A에서 오름차순으로 선택하면 1 B에서 큰 수부터 선택하면 5 두 수를 곱해주면 0 + ( 1 * 5 ) = 5 -> 5 + ( 2 * 4) = 13 -> 13 + (4 * 4) = 29가 된다.


코드

import java.util.*;
class Solution
{
    public int solution(int []A, int []B)
    {
        int answer = 0;
        Arrays.sort(A);  // 두 배열을 정렬 해준다.
        Arrays.sort(B);

        for(int i = 0; i < A.length; i++) {
            answer = answer + (A[i] * B[A.length - 1 - i]);  // a는 오름차순으로 선택하고 b는 큰 수 부터 선택헤서 곱해준다.
        }
        return answer;
    }
}

JadenCase 문자열 만들기

(문제 설명 혹은 링크)
https://school.programmers.co.kr/learn/courses/30/lessons/12951

스크린샷 2022-09-23 오후 4 28 38


문제 설명

JadenCase란 모든 단어의 첫 문자가 대문자이고, 그 외의 알파벳은 소문자인 문자열입니다. 단, 첫 문자가 알파벳이 아닐 때에는 이어지는 알파벳은 소문자로 쓰면 됩니다. (첫 번째 입출력 예 참고)
문자열 s가 주어졌을 때, s를 JadenCase로 바꾼 문자열을 리턴하는 함수, solution을 완성해주세요.


제한 조건

  • s는 길이 1 이상 200 이하인 문자열입니다.
  • s는 알파벳과 숫자, 공백문자(" ")로 이루어져 있습니다.
    • 숫자는 단어의 첫 문자로만 나옵니다.
    • 숫자로만 이루어진 단어는 없습니다.
    • 공백 문자가 연속해서 나올 수 있습니다.

입출력 예

s return
"3people unFollowed me" "3people Unfollowed Me"
"for the last week" "For The Last Week"

풀이

이 문제를 봤을 때 비교적 간단한 문제라고 생각하고 풀었습니다. 하지만 문제를 제대로 읽지 않은 탓에 엄청 헤맸습니다. 우선 공백 문자를 보자마자 String []str = s.split(" "); 으로 잘랐습니다. 잘못된 풀이로 풀었을 때 substring(0, 1)을 이용해서 첫 번째 문자를 구하고 toUpperCase()를 이용해 첫 번째 문자를 대문자로 변환해 주었습니다. 또한 substring(1, str[i].length()).toLowerCase()를 이용해서 첫 번째 문자를 제외하고 변환하여 더하였습니다. 하지만 answer를 더해주는 과정에서 마지막 문자열에 공백 문자가 포함됩니다. 따라서 원래 문자열 마지막이 공백일 경우와 아닐 경우에 대한 코드를 작성하였습니다. 하지만 제한 조건에 공백 문자가 연속해서 나올 수 있다는 것을 보고 다시 문제를 풀었습니다. 모든 문자열 소문자로 변경하고 첫 번째 글자인지 판단하는 boolean 변수를 추가해 주었습니다. 문자열만큼 반복해서 for문을 수행하고 만약 공백이 나오면 isFirst를 true로 변경하고 아니면 false를 수행한다. 만약 isFirst가 true일 경우 대문자로 변경한다.


잘못된 코드

public class JadenCase {
    public static void main(String[] args) {
        String s = "for the last week ";
        String []str = s.split(" "); // 공백을 기준으로 문자열 자르기
        String answer = "";

        // 공백을 기준으로 잘려진 문자열의 수만큼 반복
        for(int i = 0; i < str.length; i++) {
            if(str.length == 0) {
                answer += " ";
            }
            else {
                answer += str[i].substring(0, 1).toUpperCase(); // 단어 첫번째 대문자로 변환하여 더하기
                answer += str[i].substring(1, str[i].length()).toLowerCase(); // 첫글자를 제외하고 소문자로 변환하여 더하기
                answer += " "; // 띄어쓰기
            }
        }
        //원래 문자열 마지막이 공백일 경우 그대로 answer 반환
                if(s.substring(s.length() -1, s.length()).equals(" ")) {
               System.out.println(answer);
                }
                //마지막에 공백이 더해져서 그 공백을 제외한 answer값 반환
                else {
              answer = answer.substring(0, answer.length() - 1);
              System.out.println(answer);
                }
    }
}

정확한 코드

class Solution {
    public String solution(String s) {
        String answer = "";
         // 모든 문자열 소문자로 변경
        String[] srr = s.toLowerCase().split("");

        boolean isFirst = true; // 첫번째 글자인지 판단 
        // 문자열 만큼 반복
        for(int i = 0; i < srr.length; i++) {
            // 첫 글자일 경우 대문자로 변경
            if(isFirst) {
                answer += srr[i].toUpperCase(); 
            }
            else {
                answer += srr[i];
            }
            // 공백이 나오면 첫 글자 true로 변경
            if(srr[i].equals(" ")) {
                isFirst = true;
            }
            else {
                isFirst = false;
            } 
        }
        return answer;
    }
}

 

728x90

'알고리즘 > 알고리즘 문제풀이' 카테고리의 다른 글

LeetCode Valid Parentheses, Merge Two Sorted Lists  (0) 2022.10.03
백준) DP, DFS  (0) 2022.08.27
백준) HashMap  (0) 2022.07.23
백준) BFS, 다익스트라  (0) 2022.07.19
백준) 우선순위 큐, DP  (0) 2022.07.18
728x90

수익 4097번


내가 떠올린 풀이 해설

입력이 많지 않아 BufferedReader보단 Scanner를 사용했습니다. 처음 코드를 작성했을 때 max 값을 0으로 선언을 해주었지만 입력값이 음수일 경우 max 값을 구할 때 max 값이 0이 되므로 max 값을 Integer.MIN_VALUE로 선언해 주어야 합니다. 총수입을 담을 sum 변수를 만들었습니다. 입력의 마지막은 0으로 구분해서 입력 n이 0이면 break 하고 0이 아니면 for 문으로 n 미만까지 for 문을 수행한다. for 문에는 입력 값을 담을 num을 선언해 주었고 입력받은 값을 sum에 누적해서 더합니다. Math.max를 이용해 max와 sum을 비교해 큰 값을 max에 담았습니다. sum의 값이 음수가 되면 sum 값을 0으로 다시 초기화하였습니다.


정확한 풀이

import java.util.*;
public class Baek4097 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while(true) {
			int n = sc.nextInt();
			int max = Integer.MIN_VALUE; 
			int sum = 0;
			if(n == 0) {
				break;
			}
			else {
				for(int i = 0; i < n; i++) {
					int num = sc.nextInt();
					sum += num;                // -3, 1, 10, 8, 3, 11
					max = Math.max(max, sum);  // 0, 1, 10, 10, 10, 11
					if(sum < 0) {
						sum = 0;
					}
				}
				System.out.println(max);
			}
		}
	}
}

풀이 2

문제 분류가 다이나믹 프로그래밍이어서 DP로 풀어보려 했는데 방법이 떠오르지 않아 DP를 이용해서 푼 풀이를 가져왔습니다. 위의 코드와 차이점은 배열을 이용해서 현재 i의 값과 직전 값과 현재 i의 값을 더한 게 더 클 때 arr[i]의 값을 직전 값과 현재 i의 값으로 바꿔주는 것입니다. DP의 메모리제이션을 이용해서 해결한 것 같습니다.
https://velog.io/@pss407/%EB%B0%B1%EC%A4%804097-%EC%88%98%EC%9D%B5

 

[백준]#4097 수익

문제연종이는 창업했다. 오늘은 창업한지 N일이 되었고, 매일 매일 수익을 적어놓았다.어느 날 연종이는 가장 많이 돈을 번 구간이 언제인지 궁금해졌다.오늘이 창업한지 6일 되었고, 수익이 다

velog.io


정확한 풀이

import java.util.*;

public class Baek4097 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while(true) {
			int n = sc.nextInt();
			int max = Integer.MIN_VALUE;
			int sum = 0;
			int[] arr = new int[n];
			if(n == 0) {
				break;
			}
			else {
				for(int i = 0; i < n; i++) {
				        int x = sc.nextInt();
	                                arr[i] = x;
                                        if(i > 0) {
	                                       int y = arr[i-1];
                                               if(x + y > x) {   //직전 값과 현재 i의 값을 더한게 더 클 때
	                                          arr[i] = x + y;
                                               }
	                                 }
	                         }
	                         max = Math.max(max, arr[i]);
			}
			System.out.println(max);
		}
	}
}

단지 번호 붙이기 2667번


내가 떠올린 풀이 해설

상하좌우를 탐색할 int 배열 dx, dy를 선언합니다. 지도 크기를 입력받을 n, 2차원 배열의 map, DFS의 visit 배열, 총 단지 수를 구하기 위한 total, 각 단지에 속하는 집의 수를 구하기 위해 cnt를 선언해 주었습니다. BufferedReader를 이용해 입력을 받았습니다. map의 입력은 split를 이용해 잘라서 map의 2차원 배열에 넣어 주었습니다.(split("")[i]의 참고 자료: https://crazykim2.tistory.com/549) 전체 map을 탐색하기 위해 이중 for 문을 이용하였고 map의 (i, j)가 1이고 방문하지 않았다면 총 단지 수와 cnt의 수를 늘려주고 DFS를 호출합니다. DFS에서는 상하좌우 탐색을 진행하면서 cnt를 늘려줍니다. 마지막으로 cnt의 값을 List에 담아줍니다. 각 단지 내 집의 수를 오름차순으로 정렬하여 출력해 주어야 하므로 Collections.sort()를 이용해 정렬하였습니다.


정확한 풀이

import java.util.*;
import java.io.*;
public class Baek2667 {
	static int[] dx = {1, 0 ,0, -1};
	static int[] dy = {0, 1, -1, 0};
	static int n; // 지도 크기 
	static int[][] map;
	static boolean[][] visit;
	static int total = 0;  // 총 단지 수 
	static int cnt;
	static List<Integer> cnts = new ArrayList<>(); // 각 단지에 속하는 집의 수 
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		n = Integer.parseInt(br.readLine());
		map = new int[n][n];
		visit = new boolean[n][n];
		
		String str;
		for(int i = 0; i < n; i++) {
			str = br.readLine();
			for(int j = 0; j < n; j++) {
				map[i][j] = Integer.parseInt(str.split("")[j]);
			}
		}
		for(int i = 0; i < n; i++) {
			for(int j = 0; j < n; j++) {
				cnt = 0;
				if(map[i][j] == 1 && !visit[i][j]) {
					total++;
					cnt++;
					dfs(i, j);
					cnts.add(cnt);
				}
			}
		}
		System.out.println(total);
		Collections.sort(cnts);
		for(int i = 0; i < cnts.size(); i++) {
			System.out.println(cnts.get(i));
		}
	}

	private static void dfs(int i, int j) {
		visit[i][j] = true;
		for(int k = 0; k < 4; k++) {
			int nx = dx[k] + i;
			int ny = dy[k] + j;
			if(nx >= 0 && nx < n && ny >= 0 && ny < n) {
				if(!visit[nx][ny] && map[nx][ny] == 1) {
					cnt++;
					dfs(nx, ny);
				}
			}
		}
	}
}

오늘의 회고

요즘 스터디와 공모전으로 너무 바빠서 코딩 테스트 문제를 풀지 못했더니 많이 까먹은 것 같습니다. 이제 곧 하반기 채용 시작인데 다시 코딩 테스트 공부를 좀 해야겠습니다. 알고리즘 너무 어려워 이번에 알고리즘 스터디에 참여하게 되었는데 다들 실력이 좋으셔서 놀랐습니다. 분발하자

728x90
728x90

영속 단위 기준으로 초기화

EntitiyManagerFactory emf = Persistence.createEntityManagerFactory("jpabegin");

persistence.xml 파일에 정의한 영속 단위 기준으로 초기화

필요한 자원 생성

emf.close();

팩토리 닫음

사용한 자원 반환

EntityManager로 DB 연동

EntityManager entityManager = emf.createEntityManager(); //EntityManager 생성
EntityTransaction transaction = entityManager.getTransaction(); //EntityTransaction 구함
try {
	transaction.begin();  // 트렌젝션 시작
	...entityManager로 DB 작업
	transaction.commit(); // 트렌젝션 커밋
} catch (Exception ex) {
	transaction.rollback(); // 트렌젝션 롤백
} finally {
	entityManager.close(); // 엔티티매니저 닫음
}

저장과 쿼리 실행 시점

transaction.begin();
User user = new User("user@user.com", "user", LocalDateTime.now());
entityManager.persist(user);
log.info("EntityManager.persist 호출함");
transaction.commit();
log.info("EntityTransaction.commit 호출함");

persist때 insert쿼리문이 실행되지 않고 commit 시점에 insert 쿼리가 실행된다.

수정도 commit 시점에 알맞게 실행된다.

영속 컨텍스트

EntityManager 단위로 영속 컨텍스트 관리

커밋 시점에 영속 컨텍스트의 변경 내역을 DB에 반영(변경 쿼리 실행)

정리

기본구조

  • EntityManagerFactory 초기화
  • DB 작업이 필요할 때마다
    • EntityManager 생성
    • EntityManager로 DB 조작
    • EntityTransactio으로 트렌젝션 관리
  • 하지만 스프링과 연동할 때는
    • 대부분 스프링이 대신 처리하므로 매핑 설정 중심으로 작업

영속성 컨텍스트

  • 엔티티를 메모리에 보관
  • 변경을 추적해서 트렌젝션 커밋 시점에 DB에 반영

https://www.youtube.com/watch?v=7ljqL8ThUts&list=PLwouWTPuIjUi9Sih9mEci4Rqhz1VqiQXX&index=2 

엔티티 CRUD 처리

영속 컨텍스트는 트렌젝션 범위 안에서 유지가 된다.

EntityManager가 제공하는 메서드 이용

  • persist() : 저장
  • find(클래스, 식별자) : 조회
    • 엔티티 타입, ID 타입이 맞아야 함
    • 일치하지 않으면 익셉션
  • 수정 : 트렌젝션 범위 내에서 변경된 값을 자동 반영
  • remove() : 삭제, find메서드로 읽어온 객체를 전달해야 된다.
  • merge()

https://www.youtube.com/watch?v=kmCKAwOie_I&list=PLwouWTPuIjUi9Sih9mEci4Rqhz1VqiQXX&index=3 

엔티티 매핑

  1. 기본 어노테이션
    1. @Entity : 엔티티 클래스에 설정, 필수
    2. @Table : 매핑할 테이블 지정
      1. 애노테이션을 생략하면 클래스 이름과 동일한 이름에 매핑
      2. 속성
        1. name : 테이블 이름(생략 하면 클래스 이름과 동일한 이름)
        2. catalog : 카탈로그 이름 (예, MySQL DB 이름)
        3. schema : 스키마 이름 (예, 오라클 스키마 이름)
    3. @Id : 식별자 속성에 설정, 필수
    4. @Column : 매핑할 칼럼명 지정
      1. 지정하지 않으면 필드명/프로퍼티명 사용
    5. @Enumerated : enum 타입 매핑할 때 설정
      1. 설정 값
        1. EnumType.ORDINAL(기본값) : enum타입의 값의 순서를 저장
          1. 문자열 타입 칼럼에 매핑
        2. EnumType.STRING : enum 타입 값 이름을 저장
          1. 숫자 타입 칼럼에 매핑
    6. @Temporal : java.util.Date, java.util.Calender 매핑
      1. 자바 8 시간/날짜 타입 등장 이후로 거의 안 씀
    7. @Basic : 기본 지원 타입 매핑(거의 안 씀)

엔티티 클래스 제약 조건(스펙 기준)

  1. @Entity 적용해야 함
  2. @Id 적용해야 함
  3. 인자 없는 기본 생성자 필요
  4. 기본 생성자는 public이나 protected여야 함
  5. 최상의 클래스여야 함
  6. final이면 안됨

접근 타입

  1. 두 개의 접근 타입
    1. 필드 접근 : 필드 값을 사용해서 매핑
    2. 프로퍼티 접근 : getter/setter 메서드를 사용해서 매핑
  2. 설정 방법
    1. @Id 애노테이션을 필드에 붙이면 필드 접근
    2. @Id 애노테이션을 getter 메서드에 붙이면 프로퍼티 접근
    3. @Access 애노테이션을 사용해서 명시적으로 지정
      1. 클래스 / 개별 필드에 적용 가능
      2. @Access(AccessType.PROPERTY) / @Access(AccessType.FIELD)
    4. 개인적으로 필드 접근 선호
      1. 불필요한 setter 메서드를 만들 필요 없음

https://www.youtube.com/watch?v=SbMJVuv8Iyo&list=PLwouWTPuIjUi9Sih9mEci4Rqhz1VqiQXX&index=4 

 

 

728x90
728x90

이 블로그는 최범균 님의 JPA 기초 강의를 듣고 작성한 블로그입니다.

일단 해보기 (jpa 3.0 기준)

JPA 특징

  1. 애노테이션을 이용한 매핑 설정
    • xml 파일을 이용한 매핑 설정도 가능
  2. String, int, LocalDate 등 기본적인 타입에 대한 매핑 지원
  3. 커스텀 타입 변환기 지원
    • 내가 만든 Money 타입을 DB 칼럼에 매핑 가능
  4. 벨류 타입 매핑 지원
    • 한 개 이상 칼럼을 한 개 타입으로 매핑 가능
  5. 클래스 간 연간 지원 : 1 - 1, 1 - N, N - 1, N - M
  6. 상속에 대한 매핑 지원
DB USER 생성

create database jpabegin CHARACTER SET utf8mb4;

CREATE USER 'jpauser'@'localhost' IDENTIFIED BY 'jpapass';
CREATE USER 'jpauser'@'%' IDENTIFIED BY 'jpapass';

GRANT ALL PRIVILEGES ON jpabegin.* TO 'jpauser'@'localhost';
GRANT ALL PRIVILEGES ON jpabegin.* TO 'jpauser'@'%'; 
create table jpabegin.user (
	email varchar(50) not null primary key,
	name varchar(50),
	create_date datetime,
) engine innodb character set utf8mb4; 

JPA 코드

@Entity DB 테이블과 매핑할 대상
@Table(name = "user") user 테이블과 매핑
public class User {
	@Id 식별자에 대응
	private String email;
	private String name;
	@Column(name = "create_date") create_date 칼럼과 매핑 칼럼이름과 필드 이름이 다를때 사용
	private LocalDateTime createDate;

일단 해보기 정리

  1. 간단한 설정으로 클래스와 테이블 간 매핑 처리
  2. EntityManager를 이용해서 DB 연동 처리
  3. 객체 변경만으로 DB 테이블 업데이트
  4. 쿼리 작성 x

https://www.youtube.com/watch?v=Zwq2McbFOn4&list=PLwouWTPuIjUi9Sih9mEci4Rqhz1VqiQXX&index=1 

728x90
728x90

9375번 패션왕 신해빈


내가 떠올린 풀이 해설

프로그래머스 위장 문제와 동일한 문제여서 어렵지 않게 해결할 수 있었습니다. HashMap을 이용해서 의상 종류를 key값으로 넣고 value값은 숫자로 넣습니다. 만약 같은 키가 있으면 숫자를 1 늘려줍니다. 정해진 value값으로 경우의 수를 이용해서 풀었습니다.


정확한 풀이

mport java.util.*;
import java.io.*;

public class Baek9375 {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int n = Integer.parseInt(br.readLine());
		int answer = 1;
		for(int i = 0; i < n; i++) {
			HashMap<String, Integer> hash = new HashMap<>();
			answer = 1;
			int m = Integer.parseInt(br.readLine());
			for(int j = 0; j < m; j++) {
				StringTokenizer st = new StringTokenizer(br.readLine());
				String clo = st.nextToken();
				String qwe = st.nextToken();
				hash.put(qwe, hash.getOrDefault(qwe, 0) + 1);
			}
			Set<String> keySet = hash.keySet();
			for(String key : keySet) {
				answer *= hash.get(key) + 1;
			}
			System.out.println(answer - 1);
		}
	}

}
728x90
728x90

step 2 - 4. 정수 삼각형


내가 떠올린 풀이 해설

  1. DP 삼각형의 가장 왼쪽의 값 (DP[i][0])은 한 줄 위의 가장 왼쪽 값(DP[i - 1][0])에 현재 값(triangle[i][0])을 더한 값이 된다.
    DP[i][0] = DP[i-1][0] + triangle[i][0]이 됩니다.
  2. 삼각형의 가장 오른쪽의 값 (DP[i][i])은 한 줄 위의 가장 오른쪽 값(DP[i-1][i-1])에 현재 값(triangle[i][i])을 더한 값이 된다.
    DP[i][i] = DP[i-1][i-1] + triangle[i][i]이 됩니다.
  3. 삼각형의 1번과 2번을 제외한 나머지는 한줄 위의 오른쪽 값과 왼쪽 값 중 큰 값에 현재 값을 더한 값이 된다.
    DP[i][i] = Max(DP[i - 1][j - 1], DP[i - 1][j]) + triangle[i][j]가 됩니다.
  4. DP 배열에서 max 값을 출력하기 위해 answer = Math.max(answer, dp[i][j])을 해준다.

정확한 풀이

public class step2_4 {

	public static void main(String[] args) {
		int[][] tri = {{7},
				{3, 8},
				{8, 1, 0},
				{2, 7, 4, 4},
				{4, 5, 2, 6, 5}};
		int [][]dp = new int[tri.length][tri[tri.length - 1].length];
		int answer = 0;
		int max = 0;
		dp[0][0] = tri[0][0];
		for(int i = 1; i < tri.length; i++) {
			dp[i][0] = dp[i - 1][0] + tri[i][0];
			dp[i][i] = dp[i - 1][i - 1] + tri[i][i];
			for(int j = 1; j <= i - 1; j++) {
				dp[i][j] = Math.max(dp[i - 1][j - 1], dp[i - 1][j]) + tri[i][j];
				answer = Math.max(answer, dp[i][j]);
			}
		}
		System.out.println(answer);
	}
}

오늘의 회고

오늘은 DP문제와 프로그래머스 위장 문제와 유사한 문제를 백준에서 찾아서 HashMap 문제를 풀었습니다. 점화식은 도출을 해냈지만 DP 배열을 만들 생각을 하지 못하고 triangle 배열에서 점화식을 처리해주려고 했는데 생각처럼 되지 않았습니다. HashMap문제는 거의 동일해서 어렵지 않게 해결할 수 있었습니다. 알고리즘 고수가 되고 싶습니다.ㅠㅠ

728x90
728x90

step 2 - 3. 올바른 괄호의 개수


내가 떠올린 풀이 해설

괄호를 보고 stack을 이용해서 풀려고 했는데 괄호 문자를 입력으로 주지 않아 DFS의 성질을 이용해 풀었다. 올바른 괄호의 짝 중에, '('로 시작했으면 ')'로 끝나는 성질을 이용해 ')'의 개수가 '('보다 많으면 올바르지 않은 식으로 간주하고, 이 모든 경우의 수를 dfs로 찾았다.

https://tosuccess.tistory.com/173

 

[프로그래머스 level_4] 올바른 괄호의 갯수 for JAVA

programmers.co.kr/learn/courses/30/lessons/12929 코딩테스트 연습 - 올바른 괄호의 갯수 올바른 괄호란 (())나 ()와 같이 올바르게 모두 닫힌 괄호를 의미합니다. )(나 ())() 와 같은 괄호는 올바르지 않은 괄..

tosuccess.tistory.com


정확한 풀이

import java.util.*;
public class step2_3 {
	static int answer;
	public static void main(String[] args) {
		int n = 2;
		answer = 0;
		DFS(0, 0, n);
		System.out.println(answer);
	}
	private static void DFS(int left, int right, int n) {
		if(left < right) {
			return;
		}
		if(left == n && right == n) {
			answer++;
			return;
		}
		if(left > n || right > n) {
			return;
		}
		DFS(left + 1, right, n);
		DFS(left, right + 1, n);
	}
}

오늘의 회고

오늘은 프로그래머스 3주 차 문제를 풀었습니다. DFS를 이용해서 푸는 문제였다. DFS 문제라고 떠올리기는 했지만 문제를 해결하는 방법의 아이디어가 떠오르지 않았다... 좀 더 넓은 방식으로 문제를 해결해야 되는데 어떻게 공부해야 될지 잘 모르겠다.ㅠㅠ

728x90
728x90

step 2 - 2. 게임 맵 최단거리


내가 떠올린 풀이 해설

DFS로 풀어도 답이 나오는 문제인데 저는 BFS로 풀었습니다. dx, dy로 상하좌우를 탐색할 배열을 만들어 준다. 또한 visit 배열을 만들어준다. visit배열은 BFS를 탐색하면서 거리가 1씩 늘어날수록 이동한 거리를 담아 줄 배열이다. 만약 answer가 0이면 -1, 아니면 answer를 리턴해준다. BFS 메서드에서는 BFS를 이용할 Queue를 생성하고 시작점인 0,0을 배열로 Queue에 add 해준다. Queue가 빌 때까지 반복한다. for문으로 상하좌우를 탐색하면서 만약 nx, ny가 0보다 같거나 크고, nx, ny가 map길이보다 작아야 하고, maps배열의 nx, ny위치가 1이고, visit배열의 nx, ny가 0이면 visit [nx][ny]에 visit [x][y] + 1 값을 넣어준다. 그리고 Queue에 nx, ny를 add 해준다.


정확한 풀이

import java.util.*;
public class step2_2 {
    static int[] dx = {1, 0, -1, 0};
    static int[] dy = {0, -1, 0, 1};
    static int answer;
    static int[][] visit;
	public static void main(String[] args) {
		int [][]maps = {{1, 0, 1, 1, 1},
				{1, 0, 1, 0, 1},
				{1, 0, 1, 1, 1},
				{1, 1, 1, 0, 1,},
				{0, 0, 0, 0, 1}};
		answer = 0;
		int [][] visit = new int[maps.length][maps[0].length];
		visit[0][0] = 1;
		BFS(maps, visit);  
		answer = visit[maps.length - 1][maps[0].length - 1];
		if(answer == 0) {
			System.out.println(-1);
		}
		System.out.println(answer);
	}
	private static void BFS(int[][] maps, int[][] visit) {
		Queue<int[]> que = new LinkedList<>();
		que.add(new int[] {0, 0});
		while(!que.isEmpty()) {
			int[] now = que.poll();
			int x = now[0];
			int y = now[1];
			for(int i = 0; i < 4; i++) {
				int nx = dx[i] + x;
				int ny = dy[i] + y;
				if(nx >= 0 && nx < maps.length && ny >= 0 && ny < maps[0].length && maps[nx][ny] == 1 && visit[nx][ny] == 0) {
					visit[nx][ny] = visit[x][y] + 1;
					que.add(new int[] {nx, ny});
				}
			}
		}
    }
}

오늘의 회고

요즘 계속 알고리즘 문제를 1문제밖에 풀지 못하네요. 알고리즘 고수가 되는 그날까지 분발하겠습니다. 

728x90

+ Recent posts