위코드-TIL-22-06.20-코드카타 2주차(1~5)

jin_sk·2020년 6월 20일
0

위코드

목록 보기
47/49

1번

문제

로마자에서 숫자로 바꾸기

1~3999 사이의 로마자 s를 인자로 주면 그에 해당하는 숫자를 반환해주세요.
로마 숫자를 숫자로 표기하면 다음과 같습니다.

Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

로마자를 숫자로 읽는 방법은 로마자를 왼쪽부터 차례대로 더하면 됩니다.
III = 3
XII = 12
XXVII = 27
입니다.

그런데 4를 표현할 때는 IIII가 아니라 IV 입니다.
뒤의 숫자에서 앞의 숫자를 빼주면 됩니다.
9는 IX입니다.

I는 V와 X앞에 와서 4, 9
X는 L, C앞에 와서 40, 90
C는 D, M앞에 와서 400, 900

코드 작성

내 코드

const romanToNum = s => {
  let transNum = 0;
  
  for (let i = 0; i < s.length; i++) {
    switch(s[i]) {
      case 'I':
        transNum += 1;
        break;
      
      case 'V':
        s[i-1] === 'I' ? transNum += 3 : transNum += 5;
        break;
        
      case 'X':
        s[i-1] === 'I' ? transNum += 8 : transNum += 10;
        break;
        
      case 'L':
        s[i-1] === 'X' ? transNum += 30 : transNum += 50;
        break;
        
      case 'C':
        s[i-1] === 'X' ? transNum += 80 : transNum += 100;
        break;
  
      case 'D':
        s[i-1] === 'C' ? transNum += 300 : transNum += 500;
        break;
  
      case 'M':
        s[i-1] === 'C' ? transNum += 800 : transNum += 1000;
        break;
                
      default:
        ""
        break;
    }
  }
  
  return transNum
}

console.log(romanToNum('III'));
console.log(romanToNum('XII'));
console.log(romanToNum('XXVII'));
console.log(romanToNum('MCMXCIV'));
console.log(romanToNum('LVIII'));
console.log(romanToNum('CD'));

결과

3
12
27
1994
58
400

내 코드 생각

switch case 문으로 작성해보았다
I(1), X(10), C(100)가 다른 문자 앞의 올 경우 그 숫자만큼 빼진다는 것을 반영해야하니
위의 숫자가 앞에 올 때 마다 이미 더해줬으니 그 숫자의 2배 만큼 빼줬다
코드가 썩 효율적이진 않으나 그래도 돌아는 간다...

모델 솔루션

function romanToNum(s) {
  let matching = {
      I: 1,
      V: 5,
      X: 10,
      L: 50,
      C: 100,
      D: 500,
      M: 1000
  }
  
  let strArr = s.split('');
  let numArr = strArr.map(el => matching[el]);
  let sum = 0;
  
  for (let i = 0; i < numArr.length; i++) {
      if (numArr[i] < numArr[i+1]) {
          sum += (numArr[i+1] - numArr[i]);
          i++;
      } else {
          sum += numArr[i];
      }
  }
  
  return sum;
}

모델 솔루션 내 생각

object를 이용한 방법은 생각하지 못했는데 앞으로 잘 사용할 수 있을 것 같다
object의 key, value 를 이용해 값을 가져오면 되는데 이건 미처 생각하지 못한 방법이었다

//   확인용 object 만들기
  const romanMatching = {
    'I': 1,
    'V': 5,
    'X': 10,
    'L': 50,
    'C': 100,
    'D': 500,
    'M': 1000
  }
  
//   인자로 전달받은 s 배열로 변환
  let romanArr = s.split("");
//   배열로 변환한 romanArr 숫자로 변환하기
  let numArr = romanArr.map(el => romanMatching[el]);
//   누적되는 값을 저장할 sum 변수 선언
  let sum = 0;
  
//   변환되는 값 저장을 위한 반복문 생성
  for (let i = 0; i < numArr.length; i++) {
//   로마숫자는 큰 숫자가 먼저나온다, 그런데 만약
//   V, X 앞에 I가 오면 -1
//   L, C 앞에 X가 오면 -10
//   D, M 앞에 C가 오면 -100 을 해줘야 한다
//   그래서 만약 앞에 더 작은 숫자가 오면 뒤에 숫자에서 앞의 숫자를 빼준 값을 sum에 저장하고
//   미리 값을 더했으니 여기서 반복하는 변수를 1 증가 시켜야한다 
//   증가시키지 않으면 값이 이중으로 더해진다 
//   왜냐하면 i번째 에서 이미 i와 i+1까지 더한 값을 반환했기 때문이다
//   그런경우가 아니라면 그냥 더하면된다
    if (numArr[i] < numArr[i+1]) {
      sum += (numArr[i+1] - numArr[i]);
      i++;
    } else {
      sum += numArr[i];
    }
  }
