Skip to content
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
102 changes: 102 additions & 0 deletions combination-sum/rivkode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*

1. 문제 이해

모든 조합 (중복 허용) 을 통해 target 숫자를 찾는다.

2
2, 2
2, 2, 2
2, 2, 2, 2 - 초과
2, 2, 3 - 타겟
2, 2, 6 - 초과
2, 3
2, 3, 3
...
6,
6, 6



2. 알고리즘

dfs ?

3. 예외 케이스
일치 케이스 없는 경우 ?
다 돌면 예외가 있을까 ?

4. 구현

종료 트리거는 일치할 경우
target 숫자보다 높은 경우는 뒤로 감
뒤로 가서 다음 숫자를 넣어 보자

candidates 정렬
dfs 로 진행, 입력 파라미터는 더할 숫자 ?
대소 비교해서 만약 더 작으면 같은 숫자 넣고 더 크면 뒤로 이동

dfs 함수

새로운 Num 입력받음
입력받은 숫자를 tmp 리스트에 더하고
전체 합이 target 에 대해 대소 관계 비교

1. 크다면 뒤로 이동하고 다음 숫자 입력
2. 같다면 result에 넣고 뒤로 이동
3. 작다면 동일한 숫자 넣기

이상하게 dfs 를 구현했다. 순서도 맞지 않고
for문 구현, 인자, 접근 방법 모두 틀렸다.
기억하자
1. 호출은 main 에서 dfs() 한다
2. 백트래킹 for 문은 dfs() 내에서 구현한다.

답변을 보고 오니 백트래킹을 어떻게 해야겠다는 감이 왔다.

뒤로 가는걸 어떻게 구현할까 생각했는데 For 문에서 tmp에 새로운 숫자를 넣고 제거하면서 그 사이에 dfs 를 넣으면 되는거였다.

for loop
tmp.add num
dfs()
tmp.remove num

식으로 말이다.

*/

import java.util.*;

class Solution {
private int t;
private List<List<Integer>> result;

public List<List<Integer>> combinationSum(int[] candidates, int target) {
t = target;
result = new ArrayList<>();
Arrays.sort(candidates);
List<Integer> nums = new ArrayList<>();

dfs(candidates, 0, nums, 0);

return result;
}

public void dfs(int[] candidates, int total, List<Integer> nums, int start) {
if (total > t) return; // total이 target 보다 크다면 이전으로 돌아가기 위해 return
if (total == t) { // 정답일 경우 해당 값 추가 및 return
result.add(new ArrayList<>(nums)); // nums 와 new ArrayList<>(nums) 차이 이해하기
// 빈 배열로 저장되길래 왜 저때의 값이 저장안되지 ? 라고 생각했지만
// 당연히 안됨. ref 주소값을 저장했으므로 나중에는 이 Nums가 모두 빈배열이 되므로
return;
}

for (int i=start; i < candidates.length; i++) { // start 부터 시작하는것 포인트!
int num = candidates[i];
nums.add(num);
dfs(candidates, total + num, nums, i);
nums.remove(nums.size() - 1); // 다음에는 stack 사용하자
}
}
}
69 changes: 69 additions & 0 deletions maximum-subarray/rivkode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
1. 문제 이해

[-2,1,-3,4,-1,2,1,-5,4]
* 정답부분 참고
각 인덱스를 시작점으로 잡고 모든 부분에 대한 부분 배열의 합을 구한다
이전에 계산했던 내용을 저장해서 사용한다
-> 이렇게 계산해도 Time Limit Exceeded 발생하네 ..

결국엔 이렇게 해도 n^2 시간이 발생하므로 시간초과
포인트는 n^2 가 걸리는 시간을 어떻게 nlogn이나 n으로 줄일 수 있는지임

* 정답 부분 참고
누적합이 음수라면 시작 인덱스를 다음으로 과감하게 옮긴다


이 문제는 직관적으로 문제를 바라보는것이 중요했다.
아마도 이렇게 접근하는건 어떨까 ?
나는 최대합을 구하고싶었다. 부분 배열로!
부분배열이라는 것은 연속된다는 것이 특징이다.

즉, 연속되어야 하므로 이전의 합들이 만약 음수라면 ? 이 부분들은 필요가 없어지므로 과감히 버릴 수 있다는 것을 아는 것이 포인트였다.

버린다는 것의 의미는 ? -> 현재 인덱스의 값과 이전 전체의 값들의 합을 비교해서 현재 인덱스부터 다시 출발한다는 것이다. 그러므로 비교해서 더 큰값을 total로 가져가는 것이다.

만약 이걸 처음부터 알았다면 그리고 기존에 작성한 n^2 를 소요하면서 모든 합을 구하려 했을때 비효율적인것을 직감했다면 다른 방법으로 접근할 수 있었어야 했다.

그리고 처음 total, maxTotal을 첫번째 인덱스로 지정해줬기 때문에 i 인덱스는 1부터 시작해야한다


*/

import java.util.*;

class Solution {
public int maxSubArray(int[] nums) {
int total = nums[0];
int maxTotal = nums[0];


for (int i=1; i<nums.length; i++) {
total = Math.max(nums[i], total + nums[i]);
maxTotal = Math.max(total, maxTotal);
}

return maxTotal;

// for (int i=0; i<nums.length; i++) {
// int total = 0;
// for (int j=i; j<nums.length; j++) {
// total += nums[j];
// max = Math.max(total, max);
// if (total < 0) {
// break;
// }
// }
// }

// return max;
}

private int sum(int[] arr, int start, int end) {
int cnt = 0;
for (int i=start; i<end + 1; i++) {
cnt += arr[i];
}
return cnt;
}
}
23 changes: 23 additions & 0 deletions number-of-1-bits/rivkode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
Integer.toBinaryString() 메서드 기억하기
*/


import java.util.*;

class Solution {
public int hammingWeight(int n) {
String s = Integer.toBinaryString(n);
int count = 0;

for (int i=0; i<s.length(); i++) {
char c = s.charAt(i);
if (c == 49) {
count += 1;
}
}

return count;
}
}

50 changes: 50 additions & 0 deletions valid-palindrome/rivkode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
1. 문제 이해
입력받은 글자에 대해 뒤집어도 동일한 글자인지 아닌지를 판단

2. 예외 케이스
빈 문자열, 글자가 아닌 다른 내용일 경우 제거

3. 알고리즘
단순 루프

4. 구현

글자를 입력받고 글자가 아닌 내용에 대해서는 필터링한다
전체 길이를 구하고 2포인터로 왼쪽, 오른쪽을 서로 줄여가면서
같거나 교차할때 종료

다른 부분이 있으면 false 반환, 모두 통과하면 true 반환

빈 값일경우 바로 true


*/

import java.util.*;

class Solution {
public boolean isPalindrome(String s) {
String result = s.replaceAll("[^a-zA-Z0-9]", "");
result = result.toLowerCase();

int len = result.length();
int left = 0;
int right = len - 1;

while (left < right) {
char leftS = result.charAt(left);
char rightS = result.charAt(right);

if (leftS != rightS) {
return false;
}

left += 1;
right -= 1;
}

return true;
}
}