프로그래머스 lv.1 문제


사실 문제가 어려워서 글을 작성하는 것이 아니고

'자바 - 컬렉션과 제네릭' 파트 부분이 많이 부족하다는 것은 인지 하고 있었지만


제가 10줄이 넘어가게 코드를 짤 동안 이것을 아는 사람들은 1~2줄 만에 끝내버리는 격차를 발견 후

살짝 현타가 와서 정리합니다 ㅋㅋㅋㅋㅋ

늦기 전에 다시 공부하기 ㅠㅠ 컬렉션 제네릭 람다식..


[문제 설명]

array의 각 element 중 divisor로 나누어 떨어지는 값을 오름차순으로 정렬한 배열을 반환하는 함수, solution을 작성해주세요.
divisor로 나누어 떨어지는 element가 하나도 없다면 배열에 -1을 담아 반환하세요.

[제한사항]
  • arr은 자연수를 담은 배열입니다.
  • 정수 i, j에 대해 i ≠ j 이면 arr[i] ≠ arr[j] 입니다.
  • divisor는 자연수입니다.
  • array는 길이 1 이상인 배열입니다.
[입출력 예]

arr                  divisor     return

[5, 9, 7, 10] 5              [5, 10]

[2, 36, 1, 3] 1          [1, 2, 3, 36]

[3,2,6]         10          [-1]


[문제 풀이]

1. arr 배열에 있는 수를 divisor로 나누어 떨어지면 ArrayList에 add

2. ArrayList를 다시 asnwer로 옮긴 후 정렬해서 return


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.ArrayList;
import java.util.Arrays;
class Solution {
  public int[] solution(int[] arr, int divisor) {
      //int[] answer = {};
      ArrayList<Integer> arr_list = new ArrayList<Integer>();
      int cnt=0;
      for(int i=0; i<arr.length; i++){
          if(arr[i]%divisor == 0){
              arr_list.add(arr[i]);
          }
      }
      
      if(arr_list.size()==0){
          arr_list.add(-1);
      }
      int[] answer = new int[arr_list.size()];
      for(int j=0; j<arr_list.size(); j++){
          answer[j] = arr_list.get(j);
      }
      Arrays.sort(answer);
      return answer;
  }
}
cs


위의 내용을 이렇게도 풀 수 있습니다!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.Arrays;
class Solution {
  public int[] solution(int[] arr, int divisor) {
 
        int[] answer = Arrays.stream(arr).filter(factor -> factor % divisor == 0).toArray();
        int[] answer_null = {-1};
        
        Arrays.sort(answer);
        if(answer.length==0) {
            return answer_null;
        }
        else        
            return answer;
  }
}
cs


오히려 어려운 문제 풀었을 때 보다 이렇게 내가 어리석다는 것을 깨달을 때가 더욱 자극 되는 것 같습니다.

(관련 내용 정리하기 ~)


'알고리즘 공부 > 알고리즘 문제' 카테고리의 다른 글

트리 dfs 탐색  (0) 2021.04.23
백준 (2178) - 미로탐색 (java)  (0) 2019.06.04
문자열 내 맘대로 정렬하기  (0) 2019.03.12
빙고 개수 카운트하기  (0) 2019.01.31
배열 회전 결과값 확인하기  (1) 2019.01.26

요즘 자소서만 쓰다보니 코딩에 무뎌져서 감각 좀 살릴 겸

차근차근 다시 lv.1 짜리 위주로 문제풀고있는데 정렬 문제가 생각이 안나서 멘붕


그래서 정리 할 겸 작성 해 봅니다.



시작!


내 마음대로 정렬하기

[문제 설명]

문자열로 구성된 리스트 strings와, 정수 n이 주어졌을 때, 각 문자열의 인덱스 n번째 글자를 기준으로 오름차순 정렬하려 합니다. 예를 들어 strings가 [sun, bed, car]이고 n이 1이면 각 단어의 인덱스 1의 문자 u, e, a로 strings를 정렬합니다.

[제한 조건]
  • strings는 길이 1 이상, 50이하인 배열입니다.
  • strings의 원소는 소문자 알파벳으로 이루어져 있습니다.
  • strings의 원소는 길이 1 이상, 100이하인 문자열입니다.
  • 모든 strings의 원소의 길이는 n보다 큽니다.
  • 인덱스 1의 문자가 같은 문자열이 여럿 일 경우, 사전순으로 앞선 문자열이 앞쪽에 위치합니다.



[입출력 예]

strings                 n return
[sun, bed, car]         1 [car, bed, sun]
[abce, abcd, cdx] 2 [abcd, abce, cdx]

[입출력 예 설명]
입출력 예 1
sun, bed, car의 1번째 인덱스 값은 각각 u, e, a 입니다. 이를 기준으로 strings를 정렬하면 [car, bed, sun] 입니다.

입출력 예 2
abce와 abcd, cdx의 2번째 인덱스 값은 c, c, x입니다. 따라서 정렬 후에는 cdx가 가장 뒤에 위치합니다. abce와 abcd는 사전순으로 정렬하면 abcd가 우선하므로, 답은 [abcd, abce, cdx] 입니다.

[문제 풀이]

문제 푸는 과정

1. 기본문제 해결 방법이 안떠올라 멘붕하기

