diff --git a/linked-list-cycle/Tessa1217.java b/linked-list-cycle/Tessa1217.java new file mode 100644 index 000000000..f4f27b2fc --- /dev/null +++ b/linked-list-cycle/Tessa1217.java @@ -0,0 +1,57 @@ +/** + * Definition for singly-linked list. + * class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +/** + * head는 연결 리스트의 헤드다. + * 특정 노드가 리스트 내의 다른 노드와 next 포인트를 통해 연결되어 있을 때 이 리스트에는 사이클이 있다고 할 수 있다. + * pos는 next 포인터와 연결된 노드의 인덱스를 나타내는데 쓰이며 pos는 파라미터로 주어지지 않는다. + * 주어진 리스트에 사이클이 있다면 true를 그렇지 않다면 false를 반환하세요. + * */ +public class Solution { + + // 시간복잡도: O(n), 공간복잡도: O(1) + public boolean hasCycle(ListNode head) { + if (head == null) { + return false; + } + + ListNode next = head; + ListNode furtherNext = head; + + while (furtherNext != null && furtherNext.next != null) { + next = next.next; + furtherNext = furtherNext.next.next; + if (next == furtherNext) { + return true; + } + } + + return false; + } + + // head 없을 때까지 계속 탐색 반복 : 시간복잡도, 공간복잡도 O(n) + // public boolean hasCycle(ListNode head) { + + // Set nodeSet = new HashSet<>(); + + // while (head != null) { + // if (nodeSet.contains(head)) { + // return true; + // } + // nodeSet.add(head); + // head = head.next; + // } + + // return false; + + // } +} + diff --git a/maximum-product-subarray/Tessa1217.java b/maximum-product-subarray/Tessa1217.java new file mode 100644 index 000000000..24cef59a4 --- /dev/null +++ b/maximum-product-subarray/Tessa1217.java @@ -0,0 +1,42 @@ +class Solution { + + // 시간복잡도: O(n) + public int maxProduct(int[] nums) { + + if (nums == null || nums.length == 0) { + return 0; + } + + // 최대 곱 케이스 + int maxProduct = nums[0]; + // 최소 곱 케이스 + int minProduct = nums[0]; + // 최대 값 + int max = nums[0]; + + // DP로 풀이하였지만 음수 * 음수의 반례 케이스 발생하여 해당 풀이로 수정 + // Test Case : [-2, 3, -4] => dp로 풀이 시 3이 반환되는 문제 있었음 + + for (int i = 1; i < nums.length; i++) { + + int current = nums[i]; + + // 음수일 경우 : 최소 곱과 최대 곱 위치 바꿈 + if (current < 0) { + int tempMax = maxProduct; + maxProduct = Math.max(current, minProduct * current); + minProduct = Math.min(current, tempMax * current); + } else { + maxProduct = Math.max(current, maxProduct * current); + minProduct = Math.min(current, minProduct * current); + } + + max = Math.max(max, maxProduct); + + } + + return max; + + } +} + diff --git a/minimum-window-substring/Tessa1217.java b/minimum-window-substring/Tessa1217.java new file mode 100644 index 000000000..b8c1c2088 --- /dev/null +++ b/minimum-window-substring/Tessa1217.java @@ -0,0 +1,70 @@ +import java.util.HashMap; +import java.util.Map; + +class Solution { + + // 시간복잡도: O(n), 공간복잡도 O(1) + public String minWindow(String s, String t) { + + int strLength = s.length(); + int targetLength = t.length(); + + // 목표 분자열이 주어진 문자열보다 길다면 부분 문자열로 볼 수 없음 + if (targetLength > strLength) { + return ""; + } + + // 목표 문자열에 필요한 문자와 그 개수를 담는 맵 + Map charMap = new HashMap<>(); + + for (char c : t.toCharArray()) { + charMap.put(c, charMap.getOrDefault(c, 0) + 1); + } + + // 투 포인터 선언 + int left = 0; + int right = 0; + int minWindowLength = Integer.MAX_VALUE; + int minWindowStart = 0; // 최소 윈도우 시작 위치 + int remaining = targetLength; + + while (right < strLength) { + + Character end = s.charAt(right); + + if (charMap.containsKey(end)) { + charMap.put(end, charMap.get(end) - 1); + if (charMap.get(end) >= 0) { + remaining--; + } + } + + // target 문자열의 모든 문자를 찾았다면 left 포인터 이동하면서 + // 최소 윈도우 찾기 시작 + while (remaining == 0) { + if (right - left + 1 < minWindowLength) { + minWindowLength = right - left + 1; + minWindowStart = left; + } + + char startChar = s.charAt(left); + if (charMap.containsKey(startChar)) { + charMap.put(startChar, charMap.get(startChar) + 1); + if (charMap.get(startChar) > 0) { + remaining++; + } + } + + left++; + } + + right++; + + } + + return minWindowLength == Integer.MAX_VALUE ? "" + : s.substring(minWindowStart, minWindowStart + minWindowLength); + + } +} + diff --git a/pacific-atlantic-water-flow/Tessa1217.java b/pacific-atlantic-water-flow/Tessa1217.java new file mode 100644 index 000000000..bb52a2cb0 --- /dev/null +++ b/pacific-atlantic-water-flow/Tessa1217.java @@ -0,0 +1,140 @@ +import java.util.ArrayList; +import java.util.List; + +class Solution { + + int[] dx = {1, -1, 0, 0}; + int[] dy = {0, 0, 1, -1}; + // boolean[][] visited; + int width, height; + + // 시간복잡도, 공간복잡도: O(m * n) + public List> pacificAtlantic(int[][] heights) { + height = heights.length; + width = heights[0].length; + + boolean[][] pacific = new boolean[height][width]; + boolean[][] atlantic = new boolean[height][width]; + + /** + * 가장자리에 도달하는 경로를 일일이 탐색하는 것이 아닌 + 가장자리부터 물이 흐를 수 있는 경로를 역으로 탐색 + */ + + // height check + for (int i = 0; i < height; i++) { + dfs(i, 0, heights, pacific); + dfs(i, width - 1, heights, atlantic); + } + + // width check + for (int j = 0; j < width; j++) { + dfs(0, j, heights, pacific); + dfs(height - 1, j, heights, atlantic); + } + + List> answer = new ArrayList<>(); + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + if (pacific[i][j] && atlantic[i][j]) { + answer.add(List.of(i, j)); + } + } + } + + return answer; + } + + private void dfs(int x, int y, int[][] heights, boolean[][] visited) { + visited[x][y] = true; + for (int i = 0; i < 4; i++) { + int nx = x + dx[i]; + int ny = y + dy[i]; + if (nx >= 0 && nx < height && ny >= 0 && ny < width) { + if (!visited[nx][ny] && heights[nx][ny] >= heights[x][y]) { + dfs(nx, ny, heights, visited); + } + } + } + } + + // public List> pacificAtlantic(int[][] heights) { + // height = heights.length; + // width = heights[0].length; + // visited = new boolean[height][width]; + + // List> answer = new ArrayList<>(); + // for (int i = 0; i < height; i++) { + // for (int j = 0; j < width; j++) { + // WaterFlow checkWaterFlow = dfs(i, j, new WaterFlow(), heights); + // if (checkWaterFlow.crossBothOceans()) { + // List coordinate = List.of(i, j); + // answer.add(coordinate); + // } + // } + // } + // return answer; + // } + + // private WaterFlow dfs(int x, int y, WaterFlow checkWaterFlow, int[][] heights) { + // /** + // 0, 0 | 0, 1 | 0, 2 | 0, 3 | 0, 4 + // 1, 0 | 2, 0 | 3, 0 | 4, 0 + // */ + // if (x == 0 || y == 0) { + // checkWaterFlow.crossPacificFlow(); + // } + // /** + // 4, 0 | 4, 1 | 4, 2 | 4, 3 | 4, 4 + // 3, 4 | 2, 4 | 1, 4 | 0, 4 + // */ + // if (x == height - 1 || y == width - 1) { + // checkWaterFlow.crossAtlanticFlow(); + // } + + // if (checkWaterFlow.crossBothOceans()) { + // return checkWaterFlow; + // } + + // visited[x][y] = true; + + // for (int i = 0; i < 4; i++) { + // int nx = x + dx[i]; + // int ny = y + dy[i]; + // if (nx >= 0 && nx < height && ny >= 0 && ny < width) { + // if (!visited[nx][ny] && heights[nx][ny] <= heights[x][y]) { + // dfs(nx, ny, checkWaterFlow, heights); + // } + // } + // } + // visited[x][y] = false; + + // return checkWaterFlow; + // } + + // static class WaterFlow { + + // private boolean pacificFlow; + + // private boolean atlanticFlow; + + // WaterFlow() { + // pacificFlow = false; + // atlanticFlow = false; + // } + + // public void crossPacificFlow() { + // pacificFlow = true; + // } + + // public void crossAtlanticFlow() { + // atlanticFlow = true; + // } + + // public boolean crossBothOceans() { + // return pacificFlow && atlanticFlow; + // } + + // } +} + diff --git a/sum-of-two-integers/Tessa1217.java b/sum-of-two-integers/Tessa1217.java new file mode 100644 index 000000000..ef468f3b8 --- /dev/null +++ b/sum-of-two-integers/Tessa1217.java @@ -0,0 +1,26 @@ +/** +, - 부호 쓰지 않고 두 수의 합 구하기 */ +class Solution { + + // 비트 연산으로 계산 수행 + public int getSum(int a, int b) { + while (b != 0) { + // 왼쪽 쉬프트하여 자리 올림에 대한 계산 수행 + int bit = (a & b) << 1; + // XOR 연산으로 자리 올림 없는 덧셈 수행 + a = a ^ b; + b = bit; + } + return a; + } + + /** + * 풀리기는 하지만, 이런 식은 편법일 것 같은...? + * Class Integer 내부에 sum 연산: Adds two integers together as per the + operator. + * + operator 쓴다고 되어있음... + * */ +// public int getSum(int a, int b) { +// return Integer.sum(a, b); +// } + +} +