//   반복을 통해 더 한 값을   return 한다
  return sum
}

2번

문제

숫자로 이루어진 배열인 nums를 인자로 전달합니다.
숫자중에서 과반수(majority, more than a half)가 넘은 숫자를 반환해주세요.

예를 들어,

nums = [3,2,3]
return 3

nums = [2,2,1,1,1,2,2]
return 2

가정
nums 배열의 길이는 무조건 2개 이상

코드작성

내 코드

function moreThanHalf(nums) {
  let newNums = Array.from(new Set(nums))
  let findNums = [];
  
  for (let i = 0; i < newNums.length; i++ ) {
    countNum = 0;
    for (let j = 0; j < nums.length; j++) {
      if (newNums[i] === nums[j]) {
        countNum += 1
      } 
    }
    findNums.push(countNum)
  }
  let resultNum = findNums.indexOf(Math.max.apply(null, findNums))
  return newNums[resultNum]
}

console.log(moreThanHalf([3,2,3]))

console.log(moreThanHalf([2,2,1,1,1,2,2]))

결과

3
2

내 코그 생각

먼저 인자로 전달 받은 배열에서 중복을 제외한 값으로 새 배열인 newNums을 생성하고
과반수가 넘은 숫자를 찾기위한 빈 배열인 findNums를 생성한다
우선 각 숫자가 몇번 나왔는지 확인해야 하니 이중 반복이 필요하다
중복을 제외한 배열(newNums)을 기준으로 인자로 전달받은 배열(nums)의 요소를 비교해야 한다
값을 세기 위한 변수 countNum을 설정하고 0으로 초기화 한다
newNums의 0번째 요소와 nums의 요소 전체를 비교한다
만약 nums의 요소와 findNum의 요소의 값이 같다면 countNum을 1 증가 시킨다
위의 반복이 끝나면 findNums에 push 메서드를 사용애 countNum을 요소로 배열의 마지막 요소로 추가한다
그다음 i를 증가시켜 newNums의 다음 요소를 기준으로 nums의 전체 요소를 하나하나 비교해,
산출된 countNums을 findNums 배열에 추가한다
여기서 newNums가 몇번 반복되었는지 값의 순서는 findNums 의 인덱스 순서와 같다
push 메서드로 마지막 요소로 추가했기 때문이다
그래서 findNums의 최대값의 인덱스를 구해 그 값을 newNum의 인덱스로 그대로 활용할 수 있다
여기서 굳이 배열이 아니라 object를 활용할 수 있을것 같다

모델 솔루션

function moreThanHalf(nums) {
  let result;
  
  for (let i = 0; i < nums.length; i++) {
    let sum = 0;
    
    for (let j = 0; j < nums.length; j++ ) {
      if (nums[i] === nums[j]) {
        sum += 1;
      }
    }
    
    if (sum > nums.length/2) {
      return nums[i];
    }
  }
}

// or

function moreThanHalf(nums) {
  let obj = {};
  let key = '';
  let count = nums.length/2;
  
  for (let i = 0; i < nums.length; i++) {
      let thisNum = nums[i];
      
      if (obj[thisNum]) {
          obj[thisNum]++;
      } else {
          obj[thisNum] = 1;
      }
      
      if (obj[thisNum] > count) {
          key = thisNum;
          break;
      }
  }    
  
  return Number(key);
}

3번

문제

s는 여러 괄호들로 이루어진 String 인자입니다.
s가 유효한 표현인지 아닌지 true/false로 반환해주세요.

종류는 '(', ')', '[', ']', '{', '}' 으로 총 6개 있습니다.
아래의 경우 유효합니다.
한 번 괄호를 시작했으면, 같은 괄호로 끝내야 한다.
괄호 순서가 맞아야 한다.

예를 들어 아래와 같습니다.

s = "()"
return true

s = "()[]{}"
return true

s = "(]"
return false

s = "([)]"
return false

s = "{[]}"
return true

코드 작성

내코드

