Skip to content

[forest000014] Week 08 #968

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 7 commits into from
Jan 31, 2025
Merged

[forest000014] Week 08 #968

merged 7 commits into from
Jan 31, 2025

Conversation

forest000014
Copy link
Contributor

@forest000014 forest000014 commented Jan 28, 2025

답안 제출 문제

체크 리스트

  • 우측 메뉴에서 PR을 Projects에 추가해주세요.
  • Projects의 오른쪽 버튼(▼)을 눌러 확장한 뒤, Week를 현재 주차로 설정해주세요.
  • 바로 앞에 PR을 열어주신 분을 코드 검토자로 지정해주세요.
  • 문제를 모두 푸시면 프로젝트에서 StatusIn Review로 설정해주세요.
  • 코드 검토자 1분 이상으로부터 승인을 받으셨다면 PR을 병합해주세요.

@forest000014 forest000014 requested a review from mmyeon January 28, 2025 16:08
@forest000014 forest000014 self-assigned this Jan 28, 2025
@forest000014 forest000014 requested a review from a team as a code owner January 28, 2025 16:08
@github-actions github-actions bot added the java label Jan 28, 2025
@forest000014
Copy link
Contributor Author

forest000014 commented Jan 28, 2025

#232 number of 1 Bits의 경우, solution 1만 제 아이디어이고, 나머지는 검색을 통해서 추가로 공부한 풀이입니다.

@forest000014
Copy link
Contributor Author

#244 Longest Repeating Character Replacement 풀이의 분류는 투 포인터 기법이라고 생각했는데, (Dale님의 설명처럼) (가변 길이) 슬라이딩 윈도우라고 보는 게 좀 더 적절할 것 같네요. 단순히 왼쪽/오른쪽 포인터를 이동한다-라는 개념보다는, 양 끝 사이의 윈도우 내에 포함되어있는 문자의 개수를 카운팅한다는 것을 고려하면, '윈도우'라고 하는 게 더 맞을 것 같다는 생각입니다. 코치님은 어떻게 생각하시나요?

@forest000014
Copy link
Contributor Author

#259 Clone Graph 문제에서, Dale님의 풀이에서는 이미 복제한 노드를 다시 복제하지 않기 위해 clone 해시 테이블을 사용하셨는데요. 저는 모든 노드가 다른 값을 가진다는 점에 착안해서, val에 해당하는 Node 인스턴스를 저장해두고 사용하는 식으로 구현했습니다. (주석에는 싱글톤이라고 적었는데, 생각해보니 클래스 당 인스턴스 1개가 아니라서 싱글톤이라는 표현은 적절하지 않을 것 같네요.)
이렇게 구현하는 경우에 단점이 있을까요? (개인적으로는 clone 해시 테이블과 비교했을 때 메모리 사용도 비슷하고, 속도 측면에서도 큰 차이가 없지 않을까 생각합니다 🤔)

Copy link
Contributor

@TonyKim9401 TonyKim9401 left a comment

Choose a reason for hiding this comment

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

7주차 문제 풀이 고생 많으셨습니다!
각종 시도하신 방법들 정리된 것과 자신만의 해답을 어떻게든 찾아내신게 너무 멋있고 존경스럽습니다.
8주차 문제 풀이도 파이팅입니다!

@obzva
Copy link
Contributor

obzva commented Jan 31, 2025

#244 Longest Repeating Character Replacement 풀이의 분류는 투 포인터 기법이라고 생각했는데, (Dale님의 설명처럼) (가변 길이) 슬라이딩 윈도우라고 보는 게 좀 더 적절할 것 같네요. 단순히 왼쪽/오른쪽 포인터를 이동한다-라는 개념보다는, 양 끝 사이의 윈도우 내에 포함되어있는 문자의 개수를 카운팅한다는 것을 고려하면, '윈도우'라고 하는 게 더 맞을 것 같다는 생각입니다. 코치님은 어떻게 생각하시나요?

슬라이딩 윈도우 기법을 사용하기 위해 포인터를 두 개 쓰니까, 슬라이딩 윈도우는 투 포인터에 포함되는 개념 아닐까요? (왕개인적인 생각입니다)

@obzva
Copy link
Contributor

obzva commented Jan 31, 2025

@forest000014

#259 Clone Graph 문제에서, Dale님의 풀이에서는 이미 복제한 노드를 다시 복제하지 않기 위해 clone 해시 테이블을 사용하셨는데요. 저는 모든 노드가 다른 값을 가진다는 점에 착안해서, val에 해당하는 Node 인스턴스를 저장해두고 사용하는 식으로 구현했습니다. (주석에는 싱글톤이라고 적었는데, 생각해보니 클래스 당 인스턴스 1개가 아니라서 싱글톤이라는 표현은 적절하지 않을 것 같네요.)
이렇게 구현하는 경우에 단점이 있을까요? (개인적으로는 clone 해시 테이블과 비교했을 때 메모리 사용도 비슷하고, 속도 측면에서도 큰 차이가 없지 않을까 생각합니다 🤔)

