노트/알고리즘

JavaScript 연습 문제

작성 수정

Python 으로만 풀다가 JavaScript 로 옮겨 온 뒤의 연습이다. 2022년 4월 8일에 하루 동안 푼 네 문제, TestDome 연습 세 문제, 2024년 6월의 LeetCode 균형 이진 트리와 프로그래머스 숫자 문자열과 영단어가 있다. 체스는 함수 틀만 있고, 출석 이벤트의 DP 풀이는 if 뒤가 비어 있어 문법 오류 상태이며, 숫자 문자열과 영단어는 토큰을 모으는 중간에 멈췄다. 끝내지 못한 것도 그대로 둔다.

온풍기 (k×k 창에서 1 의 최대 개수)

function solution(office, k) {
  let result = 0;
  const cnt = office.length - k + 1;
  for (let i = 0; i < cnt; i++) {
    for (let j = 0; j < cnt; j++) {
      let temp = 0;
      for (let n = 0; n < k; n++) {
        for (let m = 0; m < k; m++) {
          office[i + n][j + m] === 1 && temp++;
        }
      }
      temp > result && (result = temp);
    }
  }
  return result;
}

// console.log(
//   solution(
//     [
//       [1, 0, 0, 0],
//       [0, 0, 0, 1],
//       [0, 0, 1, 0],
//       [0, 1, 1, 0],
//     ],
//     2
//   )
// );

console.log(
  solution(
    [
      [1, 0, 0],
      [0, 0, 1],
      [1, 0, 0],
    ],
    2
  )
);

차익 계산 (며칠 뒤에 가격이 오르는가)

function solution(price) {
  let result = [];

  for (let i = 0; i < price.length - 1; i++) {
    const todayPrice = price[i];
    let temp = 0;
    for (let nextDayPrice of price.slice(i + 1)) {
      temp++;
      if (nextDayPrice - todayPrice > 0) {
        result.push(temp);
        break;
      }
    }
    result[i] || result.push(-1);
  }
  result.push(-1);
  return result;
}

console.log(solution([4, 1, 4, 7, 6]));
console.log(solution([13, 7, 3, 7, 5, 16, 12]));

출석 이벤트 (연속 k 개의 최대 합)

function solution(estimates, k) {
  let sum = 0;
  for (let i = 0; i < estimates.length - k + 1; i++) {
    const curSum = estimates.slice(i, i + k).reduce((acc, cur) => acc + cur, 0);
    curSum > sum && (sum = curSum);
  }

  return sum;
}

function dp_solution(estimates, k) {
  const n = estimates.length;
  let maxNum = 0;
  let partialNum = 0;
  let pos = 0;
  for (let i = 0; i < n; i++) {
    if (pos < k) {
      partialNum += estimates[i];
      pos++;
    } else {
      if
    }

    if (partialNum > maxNum) {
      maxNum = partialNum;
    }
  }

  return maxNum;
}

체스 (틀만 있음)

function solution(n, k) {
  var answer = -1;
  return answer;
}

console.log(solution(2, 2));
console.log(solution(3, 2));

TestDome: 중복 없는 수 찾기

function findUniqueNumbers(numbers) {
  let sorted = numbers.sort((a, b) => a - b);
  let duplicated = [];
  let unique_set = new Set(numbers);

  for (let i = 0; i < sorted.length; i++) {
    sorted[i] === sorted[i + 1] && duplicated.push(sorted[i]);
  }

  for (item of duplicated) {
    unique_set.delete(item);
  }

  return [...unique_set];
}

let result = findUniqueNumbers([1, 2, 1, 3]);
console.log(result);

TestDome: 별점 매기기

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script defer src="index2.js"></script>
    <link rel="stylesheet" href="index2.css" />
  </head>
  <body>
    <div id="rating">
      <span>*</span>
      <span>*</span>
      <span>*</span>
      <span>*</span>
      <span>*</span>
    </div>
  </body>
</html>

CSS

span {
  font-size: 42px;
}

.active {
  color: red;
}

JavaScript

function setup() {
  const rating = document.querySelector('#rating');
  function getNumber(e) {
    const children = document.getElementsByTagName('span');
    for (i in children) {
      // i는 문자열로 이루어진 숫자가 들어가기 때문에 숫자로 변환해야한다.
      if (children[i] == e.target) {
        return parseInt(i);
      }
    }
  }

  function paintStar(num) {
    for (let i = 4; i > num - 1; i--) {
      document.getElementsByTagName('span')[i].classList.remove('active');
    }

    for (let i = 0; i < num + 1; i++) {
      document.getElementsByTagName('span')[i].classList.add('active');
    }
  }

  function handleClick(e) {
    const num = getNumber(e);
    paintStar(num);
  }

  rating.addEventListener('click', handleClick);
}

