Skip to content
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

1주차 과제 풀이 제출 #9

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
65 changes: 65 additions & 0 deletions src/main/java/week1/problem1/Problem1.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package main.java.week1.problem1;

import java.util.Arrays;

public class Problem1 {

public Problem1() {
}

public int solution1(int[] input) {
int output = 0;
for (int i : input) {
output += i;
}
return output;
}

public int solution2_1(int[] input) {
if (input.length == 0) {
return 0;
}
if (input.length == 1) {
return input[0];
}
int mid = input.length / 2;
return solution2_1(Arrays.copyOfRange(input, 0, mid)) + solution2_1(Arrays.copyOfRange(input, mid, input.length));
}
Comment on lines +18 to +27
Copy link
Contributor

Choose a reason for hiding this comment

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

2개씩 나누면서 1개가 될 때까지 나누어서 더하는 방식이군요 ㅎㅎ 저는 생각 못 했던 방식이네요!


public int solution2_2(int[] input) {
return plus_1(input, input.length - 1);
}

public int solution3(int[] input) {
return plus_2(input, input.length - 1, 0);
}

public int solution4(int[] input) {
return plus_3(input, input.length - 1);
}

private int plus_1(int[] input, int index) {
if (index < 0) {
return 0;
}
return input[index] + plus_1(input, index - 1);
}

private int plus_2(int[] input, int index, int output) {
if (index < 0) {
return output;
}
return plus_2(input, index - 1, output + input[index]);
}

private int plus_3(int[] input, int index) {
int output = 0;
while (true) {
if (index < 0) {
return output;
}
output += input[index];
index--;
}
}
}
23 changes: 23 additions & 0 deletions src/main/java/week1/problem1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# 자료구조와 알고리즘 1주차 과제 - 총합 구하기

숫자의 배열을 받아서 총합을 구하는 함수를 구현해 주세요.

## 요구 사항

1. 가장 익숙한 방법으로 문제를 해결해 주세요.
2. 이번에는 재귀 함수로 문제를 해결해 주세요.
3. 꼬리 재귀 함수로 바꿔보세요.
4. 꼬리 재귀 최적화를 통해서 최적화해 보세요.

### 입력 예시

| numbers | return |
| --- | --- |
| [1, 2, 3, 4] | 10|
| [-1, 3, 8, 9, 10, 11] | 40 |
| [] | 0 |

## 제한조건

- 모든 테스트를 통과해야 합니다.
- 스스로 문제 해결법을 떠올리기 위해 Copilot은 사용하지 말아주세요.
52 changes: 52 additions & 0 deletions src/main/java/week1/problem2/Problem2.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package main.java.week1.problem2;

public class Problem2 {

public Problem2() {
}

public int solution1(int input) {
if (input < 2) {
return input;
}
int[] dp = new int[input + 1];
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i <= input; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[input];
}

public int solution2(int input) {
if (input == 0 || input == 1) {
return input;
}
return solution2(input - 1) + solution2(input - 2);
}


public int solution3(int input) {
return plus_1(input, 0);
}

public int solution4(int input) {
return plus_2(input, 0);
}

private int plus_1(int input, int output) {
if (input == 0 || input == 1) {
return input;
}
return output + plus_1(input - 1, output) + plus_1(input - 2, output);
}
Comment on lines +37 to +42
Copy link
Contributor

Choose a reason for hiding this comment

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

output이 처음에 0으로 주어지고, 재귀적인 호출에도 같은 output을 계속 넘겨주기 때문에 0에서 변하지 않네요. 그래서 위에서 구현했던 solution2랑 같은 결과가 나오게 되겠어요. 따라서 output은 없어도 되겠네요


private int plus_2(int input, int output) {
while(true) {
if (input == 0 || input == 1) {
return input;
}
return output + plus_2(input - 1, output) + plus_2(input - 2, output);
}
}
Comment on lines +44 to +51
Copy link
Contributor

Choose a reason for hiding this comment

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

아마 꼬리재귀 최적화를 시도하셨던 것 같네요. 꼬리 재귀 최적화가 된 결과는 solution1과 동일하긴 해요. 그전에 꼬리재귀 최적화가 된 모양은 다음과 같습니다.

