TIL 20180618

오늘 한 일

프로트엔드 스쿨과정 - 리액트

  • children prop
  • 로그인 시 예외 처리 (비동기 예외처리)
  • ref와 “제어되지 않는 컴포넌트”로 폼 바꿔보기
  • Presentational component & Container component
  • Storybook

제어되지 않는 컴포넌트 부분은 break week 기간에 잠깐 튜토리얼 따라해 보면서 봤던 부분인데 다시 복습하게 되었다. form의 기본 submit 기능을 사용하게 되면, 따로 이벤트 메서드를 만들지 않아도 되어 코드가 간결해지는 장점이 있지만, 나중에 폼을 쓰게 될 경우 유효성 검사를 하거나 키보드 접근 관련해서 추가적인 처리를 하게 될 것 같아서 대부분의 경우 제어되는 컴포넌트로 하게 되지 않을까 싶다.

프레젠테이션과 컨테이너 컴포넌트 관련 글은 전날에 올려주셔서 자기 전에 읽어봤는데, 읽어보니 왠지 rgb챌린지 만들면서 이 둘을 잘 구분해서 사용하지 않은 것 같다고 느꼈다. 또 글이 잘 이해가 안되었는데, 오늘 수업을 통해 조금 정리되는 느낌이다.

오늘 읽은 글

내일 할 일

Share Comments

TIL 20180617

오늘 한 일

1. 리액트 RGB Challenge 완성

공식문서 Context 파트와 지난 수업 시간했던 todo 리스트 실습을 참고해서 context를 사용해 완성했다. 만들다보니 컴포넌트를 굉장히 많이 나누게 되었는데, 그러다보니 DOM API로 단순하게 만들었던 것이 굉장히 복잡해진 것 같아서 내가 제대로 만든 건지 확신이 없다. context는 컬러, 스코어, 결과로 나눠서 각 파일을 따로 만들다.
setState()로 각 상태를 변화시키는 메서드를 따로 만들었는데, 예를들면 스코어에서는 upScore, reset으로 하나는 score를 추가해주는 것 하나는 score를 다시 0으로 만드는 메서드이다. 결과 context에서는 showResultGood, showResultBad, reset으로 각각 상태에 ‘good’, ‘bad’, 빈 문자열로 수정하는 메서드이다.
이렇게 하는게 맞는 것일까 아니면 메서드는 하나만 만들고 나중에 사용할 때 값을 던져주는 것을 인자로 받아서 setState에 던져주도록 만들어야했을까… 이런저런 사용법에 고민이 많아진다.
역할과 책임이라는 것에 신경쓰면서 만드려고 했는데, 잘 한건지는 모르겠다. 좀 더 다른 사람들의 코드나 글을 읽어봐야겠다.

만들면서 그동안 배운것을 다시 정리하고 context를 좀 더 이해하게 되었다. 강사님이 오늘 읽으려고 해두었던 글을 번역해서 올려주셔서 그걸 읽어보고 다시 고민해봐야겠다.

2. 알고리즘 문제 풀이

1일 1알고리즘 하려고 하는데 지키기 힘든 일인 것 같다. 특히나 문제가 어려우면 고민하다가 하루가 지나가버린다. 지금은 리액트를 익히는 것 역시 중요하니까 우선순위를 정해서 신간 분배를 잘 해야 될 것 같다.

내일 할 일

  • 리덕스 예습/복습
  • 리액트로 다른 미니 프로젝트 하기(캘린더 다시 만들어본다거나)
Share Comments

Longet Common Prefix

leetcode 문제링크

Write a function to find the longest common prefix string amongst an array of strings.

If there is no common prefix, return an empty string “”.

Example 1:

  • Input: [“flower”,”flow”,”flight”]
  • Output: “fl”

Example 2:

  • Input: [“dog”,”racecar”,”car”]
  • Output: “”
  • Explanation: There is no common prefix among the input strings.
    Note:
    All given inputs are in lowercase letters a-z.

나의 풀이