setup();

TestDome: 새 폴더 이름 만들기

function generateNewFolderName(existingFolders) {
  const existingFolderNumber = existingFolders.length;
  const isNew = existingFolders.some((item) => item === 'New Folder');

  if (!existingFolderNumber) {
    return;
  }

  if (!isNew) {
    return 'New Folder';
  } else {
    let count = 2;
    function checkFolder() {
      let str = `New Folder (${count})`;
      let has = existingFolders.some((item) => item === str);
      if (has) {
        ++count;
        return checkFolder();
      } else {
        return str;
      }
    }
    return checkFolder();
  }
}

console.log(generateNewFolderName(['New Folder']));

LeetCode 110: 균형 이진 트리 (DFS 와 BFS 두 가지)

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {boolean}
 */

 // 1. 트리 구조의 데이터 구조
 // 2. 각 노드는 parent 노드를 기억해야함
 // 3. 재귀로 접근
 // 4. subtree left right 차이가 1을 넘는지 확인
 // 5. 높이값을 계산해야함 -> 자식 노드들이 가져와야

 /**
  *
  * @param {} rootNode
  * @returns [boolean, number] isBalanced, height
  */

var isBalancedDFS = function(rootNode) {
    function calcHeight(node) {
        if (node === null) {
            return 0;
        }
        let leftHeight = calcHeight(node.left);
        let rightHeight = calcHeight(node.right);
        const isUnbalanced = leftHeight === -1 || rightHeight === -1;

        if (Math.abs(leftHeight - rightHeight) > 1 || isUnbalanced) {
            // 1.현재 노드의 서브트리 높이 차이가 1을 초과하는 경우
            // 2. 서브트리 중 하나가 이미 불균형인 경우
            return -1;
        }
        return Math.max(leftHeight, rightHeight) + 1;
    }
    return calcHeight(rootNode) !== -1;
};





var isBalancedBFS = function (root) {
    if (!root) return true;

    // 큐 초기화: 루트 노드를 큐에 추가
    let queue = [root];

    while (queue.length > 0) {
        let currentNode = queue.shift();

        // 현재 노드의 서브트리 높이를 계산
        let leftHeight = calcHeight(currentNode.left);
        let rightHeight = calcHeight(currentNode.right);

        // 서브트리 높이 차이가 1을 초과하면 트리는 불균형
        if (Math.abs(leftHeight - rightHeight) > 1) {
            return false;
        }

        // 왼쪽 자식 노드가 있으면 큐에 추가
        if (currentNode.left !== null) {
            queue.push(currentNode.left);
        }

        // 오른쪽 자식 노드가 있으면 큐에 추가
        if (currentNode.right !== null) {
            queue.push(currentNode.right);
        }
    }

    // 현재 노드에서 서브트리의 높이를 계산하는 함수
    function calcHeight(node) {
        if (!node) return 0;

        // 큐 초기화: 시작 노드를 큐에 추가
        let nodeQueue = [node];
        let height = 0;

        while (nodeQueue.length > 0) {
            let levelSize = nodeQueue.length;
            for (let i = 0; i < levelSize; i++) {
                let currentNode = nodeQueue.shift();
                if (currentNode.left !== null) nodeQueue.push(currentNode.left);
                if (currentNode.right !== null) nodeQueue.push(currentNode.right);
            }
            height++;
        }
        return height;
    }

    return true;
};

프로그래머스: 숫자 문자열과 영단어 (미완)

const mapNumber = {
    zero: '0',
    one: '1',
    two: '2',
    ...
}

let token = '';

function solution(s) {
    var answer = '';
    const words = Object.keys(mapNumber);
    const numbers = Object.values(mapNumber);
    let token = '';

    for (_s of s) {
        if (_s in numbers) {
            answer += _s
        } else {
            tokenize(_s) && clearToken();
        }
    }

    return answer;
}

function tokenize(string) {
    token += string;
    if (token in words) {
        return true;
    }
}

function addAnswer() {
    answer += mapNumber[token];
}

function clearToken() {
    token = '';
}