Skip to content

[grapefruitgreentealoe] Week 01 Solutions #1671

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 16 commits into from
Jul 25, 2025
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
20 changes: 20 additions & 0 deletions contains-duplicate/grapefruitgreentealoe.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,23 @@ var containsDuplicate = function (nums) {
}
return false;
};

//25.7.23 풀이시간 10분
/**
* @param {number[]} nums
* @return {boolean}
*/
var containsDuplicate = function(nums) {
//두번 이상 나타나는게 있으면 바로 리턴하시오.
//이중 순회하게 되면 시간 초과할 예정.
//시간복잡도 중요.
//1. 저장하는 배열을 만들고, 그 배열에 값이 있으면 리턴 false.
//2.배열보다 Set을 사용한,삽입 및 조회 속도 최적화 활용하기.
const container = new Set();
for(let i =0; i<nums.length;i++){
if(container.has(nums[i])) return true;
else container.add(nums[i])
}
return false
};
//위의 코드보다, 리턴을 더 빨리한다는 이점이 있다.
20 changes: 20 additions & 0 deletions house-robber/grapefruitgreentealoe.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,23 @@ var rob2 = function (nums) {
};
//공간복잡도를 O(1)로 개선


//7.21 풀이시간 10분 소요


/**
* @param {number[]} nums
* @return {number}
*/
var rob = function(nums) {
const dp = new Array(nums.length+1).fill(0);
dp[1] = nums[0]
for(let i = 2; i<=nums.length;i++){
dp[i] = Math.max(dp[i-1],dp[i-2]+nums[i-1])
}
return dp[nums.length]
};
/**
시간복잡도 : O(n)
공간복잡도 : O(n)
*/
103 changes: 86 additions & 17 deletions longest-consecutive-sequence/grapefruitgreentealoe.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,99 @@

/**
* 정수 배열 nums
* 가장 많이 연속되는 요소의 길이 리턴.
* O(n) 시간안에 돌아가는 알고리즘 사용할것.
*/
/*우선 처음 푼 방법은*/

var longestConsecutive = function(nums) {
let maxCount = 0;
nums = [...nums].sort((a,b)=>a-b);
for(let i = 0;i < nums.length;i++){
let current = nums[i];
let count = 1;
for(let j = i+1;j<nums.length;j++){
if(current+1 == nums[j]){
current = nums[j]
count +=1;
}else if(current == nums[j]){
continue;
}
}
maxCount = Math.max(maxCount,count)
count = 1;
}
return maxCount
};


/*시간복잡도:
2중for문+sort
n^2 + nlogn => n^2.
공간복잡도:
nums는 초기화했고,
기타 변수들만 사용을 했다(maxCount,current,count)=> O(1)

하지만 이문제는 O(n)의 시간복잡도를 가져가야한다.
그러려면 sort도 하지말아야하고, 2중for문을 쓰지도 말아야한다.
(생각해보니 내가 사용한 방법을 인덱스+1해서 해결해도 되긴한다. 그래도 정렬때문에 nlogn이 된다.)

두번째 방법으로는,set을 사용해서 중복을 제거하는 방법이다.
*/