더 좋은 방법이 생각나지 않아서 일단 난폭하게 for 문 두 번 돌려서 풀어보기로 했다. 이렇게 하지 않고 푸는 방법이 있을까… 생각이 안 난다.
배열에 아무것도 들어있지 않은 경우도 고려한 문제였던 모양이다. 계속 런타임 에러가 나길래 보니 빈 배열이 들어가고 있었다.
for문을 두 번 돌렸지만, 어차피 prefix 찾는 거라서 앞에서 일치하는 경우 외에는 버리기 때문에 return으로 종료시켜 버렸다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 64ms
var longestCommonPrefix = function(strs) {
const first = strs[0];
if (first == null) return '';
let str = '';
for(let i = 0, il = first.length; i < il; i++) {
for(let j = 1, jl = strs.length; j < jl; j++) {
if(first[i] !== strs[j][i]) {
return str;
}
}
str += first[i];
}
return str;
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 60ms
var longestCommonPrefix = function(strs) {
const first = strs[0];
if (first == null) return '';
const newStrs = strs.slice(1);
let str = '';
let i = 0;
while(i < first.length) {
if(newStrs.every((item) => item[i] === first[i])) {
str += first[i]
} else {
return str;
}
i++;
}
return str;
}

배열의 every 메서드와 while로 풀어봤다. 속도가 크게 개선되지는 않았다.

다른 사람 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 50ms
var longestCommonPrefix = function(strs) {

if(!strs.length) return '';
if(strs.length === 1) return strs[0];

let prefix = strs[0];

for(let i in strs) {
while(strs[i].indexOf(prefix) !== 0) {
prefix = prefix.substring(0, prefix.length - 1);
if(!prefix.length) return '';
}
}
return prefix;
};

나와 다른 접근법이다. 나는 배열에 있는 요소의 인덱스를 앞에서부터 돌면서 그 인덱스의 문자열이 모두 같으면 str에 더해서 prefix를 만들어 반환했는데,
여기는 일단 첫번째 문자열을 prefix라 가정하고 시작한다. 배열의 요소를 하나씩 순회하면서 prefix와 일치하는 문자열을 가지지 않으면 prefix에서 거꾸로 문자를 줄여가며 대조한다.

그렇다면 첫번째 문자열은 이미 prefix인데 for in문으로 첫번째 요소를 굳이 돌 필요가 있나 했는데, for loop로 인덱스 1부터 도는 것보다 어차피 while문 조건에 걸려서 다음 요소로 넘어가니까 for in문을 쓰는 게 더 빠른가보다.(환경에 따라 다를 수 있겠지만)

핵심은 indexOf의 사용인 것 같다. 문자열 하나씩 더하는 것보단 문자열 뭉치가 있는 지 확인하는 것이 더 효율적이니까.

1
2
3
4
5
6
7
8
9
10
11
12
13
// 56ms
var longestCommonPrefix = function(strs) {
if(!strs.length) return '';
if(strs.length === 1) return strs[0];
let prefix = strs[0];
for (let i = 1, l = strs.length; i < l; i++) {
while(strs[i].indexOf(prefix) !== 0) {
prefix = prefix.substring(0, prefix.length - 1);
if(!prefix.length) return '';
}
}
return prefix;
};
Share Comments

TIL 20180616

오늘 한 일

Context 복습

context를 복습하면서 리액트를 단순하게 사용해본 RGB 챌린지를 수정하고 있다. 리액트 공식문서를 읽어보고, velopert님의 context API관련 예제도 따라해봤다.
공식문서를 읽어보니 어떻게 쓰는 지는 이해가 되는데, 그래서 어디까지 context를 써주는 것이 좋은지, 코드를 어떻게 관리되도록 설계하는 것이 좋은지는 아직 감이 안잡힌다.
일단 context를 활용해서 전체적으로 이벤트까지 완료한 뒤에 강사님이 공유해 주신 Dan Abramov의 ‘Presentational and Container Components’라는 글을 다시 읽어봐야겠다.

예제를 따라하는 중에 import React, {Component} from 'react' 이하 클래스를 만드는 거나 export시키는 부분은 react 사용하면서 거의 패턴처럼 치게 되니까, vscode의 사용자 코드 조각에 스니펫으로 만들어 두었다.

내일 할 일

  • RGB 챌린지 context 완성하기
  • Redux 예습하기
  • 소프트웨어 공학 시간에 정리한 글 다시 다듬어서 올리기

날이 더워졌다. 에어컨 바람이 간절해진다. 더워질수록 체력 관리를 해야겠다. ‘앞으로 할 일’이라고 썼던 것을 ‘내일 할 일’로 쓰려고 한다. 다 수행하지 못하더라도 내일 할 일로 정해놓으면 더 강제적으로 하게 될 것 같다.

일주일간 블로그를 해보니 장단점이 있다. 일단 글을 좀 더 다듬게 되고, 글 자체가 정제되어 보이는 장점이 있다.
단점은 그냥 깃헙에는 자유롭게 덜 완성된 글이나 정리도 올렸는데, 블로그는 그렇게 하는 것이 쉽지 않아졌다. 물론 누가 잘못된 정보라고 지적하는 게 두려운 것은 아니다. 누가 내 글에 관심을 가져주고, 내가 잘못 알고 있는 부분을 바로잡아 주는 것은 감사한 일이나, 혹시라도 내가 잘못된 정보를 제공하지는 않을까하는 우려도 된다.
그런데 사실 그런 부분을 걱정하기 이전에 검색 엔진 최적화 방법을 알아봐야겠다…;;

Share Comments

TIL 20180615

오늘 한 일

프론트엔드 개발 과정 - 특강 [소프트웨어 공학]

어제 한 과제는 기능 명세가 아니었던 것 같다. 화면설계 전 단계였던듯… why? 도출보다는 상세한 기능 기술이었던 것 같다…
수업시간에 클라이언트가 블록체인 거래소를 만들려고 한다는 상황을 가정해서 요구사항을 분석하고, 클라이언트(강사님)에게 질문하는 식으로 진행되었는데, 블록체인이라는 기술 자체를 잘 몰라서 질문을 할 수가 없었다.
웹 사이트를 볼때 그냥 보는 것이 아니라 어떤 기술을 사용했고, 어떤 콘텐츠로 이루어져있는지 분석해봐야겠다. 그리고 블록체인이라는 기술 자체에도 관심을 기울여야겠다.

앞으로 할 일

  • RGB 챌린지 context 활용하기
  • Redux 미리 예습하기
Share Comments

Palindrome Number

leetcode 문제링크

Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same backward as forward.

Example 1:

  • Input: 121
  • Output: true

Example 2:
Input: -121
Output: false
Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.

Example 3:
Input: 10
Output: false
Explanation: Reads 01 from right to left. Therefore it is not a palindrome.

Follow up:
Coud you solve it without converting the integer to a string?

예?? 이걸 문자열화 하지 말고 풀라구요???

나의 풀이

난이도 easy만 먼저 풀어보는데 속도에 집착하다보니 난이도가 easy가 아닌 것만 같은 기분…

1
2
3
4
5
6
// 304ms 
var isPalindrome = function(x) {
const str = x.toString();
const reverseStr = str.split('').reverse().join('');
return str === reverseStr
};

Hint: Beware of overflow when you reverse the integer.

네..그렇군요… 뒤집는 건 주의해야겠군요…세상에…
아래는 while문을 통해 앞 / 뒤로 접근해서 비교하도록 하는 방법인데,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 268ms
var isPalindrome = function(x) {
const str = x.toString();
const l = str.length - 1;
let i = 0;
let result = true;
while(i <= l) {
if(str[i] !== str[l - i]) {
return (result = false);
}
i++;
}
return result;
}

반으로 나눠야 중복되는 비교를 안하겠구나 생각해서 아래와 같이 수정했지만 속도가 크게 개선되지는 않았다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 260ms 속도 개선이 별로..
var isPalindrome = function(x) {
const str = x.toString();
const l = str.length;
const half = Math.floor(l / 2);
const strF = str.slice(0, half);
const strB = str.slice(l % 2 === 0 ? half : half + 1);
let i = 0;
let result = true;
while(i < half) {
if(strF[i] !== strB[(half - 1) - i]) {
return result = false;
}
i++;
}
return result;
};

혹시나 해서 reverse 메소드를 사용하는 방법을 반으로 나눠서 하는 방법으로 다시 풀어봤다.
300ms가 280ms로 속도가 개선되었으나 앞의 풀이 방법에 비하면 느리다.

1
2
3
4
5
6
7
8
9
10
11
12
// 280ms
var isPalindrome = function(x) {
const str = x.toString();
const l = str.length;
if (l === 1) {
return true;
}
const half = Math.floor(l / 2);
const strF = str.slice(0, half);
const strB = str.slice(l % 2 === 0 ? half : half + 1).split('').reverse().join('');
return strF === strB
};

문자열화하지 않고 숫자인 상태에서 풀면 좀 더 빠를까해서 아래와 같이 풀었는데, 더 느려졌다. 아마 이 역시 주어진 수를 반으로 나눠서 푸는 게 아니라서 그런 것 같다.(수의 길이(?)만큼 비교하게 된다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 300ms 아악 더 느려졌다.
var isPalindrome = function(x) {
if(x < 0) {
return false
}
if(x < 10) {
return true
}
let xClone = x;
const arr = [];
while(xClone) {
const X = xClone % 10;
xClone = parseInt(xClone / 10);
arr.push(X % 10);
}
return x === parseInt(arr.join(''))
}

뭔가 숫자를 반으로 쪼갤 수 있으면 좋겠는데, 이 부분은 방법이 잘 생각나지 않아서 solution을 보기로 했다.
아래는 solution을 참고한 풀이

Approach 1: Revert half of the number

1
2
3
4
5
// C#
while(x > revertedNumber) {
revertedNumber = revertedNumber * 10 + x % 10;
x /= 10;
}

이부분을 통해 수를 반으로 나눠 반복문 안에서 비교할 수 있도록 하는 방법이다.
C#의 문법을 잘 모르지만 C#은 알아서 소수점 아래는 제거해주는 건지;; 아무튼 소수점 아래가 생겨버리므로 나는 JavaScript로 풀어야하니까 parseInt를 통해 정수로 계산되도록 했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 256ms
var isPalindrome = function(x) {
let xC = x;
if(x < 0 || (x % 10 === 0 && x !== 0)) {
return false;
} else if (x < 10) {
return true;
}
let revert = 0;
while(xC > revert) {
revert = parseInt(revert * 10 + xC % 10);
xC = parseInt(xC / 10);
}
return xC === revert || xC === parseInt(revert / 10);
}

Complexity Analysis

  • Time complexity : O(log10n)
    We divided the input by 10 for every iteration, so the time complexity is O(log10n)
  • Space complexity : O(1)

라는데, 복잡성 공부를 해야겠다… 댓글에서는 ‘왜 O(log10n)이냐 O(n)이 맞다’, ‘아니다 솔루션 저자가 맞다’로 의견이 분분한 듯한데 아직 잘 모르겠다;;

Share Comments

TIL 20180614

오늘 한 일

1. RGB Challenge 리액트를 이용해 다시 만들어보기

전날 배운 context를 이용하는 부분은 잘 이해가 되지 않아서 문서를 봤는데, 일단 todo 리스트 실습때 진행했던 것처럼 컴포넌트, state, props를 통해 단순하게 만들어 보는 것부터 시작해서 하나씩 변경해 봐야할 것 같다.
그냥 DOM API로 만들때는 금방 만들었던 것을 구조를 분리해서 컴포넌트 별로 따로 만들고 어떤 것을 상태로 할 지 어떤 것이 컴포넌트 간 공유되는 상태일지를 구분하려니 오히려 오래 걸렸다. 만약 이 게임 자체가 규모가 크다면 이렇게 컴포넌트 별로 분리하는 것은 장기적으로 봤을때 유지보수 하기에는 좀 수월해 질지 모르겠지만 현재 규모에서는 생산성면에서 별로 좋은 방법이 아닌 것 같다.

아직 context를 이용해보지는 못했는데, 역할과 책임에 따라 정리하는 것이 가장 어렵게 느껴졌다.
컬러코드 컴포넌트와 공유되는 상태를 관리하는 조상 컴포넌트와의 사이에 컴포넌트가 많아져서 context를 활용해야 할 것 같다.
컬러 코드를 랜덤으로 계산해내는 부분은 클래스의 메소드로 만드는 것이 적합하지 않은 것 같아서 따로 함수로 빼냈는데, 이렇게 하는게 맞는지는 꼭 주말까지 완성해서 강사님의 피드백을 들을 수 있도록 해야겠다.

2. 기능명세 작성 과제

medical factory 사이트의 로그인 / 회원가입 / 리뷰 페이지를 분석하며 어떤 명세를 통해 만들었을지 명세를 도출해보는 것이 과제였다. 구글 드라이브를 통해 정리했다. 수업시간에 명세를 너무 자세하게 작성하지 말라고 주의해주셨었는데, 자꾸 작성할 것이 늘어나서 이렇게 작성하는게 맞는지 의구심이 든다.;;

찾아보니 기능 명세나 기술 명세에 특별한 폼은 없는 것 같았다. 그래서 그런지 이런식으로 작성해야 한다라고 딱 정리한 글도 찾기 어려웠다.
좀 시간이 걸렸지만, 로그인 / 회원가입 같은 경우는 대부분의 서비스에 들어가는 부분이라 왠지 구축할 때 도움이 될 것 같아서 자세히 분석해봤다. 보다보니 생각보다 누락하거나 유효하지 않은 입력에 대해 검증해야 하는 부분이 많았다. 나도 만들때 이런 부분은 신경 써줘야겠다는 생각을 하게되었다.

3. git alias

git 명령어 몇가지를 alias로 만들어두었다. 만들어두니 git flow ~ 명령을 쓰기가 훨씬 수월해졌다.

1
2
3
4
5
6
7
8
alias gfi='git flow init'
alias gff='git flow feature'
alias gfr='git flow release'
alias gfh='git flow hotfix'
alias gfs='git flow support'

alias gcm='git commit -m'
alias npxreact='npx create-react-app'

너무 많으면 또 외워야하고 잘못 사용할 수도 있을 것 같아서 긴 명령어 위주로 이정도만 해두었다.
작성에 사용한 명령어는 다음과 같다.

1
vi ~/.bashrc

앞으로 할 일

  • RGB 챌린지 주말까지 완성하기(context 사용하기)
Share Comments

TIL 20180613

오늘 한 일

1. 프론트엔드 개발 과정 - 리액트 실습

수업시간에 Provider와 Consumenr랑 props.children이 등장했다. 정신이 혼미해진다.
계속 상태를 필요한 하위 컴포넌트로 내려보내야 한다면 불편하지 않나라고 생각했는데, 그부분을 context를 통해 개선할 수 있단 점이 매력적이지만 역할과 책임에 따라 분리한다거나, 쓰는 방법 자체는 여러번 써봐야겠다.

2. Algorithm 문제 풀이

알고리즘 문제를 푸는 건 잘 못하지만 재미있다. 특히 끙끙 거리며 풀었는데, 가장 성능이 좋은 코드와 현저하게 차이가 나면 대체 무슨 방법으로 풀었을까 엄청 궁금하다. 그래도 한번에 보기에는 좀더 고민해야 될 것 같아서 내가 푼 풀이를 좀 더 다듬었는데, 아쉽게도 별로 속도 개선이 되지 않았다. 그래서 다른 사람 풀이를 봤는데, 접근방식이 달랐다.
이런 점이 재미있는것 같다. 이런 식으로도 풀수 있구나 대단하다 생각하면서도 앞으로 나도 이렇게 풀어봐야지 하면서 얻게되는 게 있는것 같다.


오늘은 복습을 많이 했어야 했는데, 많이 하지 못했다. 그래도 내가 많이 의지했던 언니의 고민을 들어주고 계속 우울해했던 언니의 기운을 북돋아 줄 수 있어서 오늘 하루에 그렇게 아쉬움은 없다. 대신 내일 정말 열심히 복습해야겠다.

Share Comments

Roman to Integer

leetcode 문제링크

Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M.

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

For example, two is written as II in Roman numeral, just two one’s added together. Twelve is written as, XII, which is simply X + II. The number > twenty seven is written as XXVII, which is XX + V + II.

Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used:

I can be placed before V (5) and X (10) to make 4 and 9.
X can be placed before L (50) and C (100) to make 40 and 90.
C can be placed before D (500) and M (1000) to make 400 and 900.
Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range from 1 to 3999.

나의 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 143 - 152ms
var romanToInt = function(s) {
const ROMAN = {
'I': 1,
'V': 5,
'X': 10,
'L': 50,
'C': 100,
'D': 500,
'M': 1000
}
const newS = s.split('').map(item => ROMAN[item]);
return newS.reduce((acc, item, idx, arr) => {
const before = arr[idx - 1];
return acc + (before < item && before ? item - (before * 2) : item)
}, 0)
};

다른 방법도 생각해보려고 했는데, 도저히… map(), reduce() 메소드로 배열을 두번 탐색한게 마음에 걸린다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 156ms
var romanToInt = function(s) {
const ROMAN = {
'I': 1,
'V': 5,
'X': 10,
'L': 50,
'C': 100,
'D': 500,
'M': 1000
}
return s.split('').reduce((acc, item, idx, arr) => {
const before = arr[idx - 1];
const beforeInt = ROMAN[before]
const itemInt = ROMAN[item]
return acc + (beforeInt < itemInt && beforeInt ? itemInt - (beforeInt * 2) : itemInt)
}, 0)
}

reduce 한번으로 처리하도록 변경했는데 이것도 그닥 속도가 개선되지는 않았다.

다른 사람 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
let getIntFromRoman = {
I: 1,
V: 5,
X: 10,
L: 50,
C: 100,
D: 500,
M: 1000
};

var romanToInt = function(s) {
let sum = 0;
let curr, next;
for(let i = 0; i < s.length-1; i++) {
curr = getIntFromRoman[s[i]];
next = getIntFromRoman[s[i+1]];
if(curr < next)
sum -= curr;
else
sum += curr;
}
return sum + getIntFromRoman[s[s.length-1]];
};

for문을 통해 따로 sum 에 더해주는 방식으로 처리했다. 그리고 현재 문자가 다음 문자보다 작으면 오히려 빼주는데, 그렇게 하면 4내지는 9가 나오게 되니 이렇게 풀 수도 있구나하고 깨달음이…

나는 조건 분기했는데…

Share Comments

Add Two Numbers

leetcode 문제링크

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Example

  • Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
  • Output: 7 -> 0 -> 8
  • Explanation: 342 + 465 = 807.

나의 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
// 124ms, 176ms
var addTwoNumbers = function(l1, l2) {
const arr = [];
const sum = (l1, l2) => {
if (l1 && l2) {
arr.push(l1.val + l2.val)
sum(l1.next, l2.next);
} else if (!l2 && l1) {
arr.push(l1.val)
sum(l1.next);
} else if (!l1 && l2) {
arr.push(l2.val)
sum(l2.next);
} else {
return '';
}
}
sum(l1, l2);
let over = false;
const newArr = arr.map((item, idx, arr) => {
if(item >= 10) {
arr[idx + 1] != null ? arr[idx + 1] += 1 : over = true
return item - 10
} else {
return item
}
});
if(over) {
newArr.push(1)
}
return newArr;
}

원래 기존 풀이는 200ms인데 좀 줄였다. 연결리스트에 대한 이해가 부족해서 좀 오래 걸렸다.
아래 코드가 굉장히 비효율적이라고 느껴서 위의 코드처럼 다시 만들었는데 그렇게 효율적으로 보이지는 않는다.
나중에 한번 더 다른 방법으로 풀어보고 다른 사람 풀이를 봐야겠다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 200ms
var addTwoNumbers = function(l1, l2) {
const toArray = list => {
const arr = [];
const search = node => {
arr.push(node.val)
return node.next != null ? search(node.next) : ''
}
search(list)
return arr;
}
const arr1 = toArray(l1);
const arr2 = toArray(l2);
const large = (arr1.length >= arr2.length ? arr1 : arr2);
const small = (arr1.length >= arr2.length ? arr2 : arr1);
const l = large.length;
const newArr = new Array(l).fill(0);
const splice = idx => {
if(newArr[idx + 1] == null) {
newArr.push(1);
} else {
if(newArr[idx + 1] === 9) {
newArr[idx + 1] = 0;
splice(idx + 1)
} else {
newArr[idx + 1]++;
}
}
}
for(let i = 0; i < l; i++) {
if(small[i] == null) {
const result = newArr[i] + large[i];
if(result >= 10) {
splice(i)
newArr[i] = result - 10;
} else {
newArr[i] = result;
}
} else {
const result = large[i] + small[i];
if(result >= 10 || newArr[i] + result >= 10) {
splice(i)
newArr[i] = newArr[i] + (result - 10);
} else {
newArr[i] = newArr[i] + result;
}
}
}
return newArr;
};

Share Comments