function isValid(s) {
  let result = s.split("")

  for (let i = 0; i < result.length; i++) {
    switch(result[i]) {
      case '(':
        if(result[i+1] === ')') {
          result.splice(i,2)
        }
        break;
      
      case '[':
        if (result[i+1] === ']') {
          result.splice(i,2)
        }
        break;
      
      case '{':
        if (result[i+1] === '}') {
          result.splice(i,2)
        }
        break;
      
      default:
        return false;
    }
  }
  
  if (result.length === 0) {return true}
  
  if (result.length === 2) {
    switch(result[0]) {
      case '(':
        return result[1] === ')' ? true : false
        break;
      
      case '[':
        return result[1] === ']' ? true : false
        break;
      
      case '{':
        return result[1] === '}' ? true : false
        break;
      
      default:
        return false;
    }
  } else {
    return false
  }
}

console.log(isValid("()"));
console.log(isValid("()[]{}"));
console.log(isValid("(]"));
console.log(isValid("([)]"));
console.log(isValid("{[]}"));
console.log(isValid("("));
console.log(isValid("]"));
console.log(isValid("(())[]"));
console.log(isValid('(])'));
console.log(isValid(']]'));
console.log(isValid('([)]'));

결과

true
false
false
false
true
false
false
true
false
false
false

정현님

function isValid(s) {
    let stack = [];
    let map = {
        '(': ')',
        '[': ']',
        '{': '}'
    }
    
    for (let i = 0; i < s.length; i++) {
      if (s[i] === '(' || s[i] === '{' || s[i] === '[' ) {
          stack.push(s[i])
      }
      else if (s[i] === ')' || s[i] === '}' || s[i] === ']' ) {
        let last = stack.pop()
        if (s[i] !== map[last]) {
          return false
        }
      }
    }
    
    if (stack.length !== 0) {
    return false
    }
    
    return true
}

모델 솔루션

function isValid(s) {
  let matching = {
      '(': ')',
      '[': ']',
      '{': '}'
  };

  let closeArr = [];
  let openArr = [];
  let sArr = s.split('');
  let result = true;

  for (let i = 0; i < sArr.length; i++) {
      let thisStr = sArr[i];
      let closeForOpen = matching[thisStr];
      if (closeForOpen) {
        openArr.push(thisStr);
        closeArr.unshift(closeForOpen);
      } 
      else {
        if (thisStr === closeArr[0]) {
          closeArr.shift();
          openArr.pop();
        } else {
          result = false;
          break;
        }
      }
  }
  
  return result && closeArr.length === 0;
}

설명

//s가 '({})' 라고 가정하겠습니다.
function isValidForCommnet(s) {
  let matching = {
      '(': ')',
      '[': ']',
      '{': '}'
  };

  let closeArr = [];
  let openArr = [];
  let sArr = s.split('');
  let result = true;
  
  //sArr = ['(', '{', '}', ')'] 입니다.
  //sArr을 for문 돌리면서 
  //시작괄호는 openArr에 넣어주고,  ex) openArr = ['(', '{']
  //끝 괄호는 closeArr에 넣어서,    ex) closeArr = ['}', ')']
  //openArr 마지막번째 괄호가 closeArr의 첫번째괄호랑 맞아야 된다는걸 확인하면 됩니다.
  for (let i = 0; i < sArr.length; i++) {
      let thisStr = sArr[i];
      
      //이번 순서의 괄호(thisStr)가 
      //시작괄호-(,[,{- 이라면, matching에 key로 존재하니까
      //closeForOpen가 ) or ] or } 일것이고,
      //끝 괄호라면 undefined 이겠죠.
      let closeForOpen = matching[thisStr];
      
      //thisStr가 시작괄호여서 closeForOpen가 존재한다면,
      if (closeForOpen) {
        
        //openArr에 하나씩 push합니다.
        openArr.push(thisStr);
        //closeArr에는 앞쪽에서 unshift합니다. 
        closeArr.unshift(closeForOpen);
        
      } 
      //closeForOpen가 존재하지 않는다는 뜻은 thisStr가 끝괄호라는 뜻
      else {
        //이번 괄호인 thisStr가 끝괄호면 closeArr에 무조건 첫 번째에 있어야 합니다.
        if (thisStr === closeArr[0]) {
          //제대로 괄호가 여닫기 됐으므로, 
          //closeArr의 첫번째 요소를 제거해주고
          //해당 끝괄호랑 매치되는 openArr의 첫 요소도 제거해줍니다.
          closeArr.shift();
          openArr.pop();
        } else {
          //thisStr가 끝괄호인데, 
          //closeArr의 첫 번째 요소에 있지 않다는 뜻은 제대로 여닫기가 안 된 것이므로
          //for문을 break로 끝내줍니다.
          result = false;
          break;
        }
      }
  }
  
  return result && closeArr.length === 0;
}

4번

문제

nums는 숫자로 이루어진 배열입니다.
가장 자주 등장한 숫자를 k 개수만큼 return해주세요.