왜냐면 맨날 문제 풀다가 정렬이 필요한 경우 자바에서 지원해주는 Arrays.sort() 메서드를 사용했기 때문 ㅋㅋㅋㅋ

2.  정렬 하기

nlog(n)의 기댓값을 갖는 퀵정렬은 구현하기 힘드니(?) 선택/버블/삽입 정렬 중 선택한다.

(개인적으로 선택 정렬이 제일 외우기 쉬우니 선택 정렬로 구현)

3. 정렬 조건에 문자열을 기준으로 할지 선택한다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public String[] solution(String[] strings, int n) {
        String[] answer = {};
        int min;
        String temp;
        //선택 정렬 구현하기
        for(int i=0; i<strings.length-1; i++) {
            min = i;
            for(int j=i+1; j<strings.length; j++) {
                //비교해서 가장 작은 값을 찾는다.
                System.out.println(" "+strings[min].substring(n, n+1)+" vs "+strings[j].substring(n, n+1));
                if(strings[min].substring(n, n+1).compareTo(strings[j].substring(n, n+1))>0) {
                    min = j;
                }
                //n번째 문자까지 같다면 걍 문자 비교하기
                else if(strings[min].substring(n, n+1).compareTo(strings[j].substring(n, n+1))==0) {
                    if(strings[min].compareTo(strings[j])>0) {
                        min = j;
                    }
                }
              }
            //min값을 i번째와 바꾼다.
            temp = strings[i];
            strings[i] = strings[min];
            strings[min] = temp;
        }
        
        for(String k : strings) {
            System.out.println(k);
        }
        return strings;
    
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        programmers_SuitMyselfSort s = new programmers_SuitMyselfSort();
        
        String[] strings = {"sun","bed","car"};//{"abce","abcd","cdx"};
        int n = 1;
        
        s.solution(strings, n);
 
    }
cs


풀고 보니 어려운게 아니고 정리할 것도 딱히 없어보인 문제

해결방법이 갑자기 안떠올라서 ㅠㅠ 

어쨋거나 정렬이 안떠올랐다는건 기본기가 부족하다는 것이니, 다시 복습하는 시간을 가져야 겠습니다.


각 정렬 알고리즘 구현 하는 시간을 가져봐야겠네요.





면접을 보고왔는데...

DB쪽 이론은 "그냥 말하면 되지 뭐"하는 상당히 멍청한 생각을 하고 준비를 안해서 당황했네요 ㅋㅋㅋ


복습을 안하니 전부 다 아는 내용인데 입안에서 단어만 맴돌다 헛소리만 하다 오는것 같아 멘탈이 가루가 되더군요

(=> 핑계임ㅎ 급 질문에 대답 못하면 '모른다'는 것이지요)

지난날의 과오를 반성하며 꼼꼼하게 공부하겠습니다 ㅋㅋㅋ



일단 오늘은 면접 가다가 지하철에서 읽어 볼 수 있도록 DB 용어만 간단히 정리하겠습니다.


Q. DB 정규화를 하는 이유는 ?

A. 데이터의 중복 및 이상 현상을 방지하기 위해서 정규화를 진행 합니다.


Q. DB 이상의 종류는 ?

A. 삽입이상, 삭제이상, 수정이상 이렇게 총 3가지 이상이 있습니다.

'삽입 이상'이란 원하지 않는 자료가 삽입되거나, 삽입을 하는데 자료가 부족해 정상적으로 삽입이 되지 않는 현상입니다.

'삭제 이상'이란 하나의 자료를 삭제하려고 하는데 그와 관련된 튜플 전체가 삭제되는 현상 입니다.

'수정(갱신) 이상'이란 자료를 수정하는데 관련된 다른 테이블의 내용이 수정되지 않아 정보가 모호해지는 현상 입니다.


Q. PK란 무엇입니까?

A. 테이블 내에서 튜플을 완벽하게 구분할 수 있는 유일한 속성(Attribute) 입니다.


Q. 다른 Key 종류 설명

A. Key는 총 5가지 종류가 있습니다.

후보키(Candinate Key)란 테이블 내에서 튜플을 완벽하게 구분할 수 있는 유일한 속성(Attribute)들의 부분 집합입니다. 유일성과 최소성을 만족해야 합니다. 

기본키(Prime Key)란 후보키 중 선택된 주 키 이며 Null 값을 가질 수 없습니다.

대체키(Alternate Key)란 후보키들 중에서 주 키가 아닌 나머지를 지칭 합니다.

슈퍼키(Super key) 테이블 내에서 하나의 튜플을 완벽하게 구분하기 위해 두개 이상으로 조합된 키 입니다. 유일성은 만족하지만 최소성은 만족시키지 못합니다. 

외래키 관계가 있는 R1,R2 테이블이 있고 R1에서 R2를 참조하려 할때 R1의 기본키와 대응되어 R2의 튜플을 구분할 수 있는 속성을 외래키라고 합니다.



/*이것은 개념 이해가 필요할 것 같아 따로 정리하기*/

Q. index Cluster가 무엇이고 이것의 중요성 좀 설명해주세요

A. Cluster index란 물리적으로 테이블의 데이터를 정렬한 것입니다.

Join과 같이 자주 사용되는 내용들을 클러스터 인덱스로 지정해 두면 데이 탐색 시간을 단축할 수 있습니다.





