Skip to content

[jaejeong1] WEEK 09 Solutions #522

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 2 commits into from
Oct 13, 2024
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
23 changes: 23 additions & 0 deletions find-minimum-in-rotated-sorted-array/jaejeong1.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class Solution {
public int findMin(int[] nums) {
// TC: O(log N)
// SC: O(1)
var left = 1; // N번 회전해 이미 오름차순 정렬일 경우 0으로 시작하면 루프가 안끝남. 1로 시작
Copy link
Contributor

@obzva obzva Oct 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left를 0으로 초기화하면서 재정님의 이진탐색을 자연스럽게 종료시키는 방법을 생각해보았습니다

class Solution {
  public int findMin(int[] nums) {
    // TC: O(log N)
    // SC: O(1)
    var left = 0;
    var right = nums.length-1;

    while (left <= right) { // left가 right보다 작거나 같을때까지
      var mid = (left + right) / 2;
      if (nums[mid] <= nums[right]) {
        right = mid - 1;
      } else {
        left = mid + 1;
      }
    }

    return nums[left]; // 만약 Rotation이 없는 배열일 경우 left는 0이 되고, Rotation이 있는 배열일 경우엔 right와 left가 엇갈리는 부분이 Rotation의 경계가 되도록 이진탐색이 종료됨
  }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋은 피드백 및 코드 예시 감사합니다!
특히 마지막 comment 주신 부분이 큰 도움이 되었습니다.
// 만약 Rotation이 없는 배열일 경우 left는 0이 되고, Rotation이 있는 배열일 경우엔 right와 left가 엇갈리는 부분이 Rotation의 경계가 되도록 이진탐색이 종료됨

참고해서 리팩토링 진행해보겠습니다 :) 감사합니다!!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@obzva 님, 제안해주신 코드에 버그가 있는 것 같은데용? 😵
예를 들어, 입력으로 [9,4,6]이 주어지면 4 대신에 9가 나올 것 같습니다...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

확인했습니다 정말이네요 😟

var right = nums.length-1;

while (left <= right) { // left가 right보다 작거나 같을때까지
var mid = (left + right) / 2;
if (nums[mid - 1] > nums[mid]) { // mid - 1 요소가 mid 보다 값이 크면 변곡점을 찾은 것. 그대로 반환
return nums[mid];
}

if (nums[mid] > nums[0]) { // 변곡점이 아니고, 0번째 인덱스보다 mid 요소가 값이 크면 정렬이 잘 되어 있는것. 오른쪽으로 탐색
left = mid + 1;
} else {
right = mid - 1;
}
}

return nums[0]; // N번 회전해 이미 오름차순 정렬일 경우 0번째 인덱스 요소 반환
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 이렇게 되면 더 좋겠다는 생각을 했습니다 :)
물론 그냥 개인적인 욕심입니다..

  1. 이진탐색으로는 N번 회전해 이미 오름차순 정렬인 경우의 답을 return할 수 없다면, 애초에 이진탐색을 수행하기 전에 nums[0]을 return 해주기
if (nums[0] < nums[nums.length - 1]) {
  return nums[0];
}
// 이후 이진탐색 관련된 로직 등장
  1. 아예 N번 회전해 이미 오름차순 정렬인 경우도 이진탐색에서 자연스럽게 도출될 수 있게끔 로직 설계

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@obzva 좋은 피드백 감사합니다. 알고리즘 문제풀때는 유독 가독성에 신경을 덜쓰게 되는 경향이 있는데, 다시 한번 중요성을 느낍니다.. 개인적으로는 1번 처럼 early return 해주는 방식을 선호합니다 :)

}
}
46 changes: 46 additions & 0 deletions linked-list-cycle/jaejeong1.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//Definition for singly-linked list.
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}

class Solution {
public boolean hasCycle(ListNode head) {
// 풀이 1: Set에 객체를 집어 넣고, 사이즈가 안늘어나면 사이클이 있다고 판단할 수 있다
// TC: O(N)
// SC: O(N)
// Set<ListNode> set = new HashSet<>();
//
// while(head != null) {
// var before = set.size();
// set.add(head);
// var after = set.size();
// if (before == after) {
// return true;
// }
// head = head.next;
// }
//
// return false;

// 풀이 2: 두개의 포인터를 사용해 첫번째 포인터는 하나씩, 두번째 포인터는 두개씩 순환하다 겹치는 부분이 생기면 순환이라고 판단할 수 있다
// TC: O(N)
// SC: O(1)
var slow = head;
var fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;

if (slow == fast) {
return true;
}
}

return false;
}
}