정의 : 특정 작업을 달성하기 위한 과정이나 일련의 단계를 의미, 문제를 해결하기 위한 일련의 수학적 단계 (ex. 유튜브 알고리즘)
필요성 :
어떻게 해야 알고리즘을 더 잘 이해할 수 있을까?
→ 타고난 문제 해결 능력도 있겠지만, 노력하면서 향상될 수 있음.
- 문제 해결을 위한 계획을 수립한다.
- 일반적인 문제 해결 패턴을 파악한다. → 카테고리화
Q. 문자열을 입력받아 각 문자의 개수를 반환하는 함수를 작성하시오.
function charCount(str) {
let result = {};
for(let i = 0; i < str.length; i++) {
let char = str[i].toLowerCase();
if(result[char] > 0) { // value가 0보다 크면 이미 해당 문자가 존재한다
result[char]++; // 1 증가
}
else {
result[char] = 1; // 1로 설정
}
}
return result;
}
function charCount(str) {
let obj = {};
for(let char of str) {
char = char.toLowerCase();
if(/[a-z0-9]/.test(char)){ // 문자가 영숫자인지 test하는 정규 표현식 (특수문자 제외)
obj[char] = ++obj[char] || 1; // ||을 기준으로 truthy면 값 증가, falsy면 1로 설정
}
}
return obj;
}
function charCount(str) {
let obj = {};
for(let char of str) {
if(isAlphaNumeric(char)) {
char = char.toLowerCase();
obj[char] = ++obj[char] || 1;
}
}
return obj;
}
function isAlphaNumeric(char){
let code = char.charCodeAt(0); // 첫번째 문자를 할당
if(!(code > 47 && code < 58) && // 숫자 (0-9)
!(code > 64 && code < 91) && // 대문자 (A-Z)
!(code > 96 && code < 123)) { // 소문자 (a-z)
return false;
}
return false;
}
charCodeAt(0)
Q. 배열 2개를 입력받아 첫번째 배열의 모든 값의 제곱이 두번째 배열에 포함되면 참을 반환하는 same 함수를 작성해라. (순서 상관없음)
same([1,2,3], [4,1,9]) // true
same([1,2,3], [1,9]) // false
same([1,2,1], [4,4,1]) // false (must be same frequency)
function same(arr1, arr2){
if(arr1.length !== arr2.length){
return false;
}
for(let i = 0; i < arr1.length; i++){
let correctIndex = arr2.indexOf(arr1[i] ** 2)
if(correctIndex === -1) {
return false;
}
console.log(arr2);
arr2.splice(correctIndex,1)
}
return true;
}
same([1,2,3,2], [9,1,4,4]) // true
function same(arr1, arr2){
if(arr1.length !== arr2.length){
return false;
}
let frequencyCounter1 = {}
let frequencyCounter2 = {}
for(let val of arr1){
frequencyCounter1[val] = (frequencyCounter1[val] || 0) + 1
}
for(let val of arr2){
frequencyCounter2[val] = (frequencyCounter2[val] || 0) + 1
}
console.log(frequencyCounter1);
console.log(frequencyCounter2);
for(let key in frequencyCounter1){
if(!(key ** 2 in frequencyCounter2)){
return false
}
if(frequencyCounter2[key ** 2] !== frequencyCounter1[key]){
return false
}
}
return true
}
same([1,2,3,2,5], [9,1,4,4,11]) // false
Q. 두 개의 문자열이 주어지면 두 번째 문자열이 첫 번째 문자열의 애너그램인지 확인하는 함수를 작성해라. 애너그램은 단어의 문자를 재배열해 다른 뜻을 가진 단어로 바꾸는 것을 말한다. (ex. iceman → cinema)
validAnagram('', '') // true
validAnagram('aaz', 'zza') // false
validAnagram('anagram', 'nagaram') // true
validAnagram("rat","car") // false) // false
validAnagram('awesome', 'awesom') // false
validAnagram('amanaplanacanalpanama', 'acanalmanplanpamana') // false
validAnagram('qwerty', 'qeywrt') // true
validAnagram('texttwisttime', 'timetwisttext') // true
function validAnagram(first, second) {
if(first.length !== second.length) {
return false;
}
const lookup = {};
for(let i = 0; i < first.length; i++) {
let letter = first[i];
lookup[letter] ? lookup[letter] += 1 : lookup[letter] = 1;
}
for(let i = 0; i < second.length; i++) {
let letter = second[i];
if(!lookup[letter]) {
return false;
} else {
lookup[letter] -= 1;
}
}
return true;
}
function validAnagram(str1, str2){
// add whatever parameters you deem necessary - good luck!
let obj1 = {};
let obj2 = {};
if(str1.length !== str2.length) {
return false;
}
for(let val of str1) {
obj1[val] = (obj1[val] || 0) + 1;
}
for(let val of str2) {
obj2[val] = (obj2[val] || 0) + 1;
}
for(let key in obj1) {
if(obj1[key] !== obj2[key]) {
return false;
}
}
return true;
}
Q. 정렬된 배열을 받는 sumZero 함수를 작성해라. 함수는 합계가 0인 첫 번째 쌍을 찾아야 하며, 합계가 0이거나 쌍이 존재하지 않는 경우 정의되지 않은 두 값을 모두 포함하는 배열을 반환한다. (양 끝에서 시작하여 중간으로 이동하는 경우)
sumZero([-3,-2,-1,0,1,2,3]) // [-3, 3]
sumZero([-2,0,1,3]) // undefined
sumZero([1,2,3]) // undefined
function sumZero(arr){
for(let i = 0; i < arr.length; i++){
for(let j = i+1; j < arr.length; j++){
if(arr[i] + arr[j] === 0){
return [arr[i], arr[j]];
}
}
}
}
sumZero([-4,-3,-2,-1,0,1,2,5])
function sumZero(arr){
let left = 0;
let right = arr.length - 1;
while(left < right){
let sum = arr[left] + arr[right];
if(sum === 0){
return [arr[left], arr[right]];
} else if(sum > 0){
right--;
} else {
left++;
}
}
}
sumZero([-4,-3,-2,-1,0,1,2,5]) // [-2, 2]
Q. 정렬된 배열을 받아 배열의 고유한 값을 계산하는 countUniqueValues라는 함수를 구현해라. 배열에 음수가 있을 수 있지만 항상 정렬된다.
countUniqueValues([1,1,1,1,1,2]) // 2개
countUniqueValues([1,2,3,4,4,4,7,7,12,12,13]) // 7개
countUniqueValues([]) // 0개
countUniqueValues([-2,-1,-1,0,1]) // 4개
function countUniqueValues(arr){
if(arr.length === 0) return 0;
var i = 0;
for(var j = 1; j < arr.length; j++){
if(arr[i] !== arr[j]){
i++;
arr[i] = arr[j]
}
}
return i + 1;
}
countUniqueValues([1,2,2,5,7,7,99])
function countUniqueValues(arr){
let i = 0;
let j = 1;
if(arr.length === 0) return 0;
while(arr.length > j) {
if(arr[i] === arr[j]) {
j++;
} else {
i++;
arr[i] = arr[j];
}
}
return i + 1;
}
Q. 정수 배열과 n이라는 숫자를 받아들이는 maxSubarraySum이라는 함수를 작성해라. 함수는 배열에서 n개의 연속된 요소의 최대 합을 계산해야 한다.
maxSubarraySum([1,2,5,2,8,1,5],2) // 2 + 8 = 10
maxSubarraySum([1,2,5,2,8,1,5],4) // 2 + 5 + 2 + 8 = 17
maxSubarraySum([4,2,1,6],1) // 6
maxSubarraySum([4,2,1,6,2],4) // 4 + 2 + 1 + 6 = 13
maxSubarraySum([],4) // null
function maxSubarraySum(arr, num) {
if (num > arr.length){ // 주어진 수가 배열의 길이보다 크면 null 반환
return null;
}
var max = -Infinity; // 배열이 모두 음수일 경우 가장 큰 합은 여전히 음수이므로 음수로 최댓값 지정
for (let i = 0; i < arr.length - num + 1; i ++){
temp = 0; // 각 루프의 합계가 저장되는 변수
for (let j = 0; j < num; j++){ // i를 기준으로 num개씩 더함
temp += arr[i + j];
}
if (temp > max) {
max = temp;
}
}
return max;
}
maxSubarraySum([2,6,9,2,1,8,5,6,3],3)
function maxSubarraySum(arr, num){
let maxSum = 0;
let tempSum = 0;
if (arr.length < num) return null; // 주어진 수가 배열의 길이보다 크면 null 반환
for (let i = 0; i < num; i++) { // num 개수 만큼 합산
maxSum += arr[i];
}
tempSum = maxSum;
for (let i = num; i < arr.length; i++) {
tempSum = tempSum - arr[i - num] + arr[i]; // 윈도우의 첫번째 요소 제거 후 다음 요소를 추가해서 합산
maxSum = Math.max(maxSum, tempSum); // 최댓값 비교 후 재할당
}
return maxSum;
}
maxSubarraySum([2,6,9,2,1,8,5,6,3],3)
Q. 정렬된 정수 배열이 주어지면 값을 받아 함수에 전달된 값이 있는 인덱스를 반환하는 search라는 함수를 작성해라. 값을 찾을 수 없으면 -1을 반환한다.
search([1,2,3,4,5,6],4) // 3
search([1,2,3,4,5,6],6) // 5
search([1,2,3,4,5,6],11) // -1
function search(arr, val){
for(let i = 0; i < arr.length; i++){
if(arr[i] === val){
return i;
}
}
return -1;
}
function search(array, val) {
let min = 0;
let max = array.length - 1;
while (min <= max) {
let middle = Math.floor((min + max) / 2); // 반복적으로 절반을 나누어 중간 지점을 찾는다
let currentElement = array[middle];
if (array[middle] < val) {
min = middle + 1;
}
else if (array[middle] > val) {
max = middle - 1;
}
else {
return middle;
}
}
return -1;
}
Udemy의 JavaScript 알고리즘 & 자료구조 마스터클래스를 학습하고 정리한 내용입니다.
잘못된 부분이 있다면 댓글로 피드백 부탁드립니다!