머릿속으로 말고 말로하는 연습하기!

DB 개념들 꼼꼼하게 정리하고, 할 수 있다면 간단한 예제도 같이 외워두기!

/*생각나는대로 내용들 지속적으로 추가하기*/





'DataBase > DataBase 이론 공부' 카테고리의 다른 글

정규화 (제1 정규화 ~ 제3 정규화)  (11) 2019.01.15


이제 DB 출력을 확인했으니, 입력하는 방법을 알아보겠습니다.

간단합니다! 출력 반대로(?)


요약

- DB에 data insert하기-

1. .jsp 에 input 추가하여 controller로 던져주기

2. controller에 데이터 삽입 메서드 작성하기

3. mapper에 insert 문 작성하기

4. 동작 확인하기



시작합니다!

1. jsp에 input 추가하여 contoller로 던져주기

처음에 데이터 입력할 페이지를 설정을 해줍니다. 저는 testpage.jsp에다가 하려고 합니다.

데이터 삽입 페이지, 출력 페이지 따로 구성할 수 도 있지만

저는 그냥 한 페이지에 입력하면 바로 출력할 수 있도록 만들 계획입니다.


- form을 이용하여 페이지에서 입력된 값을 구분자 값 -"/testPage/insert_data"를 'POST'형식으로 controller로 던져줄 것입니다.


일단 작성 했으니 페이지 동작하는지 확인


굿


2.  Contoller에 메서드 추가하기

이제 Controller에 던져준 값을 처리할 메서드를 작성합니다.

저는 testPageController.java에 추가하면 되겠군요


1
2
3
4
5
6
7
8
9
10
11
/*jsp 페이지에서 구분자로 "/testPage/insert_data" 값으로 던져주었기 떄문에 해당 값으로 RequesetMapping을 합니다.
  post 형식으로 던졌기 때문에 post로 받아주기! (GET/POST 형식의 차이는 면접에서 자주 물어보는 기본 질문이니 숙지합시다 ㅎㅎ) */
@RequestMapping(value = "/testPage/insert_data", method = RequestMethod.POST)
 
    //메서드 작성하기 @Model 어노테이션을 통해 testPage 생성
    public String insert_data(@ModelAttribute testPage testpage){
        
        System.out.print(testpage.toString()); //view에서 제대로 값 던져주는지 확인하기        
        
        return "redirect:/testPage";  //요청 처리 후 testPage로 다시 연결
    }
cs

* GET/POST 간단정리 (자세한건 검색하기!)



2.1 이후 웹 페이지에서 데이터 입력하고 확인해봅니다.

console로 확인 하면 완료!



3. mapper에 insert 문 작성하기

mapper에 DB로 입력 할 Inert문을 작성합니다.



3.1 mapper에 insert_data를 생성 후 controller에서 mapper로 전달 해 줄 문장을 추가합니다.


4. 확인하기

- 데이터 jin / user 데이터 작성 


- 저장 버튼 누른 후 테이블 변동 확인


정상 동작하면 완료!!


이렇게 DB를 입력 출력을 완성했습니다.

이것을 응용하면 회원가입/ 로그인 / 게시판 입력/수정/삭제 와 같은 기능을 작성할 수 있을 것 입니다.

물론 깊게 들어가면 부가적으로 들어가는 개념들을 이해해야겠지만요


아무튼 오늘은 끝!






프로그래머스 모의테스트 마지막 문제였던 빙고 문제

솔직히 다른 알고리즘이 자신있는건 아니지만

현재 가장 자신없는 알고리즘 부분은 BFS/DFS.. 탐색!! 부분입니다.


그래서 문제로 다중 행렬 나온다음에 넓이 체크하라는거 나오면 솔직히 겁부터 나긴 합니다. 

탐색 알고리즘을 완전히 이해한 후 문제를 풀려고 했으나 

일단 그냥 풀어보고 싶은 알수없는 오기(?) 발동으로 빙고 문제를 풀어봤습니다.

막 풀어서 코드가 길어요..


그럼 풀어봅시다

[문제]

* 빙고는 NxN 크기의 게임 보드 칸에 1부터 NxN까지의 자연수를 중복 없이 하나씩 적은 후 숫자를 하나씩 지워나가는 게임입니다.

*  이때, 가로, 세로, 대각선 방향으로 한 줄에 적힌 숫자를 모두 지울 경우 빙고를 1개 만들었다고 합니다.

- 다음은 4X4 크기의 게임 보드를 이용해 게임을 진행한 예시입니다.

- 위와 같이 각 칸에 숫자가 적혀 있을 때, 위 게임 보드에서 순서대로 지운 숫자가 [14,3,2,4,13,1,16,11,5,15]인 경우 아래와 같이 빙고 3개가 만들어집니다.

빙고 게임 보드에 적힌 숫자가 담겨있는 배열 board, 게임 보드에서 순서대로 지운 숫자가 들어있는 배열 nums가 매개변수로 주어질 때,

board에서 nums에 들어있는 숫자를 모두 지우면 몇 개의 빙고가 만들어지는지 return하도록 solution함수를 완성해주세요.


[제한사항]

board는 게임 보드 칸에 적힌 숫자를 뜻하는 NxN크기의 2차원 배열이며, N은 2 이상 500이하의 자연수입니다.

