<코드타카 2주차 03.>

강민수·2021년 12월 19일
0

Day 3

문제

입력과 예상 출력 데이터 타입

  • Input 입력 데이터 타입: String
  • Output 출력 데이터 타입: Boolean

문제 접근 / 정리 / 아이디어들/ 주의할 점

  1. 스트링값으로 받은 3종류의 괄호들이 각자 자기의 짝으로 시작하고 끝나는지 확인해야한다.
  2. ⚠️ 괄호 안에 괄호가 중첩되어있을수 있어서 스트링 값을 한번 순회하는것으로 확인이 안될수도있는 점 주의!

테스트 성공한 풀이들

첫번째 풀이와 설명

  • 빈 배열을 선언한다.
  • 3종류(소괄호, 중괄호, 대괄호)의 괄호를 객체에 담아 각 짝별로 연결되는 숫자값을 지정해준다.
  • 스트링값을 배열로 변환하는데, 괄호 별로 일치 하는 키의 값을 위에 선언한 배열에 담아 준다.
    • 배열로 담아주는 요소의 개수만큼 순회하여 반환하는 메서드가 필요하지만, 새로운 배열이 필요한것은 아니기 때문에 Array.prototype.forEach 메서드를 사용하여 순회할때 마다 값을 arr 객체에서 불러와 result 배열에 담아주었다.
  • 배열은 순서가 있는 자료구조 이기 때문에 배열에 담긴 각 요소들은 0부터 들어온 순서대로 인덱스 값이 정해진다. 여기서 배열의 순서가 중요하다. 이유는 열어주는 괄호의 다음 순서로 들어온 괄호가 짝인지 아닌지를 구분 하기 위해서다.
  • 이제 괄호의 짝이 잘열고 닫혀젔는지, 중첩은 잘되었는지 확인해보자.
    • line16 ~ line23 i반복문: 배열을 배열의 길이 만큼 순회 하면서 각 요소의 값이 다음 요소의 값과 짝인지 아닌지를 구분하며, 다음 요소와 짝이 맞다면 0 값으로 할당 하게 해주었다.
    • line24 ~ line28 배열의 요소 만큼 짝 이 맞는 값들은 0값으로 대체 할당 해주었으니, 그 요소들을 제외하고 새로운 배열을 만들어준다. 여기서는 Array.prototype.filter 메서드를 사용하여 짝이 아직 안맞춰진 괄호들에 일치하는 값들이 남아있다.
    • line29 ~ line31 여기서 result에 요소가 남아있지 않다면 위의
    • line16 ~ line28 의 i 반복문과 필터 메서드를 중첩된 괄호들에도 적용시킬수 있도록 j 반복문으로 한번 더 감쌌다.
      • 여기서 중요한 포인트는 result 가 빈 배열일 경우에는 j 반복문을 탈출하여 함수의 반환값으로 넘어가게끔 해준것이다.
      • j 반복문을 100번 돌았는데도 괄호에 대칭하는 값이 남아있다면 그것은 짝이 맞지않는 다는것이다.
01		function isValid(s) {
02		  // 여기에 코드를 입력해주세요.
03		  let result = [];
04		  let arr = {
05		    '(': 10,
06		    ')': 9,
07		    '[': 6,
08		    ']': 5,
09		    '{': 2,
10		    '}': 1,
11		  };
12		  s.split('').forEach((e, i) => {
13		    result.push(arr[e]);
14		  });
15		  for (let j = 0; j < 100; j++) {
16		    for (let i = 0; i < result.length; i++) {
17		      if (result[i] === 9 || 5 || 2) {
18		        if (result[i] === result[i + 1] + 1) {
19		          result[i] = 0;
20		          result[i + 1] = 0;
21		        }
22		      }
23		    }
24		    result = result.filter((e) => {
25		      if (e !== 0) {
26		        return e;
27		      }
28		    });
29		    if (!result[0]) {
30		      break;
31		    }
32		  }
33		  return !result[0] ? true : false;
34		}

두번째 풀이 리팩토링

