복습 5
2020-03-09
복습 5
3.6부터 앞으로
-
좋은 단어 (Stack) -> 문제.. 헷갈리지말자
-
퇴사 (DP)
1. n일까지도 일할 수 있다 + (n+1)과 n일을 비교하므로 배열은 p[n+2], t[n+2], dp[n+2]로 진행 2. 또 dp[day]가 day일이후로 가질 수 있는 최대값이면서, 1일차값이 p[1]과 dp[day+1]로 진행된다면 끝에서부터 dp[막날 이후로 가질수있는 값], dp[막날 전날 가질 수 있는값].. 으로 진행해야한다. 3. 따라서 for(i=n; i>0; i--) 1일부터 시작하게 했으니까 i>0 이어야한다 4. day는 현재 내 날짜 i + 상담기간 t[i] 이며, day가 <=n 날짜 안에 끝난다면 dp[i] = max(p[i]+dp[day], dp[i+1]); 중 큰 값을 넣고 day가 >n 이라면 dp[i] = dp[i+1]; 뒤에서부터 오니까 다음날이 가질 수 있는 최대값이 오늘 가질 수 있는 최대값!! 5. 따라서 dp[1]에 가질 수 있는 최대의 값이 담겨있다
-
가장 긴 펠린드롬 (String)
스터디원이 푼 것 처럼, 모든 나올 수 있는 숫자의 조합으로 나눠서 계산했다. 코드도 짧아지고 답은 정답인데 효율성에서 0점 맞음…(?)
import java.util.*; public class Review { boolean palen(String s) { int j=s.length()-1; //끝부터 시작 for(int i=0; i<s.length()/2; i++,j--) {//i는 0부터 j는 끝부터 다가오다 만난다 if(s.charAt(i) != s.charAt(j)) return false; //아닐때만 잡아내면 되니까 } return true; // 안걸리고 나왔으면 true } public int solution(String s) { int answer = 0; for(int i=1; i<=s.length(); i++) { for(int j=0; j<s.length(); j++) { if(j+i <=s.length()) { String a = s.substring(j, j+i); System.out.println(a); if(palen(a) == true) answer = Math.max(answer, a.length()); } }//in for - 0부터 돌려보는 갯수까지 쪼개봄 (0~5) }//out for - 돌려보는 갯수 (1~5) return answer; } }
-
문자열 압축 (String)
오우… 위의 문제랑 비슷해서 비슷하게 풀었는데 다른점은
1) 위에 문제는 j+i 끊어지는 부분에서 멈춘다는 것
2) 이 문제는 j+i 끊어지는 부분에서 멈춘 후에, 그 뒷부분도 찾아내야 한다는 점이었다
import java.util.*; //28min public class Review { //작은 문자열의 사이즈로 static int solution(String s) { int answer=2500; for(int i=1; i<=s.length(); i++) { //일단 하나 넣고 시작하기 String answer_s = ""; String temp = s.substring(0, i); int num = 1; int idx = 0; boolean chk = false; for(int j=i; j<s.length(); j = j+i) { if(j+i<=s.length()) { if(temp.equals(s.substring(j, j+i))) { // 음... 문자열끼리 비교할때는 == 안쓰는거 잊지말자... num++; } else { if(num == 1) answer_s += temp; else answer_s += num+temp; num = 1; } temp = s.substring(j, j+i); // if 든 else 든 무조건 temp에는 다음 값 넣어줌 }//배열 size안에 들어온다는 조건 else { chk = true; idx = j; } }//in for //비교는 이미 했고, 못들어간거 넣어주기 if(num == 1) answer_s += temp; else answer_s += num + temp; if(chk == true)// 끝까지 도달못했으면 answer_s += s.substring(idx, s.length()); System.out.println(answer_s); answer = Math.min(answer, answer_s.length()); }//out for return answer; } public static void main(String[] args) { System.out.println(solution("abcabcabcabcdededededede")); } }
-
경로찾기 (BFS)
Pos 클래스 필요없고, j행만 가지고 들어가기때문에 큐는 Integer로 설정해준다! 기억해놓기!
또한, 큐가 무한루프를 돌지 않기위해서 어떤 조건일때 add 해주는지도 잘 생각해야한다!
import java.util.*; public class Review { //30min public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int arr[][] = new int[n][n]; for(int i=0; i<n; i++) { for(int j=0;j<n; j++) arr[i][j] = sc.nextInt(); } Queue<Integer> qu = new LinkedList<>(); for(int i=0; i<n; i++) {// 인접행렬이니까 0-n행까지만 가보면 된다 for(int j=0; j<n; j++) {//i행 쫙 돌기 if(arr[i][j] == 1) qu.add(j); } while(!qu.isEmpty()) {//j행에 방문할 수 있는데까지 다 방문하면서 1로만들어주고 나온다. int nextj = qu.poll(); arr[i][nextj] = 1; //i행의 j는 갈수있으니까 1로 만들어줌 for(int k=0; k<n; k++) { if(arr[nextj][k] == 1 && arr[i][k] !=1) { //arr[i][k]!=1이라는 뜻은 전행의 1이 있는곳은 전부 안가겠다는 뜻! qu에 안넣겠다는 뜻! qu.add(k); } } }//while //그렇게 while 돌고나오면 다음 i행으로 진행한다! }//out for for(int i=0;i<n;i++) { for(int j=0; j<n; j++) System.out.print(arr[i][j] + " "); System.out.println(); } } }
-
RGB거리 (DP)
-
Z (Recursion)
면이 아닌 점이라고 생각하면 쉽게 풀 수 있다.
또한, 기저조건에서 return 을 해주는것과 멈출 수 없다면 그냥 거기서 출력해주는 것도 좋은 방법!
import java.util.*; public class Review { //10min static int answer = 0; static void go(int m, int i, int j, int x, int y) { if(m == 1) {//기저조건 if(i==x && j==y) System.out.println(answer); answer++; return; } int h = m/2; go(h, i, j, x, y); go(h, i, j+h, x, y); go(h, i+h, j, x, y); go(h, i+h, j+h, x, y); } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); //점이라고 생각 int m = (int)Math.pow(2, n); // 한면만 가지고 들어가면 나머지는 half 옮기면서 알 수 있다 int x = sc.nextInt(); int y = sc.nextInt(); go(m, 0, 0, x, y); } }
-
잃어버린 괄호 (Greedy)
첫 시작은 무조건 +로 시작하니까, - 시작 전까지오는 s[0]은 전부 더해주면 된다
또, 뒤의 -로 쪼개져있는 배열들은 뒤에 +가 있으면 전부 괄호로 묶어서 더해준다는 개념이니까
-가나오는 배열마다 안에있는 애들을 전부 더해서 -처리해주면 된다.
import java.util.*; public class Review { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String a = sc.nextLine(); String a_split[] = a.split("-"); //-로 나누기 String first_split[] = a_split[0].split("\\+"); //첫 -의 앞부분 +들은 전부 더해준다 int f = 0; for(int i=0; i<first_split.length; i++) f += Integer.parseInt(first_split[i]); //나머지 -로 쪼개진 부분들은 전부 더해준다 int l =0; for(int i=1; i<a_split.length; i++) { //+가 있는 부분은 제거하고 숫자만 더해준다 String s[] = a_split[i].split("\\+"); for(int j=0;j<s.length; j++) l += Integer.parseInt(s[j]); } System.out.println(f-l); } }
-
0 만들기 (Greedy)
실패!!!!!!!!!!! 비슷하게 따라가다가 결국 조건에서 헤맸다… 으ㅏ아
import java.util.*; public class Review { static int target = 0; static void rec(int sum, int sign, int num, int increase, String a) { if(target == increase) {//기저조건 sum = sum + sign*num; if(sum == 0) System.out.println(a); return; } rec(sum, sign, num*10 + (increase+1), increase+1, a+ " " + String.valueOf(increase+1)); rec(sum + (sign*num), 1, increase+1, increase+1, a + "+" + String.valueOf(increase+1)); rec(sum + (sign*num), -1, increase+1, increase+1, a + "-" + String.valueOf(increase+1)); } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); for(int i=0; i<n; i++) { target = sc.nextInt(); String a = "1"; //sum, 부등호 , 초기값, 하나씩 증가해서 n 도달하는 값, 1넣고 출발 rec(0,1, 1, 1, a); System.out.println(); } } }