board의 각 칸에는 1 이상 NxN이하의 자연수가 중복 없이 하나씩 들어있습니다.

nums는 board에서 지울 숫자가 들어있는 배열이며, 길이는 1 이상 NxN이하입니다.

nums에 들어있는 숫자는 1 이상 NxN이하의 자연수이며, 중복된 수가 들어있지 않습니다.



[문제 풀이]

저는 다음과 같은 순서로 문제를 풀었습니다.

1. num 배열에 있는 수를 하나씩 체크하며 보드 판에 해당 숫자가 있는지를 확인하고, 있으면 0으로 바꾸어 준다.

2. 바꾸어진 빙고판을 count_bingo() 함수로 보내어 빙고 갯수를 판별한다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package pracitce_note;
 
public class mock_test03 {
    //빙고판 확인 함수
    public static int[][] confirm_borad(int[][] b,int num) {
        
        for(int i=0; i<b.length; i++) {
            for(int j=0; j<b.length; j++) { //숫자 있으면 0으로 변경
                if(b[i][j]==num) {
                    b[i][j] = 0;
                }
            }
        }
        return b;
    }
    //디버깅용 출력 함수
/*public static void print(int[][] b) {
        for(int i=0; i<b.length; i++) {
            for(int j=0; j<b.length; j++) {
                System.out.print(b[i][j]+" ");
            }
            System.out.println();
        }
    }*/
    //빙고 카운트
    public static void count_bingo(int[][] board) {
        
        //가로와 세로를 체크해 줄 V - H 배열 생성
        int v[] = new int[board.length];
        int h[] = new int[board.length];
        int c[] = new int[2]; //대각선은 두개 뿐 
        int count =0;
        //0으로 바뀐거 체크하면서 가로 / 세로/ 대각선 체크
            for(int i=0; i<board.length; i++) {
                for(int j=0; j<board.length; j++) {
                    //가로 카운트
                    if(board[i][j]==0) {
                        v[i]++//가로 체크
                        h[j]++//세로 체크
                        if(i==j) { //대각선 체크
                            c[0]++;
                        }
                        if(i+j==board.length-1) {
                            c[1]++;
                        }
                    }
                }
            }
        //체크값 확인해서 빙고면 count++    
        for(int k=0; k<v.length; k++) {    
             if(v[k] == v.length) {
                 count++;
             }
             if(h[k] == v.length) {
                 count++;
             }
        }
        //대각선은 어떤 빙고판이든 2개라서.. 따로 빼서 체크..
         if(c[0]==v.length) {
             count++;
         }
         if(c[1]==v.length) {
             count++;
         }
         //count 값
         System.out.println(count);
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        int[][] board = {{11,13,15,16},{12,1,4,3},{10,2,7,8},{5,14,6,9}};
        int[] num = {14,3,2,4,13,1,16,11,5,15};
        
        /* solution
         * 1. num에 있는 숫자를  하나씩 비교하며 board에 있는경우 0으로 바꾼다
         * 2. 바꾸어진 board에 빙고 부분을 카운트 한다.
         * */
        //num 하나씩 보내면서 체크하기
        for(int i=0; i<num.length; i++) {
            confirm_borad(board,num[i]);
        }
        //print(board);
        
        count_bingo(board); //빙고 체크하기
 
    }
 
}
 

cs


효율성은 O(2n^2)? 되는거같은뎅 

풀고보니 num 체크하면서 바로바로 카운트하면 함수를 두개로 나눌 필요가 없어보이긴 합니다


근거없는 자신감이지만 탐색 알고리즘을 공부하고나면 코드가 엄청 줄고 효울성도 올라갈 것 같은 기분이 ㅋㅋ

빨리 탐색 알고리즘 공부를 해야겠네요

 

기본 셋팅의 마지막!

오늘 할 일은 DB와 연동하기!

- 테스트 페이지 만들기

- Spring과 DB 연동

- 등록한 데이터 확인하기

- Web에서 DB에 데이터 등록하기


이것만 끝나면 이제 슬슬 기능을 만들어 볼 수 있을 것 같습니다.


DB 연동 요약 정리 하기 

-----------------------------------------------------------------

* DB 연동 페이지 생성하기 (페이지 생성될때마다 하는 것)

-----------------------------------------------------------------

1) VIEW : page.jsp 생성

2) Controller : pageController.java 생성 -> 메서드 작성

3) Mapper : pageMapper 생성 -> 쿼리문 작성 

-> 새로운 Mapper일 경우 root-context.xml에 mapper 추가

4) VO : DB getter/setter / return toString 작성

5) tiles.xml 새로운 페이지 추가

----------------------------------------------------------------


----------------------------------------------------------------

* DB 최초 연동하기 (최초 설정 후 안건드려도 되는 것)

----------------------------------------------------------------

1) pom.xml DBMS 관련 라이브러리 작성하여 메이븐 추가

2) root-context.xml에 properties, DBMS, Mapper 추가

3) mybatis-config.xml 추가

4) resource에 jdbc.properties 추가

----------------------------------------------------------------

시작!


먼저 테스트 페이지를 하나 만들겠습니다.


1. 테스트 페이지 만들기

1.1 Sidebar.jsp 수정

