Skip to content

[Tessa1217] Week 09 Solutions #1524

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions linked-list-cycle/Tessa1217.java
Original file line number Diff line number Diff line change
@@ -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<ListNode> nodeSet = new HashSet<>();

// while (head != null) {
// if (nodeSet.contains(head)) {
// return true;
// }
// nodeSet.add(head);
// head = head.next;
// }

// return false;

// }
}

42 changes: 42 additions & 0 deletions maximum-product-subarray/Tessa1217.java
Original file line number Diff line number Diff line change
@@ -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;

}
}

70 changes: 70 additions & 0 deletions minimum-window-substring/Tessa1217.java
Original file line number Diff line number Diff line change
@@ -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<Character, Integer> 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);

}
}

140 changes: 140 additions & 0 deletions pacific-atlantic-water-flow/Tessa1217.java
Original file line number Diff line number Diff line change
@@ -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<List<Integer>> 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<List<Integer>> 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<List<Integer>> pacificAtlantic(int[][] heights) {
// height = heights.length;
// width = heights[0].length;
// visited = new boolean[height][width];

// List<List<Integer>> 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<Integer> 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;
// }

// }
}

26 changes: 26 additions & 0 deletions sum-of-two-integers/Tessa1217.java
Original file line number Diff line number Diff line change
@@ -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);
// }

}