nums = [1,1,1,2,2,3],
k = 2

return [1,2]

nums = [1]
k = 1

return [1]

코드작성

내코드

function topK(nums, k) {
  let newNums = Array.from(new Set(nums));
  let findNums = [];
  let resultNums = [];
  
  for (let i = 0; i < newNums.length; i++) {
    countNum = 0;
    for (let j = 0; j < nums.length; j++) {
      if (newNums[i] === nums[j]) {
        countNum += 1
      }
    }
    findNums.push(countNum)
  }

  for (let x = 0; x < k; x++) {
    let maxNum = findNums.indexOf(Math.max.apply(null, findNums))
    resultNums.push(newNums[maxNum])
    
    findNums.splice(maxNum, 1)
    newNums.splice(maxNum,1)
  }
  
  return resultNums;
}

console.log(topK([1,1,1,2,2,3], 2));
console.log(topK([1], 1));
console.log(topK([1,2,2,2,3,4,4,4,4] , 2));

결과

[ 1, 2 ]
[ 1 ]
[ 4, 2 ]

모델솔루션

function topK(nums, k) {
    let obj = {};
    let arr = [];
    
    nums.forEach(el => {
        if (obj[el]) {
            obj[el]++;
        } else {
            obj[el] = 1;
        }
    });
    
    for (let properyName in obj) {
        arr.push([properyName, obj[properyName]]);
    }
    
    return arr.sort((a, b) => (b[1] - a[1])).slice(0,k).map(el => Number(el[0]));
}

topK([1,2,2,2,3,4,4,4,4] , 2);

5번

문제

인자인 height는 숫자로 이루어진 배열입니다.
그래프로 생각한다면 y축의 값이고, 높이 값을 갖고 있습니다.

아래의 그래프라면 height 배열은 [1, 8, 6, 2, 5, 4, 8, 3, 7] 입니다.

![]

저 그래프에 물을 담는다고 생각하고,
물을 담을 수 있는 가장 넓은 면적의 값을 반환해주세요.

가정
배열의 길이는 2이상입니다.

코드 작성

내코드

function getMaxArea(height) {
  let y = height;
  let result = [];
  
  for (let w = 0; w < y.length; w++) {
    for (let h = 0; h < y.length; h++) {
      if (y[w] <= y[h]) {
       let area = y[w] * Math.abs(h-w);
       result.push(area)
      }
    }
  }
  
  return Math.max.apply(null, result)
  
}

console.log(getMaxArea([1, 8, 6, 2, 5, 4, 8, 3, 7]))
console.log(getMaxArea([1, 1]))
console.log(getMaxArea([35, 46, 43, 59, 59]))
console.log(getMaxArea([96,84,31,57,7,2,12,90,73,15,6,7,7,31,35,20,13,40,74,77,10,36,60,13,49,97,69,33,19,100,74,13,97,56,68,76,50,89,95,7,20,5,30,92,88,11,75,12,87,77,79,15,69,14,7,39,8,99,13,33,81,68,22,78,56,33,86,68,90,92,90,61,45,85,52,54,66,74,10,91,25,73,6,87,65,63,65,85,49,2,22,37,88,71,84,18,10,88,96,43,65,20,37,57,81,43,49,46,51,11,9,65,49,9,52,6,68,26,96,16,27,36,31,45,49,39,32,57,48,24,89,64,8,3,61,23,53,53,38,38,79,86,79,77,7,64,100,75,64,46,31,63,28,88,42,28,28,70,18,19,33,96,74,58,27,87,51,76,44,61,10,47,78,90,58,16,17,22,2,58,83,21,51,90,55,25,75,85,94,52,73,40,39,93,14,91,9,60,90,63,93,71,23,79,95,16,79,5,80,40,36,80,2,82,7,15,95,68,11,71,30,47,87,88,76,72,47,91,10,74,9,73,88,23,31,30,4,39,62,64,48,60,80,11,16,18,35,12,6,17,5,64,20,74,6,42,73,51,41,2,65,37,40,76,64,84,76,57,73,28,11,12,10,86,90,70,33,50,60,90,37,1,61,96,82,4,7,71,11,80,5,4,51,71,95,83,23,41,51,96]))

결과

49
1
140
28704

모델 솔루션

function getMaxArea(height) {
    let size = 0;
    
    for (let i = 0; i < height.length; i++) {
        for (let j = i+1; j < height.length; j++) {
            size = Math.max(Math.min(height[i], height[j]) * (j-i), size);
        }
    }
    
    return size;
}

0개의 댓글