  public int _solution(int input, int count, int a, int b) {
    if (input == 0 || input == 1) {
      return input;
    }

    if (input == count - 1) {
      return b;
    }

    return solution(input, count + 1, b, a + b);
  }

  public int solution(int input) {
    return _solution(input, 0, 0, 1);
  }

Copy link

@kyupid kyupid Jan 6, 2024

Choose a reason for hiding this comment

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

@hannut91
안녕하세요. 코드숨 공개 레포로 개인공부하고 있는 개발자입니다~ 먼저 좋은 학습자료 올려주셔서 감사하다는 인사의 말씀 드립니다.

저는 자바로 공부하고 있는데 꼬리 재귀 최적화는 현재 자바에서 지원되지 않습니다.

https://blogs.oracle.com/javamagazine/post/curly-braces-java-recursion-tail-call-optimization

I spoke to Brian Goetz, the Java language architect at Oracle, about TCO back in 2014. At the time, he told me that it’s on a list of things to be added to the JVM. I caught up with him recently (이게 블로그 글로 미루어보아 2022년인거 같습니다) to discuss the topic, and he said that while progress has been made, and more may occur in the future, TCO hasn’t been fully implemented due to some security concerns.

아래 링크를 확인해보시면 workaround가 있는 것 같긴합니다.
https://stackoverflow.com/a/53787951
https://github.com/jonckvanderkogel/java-tail-recursion

Copy link
Contributor

@hannut91 hannut91 Jan 6, 2024

Choose a reason for hiding this comment

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

@kyupid 맞습니다. 꼬리 재귀 최적화가 된 결과가 아니라 꼬리 재귀로 작성된 이라고 정정해야겠네요! 제보 감사합니다 ㅎㅎ
자바에서 꼬리 재귀 최적화를 지원하지 않으므로, 직접 꼬리 재귀 최적화를 해야 합니다.

}
33 changes: 33 additions & 0 deletions src/main/java/week1/problem2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# 자료구조와 알고리즘 1주차 과제 - 피보나치 수

피보나치 수는 첫째 및 둘째 항이 1이며 그 뒤의 모든 항은 바로 앞 두 항의 합인
수열입니다.
n번째 피보나치 수를 구하는 함수를 작성해 주세요.

## 요구 사항

1. 가장 익숙한 방법으로 문제를 해결해 주세요.
2. 이번에는 재귀 함수로 문제를 해결해 주세요.
3. 꼬리 재귀 함수로 바꿔보세요.
4. 꼬리 재귀 최적화를 통해서 최적화해 보세요.

### 입력 예시

| n | return |
| --- | --- |
| 0 | 0|
| 1 | 1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 3 |
| 5 | 5 |
| 6 | 8 |

## 제한조건

- 모든 테스트를 통과해야 합니다.
- 스스로 문제 해결법을 떠올리기 위해 Copilot은 사용하지 말아주세요.

## 참고

