[알고리즘] String 다루기 (가운데 문자 출력, 중복문자 제거, 중복단어 제거, 조건에 일치하는 문자 갯수 찾기)

Perfume·2022년 4월 29일
0

Algorithm

목록 보기
6/11
post-thumbnail
post-custom-banner

오늘은 string을 다루는 문제들을 풀었다. 이전까지 배열 문제들만 풀어서인지 배열로 바꾸어서 푸는 비효율적인 방식을 많이 썼지만, 이 문제들을 풀며 string 메소드에도 익숙해졌다.

💡 가운데 문자 출력

소문자로 된 단어(문자열)가 입력되면 그 단어의 가운데 문자를 출력하는 프로그램을 작성하세요. 단 단어의 길이가 짝수일 경우 가운데 2개의 문자를 출력합니다.

나는 일단 인자로 받은 문자열을 split을 이용해 배열로 만들고, 그 배열의 길이를 2로 나누어 가운데 값을 구한 다음 그 값을 answer라는 빈 배열로 push하고, return할 때 answer에 join("")을 사용하는 방식으로 문제를 풀었다. 배열을 다루는데 익숙해서 일단 string을 배열로 바꾸어 문제를 푼 것이다. 전체 코드는 다음과 같다.

function solution(s) {
  let answer = [];
  const sToArr = s.split("");
  const mid = Math.floor(sToArr.length / 2);
  if (sToArr.length % 2 === 0) {
    answer.push(sToArr[mid - 1], sToArr[mid]);
  } else {
    answer.push(sToArr[mid]);
  }
  return answer.join("");
}

원하는 대로 동작하긴 하지만 다소 아쉬운 점이 있다. string을 굳이 배열로 바꿀 필요 없이, string 메소드를 이용해서 푸는 편이 더 좋았을 것 같다. 이 문제의 경우 substring과 substr을 사용하면 훨씬 간단했다. 아래는 substring을 사용한 풀이다.

function solution2(s) {
  let answer;
  let mid = Math.floor(s.length / 2);
  if (s.length % 2 == 1) answer = s.substring(mid, mid + 1);
  else answer = s.substring(mid - 1, mid + 1);
  return answer;
}

위의 코드보다 확실히 간결하다.

substring의 문법은 다음과 같다.

str.substring(indexStart[, indexEnd])
indexStart - 반환문자열의 시작 인덱스
indexEnd - (옵션) 반환문자열의 마지막 인덱스로, 포함하지 않음.

마지막 인덱스는 포함하지 않기 때문에 (mid, mid+1) 처럼 넣어주었다.

substr을 쓰면 (약간이지만) 코드가 더 짧아진다.

function solution3(s) {
  let answer;
  let mid = Math.floor(s.length / 2);
  if (s.length % 2 == 1) answer = s.substr(mid, 1);
  else answer = s.substr(mid - 1, 2);
  return answer;
}

이 문제를 통해 string 메소드를 공부하게 되서 좋았다.

💡 중복문자 제거

소문자로 된 한개의 문자열이 입력되면 중복된 문자를 제거하고 출력하는 프로그램을 작성하세요. 제거된 문자열의 각 문자는 원래 문자열의 순서를 유지합니다.

이 문제는 일단 실패한 코드부터 적겠다. 나는 또 split()으로 문자열을 쪼갠 배열을 만들었고(이쯤되면 split 중독자인듯) for문을 통해 i와 j값을 비교해서 동일할 경우 j 값을 splice()로 없애는 방식을 사용했다. 그런데 조건을 잘못 설정해서 i와 j값이 동일하면 모든 값이 splice되게 코드를 작성해버렸다. 빈 배열만 덩그라니 return~ 물론 이 방식도 잘 다듬으면 풀 수는 있겠지만, 그냥 indexOf()를 쓰는 해결방식이 나을 듯하다. 아래는 내가 처음 작성했던 코드다. (return값은 당연하게도 아무 것도 없다..)

