diff --git a/EunseoPark/Week1/LTC_Binary Search.java b/EunseoPark/Week1/LTC_Binary Search.java new file mode 100644 index 0000000..51476c3 --- /dev/null +++ b/EunseoPark/Week1/LTC_Binary Search.java @@ -0,0 +1,35 @@ +import java.util.*; +/* + [스스로 풀이] 0ms 43.52MB +*/ +class Solution { + public int search(int[] nums, int target) { + int l = 0, r = nums.length-1; + + while(l <= r){ + int mid = (l+r)/2; + if(nums[mid] == target) return mid; + + else if(nums[mid] < target){ + l = mid + 1; + } + else{ + r = mid -1; + } + } + return -1; + } +} +import java.util.*; +/* + [2차 메서드] 0ms 45.88MB + 이거 메서드있었는데 해서 메서드 바로 적용 +*/ +class Solution { + public int search(int[] nums, int target) { + int result = Arrays.binarySearch(nums, target); + + if(result < 0) return -1; + return result; + } +} \ No newline at end of file diff --git a/EunseoPark/Week1/LTC_Combinations.java b/EunseoPark/Week1/LTC_Combinations.java new file mode 100644 index 0000000..a36c191 --- /dev/null +++ b/EunseoPark/Week1/LTC_Combinations.java @@ -0,0 +1,51 @@ +import java.util.*; +/* + [1차 스스로 풀이] 63ms 94.56MB +*/ +class Solution { + public List> combine(int n, int k) { + List> result = new ArrayList<>(); + comb(result, new ArrayList<>(), n, k, 1); + return result; + } + private void comb(List> result, List cur, int n, int k, int now){ + if(cur.size() == k) { + result.add(new ArrayList<>(cur)); + return; + } + + for(int i = now; i <= n; i++){ + if(cur.contains(i)) continue; + cur.add(i); + comb(result, cur, n, k, i); + cur.remove(cur.size()-1); + } + } +} + + +import java.util.*; +/* + [2차 성능 최적화 참고] 18ms 94.56MB + 1. contains -> O(N^2) 소요를 제거 + 2. i => i + 1을 넘겨 중복 방지 +*/ +class Solution { + public List> combine(int n, int k) { + List> result = new ArrayList<>(); + comb(result, new ArrayList<>(), n, k, 1); + return result; + } + private void comb(List> result, List cur, int n, int k, int now){ + if(cur.size() == k) { + result.add(new ArrayList<>(cur)); + return; + } + + for(int i = now; i <= n; i++){ + cur.add(i); + comb(result, cur, n, k, i + 1); + cur.remove(cur.size()-1); + } + } +} \ No newline at end of file diff --git a/EunseoPark/Week1/LTC_N-Queen.java b/EunseoPark/Week1/LTC_N-Queen.java new file mode 100644 index 0000000..a940068 --- /dev/null +++ b/EunseoPark/Week1/LTC_N-Queen.java @@ -0,0 +1,51 @@ +import java.util.*; +/* + 1. 방문 위치를 기록하기 위해 -1로 초기화하고, (행 번호, 놓인 열 위치) 기록 + 2. -1 && 갈 수 있으면 backtrack + 2. canGo : + 첫 시도 : + now가 0, n-1, 중간일때 상하좌우 대각선을 while로 업데이트하면 확인 +*/ +class Solution { + static int[] visited; + + public List> solveNQueens(int n) { + List> result = new ArrayList<>(); + visited = new int[n]; + Arrays.fill(visited, -1); + backtrack(0, n, result); + return result; + } + private void backtrack(int now, int n, List> result){ + if(now == n) { + List cur = new ArrayList<>(); + + for(int idx : visited){ + StringBuilder sb = new StringBuilder(); + sb.append(".".repeat(n)); + sb.setCharAt(idx,'Q'); + cur.add(sb.toString()); + } + result.add(cur); + return; + } + for(int t = 0; t < n; t++){ + if(canGo(now, t, n)){ + visited[now] = t; + backtrack(now + 1, n , result); + visited[now] = -1; + } + } + } + + // now 번째 queen이 t 인덱스에 갈 수 있는지 + // 🔍 이전 행만 확인 + private boolean canGo(int now, int t, int n){ + for(int pre = 0; pre < now; pre++){ + if(visited[pre]==t) return false; //이미 지난 + // 🔍 [행 차 == 열 차 + if(Math.abs(pre - now) == Math.abs(visited[pre] - t)) return false; + } + return true; + } +} \ No newline at end of file diff --git a/EunseoPark/Week1/LTC_Palindrome Partitioning.java b/EunseoPark/Week1/LTC_Palindrome Partitioning.java new file mode 100644 index 0000000..307392e --- /dev/null +++ b/EunseoPark/Week1/LTC_Palindrome Partitioning.java @@ -0,0 +1,40 @@ +import java.util.*; + +/* + 문자열.substring(startIndex, endIndex) + + [ 정답 참고 ] 20ms + 1. 첫 시도는 a, aa , aab 이렇게 만들어서 새로운 문자열 자체를 계속 + 넘겨야 하나 해서 헷갈리고 꼬임 + + // 정답 참고 정리 + 1. 문자열이 아닌 (start index) 를 넘겨 새로운 문자열을 만들기 +*/ +class Solution { + public List> partition(String s) { + List> result = new ArrayList<>(); + part(result, new ArrayList<>(), s, 0); + return result; + } + + private void part(List> result, List cur, String origin, int start){ + if(start == origin.length()) { + result.add(new ArrayList<>(cur)); + return; + } + + for(int i = start + 1, length = origin.length(); i <= length; i++){ + String newStr = origin.substring(start, i); + + if(isSame(newStr)){ + cur.add(newStr); + part(result, cur, origin, i); + cur.remove(cur.size()-1); + } + } + } + private boolean isSame(String s){ + StringBuilder sb = new StringBuilder(s); + return sb.reverse().toString().equals(s); + } +} \ No newline at end of file diff --git a/EunseoPark/Week1/LTC_Permutations.java b/EunseoPark/Week1/LTC_Permutations.java new file mode 100644 index 0000000..d4512f9 --- /dev/null +++ b/EunseoPark/Week1/LTC_Permutations.java @@ -0,0 +1,23 @@ +import java.util.*; + +class Solution { + public List> permute(int[] nums) { + List> result = new ArrayList<>(); + per(result, new ArrayList<>(), nums); + return result; + } + + private void per(List> result, List cur, int[] nums){ + if(cur.size() == nums.length){ + result.add(new ArrayList<>(cur)); + return; + } + + for(int i = 0, length = nums.length; i < length; i++){ + if(cur.contains(nums[i])) continue; + cur.add(nums[i]); + per(result, cur, nums); + cur.remove(cur.size()-1); + } + } +} \ No newline at end of file diff --git a/EunseoPark/Week1/LTC_Subsets.java b/EunseoPark/Week1/LTC_Subsets.java new file mode 100644 index 0000000..38ee515 --- /dev/null +++ b/EunseoPark/Week1/LTC_Subsets.java @@ -0,0 +1,24 @@ +import java.util.*; + +/* + [정답 참고] 0ms 43.86MB + sub 넘길때 now+1 로 시도했음 + -> 정답 참고 후 i + 1로 변경 +*/ +class Solution { + public List> subsets(int[] nums) { + List> result = new ArrayList<>(); + sub(result, new ArrayList<>(), nums, 0); + return result; + } + private void sub(List> result, List cur, int[] nums, int now){ + System.out.println(cur); + result.add(new ArrayList<>(cur)); + + for(int i = now, length = nums.length; i < length; i++){ + cur.add(nums[i]); + sub(result, cur, nums, i+1); + cur.remove(cur.size()-1); + } + } +} \ No newline at end of file diff --git a/EunseoPark/Week1/LTC_Two Sum.java b/EunseoPark/Week1/LTC_Two Sum.java new file mode 100644 index 0000000..d445b27 --- /dev/null +++ b/EunseoPark/Week1/LTC_Two Sum.java @@ -0,0 +1,49 @@ +import java.util.*; +/* + [ 1차 스스로 풀이 ] + 1. 탐색이라 O(1)인 해쉬맵이 떠오름 + 1. (값, 인덱스) 저장 -> O(N) + 2. i 돌면서 target - nums[i] && 자기 자신이 아니면 return 해당 값 -> O(N) + = O(N) + O(N) = O(2N) +*/ +class Solution { + public int[] twoSum(int[] nums, int target) { + Map hm = new HashMap<>(); + int length = nums.length; + for(int i = 0; i< length; i++){ + hm.put(nums[i], i); + } + for(int i = 0; i < length; i++){ + int t = target - nums[i]; + if(hm.containsKey(t) && hm.get(t) != i){ + return new int[]{i, hm.get(t)}; + } + } + return new int[]{}; + } +} + +import java.util.*; +/* + [ 2차 다른 코드 참고 후 최적화 ] + 1. 탐색이라 O(1)인 해쉬맵이 떠오름 + 1차 스스로 풀이에서 2번 예제의 자기 자신 제외를 저렇게 처리하지 말고 + 1. 넣을때 target -nums[i] 가 있다면 바로 return + 2. 없으면 해시 값에 추가 + = O(N) +*/ +class Solution { + public int[] twoSum(int[] nums, int target) { + Map hm = new HashMap<>(); + + for(int i = 0, length = nums.length; i< length; i++){ + int t = target - nums[i]; + if(hm.containsKey(t)){ + return new int[]{i, hm.get(t)}; + } + hm.put(nums[i], i); + } + return new int[]{}; + } +} + diff --git a/EunseoPark/Week1/LTC_Word Search.java b/EunseoPark/Week1/LTC_Word Search.java new file mode 100644 index 0000000..0bace30 --- /dev/null +++ b/EunseoPark/Week1/LTC_Word Search.java @@ -0,0 +1,102 @@ +import java.util.*; +/* + [1차 스스로 풀이] 163ms / 42.06 MB + 1. 최단거리 문제는 bfs가 더 빠르겠지만, 여기서는 순서대로 밟고 가야 하는 경로가 있으므로 dfs + 2. 보완할 점 + 1) exist함수에서 이중 for문으로 검사하는 것이 아닌 바로 dfs 호출하기 -> 기억에 안남 + 2) 재귀함수 호출하면서 return 하는 값을 잘 처리하고 싶음. +*/ +class Solution { + static int[] dy = {-1,1,0,0}, dx = {0,0,-1,1}; + static int r,c; + + public boolean exist(char[][] board, String word) { + r = board.length; c = board[0].length; + boolean[][] visited = new boolean[r][c]; + int count = 0; + boolean result = false; + + for(int i = 0 ; i < r; i++){ + for(int j = 0 ; j < c; j++){ + if(!visited[i][j] && word.charAt(count) == board[i][j]){ + visited[i][j] = true; + result = dfs(count+1, i, j, word, visited, board); + System.out.println("\n"); + if(result) return result; + visited[i][j] = false; + } + } + } + return result; + } + private boolean dfs(int count,int y, int x, String word, boolean[][] visited, char[][] board){ + if(count == word.length()) return true; + boolean result = false; + + for(int d =0; d <4; d++){ + int ny = y + dy[d], nx = x + dx[d]; + + if(inRange(ny,nx) && !visited[ny][nx] && word.charAt(count) == board[ny][nx]){ + visited[ny][nx] = true; + result = dfs(count + 1, ny, nx, word, visited,board); + if(result) return result; + visited[ny][nx] = false; + } + } + return result; + } + + private boolean inRange(int y, int x){ + return -1 < y && y < r && -1 < x && x hm = new HashMap<>(); + + for(int i = 0, length = orders.length; i < length; i++){ + // orders 돌면서 2~10개씩 combination + for(int count = 2, max = orders[i].length(); count <= max; count++){ + List combs = comb(orders[i], count); + for(String c : combs){ + hm.put(c, hm.getOrDefault(c, 0) + 1); + } + } + } + // value 값이 2 이상이면 넣기 + List ans = new ArrayList<>(); + for(Map.Entry entry : hm.entrySet()){ + if(entry.getValue() > 1) ans.add(entry.getKey()); + } + String[] answer = new String[ans.size()]; + for(int i = 0, l = ans.size(); i < l; i++){ + answer[i] = ans.get(i); + } + System.out.println(ans); + + return answer; + } + + private List comb(String order, int count){ + List result = new ArrayList<>(); + System.out.println("count = " + count +"---------------"); + makeComb(order, result, new ArrayList<>() , count, 0); + System.out.println(result); + return result; + } + + private void makeComb(String order, List result, List cur, int count, int index){ + if(cur.size() == count) { + Collections.sort(cur); //생략 가능? + StringBuilder sb = new StringBuilder(); + for(char c : cur){ + sb.append(c); + } + result.add(sb.toString()); + return; + } + + for(int i = index, length = order.length(); i < length; i++){ + cur.add(order.charAt(i)); + makeComb(order, result, cur, count, i+1); + cur.remove(cur.size()-1); + } + } +} \ No newline at end of file diff --git "a/EunseoPark/Week1/PGS_\355\224\274\353\241\234\353\217\204.java" "b/EunseoPark/Week1/PGS_\355\224\274\353\241\234\353\217\204.java" index b425429..08f2896 100644 --- "a/EunseoPark/Week1/PGS_\355\224\274\353\241\234\353\217\204.java" +++ "b/EunseoPark/Week1/PGS_\355\224\274\353\241\234\353\217\204.java" @@ -1,19 +1,26 @@ import java.util.*; - +/* + visited를 전역변수 vs 함수 인자로 넘길까 ? => 함수 인자로 넘기는 것이 더 효율적 + 1. 함수 인자로 넘겨준다고 해서 현재 visited는 배열이므로 배열의 참조값만 넘김, 값을 복사 x (성능 영향 X) + + 전역변수로 하면 코드가 깔끔하지만, Solutions 함수를 호출할 때마다 잔존 값의 영향 받을 수 있음. + 함수 인자로 넘기면 배열의 참조값만 넘기므로 성능 영향 X -> 함수 인자로 넘기는 것이 더 빨랐음 +*/ class Solution { int result; - + public int solution(int k, int[][] dungeons) { - int result = 0; + result = 0; int length = dungeons.length; boolean[] visited = new boolean[length]; - return dfs(k, dungeons, length, visited, 0); + dfs(k, dungeons, length, visited, 0); + return result; } - public int dfs(int power, int[][] dungeons, int length, boolean[] visited, int count){ - if(result == length) return result; + public void dfs(int power, int[][] dungeons, int length, boolean[] visited, int count){ + if(result == length) return; result = Math.max(result, count); for(int i = 0; i < length; i++){ @@ -24,6 +31,5 @@ public int dfs(int power, int[][] dungeons, int length, boolean[] visited, int c visited[i] = false; } } - return result; } } \ No newline at end of file