주어진 문자열에서 중복된 문자를 제거하고, 남은 문자들을 원래 순서대로 반환하는 함수를 작성하세요.
// 문자열에서 중복된 문자 제거, 남은 문자 원래순서대로 반환
// Set 객체는 고유한 값만 삽입될 수 있다. (= 중복 제거)
function distinct (s) {
// new Set을 사용하면 Set 객체가 만들어지기 때문에
// 배열과 비슷하지만 배열이 아니다.
// ... 전개 연산자를 이용하여 배열로 만든 후 문자열로 조합한다..
const str = [...new Set(s)];
return str.join('');
}
const s = "adsfawezsafy";
console.log(distinct(s)); // adsfwezy
문자열의 중복된 문자를 제거 하는 방법하면 딱 바로 떠올랐던 방법이다.
JS 기본 문법 때 배운 Set을 사용하기로 하고 구현 해보았는데 문제가 하나 있었다.
new Set(s)로 Set 객체를 만든 후 다시 문자열로 만들려고 하니
Set 객체는 배열이 아니라서 join 등을 사용할 수 없었고
로그를 찍으니 Set(8) { 'a', ... 'y' }
이런식으로 나왔다.
공부했던 부분을 다시 찾아보았는데 ES6 문법의 전개 연산자가 배열이나 객체의 요소를 하나 하나
풀어서 리턴하는 걸 상기했다.
그래서 [...new Set(s)]
로 바꾸니 해결됐다.
주어진 배열에서 최솟값과 최댓값을 찾고, [최솟값, 최댓값] 형태의 배열을 반환하는 함수를 작성하세요.
// 배열에서 최솟값, 최댓값 찾기 [최솟값, 최댓값] 형태로 반환
// 새 배열을 만든 후 최솟값과 최댓값을 차례로 삽입
function minMax (arr) {
const newArr = [];
//최솟값 /전개 구문으로 배열을 해체
newArr.push(Math.min(...arr));
//최댓값 /전개 구문으로 배열을 해체
newArr.push(Math.max(...arr));
return newArr;
}
const arr = [1,2,3,3,4,5,6,7,8,9,10,11];
console.log(minMax(arr)); // [1, 11]
생각한대로 바로 구현되어서 문제가 없었다.
주어진 문자열을 요약하는 함수를 작성해주세요!
// 문자열 요약
// 각 문자의 갯수를 카운트해서 출력
function summary (s) {
// 각 문자를 담을 객체 obj
const obj = {};
// 반환할 문자열 str
let str = "";
// 현재 요소가 객체 있으면 현재 요소++ 없으면 현재 요소를 1로 초기화
for (let i = 0; i < s.length; i++) {
const char = s[i];
if (obj[char]) obj[char]++;
else obj[char] = 1;
}
// 카운트한 객체의 키
let temp1 = Object.keys(obj);
// 카운트한 객체의 값
let temp2 = Object.values(obj);
for (let i = 0; i < temp1.length; i++ ) {
// 키+값 형태의 문자열 추가
str += temp1[i]+temp2[i];
// 마지막 요소에 /를 추가하지 않기 위해 마지막 요소면 중단
if (i == temp1.length-1) break;
str += "/";
}
return str;
}
const str = "aaabbbc";
console.log(summary(str)); // a3/b3/c1
오늘 아침에 강창민 튜터님의 알고리즘 세션에서 쓰셨던 방법이 바로 떠올랐다.
문제는 객체의 키와 값을 둘 다 가져와야 된다는 부분이였는데
obj.a 같이 키를 알고 있을 때 값을 가져오는 방법은 알고 있었는데
키가 무엇인지 아는 방법이 떠오르지 않아 js 기본 문법에 정리해놓았던 다시 찾아보았다.
객체 메소드에 답을 찾을 수 있었는데
객체의 키들을 가져오는 메소드 Object.keys() 값을 가져오는 Object.values()를 사용하니
해결할 수 있었다.
주어진 배열에서 두 수를 선택하여 그 합이 주어진 target 값과 일치하는지 확인하는 함수를 작성하세요. 일치하는 경우 true, 그렇지 않은 경우 false를 반환하세요.
// 배열에서 두 수를 선택하여 합이 target과 일치하는지 확인
// 일치하는 경우 true 아닐 경우 false 반환
function sumEqual(arr, target) {
// 중첩 반복문으로 완전 탐색
// 마지막은 다음 요소와 더할 수 없으니 시행하지 않음
for (let i = 0; i < arr.length -1; i++) {
for (let j = i + 1; j < arr.length; j++) {
// 인덱스가 겹치지 않는 두 수의 합
let sum = arr[i] + arr[j];
// 두 수의 합과 target이 일치하면 true 반환
if (sum == target) return true;
}
}
// 반복문 종료까지 true가 반환되지 않으면 false 반환
return false;
}
const arr = [2, 7, 11, 15];
const target = 9;
console.log(sumEqual(arr, target)); // true
두 수를 선택한다는 개념이 잘 이해가 안됐다. 내가 해석하기론 n번째 수를 각기 다른 값과
한번 씩 더해서 그 값이 있는지 확인한다고 생각하고 로직을 만들었다.
중첩 for문이 바로 떠올랐는데 전부 다 돌면 같은 연산이 많아 진다는게 문제였다.
그래서 j의 초기값을 i와 겹치지 않게 해서 연산 횟수를 줄였다.
주어진 문자열이 유효한 괄호 조합인지 확인하는 함수를 작성하세요. 유효한 조합은 모든 여는 괄호가 올바르게 닫혀야 하며, 괄호의 순서도 일치해야 합니다.
()
, {}
, []
의 세 종류입니다.// 문자열이 유효한 괄호 조합인지 확인
// 괄호가 전부 올바르게 여닫는지 확인, 순서도 확인
// 절반으로 나눈 후 앞 부분은 앞에서 부터 뒷 부분은 뒤에서 부터 서로 비교
function bracketCheck (str) {
// 짝수가 아니면 짝이 맞을 수 없으르모 false 반환
if (str.length % 2 !== 0) return false;
// 괄호가 올바르게 열고 닫혔는지 체크하는 객체 check
const check = {
"[" : "]",
"{" : "}",
"(" : ")"
};
str = str.split('');
// 절반으로 나눈 앞 부분
let front = str.slice(0, str.length/2);
// 절반으로 나눈 뒷 부분
// 나눈 후 반전 시켜서 비교
let back = str.slice(str.length/2).reverse();
// check 객체의 키에 해당하는 front의 값이 back과 일치하는지 확인
// 일치하지 않는 괄호가 있으면 짝이 안맞으므로 false 반환
for (let i = 0; i < front.length; i++) {
if (check[front[i]] !== back[i]) return false;
}
return true;
}
const str = "[{([)]}]";
console.log(bracketCheck(str)); // false
예전에 풀어보았던 푸드 파이트 문제의 방법이 떠올랐다.
양쪽이 0을 기준으로 대칭이였는데
그것을 이용해서 앞부분만 연산하고 뒷부분은 앞부분을 뒤집어서 붙이기만 하면 됐었다.
괄호가 열고 닫히는 것도 대칭이니 이 부분을 응용하기로 했다.
주어진 문자열을 반으로 나누고 뒷부분을 반전 시켜 앞부분과 짝을 이루는지 확인하는
로직이다.
좋은 방법이라고 생각했지만 치명적인 문제가 있었다. "([)]"이나 "(){}"같이 대칭이 되지 않으면
무조건 false가 나왔다. 계속 생각해봤지만 반으로 자르고 비교하는 시점에서 대칭이 아니면
전제부터 틀렸다는 결론을 내렸다.
// 문자열이 유효한 괄호 조합인지 확인
// 괄호가 전부 올바르게 여닫는지 확인, 순서도 확인
function bracketCheck (str) {
// 짝수가 아니면 짝이 맞을 수 없으르모 false 반환
if (str.length % 2 !== 0) return false;
// 여는 괄호를 추가할 배열
const arr = [];
// 괄호가 올바르게 열고 닫혔는지 체크하는 객체 check
const check = {
"[" : "]",
"{" : "}",
"(" : ")"
};
for (let i = 0; i < str.length; i++) {
const open = str[i];
// str[i]가 check에 값이 있을 경우 = 열린 괄호인 경우
if (check[open]) {
// 열린 괄호(키)의 값(닫힌 괄호)를 판별하고
// 열린 괄호의 짝이 맞는지 확인하기 위해 arr에 추가
arr.push(open);
// 닫힌 괄호인 경우
} else {
// 마지막 열린 괄호의 짝을 확인하기 위해 pop으로 제거하고
// close에 삽입
const close = arr.pop();
// check의 키(close)(여는 괄호)에 대응하는 값(닫는 괄호)인지 판별
if (check[close] !== open) return false;
}
}
return arr.length == 0;
}
const str = "([)]";
console.log(bracketCheck(str)); // false
열린 괄호를 추가할 배열을 만들고 열린 괄호일 경우 그 열린 괄호를 배열에 추가한다.
닫힌 괄호가 나왔을 때 추가한 배열의 마지막 열린 괄호와 현재 닫힌 괄호가 짝을 이루는지
check 객체의 키와 밸류를 이용해서 판별했다.
stack 구조로 만든 로직이다. 후입선출, 마지막 값을 빼는 구조.