function solution(s) {
  let answer = s.split("");
  for (let i = 0; i <= answer.length; i++) {
    for (let j = 1; j <= answer.length; j++) {
      if (answer[i] === answer[j]) {
        answer.splice(answer[j]);
      }
    }
  }
  return answer.join("");
}

이걸 더 다듬지 않고, 그냥 indexOf()를 쓰는 방식을 사용했다.

function solution2(s) {
  let answer = "";
  for (let i = 0; i < s.length; i++) {
    if (s.indexOf(s[i]) === i) answer += s[i];
  }
  return answer;
}

indexOf('A')를 사용하면, 'A'가 최초로 등장하는 index를 반환한다. 그러니까 이 코드는 'A'가 처음 등장한 인덱스와 A의 인덱스를 비교해서 동일할 경우 answer에 값을 더해주는 코드다.

💡 중복단어 제거

N개의 문자열이 입력되면 중복된 문자열은 제거하고 출력하는 프로그램을 작성하세요. 출력하는 문자열은 원래의 입력순서를 유지합니다.

직전 문제와 다소 유사한 문제다. 전 문제가 하나의 문자열을 받아 그 문자열에서 특정 문자를 제거하는 과정이었다면, 이번엔 배열에 담긴 여러 값 중 중복되는 값을 제거하는 것만 다르다. 똑같이 indexOf를 사용해서 인덱스가 동일할 경우 answer에 값을 더해주면 된다. 이 문제의 경우 배열이기 때문에 filter를 사용한다. filter는 참이 return되는 요소만 따로 뽑아서 새로운 배열화 시킨다. 즉,

  answer = s.filter(function (v, i) {
    if (s.indexOf(v) === i) return true;
  });

이처럼 indexOf(v)와 인덱스가 동일할 경우 true를 리턴하도록 조건문을 작성하면, answer에는 true인 값들이 담겨 새로운 배열을 형성한다. 전체 코드는 다음과 같다.

function solution(s) {
  let answer;
  answer = s.filter(function (v, i) {
    return s.indexOf(v) === i;
  });
  return answer;
}

💡 조건에 일치하는 문자 개수 찾기

문자열이 입력되면 입력된 문자열에 특정 문자 x가 모두 몇 번 들어가는지 출력하는 프로그램을 작성하세요.

이 문제에도 indexOf()를 사용하면 된다. position을 뜻하는 pos라는 변수명을 선언한 뒤 s.indexOf(x)라는 값을 할당한다. 만약 pos가 -1이 아니라면(indexOf()는 해당하는 값이 없을 경우 -1을 리턴한다) answer의 카운트를 증가시키고, indexOf()의 두번째 매개변수를 1 증가시킨다. 이유를 설명하기 전에 indexOf()의 문법을 확인하면 다음과 같다.

str.indexOf(searchValue[, fromIndex])
searchValue :찾으려는 문자열. 아무 값도 주어지지 않으면 문자열 "undefined"를 찾으려는 문자열로 사용.
fromIndex: (옵션) 문자열에서 찾기 시작하는 위치를 나타내는 인덱스 값이다. 기본값은 0이며, 문자열 전체를 대상으로 찾게 됨.

즉, fromIndex를 pos보다 +1 증가시키는 것은, 우리가 방금 찾은 문자열의 뒷부분에서부터 검색을 시작하라는 의미다. (indexOf()는 일치하는 첫번째 값만 리턴하는데, 이 문제에서 우리는 일치하는 값을 모두 찾아야 하기 때문에.)

while문은 조건문이 참일 때 실행되는 반복문이라서, 해당하는 문자열을 모두 찾으면 자동으로 break되어 반복문이 종료된다. 전체 코드는 다음과 같다.

function findIndex(s, x) {
  let answer = 0;
  let pos = s.indexOf(x);
  while (pos !== -1) {
    answer++;
    pos = s.indexOf(x, pos + 1);
  }
  return answer;
}
profile
공부하는 즐거움
post-custom-banner

0개의 댓글