- 테스트 페이지 메뉴 내용을 추가/수정 해줍니다.  (href=이동할 위치 / 표기할 이름)




1.2 테스트 페이지를 추가합니다.

이제 테스트 페이지 메뉴를 클릭하면 보여줄 view를 작성해줍니다.

폴더와 jsp 파일을 생성해주세요.


1.3 이제 컨트롤러를 생성해줍니다.

- MVC 패턴으로 생성 했기 때문에 view에 관한 동작을 통제하는 컨트롤러를 생성해주어야 합니다.

 컨트롤러는 .java로 실행되기 때문에 자바 클래스를 하나 생성해주시면 됩니다.


- 그러면 이제 testPage의 컨트롤러가 생겼고 클래스가 생성되었으니 메서드를 작석해서 동작해주도록 합시다.

코드 작성에는 @RequestMapping과 @Controller를 사용합니다.

자바의 장점 중 하나인 AOP(관심 지향 프로그래밍)를 이용하는 것이지요!


클라이언트가 /testPage로 접속하여 요청을 보내면 testPageController에서 동작을 처리해서 결과 값을 testPage/testpage로 보내주게 됩니다.



1.4  타일즈 설정하기

- 페이지까지 생성이 되었으면 이제 tiles.xml에 타일즈 디자인을 표기할 페이지를 추가해 주면 됩니다.

- name 이랑 value 수정하면 됩니다. 당연한 이야기지만 경로 정확하게 설정하지 않으면 에러나요!



1.5 페이지 생성 확인

정상 동작 확인했으면 이제 본격적으로 DB를 연동해보도록 하죠


2. DB 연동하기

저는 Mysql을 사용할 계획 입니다. 오라클과 같은 다른 DBMS를 사용하시는 구조는 동일합니다만 패키지 추가하는 내용이 조금 다를듯 해서

그 부분은 따로 찾아봐야 할 것 같네요

또한 전 HeidSQL 이라는 프로그램을 사용합니다. 하지만 면접을 준비할때는 Mysql CMD를 통해 연습하는것이 좋을 듯 합니다


DBMS와 테이블이 생성되어있다는 가정 하에 진행하겠습니다.

* 정보 

DB 이름 : spring_web_project

table 이름 : testpage

속성 : id - int-auto increament(prime key) / user_name -varchar(50) / content - varchar(50)


2.1 데이터베이스 연동하기

연동에 필요한 순서는 Pom.xml에 라이브러리 파일 추가하기 ->   root-context.xml에 DBMS 정보 등록하기 -> mybatis 설정 입니다.


2.1.1 Pom.xml

Spring에는 Maven이라는 것이 존재합니다. Maven은 라이브러리를 pom.xml에 작성을 하면 자동으로 라이브러리를 포함해주는

아주아주 편리한 기능이죠! 

그래서 아래의 내용을 pom.xml에 Mysql관련 라이브러리를 포함하도록 합니다.

추가할 내용은 다음과 같습니다.

- mysql - mysql-connetcor-java => java와 mysql 연동을 위한 라이브러리

- MyBatis => mybatis

- mybatis-spring => spring에서 사용할 mybatis 정보

- Spring JDBC => jdbc 라이브러리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
         <version>5.1.41</version>
    </dependency>
    <!-- MyBatis 3.4 -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.1</version>
    </dependency>
    <!-- MyBatis-Spring 1.3-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.3.0</version>
    </dependency>
    <!-- Spring-JDBC -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${org.springframework-version}</version>
    </dependency>
cs


이렇게 저장하면 자동으로 라이브러리가 다운로드 받아집니다. 

라이브러리 포함 후 서버는 재시작해야 동작합니다. 

보통 xml과 같은 설정 파일들을 수정하게 되면 적용하기 위해 재시작 해준다 생각하면 편할 듯 합니다.


2.2 root-context.xml 에 DBMS 관련 객체를 설정해줍니다. (여기서 스프링의 장점인 Spring DI를 알 수 있겠네요)

설정 내용은 다음과 같습니다.

- properties => jdbc에 연결할때 DB의 접속 주소, 계정, 비밀번호를 설정 관리하는 파일을 설정합니다.

- jdbc-mysql => jdbc 드라이버를 사용할때 참조할 위치 설정

- MyBatis-Spring => Spring에서 MyBatis를 설정을 참조할 부분 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- properties -->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations" value="classpath:/jdbc.properties" />
        <property name="ignoreUnresolvablePlaceholders" value="true" />
        <property name="fileEncoding" value="UTF-8" />
    </bean>
    <!-- JDBC-MYSQL -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>
    
     <!-- MyBatis-Spring -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="configLocation" value="classpath:mybatis-config.xml" />
        <property name="dataSource" ref="dataSource" />
    </bean>
cs


2.3 properties 작성하기

- 이제 DB로 접속할 정보가 작성되어있는 properties 파일을 설정합니다. root-context.xml에 작성한 위치에 생성하면 됩니다.

- jdbc.properties 생성


- jdbc.properties 내용



2.4 mybatis 설정 파일인 mybatis-config.xml를 작성해줍니다. (root-context.xml에 작성된 파일이 없으면 실행 에러나는것 참고해주세요)

작성 방법은 다음과 같습니다.

접속 경로 같은건 properties에서 작성할것이기 때문에 따로 작성 할 내용은 없습니다.


