diff --git a/longest-substring-without-repeating-characters/kdh-92.java b/longest-substring-without-repeating-characters/kdh-92.java new file mode 100644 index 000000000..cde56128a --- /dev/null +++ b/longest-substring-without-repeating-characters/kdh-92.java @@ -0,0 +1,25 @@ +class Solution { + public int lengthOfLongestSubstring(String s) { + // HashSet 풀이 + // 시간복잡도 : O(n), 공간복잡도 O(1) + // 풀이 + // HashSet에 동일한 문자가 있는지 체크하고 동일한 문자가 있으면 왼쪽 기준점을 하나씩 이동 (동일 문자가 없을 때까지 반복) + // 동일한 문자가 없을 때 현재 기준(right) - 왼쪽 기준(left) + 1 의 최대 길이를 maxLength 저장 후 반환 + + int left = 0; + int maxLength = 0; + HashSet charSet = new HashSet<>(); + + for (int right = 0; right < s.length(); right++) { + while (charSet.contains(s.charAt(right))) { + charSet.remove(s.charAt(left)); + left++; + } + + charSet.add(s.charAt(right)); + maxLength = Math.max(maxLength, right - left + 1); + } + + return maxLength; + } +} diff --git a/number-of-islands/kdh-92.java b/number-of-islands/kdh-92.java new file mode 100644 index 000000000..e59b856a2 --- /dev/null +++ b/number-of-islands/kdh-92.java @@ -0,0 +1,45 @@ +class Solution { + public int numIslands(char[][] grid) { + // bfs + // 시간복잡도 : O(r * c), 공간복잡도 O(r * c) + // 풀이 + // bfs 풀이에 방문을 Set으로 설정하여 체크, directions(상하좌우)를 통해 탐색 + // 응용 가능 : 대각선 추가하여 연결된 섬 체크 + int islands = 0; + int rows = grid.length; + int cols = grid[0].length; + Set visited = new HashSet<>(); + + int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; + + for (int r = 0; r < rows; r++) { + for (int c = 0; c < cols; c++) { + if (grid[r][c] == '1' && !visited.contains(r + "," + c)) { + islands++; + bfs(grid, r, c, visited, directions, rows, cols); + } + } + } + + return islands; + } + + private void bfs(char[][] grid, int r, int c, Set visited, int[][] directions, int rows, int cols) { + Queue q = new LinkedList<>(); + visited.add(r + "," + c); + q.add(new int[]{r, c}); + + while (!q.isEmpty()) { + int[] point = q.poll(); + int row = point[0], col = point[1]; + + for (int[] direction : directions) { + int nr = row + direction[0], nc = col + direction[1]; + if (nr >= 0 && nr < rows && nc >= 0 && nc < cols && grid[nr][nc] == '1' && !visited.contains(nr + "," + nc)) { + q.add(new int[] {nr, nc}); + visited.add(nr + "," + nc); + } + } + } + } +} diff --git a/reverse-linked-list/kdh-92.java b/reverse-linked-list/kdh-92.java new file mode 100644 index 000000000..cb1de72b4 --- /dev/null +++ b/reverse-linked-list/kdh-92.java @@ -0,0 +1,18 @@ +class Solution { + public ListNode reverseList(ListNode head) { + // while 풀이 + // 시간복잡도 : O(n), 공간복잡도 : O(1) + // 핵심 : node에 순서대로 null <- 1 <- 2 <- 3 담는 과정이 필요 + // node = null로 시작하고, 다음 값을 temp에 넣어둔 뒤 순서대로 값 변경 + ListNode node = null; + + while (head != null) { + ListNode temp = head.next; + head.next = node; + node = head; + head = temp; + } + + return node; + } +} diff --git a/unique-paths/kdh-92.java b/unique-paths/kdh-92.java new file mode 100644 index 000000000..017cceb26 --- /dev/null +++ b/unique-paths/kdh-92.java @@ -0,0 +1,41 @@ +// 풀이 핵심 +// dp나 1차원 배열 2개를 이용하는 방식의 핵심은 결국 현재 값은 왼쪽 값과 상단 값이 더해진 값으로 이루어진다는 것이다. +// dp는 2차원 배열 공간 모두를 사용해야하지만, 1차원 배열 2개의 경우 2n의 공간을 이용해 현재 값을 만들어 나가게 된다. +class Solution { + public int uniquePaths(int m, int n) { + // (1) dp - 2차원 배열 이용 + // 시간복잡도 : O(m * n), 공간복잡도 : O(m * n) + int[][] dp = new int[m][n]; + + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (i == 0 && j == 0) { + dp[i][j] = 1; + continue; + } + + int pathsFromLeft = (j - 1 >= 0) ? dp[i][j - 1] : 0; + int pathsFromUp = (i - 1 >= 0) ? dp[i - 1][j] : 0; + dp[i][j] = pathsFromLeft + pathsFromUp; + } + } + + return dp[m - 1][n - 1]; + + // (2) 1차원 배열 2개 이용 + // 시간복잡도 : O(m * n), 공간복잡도 : O(n) + int[] aboveRow = new int[n]; + Arrays.fill(aboveRow, 1); + + for (int row = 1; row < m; row++) { + int[] currentRow = new int[n]; + Arrays.fill(currentRow, 1); + for (int col = 1; col < n; col++) { + currentRow[col] = currentRow[col - 1] + aboveRow[col]; + } + aboveRow = currentRow; + } + + return aboveRow[n - 1]; + } +}