일단 풀이 잘 보았습니다 :) 풀이에 대한 코멘트 또한 남겨놓았습니다.
제가 Java를 잘 몰라서 찾아보니 Map<Node, Node> 타입의 해시맵을 만든다고 치면, 해당 해시맵의 key, value에는 각각 Node를 가리키는 reference가 저장된다고 하네요 (맞나요?)
그렇다고 치면 제 생각엔 Map<reference, reference> <-> Map<Integer, reference> 사이에서는 큰 차이가 있을 것 같진 않다고 생각합니다
만약 제가 알아본게 틀리다면 알려주세요!


# Space Complexity: O(n)
- 전체 Node 만큼의 메모리가 필요하다.
(Space Complexity를 계산하기 애매한 측면이 있네요. 저는 지금까지 출력은 space complexity에 포함하지 않고 계산했었는데, 그 이유는 "어떤 알고리즘을 구현하든 출력은 동일하기 때문"인데요. 이 문제의 경우에 출력은 Node 하나이지만, 실제로는 Node 전체만큼의 메모리를 반드시 생성해야 한다는 특수성이 있습니다. 그래서 "어떻게 구현하든 동일하게 사용해야만 하는 메모리는 Space Complexity에서 배제한다" 라는 논리로만 보자면 O(1)일 것 같고, "출력을 제외한 메모리 사용은 Space Complexity에 포함한다" 라는 논리대로라면 O(n)인 것 같습니다.)
Copy link
Contributor

Choose a reason for hiding this comment

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

"어떻게 구현하든 동일하게 사용해야만 하는 메모리는 Space Complexity에서 배제한다" 라는 논리로만 보자면 O(1)일 것 같고

createNode 메서드가 map에 복제 노드들을 저장하고 있으니까 출력값을 제외하더라도 O(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.

으음... 위에서 언급하신 것처럼 map에 레퍼런스만 저장되긴 하겠지만, 그래도 O(n)만큼 저장되겠네요. 복제된 노드들만 생각했는데, map은 고려하지 못했습니다 😓 obzva님 말씀대로 O(1)보다는 O(n)이 맞을 것 같습니다

}