- 작성 위치 및 내용



1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
   
</configuration>
cs




2.5 mapper 생성

MVC 패턴의 model 부분 입니다.

Client 요청 -> View -> 동작요청 -> Controller 메서드 실행 -> 데이터 관련 -> Model로 요청 -> 컨트롤러로 전송 -> 메서드 처리 후 다시 -> view

위에 굵은 글씨 부분을 작성하게 되는 것 입니다.

mapper의 특징은 interface로 작성된다는것! 중요하니 참고 해주세요.


2.5.1 mapper 생성

- mapper Package를 생성 후 mapper를 생성해줍니다. mapper의 확장자는 .java 입니다.


- mapper의 내용은 DB 쿼리문 이라고 생각하시면 됩니다.

여기서 또 구분할 내용이 있는데 Mapper의 경우 mapper의 역할만 합니다. 그래서 DB의 내용을 담아줄 파일을 나누어 줘야 관리하기가 편리해 주는데

이것은 VO 라고 합니다.  


MVC 패턴에선 이것을 DAO - DTO(VO) 구조로 나누어서 사용을 합니다.

지금 하는 예제 프로젝트에서는 DAO를 따로 설정하지 않았는데, 추후에 DAO 설정을 통해 접근을 관리할 수 있도록 추가하겠습니다.

(일단 연동 테스트 부터)


아직 서버 트래픽 관리 부분까지는 개념과 실력이 부족하기 때문에 관련 내용을 좀 더 깊게 공부 한 후 서버 관리 영역에 관해 글을 작성할때 내용을 추가해보도록 하겠습니다.



2.5.2 mapper 객체 root-context.xml에 아래 내용을 추가 합니다.

1
2
3
4
5
<!-- Mapper -->
    <bean id="testPageMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
        <property name="mapperInterface" value="com.mycompany.mapper.testPageMapper" />
        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
    </bean>
cs



 2.5.3 vo 생성 하기 

- vo의 내용은 getter / setter로 구성됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.mycompany.vo;
 
public class testPage {
    String id;
    String user_name;
    String content;
    
    
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    
    public String getUser_name() {
        return user_name;
    }
    public void setUser_name(String user_name) {
        this.user_name = user_name;
    }
    
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    
    @Override
    public String toString() {
        return "testPage [id=" + id + ", user_name=" + user_name + ", content=" + content + "]";
    }
 
}
 
cs


2.5.4 mapper 작성하기

- interface로 작성하기 때문에 메서드 이름만 생성해주고 내용은 생성 안합니다.

- select 어노테이션을 통해 쿼리문을 작성해줍니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.mycompany.mapper;
 
import java.util.List;
 
import org.apache.ibatis.annotations.Select;
 
import com.mycompany.vo.testPage;
 
 
public interface testPageMapper {
    @Select("select * from testpage ORDER BY date DESC")
    public List<testPage> getList();
}
 
cs


2.6 DB 출력을 위해 controller 수정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.mycompany.myapp;
 
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
import com.mycompany.mapper.testPageMapper;
import com.mycompany.vo.testPage;
 
@Controller
public class testPageController {
    
    @Autowired
    private testPageMapper testpagemapper;
    
    @RequestMapping(value = "/testPage", method = RequestMethod.GET)
    
    //DB 출력 동작 메서드
    public String testPage_print(Model model){
        //<> 안에 DTO or VO 이름
        List<testPage> testpage = testpagemapper.getList_testpage();
        
        //model을 통해 View로 전달
        model.addAttribute("testpage",testpage);
        
        return "testPage/testpage";
    }
    
 
}
 
cs




2.7 View에 표기하기

- testpage.jsp 작성한 내용입니다.

- controller로 부터 DB 내용을 가져올때 경로 설정을 c:foreach 문을 사용했는데 이 문법을 사용하기 위해서

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>를 추가해주었습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- 
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
 -->
 
<div class="container-fluid">
 
    <!-- Breadcrumbs-->
    <ol class="breadcrumb">
        <li class="breadcrumb-item"><a href="#">testPage</a></li>
        <li class="breadcrumb-item active">Overview</li>
    </ol>
 
    <!-- DataTables Example -->
    <div class="card mb-3">
        <div class="card-header">
            <i class="fas fa-table"></i> testPage-data
        </div>
        <div class="card-body">
            <div class="table-responsive">
 
                <table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
                    <thead>
                        <tr>
                            <th>id</th>
                            <th>user_name</th>
                            <th>content</th>
                        </tr>
                    </thead>
                        
                    <tbody>
                        <c:forEach items="${testpage}" var="testpage">
                                            <tr>
                                                <td>${testpage.id}</td>
                                                <td>${testpage.user_name}</td>
                                                <td>${testpage.content}</td>                                                
                                            </tr>
                        </c:forEach>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
 
 
</div>
 
cs


2.8 정상적으로 데이터 읽어오는지 확인하기

- 이제 서버를 재시작하고 페이지가 정상 동작하는지를 확인합니다.



정상적으로 출력 되었다면 잘 작성했다는 것이겠죠?

정리하며 쓰다보니  내용이 많아져서

DB작성하기는 다음편에 작성하겠습니다.




프로그래머스 모의테스트 문제

두개의 배열 arrA, arrB를 받아서 

