- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 195
[forest000014] Week 09 #994
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
Changes from all commits
c74e278
eae19b9
e7d423e
7eac78a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,38 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||
/* | ||||||||||||||||||||||||||||||||||||||||||||||||||
# Time Complexity: O(logn) | ||||||||||||||||||||||||||||||||||||||||||||||||||
# Space Complexity: O(1) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
binary search를 사용해 접근했습니다. | ||||||||||||||||||||||||||||||||||||||||||||||||||
sorted array인 경우는 while문 시작 전, 예외 체크를 했습니다. | ||||||||||||||||||||||||||||||||||||||||||||||||||
binary search를 진행하면, 각각의 loop의 mid 원소는 아래 4가지 경우 중 하나입니다. | ||||||||||||||||||||||||||||||||||||||||||||||||||
maximum / minimum / 앞쪽 수열의 원소 중 하나 / 뒤쪽 수열의 원소 중 하나 | ||||||||||||||||||||||||||||||||||||||||||||||||||
maximum이거나 minimum인 경우는 더 이상 탐색할 필요 없이 종료합니다. | ||||||||||||||||||||||||||||||||||||||||||||||||||
앞쪽 수열인 경우, 우리가 원하는 minimum은 왼쪽에는 없으므로, left 포인터를 mid의 오른쪽으로 옮기고 다음 loop를 진행하고, | ||||||||||||||||||||||||||||||||||||||||||||||||||
뒤쪽 수열인 경우, 우리가 원하는 minimum은 오른쪽에는 없으므로, rigth 포인터를 mid의 왼쪽으로 옮기고 다음 loop를 진행합니다. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||||||||
class Solution { | ||||||||||||||||||||||||||||||||||||||||||||||||||
public int findMin(int[] nums) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
int l = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||
int r = nums.length - 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
if (nums[l] <= nums[r]) { // sorted array인 경우 (size가 1인 경우도 포함) | ||||||||||||||||||||||||||||||||||||||||||||||||||
return nums[l]; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
while (l <= r) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
int m = (r - l) / 2 + l; // 만약 문제 조건상 l, r의 합이 int 범위를 넘어가서 overflow가 생길 수 있는 경우에, 이런 식으로 overflow를 방지할 수 있다고 알고 있습니다. 이 문제는 overflow 걱정은 없지만, 나중에 실전에서 나오면 잊지 않으려고 이렇게 구현해보았습니다. | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (m > 0 && nums[m - 1] > nums[m]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
return nums[m]; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (m < nums.length - 1 && nums[m] > nums[m + 1]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
return nums[m + 1]; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (nums[m] > nums[l]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
l = m + 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||
r = m - 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+25
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 조건문을 세 부분으로 줄일 수는 없을까 고민해봤습니다 :)
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
return -1; | ||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. -1을 리턴하는 경우는 없을 것 같아요 :) |
||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/** | ||
# Time Complexity : O(n) | ||
# Space Complexity: O(1) | ||
|
||
* Definition for singly-linked list. | ||
* class ListNode { | ||
* int val; | ||
* ListNode next; | ||
* ListNode(int x) { | ||
* val = x; | ||
* next = null; | ||
* } | ||
* } | ||
*/ | ||
public class Solution { | ||
private final int VISITED = -999999; | ||
public boolean hasCycle(ListNode head) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 좋은 접근인 것 같습니다 :) 리스트노드의 acyclic 여부를 판명하는 잘 알려진 알고리즘이 있으니 소개드립니다, 참고 바랍니다 :) |
||
while (head != null) { | ||
if (head.val == VISITED) { | ||
return true; | ||
} | ||
|
||
head.val = VISITED; | ||
head = head.next; | ||
} | ||
|
||
return false; | ||
} | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그동안 forest님 풀이를 봐오면서 느낀건데, 문제를 작은 단위로 쪼개어서 해결하는 능력과 끝까지 문제를 해결해내는 능력이 훌륭하십니다 :) 절대 이 풀이가 나쁘다는 건 아니구요, 리뷰어 입장에서 느꼈던 피드백 사항이 몇가지 있어 조심스레 남기고자 합니다
좀 더 간단한 로직을 사용하는 풀이를 하나 소개드리니, 참고 바랍니다 :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @obzva |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/* | ||
# Time Complexity: O(n) | ||
|
||
# Space Complexity: O(1) | ||
|
||
# Solution | ||
1. array에 0이 존재하는 경우 | ||
|
||
(observation: 정답이 음수가 될 가능성이 있는가? Yes. 다만, 원소 개수가 1개이고, 그 원소가 음수인 경우에만 그렇다. 음수인 원소가 2개 이상인 경우는 subarray를 잘 선택하면 그 곱을 항상 0 이상으로 만들 수 있다. 즉, 원소 개수가 1개이고 음수인 경우만 예외 처리를 해주면, 그 외의 경우는 정답이 0이거나 양수이다.) | ||
|
||
subarray에 0이 포함되는 순간 곱은 0이 되므로, 0보다 큰 곱을 찾기 위해서는 0을 제외하고 판단한다. | ||
즉, 0을 기준으로 slice해서, 각각의 segment만 독립적으로 검토하면 된다. (0으로 slice한 각 segment가 아래 2번 케이스로 환원된다.) | ||
|
||
2. (sub)array에 0이 존재하지 않는 경우 | ||
음수의 개수에 따라 접근을 다르게 한다. | ||
|
||
2-1. 짝수개 | ||
고민할 것 없이, 전체 subarray의 원소를 곱하면 그 subarray에서 얻을 수 있는 곱의 최대값이다. | ||
|
||
2-2. 홀수개 | ||
subarray 양 끝에서 각각 출발하여 최초의 마이너스(즉 가장 바깥쪽의 마이너스)를 만날 때까지, 원소들을 누적해서 곱하며 이동. | ||
두 값 중 절대값이 작은 쪽을 subarray에서 제외. 남은 부분의 곱을 구하면, 최대값이다. | ||
*/ | ||
|
||
class Solution { | ||
public int maxProduct(int[] nums) { | ||
if (nums.length == 1) { | ||
return nums[0]; | ||
} | ||
|
||
int ans = 0; | ||
int start = 0; | ||
for (int i = 0; i < nums.length; i++) { | ||
if (nums[i] != 0) { | ||
continue; | ||
} | ||
|
||
if (i > 0) { | ||
int res = calculateMaxProduct(start, i - 1, nums); | ||
ans = Math.max(ans, res); | ||
} | ||
start = i + 1; | ||
} | ||
|
||
if (start <= nums.length - 1) { | ||
int res = calculateMaxProduct(start, nums.length - 1, nums); | ||
ans = Math.max(ans, res); | ||
} | ||
|
||
return ans; | ||
} | ||
|
||
private int calculateMaxProduct(int l, int r, int[] nums) { | ||
if (l == r) { | ||
return nums[l]; | ||
} | ||
|
||
int minusCount = 0; | ||
int product = 1; | ||
for (int i = l; i <= r; i++) { | ||
if (nums[i] < 0) { | ||
minusCount++; | ||
} | ||
product *= nums[i]; | ||
} | ||
|
||
if (minusCount % 2 == 0) { | ||
return product; | ||
} else { | ||
int leftProduct = 1; | ||
for (int i = l; i <= r; i++) { | ||
leftProduct *= nums[i]; | ||
if (nums[i] < 0) { | ||
break; | ||
} | ||
} | ||
|
||
int rightProduct = 1; | ||
for (int i = r; i >= l; i--) { | ||
rightProduct *= nums[i]; | ||
if (nums[i] < 0) { | ||
break; | ||
} | ||
} | ||
|
||
return product / Math.max(leftProduct, rightProduct); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