/**
* @param {number[]} nums
* @return {number}
*/
var longestConsecutive = function (nums) {
const numSet = new Set(nums);
let maxCount = 0;
for (let i of numSet) {
//n 번 순회
// ++ 이전에 연속체크가 되었을 수 있으므로, 이전 숫자가 존재한다면 pass
if (numSet.has(i - 1)) continue; //이미 진행 된 연속체크의 경우 하지 않는다.
//연속이 되는지 확인해서 있으면 1추가.
let length = 0;
while (numSet.has(i + length)) {
//연속이 끊기는 순간 멈추는 반복문. 즉 for문 전체 통틀어 최대 n번 실행.
length++;
var longestConsecutive = function(nums) {
if(nums.length == 0) return 0
let maxCount = 1;
nums.sort((a,b)=>a-b);
nums = [...new Set(nums)];
let count = 1;
for (let i = 0; i < nums.length - 1; i++) {
if (nums[i] + 1 === nums[i + 1]) {
count += 1;
} else if (nums[i] === nums[i + 1]) {
// 중복일 경우 아무것도 안 하고 넘어감
continue;
} else {
maxCount = Math.max(maxCount, count);
count = 1;
}
}
maxCount = Math.max(length, maxCount);
}
return maxCount;
maxCount = Math.max(maxCount, count); // 마지막에도 비교 필요

return maxCount
};
/*sort할때 시간복잡도가 nlog(n)인데 왜 통과했지.. 빅오 계산법이 최악의 경우를 계산한거라, 운좋게 통과한 것 같다.
좀 더 최적화 해보자
*/

//시간복잡도 O(n) + O(n) = O(n) /공간복잡도 O(n)
/**
* @param {number[]} nums
* @return {number}
*/
var longestConsecutive = function(nums) {
const numsSet = new Set(nums);
let maxCount = 0;
for(let num of numsSet){
//중복된 계산 패스
if(numsSet.has(num-1)) continue;
let length = 1;
while(numsSet.has(num+length)){
length++
}
maxCount = Math.max(maxCount,length)
}
return maxCount
};

//생각할 지점. 양쪽으로 진행된다면, 시간복잡도 최적화 가능
/*
set을 이용해서 중복을 제거
set의 has메소드를 활용하여 조회 최적화
while을 썼지만, for문의 첫번째 if문을 통해 실제 수행은 O(n)의 시간복잡도를 가짐.
이 외에도, set으로 만든 다음에 삭제해가면서(while) 순회가 아닌, 왼쪽 오른쪽값들을 연속적으로(while) 지우고, 연속이 끝나면 pop에서 나온 값의 left right를 조회해서 없으면 다시 최대값과 비교하는 방식이 있다.
근데 위의 코드에서 has로 조회하나, remove를 하려면 어차피 또 조회해야하니,
성능상의 차이는 크게 없는 것 같다.
*/
28 changes: 28 additions & 0 deletions top-k-frequent-elements/grapefruitgreentealoe.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,31 @@ var topKFrequent = function (nums, k) {
};

//O(n) + O(n log n) + O(n) + O(k) = O(n log n)


//7.22 소요시간 10분
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
var topKFrequent = function(nums, k) {
//우선은, Map으로 만들어서 숫자 각각에 대한 개수를 구한다.
const numsMap = new Map();
for(let num of nums){
if(numsMap.has(num)){
numsMap.set(num,numsMap.get(num)+1)
}else{
numsMap.set(num,1)
}
}
//그런다음 Map에 대해서, 가장 큰 값을 가진 순으로 정렬을 한다.
const ret = [...numsMap].sort((a,b)=>b[1]-a[1]).slice(0,k).map(x=>x[0]);
return ret
};

// 이전 답과 비슷하지만, for문 처리에 대해서, 조금 풀어서 작성을 하게 된거같다.
// 시간복잡도와 공간복잡도는 위의 코드와 같다.

// 시간 복잡도 : for문 - O(n) , sort O(nlogn)
// 공간 복잡도 : O(n)
50 changes: 50 additions & 0 deletions two-sum/grapefruitgreentealoe.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,53 @@ var twoSum3 = function (nums, target) {
numMap.set(nums[i], i); // 공간 O(1)
}
};


//25.7.24
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
//우선 nums배열에서 target보다 큰것은 삭제한다. => 이것 또한 시간복잡도가 든다. 하지말자
//1. 투포인터 방식으로 접근한다.
for(let i=0;i<nums.length-1;i++){
let total = nums[i]
for(let j=i+1;j<nums.length;j++){
if(total+nums[j] == target){
return [i,j]
}
}
}
};

/**
* 시간복잡도: O(N^2)
* 공간복잡도: O(1)
*/

/*
투포인터로 다시 풀었지만, 이 문제의 핵심은 map 메소드를 활용해서, 조회를 빠르게 하는것..
Map.get(key) : O(1) 평균 해시 테이블 기반이기 때문에, 키 조회가 상수 시간
Array.includes(value) : O(n) 배열 처음부터 끝까지 순차 탐색 (최악의 경우 전체 탐색)
*/

var twoSum = function(nums, target) {
//현재 nums에 대해서, subnums를 저장한다.
const subNumsMap = new Map();
for(let i = 0;i<nums.length;i++){
const subNum = target - nums[i];
if(subNumsMap.has(subNum)){
return [subNumsMap.get(subNum),i]
}
subNumsMap.set(nums[i],i)
}
};
//시간복잡도: O(n) , 공간복잡도 : O(n)

/*
Q. 여기서 의문. Map이좋냐 object가 좋냐?
알고리즘용 해시맵 대용이라면 대부분 Map 추천
Object는 JSON-like 데이터 보관용에 적합
*/