arrA를 회전시켜 arrB를 만들 수 있으면 true 아니면 false 리턴하는 함수 만들기!


[문제]

* 배열의 회전이란 모든 원소를 오른쪽으로 한 칸씩 이동시키고, 마지막 원소는 배열의 맨 앞에 넣는 것을 말합니다.

* 두 배열 arrA와 arrB가 매개변수로 주어질 때, arrA를 회전해 arrB로 만들 수 있으면 true를, 그렇지 않으면 false를 return 하는 solution 함수를 작성해주세요.


[제한 조건]

arrA는 길이가 1 이상 1,500 이하인 배열입니다.

arrA의 원소는 0 이상 1,500 이하인 정수입니다.

arrB는 길이가 1 이상 1,500 이하인 배열입니다

arrB의 원소는 0 이상 1,500 이하인 정수입니다.



[문제풀이]

제가 생각한 솔루션은 다음과 같습니다.

ArrayList 이용하기!

사실, Queue를 이용해도 상관 없겠지만 이런 문제의 경우 전 ArrayList가 편해서 이걸로 풀었습니다.

1. ArrayList a를 만들어서 a에 arrA 배열을 넣는다.

2. confirm 메서드를 만든다.

2-1) a.size()와 arrB 배열 크기가 다르면 false return

2-2) a의 원소 와 arrB의 원소를 하나씩 비교해서 같으면 ture 아니면 false 리턴

3. ArrayList a를 순환시켜 arrB를 만들 수 있는지 확인한다.

confirm메서드에 a와 arrB를 던져서 answer값 받기


이것을 코드로 옮기기!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public class mock_test01 {
    //confirm 메서드 선언
    public static boolean confirm(ArrayList<Integer> a,int[] arrB) {
        boolean answer = true;
        //배열 크기가 다르면 false
        if(a.size() != arrB.length){
            answer = false;
            return answer;
        }
 
        //배열 원소 하나씩 비교하기
        else 
            for(int i=0; i<arrB.length; i++) {
                //if(!a.get(i).equals(arr2[i])) {
                //System.out.println("a.get = "+a.get(i) + " arr2 = "+arrB[i]);
                if(!a.get(i).equals(arrB[i])) {
                    answer = false;
                    break;
                }
            }
            return answer;
        
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        int[] arrA = {1,2,3,4,5,6}; //4,1,2,3 -> 3,4,1,2 -> 2,3,4,1 -> 1,2,3,4
        int[] arrB = {6,1,2,3,4,5};
        int temp = arrA[arrA.length-1]; //arrA의 마지막 값
        boolean answer = false;
        ArrayList<Integer> a = new ArrayList<Integer>();
 
        //ArrayList a에 arrA 원소 넣기
        for(int i=0; i<arrA.length; i++) {
            a.add(arrA[i]);
        }
        
        //arrA 순환시키기
        for(int j=0; j<arrA.length; j++) {
             a.add(0,temp);             //배열 맨 마지막 값을 맨 앞으로 삽입
             a.remove(arrA.length);     //맨 마지막값은 삭제
             //System.out.println(a);
             
             //만들 수 있으면 break
             if(confirm(a,arrB)) {  //순환된 ArrayList a로 arrB를 만들 수 있는지 확인
                 answer = true;
                 break;
             }
             //순환 후 맨 마지막값 다시 temp에 넣기
             temp = a.get(arrA.length-1);
        }
        
         System.out.println(answer);
    }
}
cs


효율성 검사가 없어서 통과 되긴했네요

지금은 무식하게 풀고있긴 하지만 계속 연습하다보면 더 좋은 방법들을 찾을 수 있을것 같습니다.


/* 2019 - 01 - 31 수정 */

풀이 확인하니 배열 자체를 순환시키면 됬는데, 저는 왜  위의 풀이처럼 저렇게 풀었는지 이해가 안가는군여...

역시 모르면 피곤해지나봅니다 ㅠㅠ

덕분에 Arrays.equals(arrA,arrB)처럼 간단하게 자바에서 배열 원소를 비교해주는 클래스를 지원해준다는 것을 하나 배워가네요 ㅋㅋ