- [피보나치 수](https://ko.wikipedia.org/wiki/%ED%94%BC%EB%B3%B4%EB%82%98%EC%B9%98_%EC%88%98)
25 changes: 25 additions & 0 deletions src/main/java/week1/problem3/Problem3.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package main.java.week1.problem3;

import java.util.ArrayDeque;

public class Problem3 {

public Problem3() {
}

public String solution1(int input) {
if (input == 0) {
return "0";
}
ArrayDeque<Integer> stack = new ArrayDeque<>();
while (input > 0) {
stack.push(input % 2);
input /= 2;
}
StringBuilder stringBuilder = new StringBuilder();
while (!stack.isEmpty()) {
stringBuilder.append(stack.pop());
}
return stringBuilder.toString();
}
}
33 changes: 33 additions & 0 deletions src/main/java/week1/problem3/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# 자료구조와 알고리즘 1주차 과제 - 이진수로 변환하기

주어진 10진수 숫자를 2진수 문자열로 변환하는 함수를 작성해 주세요.

## 요구 사항

1. 가장 익숙한 방법으로 문제를 해결해 주세요.
2. 이번에는 재귀 함수로 문제를 해결해 주세요.
3. 꼬리 재귀 함수로 바꿔보세요.
4. 꼬리 재귀 최적화를 통해서 최적화해 보세요.

### 입력 예시

| n | return |
| --- | --- |
| 0 | "0" |
| 1 | "1" |
| 2 | "10" |
| 3 | "11" |
| 4 | "100" |
| 5 | "101" |
| 6 | "110" |
| 7 | "111" |
| 8 | "1000" |

## 제한조건

- 모든 테스트를 통과해야 합니다.
- 스스로 문제 해결법을 떠올리기 위해 Copilot은 사용하지 말아주세요.

## 참고

- [이진법](https://ko.wikipedia.org/wiki/%EC%9D%B4%EC%A7%84%EB%B2%95)
16 changes: 16 additions & 0 deletions src/main/java/week1/problem4/Problem4.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package main.java.week1.problem4;

public class Problem4 {

public Problem4() {
}

public int solution1(String input) {
int output = 0;
String[] split = input.split("");
for (int i = 0; i < split.length; i++) {
output += Integer.parseInt(split[i]) * Math.pow(2, split.length - i - 1);
}
return output;
}
}
33 changes: 33 additions & 0 deletions src/main/java/week1/problem4/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
w# 자료구조와 알고리즘 1주차 과제 - 이진수 10진수로 변환하기

주어진 2진수 문자열을 10진수 숫자로 변환하는 함수를 작성해 주세요.

## 요구 사항

1. 가장 익숙한 방법으로 문제를 해결해 주세요.
2. 이번에는 재귀 함수로 문제를 해결해 주세요.
3. 꼬리 재귀 함수로 바꿔보세요.
4. 꼬리 재귀 최적화를 통해서 최적화해 보세요.

### 입력 예시

| binaryCharacters | return |
| --- | --- |
| "0" | 0 |
| "1" | 1 |
| "10" | 2 |
| "11" | 3 |
| "100" | 4 |
| "101" | 5 |
| "110" | 6 |
| "111" | 7 |
| "1000" | 8 |

## 제한조건

- 모든 테스트를 통과해야 합니다.
- 스스로 문제 해결법을 떠올리기 위해 Copilot은 사용하지 말아주세요.

## 참고

- [이진법](https://ko.wikipedia.org/wiki/%EC%9D%B4%EC%A7%84%EB%B2%95)
17 changes: 17 additions & 0 deletions src/main/java/week1/problem5/Problem5.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main.java.week1.problem5;

public class Problem5 {

public Problem5() {
}

public int solution1(int a, int b) {
int max = Math.max(a, b);
int min = Math.min(a, b);
int r = max % min;
if (r == 0) {
return min;
}
return solution1(min, r);
}
}
33 changes: 33 additions & 0 deletions src/main/java/week1/problem5/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
최# 자료구조와 알고리즘 1주차 과제 - 유클리드 호제법으로 최대 공약수 구하기

> 2개의 자연수(또는 정식) a, b에 대해서 a를 b로 나눈 나머지를 r이라 하면(단, a>b),
> a와 b의 최대공약수는 b와 r의 최대공약수와 같다. 이 성질에 따라, b를 r로 나눈
> 나머지 r'를 구하고, 다시 r을 r'로 나눈 나머지를 구하는 과정을 반복하여 나머지가
> 0이 되었을 때 나누는 수가 a와 b의 최대공약수이다.

위 정의에 따라 유클리드 호제법을 이용해서 최대 공약수를 구하는 함수를 작성해 주세요.

## 요구 사항

1. 가장 익숙한 방법으로 문제를 해결해 주세요.
2. 이번에는 재귀 함수로 문제를 해결해 주세요.
3. 꼬리 재귀 함수로 바꿔보세요.
4. 꼬리 재귀 최적화를 통해서 최적화해 보세요.

### 입력 예시

| a | b | return |
| --- | --- | --- |
| 4 | 12 | 4 |
| 3 | 7 | 1 |
| 16 | 72 | 8 |
| 9 | 12 | 3 |

## 제한조건

- 모든 테스트를 통과해야 합니다.
- 스스로 문제 해결법을 떠올리기 위해 Copilot은 사용하지 말아주세요.

## 참고

- [유클리드 호제법](https://ko.wikipedia.org/wiki/%EC%9C%A0%ED%81%B4%EB%A6%AC%EB%93%9C_%ED%98%B8%EC%A0%9C%EB%B2%95)
Loading
Loading