두 개의 주어진 배열이 있을 때, 두번째 인자로 전달된 배열이 첫번째 인자의 배열의 부분집합인지를 boolean을 이용하여 판단하시오.
f([1,2,3,4,5],[1,3]) //true
f([1,2,3,4,5],[6,7]) //false
f([10,99,123,7],[11,100,99,123]) //false
const isSubsetOf = function (base, sample) {
// TODO: 여기에 코드를 작성합니다.
//문제 이해
//base가 전체집합이고, sample이 부분집합이다.
//따라서 sample은 반드시 base의 원소들을 이용하여 만들어져야 한다.
//바로 처리를 할 수 있는 경우는 뭐가 있을까?
/*
-sample이 []인 경우: true;
-sample이 base보다 길이가 긴 경우: false;
*/
//예시 이해
//입출력 1: [1,3]의 각 요소는 base에 포함이 되어 있다.
//입출력2: [6,7]의 각 요소는 base에 미포함되어 있다.
//입출력 3: 99,123은 base에 있지만, 11과 100은 미포함되어 있다.
//내가 생각하는 해결책
/*
base를 순회하면서, 객체를 만든다.
예를 들어 입출력 예시 1의 경우 {1:1,2:1,3:1,4:1,5:1} 이렇게.
sample을 순회하면서, sample의 요소가 객체의 키 값으로써 존재하지 않는다면 ,
반복문을 종료하고 false를 리턴한다.
만약에 반복문을 false 리턴 없이 다 돌았다면,
그것은 base의 부분집합이라는 뜻이 되니까 true를 리턴한다.
*/
//엣지 케이스 처리
if(sample.length === 0) return true;
if(sample.length > base.length) return false;
//엣지 케이스 이외의 경우 처리!
//객체 만들기
let baseObj = {};
for(let i = 0; i < base.length; i++){
if(baseObj[base[i]] === undefined){
baseObj[base[i]] = 1;
}
}
//sample 순회하기
for(let j = 0; j < sample.length; j++){
if(baseObj[sample[j]] === undefined) return false;
//!(sample[j] in baseObj)라고 작성 해도 된다.
}
return true;
};
------------------------
아래와 같이 쓰면 시간복잡도가 N*N이다. 배열을 두번 순회하기 때문이다.
return sample.every((item) => base.includes(item));
그러면 위의 경우도 배열과 객체에 대해 한번씩 순회하는 거니까, N*N이 아니냐고 생각할 수 있는데
객체에서 키 값을 조회하는 경우, 객체는 해시구조이기 때문에 시간복잡도가 O(1)로 일정하다고 한다.
그래서 모든 테스트가 통과된다고 한다. [스택오버플로우 답변](<https://stackoverflow.com/questions/45266944/complexity-of-accessing-data-in-an-object>) 참조.
Javascript objects are actually Hashes,
so the complexity is O(1) for all engines.
obj.field is an alias for obj['field'], so they have the same performances.