[TIL] 7주차 금요일. 주간 알고리즘 문제, 타임어택

Minji Kim·2024년 5월 31일

내배캠TIL

목록 보기
32/73

화요일

문제 정의:
주어진 두 문자열에서 첫 번째 문자열이 두 번째 문자열에 포함되는지 여부를 확인하시오. 포함된다면 true, 포함되지 않는다면 false를 반환하시오.
단, 'include' 함수는 사용하지 마시오.
예시:
입력: "abc", "aabcc"
출력: true
입력: "abc", "def"
출력: false

function isSubstring(s1, s2) {
  // s1이 s2보다 길면 false
  // s2.slice 적용해서 s2[i]부터 s1.length만큼의 문자열이 s1와 일치하면 true
  // 순회 돌리기
  if (s1.length > s2.length) {
    return false;
  }
  for (let i = 0; i <= s2.length - s1.length; i++) {
    if (s1 === s2.slice(i, i + s1.length)) {
      return true;
    }
  }
  return false;
}

수요일

문제 정의:
주어진 문자열에서 각 단어를 반전시키시오. 단어의 순서는 그대로 유지되어야 합니다.
예시:
입력: "the sky is blue"
출력: "eht yks si eulb"
입력: "hello world"
출력: "olleh dlrow"

function reverseEachWord(s) {
  // 빈 문자열 result, 빈 배열 arr 생성
  // 문자열 속 단어들을 words 배열로 split
  // arr 안으로 for문으로 단어를 push. 마지막 제외 띄어쓰기 문자열도(" ")도 push
  // arr 배열 속 문자열 순회.
  // if 한 글자일 경우 result에 그대로 붙이기
  // else 문자열의 마지막 인덱스부터 순회해서 result에 붙이기
  let result = "";
  let arr = [];
  const words = s.split(" ");
  for (let i = 0; i < words.length; i++) {
    arr.push(words[i]);
    if (i < words.length - 1) {
      arr.push(" ");
    }
  }
  for (let i = 0; i < arr.length; i++) {
    if (arr[i].length === 1) {
      result += arr[i];
    } else {
      for (let j = arr[i].length - 1; j >= 0; j = j - 1) {
        result += arr[i][j];
      }
    }
  }
  return result;
}

처음엔 저렇게 작성했는데... 다른 분들 코드를 보니 다들 간결해 보여서 다른 방법을 찾았다.
다른 분들 거 보기 전에도 저거 너무 긴데.. 라는 생각을 했었다. ㅋㅋㅋ

// map과 reverse를 사용해서 다시 작성

function reverseEachWord(s) {
  let result = "";
  const words = s.split(" ");
  const reverseWords = words.map((word) => word.split("").reverse().join(""));
  return (result = reverseWords.join(" "));
}

=> 나도 이제 for문만 쓰지 말고 map을 적극 활용해보자.

목요일

문제 정의:
주어진 문자열을 반전시키시오. 문자열의 각 단어는 그대로 두고 단어의 순서만 반전시키시오.
단, reverse 함수를 사용하면 안된다.
예시:
입력: "the sky is blue"
출력: "blue is sky the"
입력: "hello world"
출력: "world hello"

function reverseWords(s) {
  // split
  // 배열의 마지막 인덱스부터 1 인덱스까지 순회
  // result에 붙이기, 띄어쓰기도
  // 0 인덱스 값도 붙여서 return
  const arr = s.split(" ");
  let result = "";
  for (let i = arr.length - 1; i > 0; i -= 1) {
    result += arr[i] + " ";
  }
  result += arr[0];
  return result;
}

목요일 추가 문제

문제 정의:
주어진 문자열이 팰린드롬인지 확인하라. 팰린드롬이란 앞에서부터 읽었을 때와 뒤에서부터 읽었을 때가 같은 문자열을 의미한다. 가능하다면 true, 아니라면 false를 반환하라.
단, reverse 함수를 사용하면 안된다.
조건:
대소문자를 구분하지 않는다.
공백과 특수 문자는 무시한다.
예시:
입력: "A man, a plan, a canal, Panama"
출력: true
입력: "hello"
출력: false

완성 코드 (튜터님의 코드)

  • 문자열을 뒤집는 대신, 좌우에서 동시에 비교하는 방식
    => 내가 처음에 생각한 로직은 문자열을 뒤집어서 원본과 비교하는 방식이었는데, 튜터님이 주신 피드백으로 이처럼 조금 더 단순하고 깔쌈한... 방법을 배울 수 있었다!
  • 그리고 이 코드 중에 대소문자 구분하지 않고 공백과 특수 문자를 무시하는 코드 메모.
    const sanitizedString = s.toLowerCase().replace(/[^a-z0-9]/g, '');
function isPalindrome(s) {
    const sanitizedString = s.toLowerCase().replace(/[^a-z0-9]/g, '');
    
    let left = 0;
    let right = sanitizedString.length - 1;
    
    while (left < right) {
        if (sanitizedString[left] !== sanitizedString[right]) {
            return false;
        }
        left++;
        right--;
    }
    return true;
}

금요일 - 타임어택 (2)

문제 정의:
주어진 문자열 배열에서 가장 긴 팰린드롬을 찾아 반환하라. 만약 팰린드롬이 없다면 빈 문자열을 반환한다.
조건:
팰린드롬은 앞에서부터 읽었을 때와 뒤에서부터 읽었을 때 동일한 문자열을 의미한다.
대소문자를 구분하지 않으며, 공백과 특수 문자는 무시한다.
reverse 함수를 사용하지 않는다.
예시:
입력: ["abc","car","ada","racecar","cool"]
출력: "racecar" (길이가 같은 팰린드롬이 여러 개라면 사전 순서대로 가장 앞에 있는 것을 선택)
입력: ["notapalindrome","racecar"]
출력: "racecar"
입력: ["def","ghi"]
출력: "" (팰린드롬이 없으므로 빈 문자열 반환)

어제 튜터님이 남겨주신 피드백을 응용해서 문제를 풀었다!

function findLongestPalindrome(words) {
  function isPalindrome(str) {
    let left = 0;
    let right = str.length - 1;
    while (left < right) {
      if (str[left] !== str[right]) {
        return false;
      }
      left++;
      right--;
    }
    return true;
  }
  words.sort((a, b) => a.localeCompare(b));
  console.log(words);
  let result = "";
  for (let i = 0; i < words.length; i++) {
    if (isPalindrome(words[i].toLowerCase().replace(/[^a-z0-9]/g, ""))) {
      if (words[i].length > result.length) {
        result = words[i];
      }
    }
  }
  return result;
}

이번주 느낀 점

알고리즘 문제 재밌다. 리액트도 재밌다. 프로젝트 처음부터 세팅하고, 중구난방 아마추어 같이 안 하려고 노력하면서 정돈되게 (나름..? 작년에 코딩했던 거랑 비교하면 정말 많이 정돈됐다) 하니까 더 재밌고 성장하는 것을 많이 느끼고 있다.
어제 튜터님과의 1대1 면담에서 심화반을 도전해보는 것도 좋다고 추천해주셨다.
알고리즘, 리액트 모두 현재는 중급반에서 공부하고 있는데 한 번 도전해보는 것도 굉장히 좋을 것 같다.
다음주에 한 번 옮겨볼까 고민 중이다. 따라가기 벅차면 언제든 다시 돌아오는 것도 되니.

0개의 댓글