Skip to content

Commit 1330142

Browse files
authored
[namuuCY] WEEK 02 Solutions (#2692)
1 parent 0b701a9 commit 1330142

5 files changed

Lines changed: 263 additions & 0 deletions

File tree

3sum/namuuCY.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// 문제 풀이 흐름
2+
// 세 개의 변수. 만약 brute-force(3중 for문 -> 3000 ^ 3 이어서 시간복잡도 너무 높음.) -> 어떤 한 값을 고정해서 변수를 줄이자.
3+
// 그러면 나머지 두 개는? 투 포인터 같은거 쓰면 안되나?
4+
// 근데 중복되는 경우에 대해서 어떻게 고려함?
5+
// 중복되는 경우가 너무 많다..
6+
// 우선 정렬 먼저 -> 이후 하나 고정하고 나머지 투포인터 생각
7+
// 중복되는거 생각나는대로, 음...
8+
9+
// N = nums.length라 할때
10+
// 시간 복잡도 정렬 + for문 1개 * 길이 N 투포인터
11+
// = O(N^2)
12+
// 공간 복잡도 두 가지로 설명
13+
// - Arrays.sort() 로 정렬 시 필요한 추가 공간(or 스택)을 따질 경우 : O(log N)
14+
// - 따지지 않을 경우 : O(1)
15+
16+
class Solution {
17+
18+
int[] nums;
19+
List<List<Integer>> answer = new ArrayList<>();
20+
21+
public List<List<Integer>> threeSum(int[] nums) {
22+
this.nums = nums;
23+
// 원본 배열 정렬
24+
Arrays.sort(nums);
25+
26+
for (int fixed = 0; fixed < nums.length - 2; fixed++) {
27+
// fixed가 이전의 값과 동일할 경우 skip
28+
if (fixed > 0 && nums[fixed] == nums[fixed - 1]) continue;
29+
30+
// fixed가 양수이면 뒤에도 무조건 양수이므로 break
31+
if (nums[fixed] > 0) break;
32+
33+
searchByTwoPointer(fixed);
34+
}
35+
36+
return answer;
37+
}
38+
39+
private void searchByTwoPointer(int fixedIdx) {
40+
int leftIdx = fixedIdx + 1;
41+
int rightIdx = nums.length - 1;
42+
43+
while (leftIdx < rightIdx) {
44+
int sum = nums[fixedIdx] + nums[leftIdx] + nums[rightIdx];
45+
46+
if (sum == 0) {
47+
answer.add(Arrays.asList(
48+
nums[fixedIdx],
49+
nums[leftIdx],
50+
nums[rightIdx]
51+
));
52+
53+
// 중복된것에 대해서 조정해줘야함.
54+
55+
leftIdx ++;
56+
rightIdx --;
57+
58+
while (leftIdx < rightIdx && nums[leftIdx] == nums[leftIdx - 1]) leftIdx++;
59+
while (leftIdx < rightIdx && nums[rightIdx] == nums[rightIdx + 1]) rightIdx--;
60+
} else if (sum < 0) {
61+
leftIdx ++;
62+
} else {
63+
rightIdx --;
64+
}
65+
}
66+
}
67+
}

climbing-stairs/namuuCY.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// 문제 풀이 흐름
2+
// 누가봐도 점화식 -> DP 문제이다.
3+
// 자세히 보니 피보나치수열 같음
4+
// 1,2번쨰 항일때만 주의해서 풀자.
5+
6+
// n에 대해서
7+
// 시간복잡도 : O(n)
8+
// 공간복잡도 : O(1)
9+
10+
class Solution {
11+
public int climbStairs(int n) {
12+
if (n == 1) return 1;
13+
if (n == 2) return 2;
14+
15+
// 3 = 2 * [1] + [2]
16+
// 4 = 2 * [2] + [3]
17+
int doublePrev = 0;
18+
int prev = 1;
19+
int current = 2;
20+
21+
for (int i = 3 ; i <= n ; i++ ) {
22+
doublePrev = prev;
23+
prev = current;
24+
current = doublePrev + prev;
25+
}
26+
return current;
27+
}
28+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// 문제 풀이 흐름 :
2+
// 전체의 합에서 자기 자신만 뺀것을 생각하듯이, 전체의 곱에서 자기 자신만 나눈 것을 생각하자
3+
// 이때, 중요한 것은 integer overflow와 0이 여러번 나올 떄 예외처리
4+
// integer overflow : 문제에서는 답이 32 bit integer 라고 했지, 그 과정에서 생길 수 있는 곱들이 int범위라고 단정지을 수 없음
5+
// 0의 개수에 따라 다르게 계산 :
6+
// 0이 없을 때 : 상관없음.
7+
// 1개만 있을 때 : 0인 곳에만 product 기입
8+
// 2개만 있을 때 : 모두 0이 된다.
9+
10+
// n = nums.length 라 할때
11+
// 시간복잡도 : O(n)
12+
// 공간복잡도 : O(n)
13+
14+
15+
class Solution {
16+
17+
static {
18+
Solution warmup = new Solution();
19+
for (int i = 0; i < 500; ++i) {
20+
warmup.productExceptSelf(new int[2]);
21+
}
22+
}
23+
24+
25+
public int[] productExceptSelf(int[] nums) {
26+
int[] answer = new int[nums.length];
27+
28+
Arrays.fill(answer, 1);
29+
30+
int leftProduct = 1;
31+
for (int i = 0 ; i < nums.length - 1; i ++) {
32+
leftProduct *= nums[i];
33+
answer[i + 1] *= leftProduct;
34+
}
35+
36+
int rightProduct = 1;
37+
for (int i = nums.length - 1 ; i > 0 ; i --) {
38+
rightProduct *= nums[i];
39+
answer[i - 1] *= rightProduct;
40+
}
41+
42+
return answer;
43+
}
44+
45+
public int[] prevSubmission(int[] nums) {
46+
int zeros = 0;
47+
long totalProduct = 1;
48+
49+
for (int number : nums) {
50+
if (number == 0) {
51+
zeros ++;
52+
}
53+
totalProduct *= number;
54+
}
55+
56+
int[] answer = new int[nums.length];
57+
58+
if (zeros == 0) {
59+
for (int i = 0 ; i < nums.length; i ++ ) {
60+
answer[i] = (int) (totalProduct / nums[i]);
61+
}
62+
} else if (zeros == 1) {
63+
int nonZeroProduct = 1;
64+
int zeroIdx = -1;
65+
for (int i = 0 ; i < nums.length; i ++ ) {
66+
if (nums[i] == 0) {
67+
zeroIdx = i;
68+
continue;
69+
}
70+
nonZeroProduct *= nums[i];
71+
}
72+
answer[zeroIdx] = nonZeroProduct;
73+
}
74+
75+
return answer;
76+
}
77+
}

valid-anagram/namuuCY.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// 문제 풀이 흐름
2+
// 아나그램 : 글자 빈도가 같으면 항상 아나그램 관계
3+
// 가장 먼저 : 전체 글자수가 같은지 비교
4+
// 그 다음 -> 알파벳 별로 빈도수가 같은지 비교
5+
6+
// n = max(s의 길이, t의 길이)라고 했을때
7+
// 시간복잡도 : O(n)
8+
// 공간복잡도 : O(1)
9+
10+
class Solution {
11+
public boolean isAnagram(String s, String t) {
12+
int[] sCount = new int[26];
13+
int[] tCount = new int[26];
14+
15+
if (s.length() != t.length()) return false;
16+
17+
for (int i = 0 ; i < s.length() ; i++) {
18+
sCount[s.charAt(i) - 'a'] ++;
19+
tCount[t.charAt(i) - 'a'] ++;
20+
}
21+
22+
for (int i = 0 ; i < 26 ; i++) {
23+
if (sCount[i] == tCount[i]) continue;
24+
return false;
25+
}
26+
27+
return true;
28+
}
29+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// 문제 풀이 흐름
2+
// 기억하기로는 트리 순회 하는 방식이 몇 가지 있던거로 기억하는데
3+
// 왼쪽 자식 -> 부모 -> 오른쪽 자식 이 방식으로 순회하는 방식을 사용해야함.
4+
// 그렇게 순회하도록 한 뒤, 순서대로 확인하는데 숫자가 증가하지 않는다면 invalid
5+
// 순회 아이디어 : 재귀를 이용 + 이전 노드 방문 값을 항상 저장
6+
// 맨 처음 노드 방문 값은 -2^32 로 하자 -> 맨 왼쪽 노드는 항상 그 다음이 되도록
7+
// param : 현재 노드
8+
// 왼쪽 자식이 있다면? 왼쪽 노드 방문,
9+
// 없으면 무시
10+
// 현재 노드 값 valid한지
11+
// 오른쪽 자식이 있다면? 오른쪽 노드 방문
12+
13+
// n = node 갯수라고 한다면
14+
// 시간복잡도 : O(n)
15+
// 공간복잡도 : O(1)
16+
17+
18+
19+
/**
20+
* Definition for a binary tree node.
21+
* public class TreeNode {
22+
* int val;
23+
* TreeNode left;
24+
* TreeNode right;
25+
* TreeNode() {}
26+
* TreeNode(int val) { this.val = val; }
27+
* TreeNode(int val, TreeNode left, TreeNode right) {
28+
* this.val = val;
29+
* this.left = left;
30+
* this.right = right;
31+
* }
32+
* }
33+
*/
34+
class Solution {
35+
36+
long currentValue = -(1L << 33);
37+
38+
public boolean isValidBST(TreeNode root) {
39+
return visitNode(root);
40+
}
41+
42+
43+
private boolean visitNode(TreeNode node) {
44+
// 왼쪽 자식
45+
if (node.left != null) {
46+
boolean isValid = visitNode(node.left);
47+
if (!isValid) return false;
48+
}
49+
50+
// 현재 노드
51+
if (currentValue >= node.val) return false;
52+
currentValue = node.val;
53+
54+
// 오른쪽 자식
55+
if (node.right != null) {
56+
boolean isValid = visitNode(node.right);
57+
if (!isValid) return false;
58+
}
59+
60+
return true;
61+
}
62+
}

0 commit comments

Comments
 (0)