수정된 풀이 입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class mock_test01 {
    
    public static boolean circulation(int[] arrA,int[] arrB) {
        
        int first;
        boolean answer = false;
        
        for(int j =0; j<arrA.length; j++) {
            //배열 순회하기 
            first = arrA[0];
            //한바퀴 돌때까지 순회
          for(int i=0; i<arrA.length-1; i++) {
                arrA[i] = arrA[i+1];
            }
            arrA[arrA.length-1= first;
            //arrA랑 arrB랑 같아지면 break
            if(Arrays.equals(arrA, arrB)) {
                answer = true;
                break;
            }
        }
        return answer;
    }
    
    
    public static void main(String[] args) {
        int[] arrA = {1,2,3,4,5,6}; //4,1,2,3 -> 3,4,1,2 -> 2,3,4,1 -> 1,2,3,4
        int[] arrB = {1,2,3,4,5,6};
        boolean answer = false;
    
        System.out.println(circulation(arrA,arrB));
        
    }
cs


공부합시다!!!


'알고리즘 공부 > 알고리즘 문제' 카테고리의 다른 글

문자열 내 맘대로 정렬하기  (0) 2019.03.12
빙고 개수 카운트하기  (0) 2019.01.31
도로에 가로등 전구 달기  (0) 2019.01.26
숫자를 한글로 읽기  (0) 2019.01.06
완주하지 못한 선수  (0) 2018.12.10

흠 프로그래머스 모의테스트 문제를 풀어보는데

주로 효율성 검사에서 항상 문제가 생기네요 ㅠㅠ

효율성 생각해서 문제 푸는건 항상 어려운것 같습니다 ㅋㅋ


아무튼 오늘 문제는 도로에 가로등 전구 달기!


[문제]

서울시에 일직선 모양의 새로운 도로가 생겼습니다. 새로운 도로의 전체 길이는 L이고 도로에는 총 n개의 가로등이 세워졌습니다. 이 도로의 모든 가로등에 전구를 사서 달려고 합니다.

 *  전구를 선택하는 기준은 다음과 같습니다.


- 전구는 길의 좌측, 우측 방향으로 각각 d 길이만큼 길을 밝힐 수 있고, d는 자연수입니다.

- 모든 가로등에는 같은 종류(d 값이 같은)의 전구를 달아야 합니다.

- 안전을 위하여 도로위에 어두운 부분이 있어서는 안 됩니다.

- 이때, d 값이 충분히 크다면 전체 도로를 밝게 비출 수 있지만, d 값이 작아진다면 도로 위에 빛이 닿지 않는 부분이 생길 수도 있습니다. 

- 따라서, 도로 위에 어두운 부분이 생기지 않도록 하는 d 값 중 최솟값을 구하려고 합니다.

- 전체 도로의 길이 L, 가로등이 세워져 있는 위치가 들어있는 배열 v가 매개변수로 주어질 때, 위의 모든 조건을 만족하는 d 의 최솟값을 return 하도록 solution 함수를 완성해주세요.


[제한사항]

- L은 1 이상 1,000,000,000 이하의 자연수입니다.

- v에는 가로등의 위치정보가 들어있습니다.

- 가로등의 위치는 0 이상 l 이하의 정수이며, 같은 위치에 2개 이상의 가로등이 있는 경우는 주어지지 않습니다.

- 가로등의 개수는 1이상 1,000 이하의 자연수입니다.



[문제 풀이]

제가 생각한 풀이법은 무식하게 다음과 같이 풀었습니다....

(사실 풀면서 이거 효율성 문제 걸릴거같은데 라고 생각했지만 딱히 다른 방법이 생각안나서 ㅋㅋ)

1. 배열을 정렬한다.

2. 배열의 첫번째 위치(가로등 첫번째 위치)가 0인지 확인한다.

3. 배열의 끝의 위치(가로등 마지막 위치)가 L(길이 값)인지 확인한다.

4. 2) or 3)의 경우가 false라면 둘 중에 큰 값 max를 구한다.

5. 정렬된 배열을 i+1 ,i를 비교해서 가장 큰 차 max_arr를 구한다.

6. max 값과 max_arr를 비교한다.

7. max가 클 경우 answer = max

8. max_arr가 클 경우 짝수일 경우 answer = max/2  홀수일 경우 answer = max/2+1


그럼 코딩해봅시다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class mock_test02 {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        int[] v = {2,9,3,6};
        int answer;
        int l = 11;
        
        //배열 정렬하기
        Arrays.sort(v);
        int max = 0;
        int max_arr=0;
        
        //가로등 첫번째 위치와 끝 위치가 0,L인지 확인하기
        if(v[0]-0 < l-v[v.length-1]) {
            max = l-v[v.length-1];
            answer = max;
            System.out.println("l과의 거리 "+max);
        }
        else {
            max = v[0]-0;
            answer = max;
            System.out.println("0과의 거리 "+max);
        }
        
        //배열 내 최댓값 구하기
        for(int i=0; i<v.length-1; i++){
            if(max_arr<v[i+1]-v[i]){
                max_arr = v[i+1]-v[i];
            }
        }
        //홀수 짝수 구분하기 ->이유 : d는 정수이기 때문에 max_arr이 1.5이면 최솟값은 2이기 때문
        if(max_arr%2==0) {
            max_arr = max_arr/2;
        }
        else {
            max_arr = (max_arr/2)+1;
        }
        
 
        //마지막 max값과 max_arr값 구해서 큰것이 최솟값이 된다.
        if(max<max_arr) {
            answer = max_arr;
        }
        else
            answer = max;
 
        System.out.print(answer);
    }
 
}
cs


음.. 정확성 테스트는 통과 했지만 효율성 검사에서 실패했네요 ㅠㅠ

Arrays.sort()만 써도 효율성에서 런타임아웃되던데 

다른 라이브러리를 사용하는 방법이 있거나 다른 간단한 솔루션이 있을것 같습니다.


생각나거나 나중에 문제풀다 생각나면 해결해보기로 ㅎㅎ


'알고리즘 공부 > 알고리즘 문제' 카테고리의 다른 글

문자열 내 맘대로 정렬하기  (0) 2019.03.12
빙고 개수 카운트하기  (0) 2019.01.31
배열 회전 결과값 확인하기  (1) 2019.01.26
숫자를 한글로 읽기  (0) 2019.01.06
완주하지 못한 선수  (0) 2018.12.10

+ Recent posts