public void dfs(Node oldNode, Node newNode) {
List<Node> dfsList = new ArrayList<>();
Copy link
Contributor

Choose a reason for hiding this comment

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

삭제해도 될 것 같아요 :)

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 on lines 57 to 60
public void dfs(Node oldNode, Node newNode) {
List<Node> dfsList = new ArrayList<>();

for (Node oldNeighbor : oldNode.neighbors) {
Copy link
Contributor

Choose a reason for hiding this comment

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

dfs함수가 parameter로 Node oldNode만 받아도 될 것 같아요. 우린 map에 새로운 노드들을 저장, 관리하고 있으니까요 :)

Suggested change
public void dfs(Node oldNode, Node newNode) {
List<Node> dfsList = new ArrayList<>();
for (Node oldNeighbor : oldNode.neighbors) {
public void dfs(Node oldNode) {
Node newNode = map.get(oldNode.val);
for (Node oldNeighbor : oldNode.neighbors) {

Copy link
Contributor

Choose a reason for hiding this comment

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

진짜 째잔하게 따지면, dfs의 재귀호출 스택에서 Node oldNode의 레퍼런스 값만큼의 공간 사용량을 감소시키는 효과가.. 있을 것 같아요 ㅋㅋㅋ

Copy link
Contributor Author

Choose a reason for hiding this comment

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

오 그렇네요. 처음 머리 속에 떠오른 아이디어를 코드로 구현하고 나면, 이미 사고의 흐름이 한 방향으로 바이어스가 생겨서인지 이런 부분이 잘 안 보이는 것 같아요. (코드 리뷰 꼼꼼히 봐주셔서 감동...입니다!)

Copy link
Contributor

@mmyeon mmyeon left a comment

Choose a reason for hiding this comment

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

이번 주도 문제 푸시느라 고생 많으셨습니다!
주석 및 질문 꼼꼼히 남겨주셔서 저도 함께 고민하면서 깊이 생각해볼 수 있었습니다 :)
고생 많으셨고 다음 주도 파이팅입니다!!

Comment on lines +38 to +40
if (r == s.length()) {
break;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

while문이 r < s.length() 조건인 경우에만 실행되고 있어서 이 로직은 없어도 될 것 같아요!

Comment on lines +9 to +10
다만, 개인적으로 에너지가 고갈된 상태에서 풀다보니,
현재 상태에서 가장 많은 문자를 카운트하는 방식을 counts[26] 배열을 순회하는 식으로 단순하게 짰습니다.
Copy link
Contributor

Choose a reason for hiding this comment

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

고생많으셨습니다~~ 저는 배열 로직도 충분히 좋은 것 같아요 😄
다만 말씀하셨던 것처럼 mostCount가 윈도우 크기가 변경될 때만 업데이트되면 더 좋을 것 같아요~

mostCount = Math.max(mostCount, counts[s.charAt(r) - 'A'])

Copy link
Contributor Author

Choose a reason for hiding this comment

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

이렇게 하면 더 효율적이겠네요~! 나중에 보니 Dale님의 풀이에서도 O(26)으로 찾으셨더라구요 😃

@forest000014
Copy link
Contributor Author

#244 Longest Repeating Character Replacement 풀이의 분류는 투 포인터 기법이라고 생각했는데, (Dale님의 설명처럼) (가변 길이) 슬라이딩 윈도우라고 보는 게 좀 더 적절할 것 같네요. 단순히 왼쪽/오른쪽 포인터를 이동한다-라는 개념보다는, 양 끝 사이의 윈도우 내에 포함되어있는 문자의 개수를 카운팅한다는 것을 고려하면, '윈도우'라고 하는 게 더 맞을 것 같다는 생각입니다. 코치님은 어떻게 생각하시나요?

슬라이딩 윈도우 기법을 사용하기 위해 포인터를 두 개 쓰니까, 슬라이딩 윈도우는 투 포인터에 포함되는 개념 아닐까요? (왕개인적인 생각입니다)

@obzva
챗GPT한테 물어봐도 (가변 길이) 슬라이딩 윈도우와 투 포인터는 꽤나 유사하다고 하네요 ㅎㅎ 스택 오버플로우 답변 중 이런 설명이 제 취향(?)에는 좀 더 맞는 것 같습니다! (두 포인터가 가리키는 원소 자체를 가지고 판단하느냐, 아니면 윈도우 내의 모든 원소를 보느냐라는 관점 차이)
but we usually compare the value at the two pointers instead of all the elements between the pointers

@forest000014
Copy link
Contributor Author

@forest000014

#259 Clone Graph 문제에서, Dale님의 풀이에서는 이미 복제한 노드를 다시 복제하지 않기 위해 clone 해시 테이블을 사용하셨는데요. 저는 모든 노드가 다른 값을 가진다는 점에 착안해서, val에 해당하는 Node 인스턴스를 저장해두고 사용하는 식으로 구현했습니다. (주석에는 싱글톤이라고 적었는데, 생각해보니 클래스 당 인스턴스 1개가 아니라서 싱글톤이라는 표현은 적절하지 않을 것 같네요.)
이렇게 구현하는 경우에 단점이 있을까요? (개인적으로는 clone 해시 테이블과 비교했을 때 메모리 사용도 비슷하고, 속도 측면에서도 큰 차이가 없지 않을까 생각합니다 🤔)

일단 풀이 잘 보았습니다 :) 풀이에 대한 코멘트 또한 남겨놓았습니다. 제가 Java를 잘 몰라서 찾아보니 Map<Node, Node> 타입의 해시맵을 만든다고 치면, 해당 해시맵의 key, value에는 각각 Node를 가리키는 reference가 저장된다고 하네요 (맞나요?) 그렇다고 치면 제 생각엔 Map<reference, reference> <-> Map<Integer, reference> 사이에서는 큰 차이가 있을 것 같진 않다고 생각합니다 만약 제가 알아본게 틀리다면 알려주세요!

@obzva
넵, 제가 알기로도 레퍼런스를 저장하는 걸로 알고 있고, 저도 obzva님과 동일한 의견입니다! :)

@forest000014 forest000014 merged commit 111feeb into DaleStudy:main Jan 31, 2025
1 check passed
Node newNeighbor = createNode(oldNeighbor.val);
newNode.neighbors.add(newNeighbor);
newNeighbor.neighbors.add(newNode);
dfs(oldNeighbor, newNeighbor);
Copy link
Member

@DaleSeo DaleSeo Feb 1, 2025

Choose a reason for hiding this comment

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

@forest000014 dfs() 함수는 인자를 하나만 받으니 여기서 컴파일 에러가 나지 않을까요? 😨 이미 PR을 병합을 하셨으니 차주 답안 제출 때 정정해주시면 좋을 것 같습니다. 참여자 분들께 최고의 답안을 기대하는 것은 아니지만 미래 기수 분들께 혼선이 없도록 적어도 실행은 되는 코드를 목표로 하고 있습니다.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

아앗..! 이 부분을 놓쳤습니다 ㅠㅠ 수정하고 제출을 해봤어야 했는데 눈으로만 보고 넘어가서 컴파일 에러를 못 찾았네요. 9주차 PR에 포함해두겠습니다!

Copy link
Member

Choose a reason for hiding this comment

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

감사합니다! 🙏

@forest000014 forest000014 changed the title [forest000014] Week 8 [forest000014] Week 08 Feb 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
No open projects
Status: Completed
Development

Successfully merging this pull request may close these issues.

5 participants