diff --git a/find-minimum-in-rotated-sorted-array/imsosleepy.java b/find-minimum-in-rotated-sorted-array/imsosleepy.java new file mode 100644 index 000000000..8ea7a77bc --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/imsosleepy.java @@ -0,0 +1,21 @@ +// 정렬을 하고하면 O(nlogn)이 나온다. +// 정렬이 되어있다 가정할 수 있으니 배열을 모두 탐색해서 편차가 가장 큰걸 찾으면 O(n) +// 위 두 방법은 속도가 너무 느리게 나와서 다른 방법을 찾아보니 +// 가장 빠른 방법은 최소값만 찾으면 되니 이진 탐색으로 찾으면 O(logn) +class Solution { + public int findMin(int[] nums) { + int left = 0, right = nums.length - 1; + + while (left < right) { + int mid = left + (right - left) / 2; // 중간 인덱스 + + if (nums[mid] > nums[right]) { + left = mid + 1; + } else { + right = mid; + } + } + + return nums[left]; + } +} diff --git a/linked-list-cycle/imsosleepy.java b/linked-list-cycle/imsosleepy.java new file mode 100644 index 000000000..9db13eb89 --- /dev/null +++ b/linked-list-cycle/imsosleepy.java @@ -0,0 +1,34 @@ +// 단순 루프 방식이 너무 오래걸려서 다른 방식을 찾아봄 +public class Solution { + public boolean hasCycle(ListNode head) { + HashSet visited = new HashSet<>(); + while (head != null) { + if (visited.contains(head)) { + return true; // 사이클 존재 + } + visited.add(head); + head = head.next; + } + return false; // 사이클 없음 + } +} + +// 투포인터로 해결 +public class Solution { + public boolean hasCycle(ListNode head) { + if (head == null || head.next == null) return false; + + ListNode slow = head; + ListNode fast = head; + + while (fast != null && fast.next != null) { + slow = slow.next; // 한 칸 이동 + fast = fast.next.next; // 두 칸 이동 + + if (slow == fast) { + return true; // 사이클 존재 + } + } + return false; // 사이클 없음 + } +} diff --git a/maximum-product-subarray/imsosleepy.java b/maximum-product-subarray/imsosleepy.java new file mode 100644 index 000000000..16aec0f07 --- /dev/null +++ b/maximum-product-subarray/imsosleepy.java @@ -0,0 +1,22 @@ +// dp인건 부분 배열 문제인걸 확인하고 바로 알아차림 +// 그런데 음수일때를 고려못해서 한참헤멤. 2번째 예제가 음수가 있을 수 있음을 알려주는 거였따... +class Solution { + public int maxProduct(int[] nums) { + int n = nums.length; + int[] maxProd = new int[n]; + int[] minProd = new int[n]; + + maxProd[0] = nums[0]; + minProd[0] = nums[0]; // 음수일 경우를 대비 + int result = nums[0]; + + for (int i = 1; i < n; i++) { + maxProd[i] = Math.max(nums[i], Math.max(nums[i] * maxProd[i - 1], nums[i] * minProd[i - 1])); + minProd[i] = Math.min(nums[i], Math.min(nums[i] * maxProd[i - 1], nums[i] * minProd[i - 1])); + + result = Math.max(result, maxProd[i]); + } + + return result; + } +} diff --git a/minimum-window-substring/imsosleepy.java b/minimum-window-substring/imsosleepy.java new file mode 100644 index 000000000..519101274 --- /dev/null +++ b/minimum-window-substring/imsosleepy.java @@ -0,0 +1,56 @@ +// DP라 생각하고 시간을 너무 많이써서 GPT에게 물어보니 아예 접근 자체를 잘못함 +// 다시 생각해봐야할듯 +class Solution { + public String minWindow(String s, String t) { + if (s == null || s.length() == 0 || t == null || t.length() == 0) return ""; + + // 1️⃣ t의 문자 개수를 카운트해서 저장 + Map tCount = new HashMap<>(); + for (char c : t.toCharArray()) { + tCount.put(c, tCount.getOrDefault(c, 0) + 1); + } + int required = tCount.size(); // 필요한 고유 문자 개수 + + // 2️⃣ 슬라이딩 윈도우 변수 초기화 + int left = 0, right = 0; // 윈도우 포인터 + int formed = 0; // t의 문자 개수를 만족하는 개수 + Map windowCounts = new HashMap<>(); + + int minLength = Integer.MAX_VALUE; + int startIdx = 0; + + // 3️⃣ 슬라이딩 윈도우 확장 + while (right < s.length()) { + char c = s.charAt(right); + windowCounts.put(c, windowCounts.getOrDefault(c, 0) + 1); + + if (tCount.containsKey(c) && windowCounts.get(c).intValue() == tCount.get(c).intValue()) { + formed++; + } + + // 4️⃣ 모든 문자가 포함되었을 때, 윈도우 크기를 줄이면서 최소 길이 찾기 + while (left <= right && formed == required) { + char leftChar = s.charAt(left); + + // 최소 길이 갱신 + if (right - left + 1 < minLength) { + minLength = right - left + 1; + startIdx = left; + } + + // 윈도우 크기를 줄이기 위해 left 이동 + windowCounts.put(leftChar, windowCounts.get(leftChar) - 1); + if (tCount.containsKey(leftChar) && windowCounts.get(leftChar) < tCount.get(leftChar)) { + formed--; + } + + left++; + } + + right++; + } + + // 5️⃣ 결과 반환 + return (minLength == Integer.MAX_VALUE) ? "" : s.substring(startIdx, startIdx + minLength); + } +} diff --git a/pacific-atlantic-water-flow/imsosleepy.java b/pacific-atlantic-water-flow/imsosleepy.java new file mode 100644 index 000000000..a89278f1c --- /dev/null +++ b/pacific-atlantic-water-flow/imsosleepy.java @@ -0,0 +1,103 @@ +// 개인적으로 행렬에서 전파되는 방식은 BFS를 이용한 구현 방식을 선호한다. +// 최적의 실행시간이 나오지 않는 것 같아서 DFS로 선회 +class Solution { + private int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; + private int m, n; + + public List> pacificAtlantic(int[][] heights) { + m = heights.length; + n = heights[0].length; + + boolean[][] pacific = new boolean[m][n]; + boolean[][] atlantic = new boolean[m][n]; + List> result = new ArrayList<>(); + + + for (int i = 0; i < m; i++) { + dfs(heights, pacific, i, 0); + dfs(heights, atlantic, i, n - 1); + } + for (int j = 0; j < n; j++) { + dfs(heights, pacific, 0, j); + dfs(heights, atlantic, m - 1, j); + } + + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (pacific[i][j] && atlantic[i][j]) { + result.add(Arrays.asList(i, j)); + } + } + } + + return result; + } + + private void dfs(int[][] heights, boolean[][] visited, int x, int y) { + visited[x][y] = true; + for (int[] dir : directions) { + int newX = x + dir[0], newY = y + dir[1]; + if (newX >= 0 && newX < m && newY >= 0 && newY < n && !visited[newX][newY] && heights[newX][newY] >= heights[x][y]) { + dfs(heights, visited, newX, newY); + } + } + } +} + +class Solution { + private int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; + private int m, n; + + public List> pacificAtlantic(int[][] heights) { + m = heights.length; + n = heights[0].length; + + boolean[][] pacific = new boolean[m][n]; + boolean[][] atlantic = new boolean[m][n]; + List> result = new ArrayList<>(); + + Queue pacificQueue = new LinkedList<>(); + Queue atlanticQueue = new LinkedList<>(); + + for (int i = 0; i < m; i++) { + pacificQueue.offer(new int[]{i, 0}); + atlanticQueue.offer(new int[]{i, n - 1}); + pacific[i][0] = true; + atlantic[i][n - 1] = true; + } + for (int j = 0; j < n; j++) { + pacificQueue.offer(new int[]{0, j}); + atlanticQueue.offer(new int[]{m - 1, j}); + pacific[0][j] = true; + atlantic[m - 1][j] = true; + } + + bfs(heights, pacificQueue, pacific); + bfs(heights, atlanticQueue, atlantic); + + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (pacific[i][j] && atlantic[i][j]) { + result.add(Arrays.asList(i, j)); + } + } + } + + return result; + } + + private void bfs(int[][] heights, Queue queue, boolean[][] visited) { + while (!queue.isEmpty()) { + int[] cell = queue.poll(); + int x = cell[0], y = cell[1]; + + for (int[] dir : directions) { + int newX = x + dir[0], newY = y + dir[1]; + if (newX >= 0 && newX < m && newY >= 0 && newY < n && !visited[newX][newY] && heights[newX][newY] >= heights[x][y]) { + queue.offer(new int[]{newX, newY}); + visited[newX][newY] = true; + } + } + } + } +}