function isValid(s) {
  // 여기에 코드를 입력해주세요.
  const sToArr = s.split('');
  const sToArrLength = sToArr.length;

  for (let i = 0; i < sToArrLength / 2; i++) {
    for (let j = 0; j < sToArr.length; j++) {
      if (sToArr[j] === '(' && sToArr[j + 1] === ')') {
        sToArr.splice(j, 2);
        break;
      } else if (sToArr[j] === '{' && sToArr[j + 1] === '}') {
        sToArr.splice(j, 2);
        break;
      } else if (sToArr[j] === '[' && sToArr[j + 1] === ']') {
        sToArr.splice(j, 2);
        break;
      }
    }

    console.log(sToArr);
  }

  return (sToArr.length ? false : true);
}

첫번째 풀이 리팩토링

첫번째 풀이와 같은 로직으로 각종 빌트인 메서드를 적용해보았다.

  1. line13 에서 스트링을 배열로 변환해주는 코드에 배열 메서드 Array.from() 를 써보았다.

    • Array.from() 은 유사배열객체 또는 이터러블한 객체를 얕은복사를 통해 새로운 객체를 만들어준다.
  2. line18 에서 i 반복문과 배열 필터 메서드를 배열 필터 메서드 하나도 통합해 보았다.

    • 코드의 줄수가 조금은 간결해 젔지만, 가독성 면에서는 둘다 비슷하게 안좋은듯 하다.
    • 사실 두번의 부정연산자와 논리곱 연산자의 사용이 가독성 면에서는 더 안좋다.
    • 하지만 한번 순회한 값을 다시 순회하여 필터 하는 것이 아니고 한번의 필터를 통해 괄호의 짝을 맞춰갈수있다는 점에서 나름 리팩토링 해보았다.
  3. line28 반환값에 지정해준 삼항 연산자의 결과가 (조건) ? true: false? 일때는 간편하게 조건만 적어주자

01		function isValid(s) {
02		  // 여기에 코드를 입력해주세요.
03		  let result = [];
04		  let arr = {
05		    '(': 10,
06		    ')': 9,
07		    '[': 6,
08		    ']': 5,
09		    '{': 2,
10		    '}': 1,
11		  };
12		
13		  Array.from(s).forEach((e, i) => {
14		    result.push(arr[e]);
15		  });
16		
17		  for (let j = 0; j < s.length ; j++) {
18		    result = result.filter((element, index, array) => {
19		      if (!(array[index] === array[index+1]+1) && !(array[index] === array[index-1]-1)){
20		        return element
21		      }
22		    });
23		    if (!result[0]) {
24		      break;
25		    }
26		  }
27		
28		  return !result[0];
29		}

break를 쓴것과 쓰지 않은 것의 차이

4개의 요소를 가진 스트링값을 인자로 전달한 isValid 홈수를 호출해서 확인해보자!

17		  for (let j = 0; j < s.length ; j++) {
18		    result = result.filter((element, index, array) => {
19		      if (!(array[index] === array[index+1]+1) && !(array[index] === array[index-1]-1)){
20		        return element
21		      }
22		    });
23		    if (!result[0]) {
24		      break;
25		    }
26  			console.log(result)
27		  }

//함수호출문
console.log(isValid("{[]}"))

break를 포함 한 반복문

23		    if (!result[0]) {
24		      break;
25		    }

// console.log(result)의 결과
// [ 2, 1 ] 
// true

break가 없는 반복문

~~23		    if (!result[0]) {
24		      break;
25		    }~~

// console.log(result)의 결과
//[ 2, 1 ]
//[]
//[]
//[]
//true
  • 반복문에서 result배열의 괄호 짝들은 제외하고 남은 괄호들을 새로운 배열로 반환해주는데,
  • 반복문은 기본적으로 입력받은 String값의 길이만큼만 순회하면 되지만, 짝이 모두 맞는 경우라면 길이만큼 순회하지 않아도 된다.
  • 위의 예제를 보면 break를 포함한 반복문은 한번 만 순회한 후 다음 순회때 배열에 요소가 없어 반복문을 탈출하고 함수의 반환값으로 넘어간다.
  • break가 없는 경우 불필요한 순회를 많이 하게 되므로 효율성도 떨어지고 시간도 더 많이 걸릴것이다.
  • 현재 예제는 4개의 요소만 있는 스트링값을 전달했지만, 더 많을 경우 그 효과는 더 커질것이라고 생각한다.

✌️ All tests have passed 6/6

첫풀이

리팩토링된 풀이

profile
개발도 예능처럼 재미지게~

0개의 댓글