defsolution(n, times): answer = 0; left,right=1,max(times)*n; # left는 최소시간 right는 최대시간 while(left<=right): mid=(left+right)//2; people=0; for time in times: people += mid //time; # mid 시간동안 심사한 사람의 수
if people>=n: break;
# 검사할 수 있는 사람이 검사할 사람보다 많을 경우
if people >= n: answer =mid; right = mid - 1;
# 검사할 수 있는 사람이 검사할 사람보다 적을 경우
elif people<n: left = mid + 1;
return answer;
로직은 다음과 같다.
최소시간(left)과 최대시간(right)을 정한다.
중간값인 (mid)시간에는 몇 명 검사할 수 있는지 검사한다. 즉 mid를 기준으로 삼는다.
n명 검사할 수 있을경우 right를 mid-1로, n명을 다 검사하지 못할 경우 left를 mid+1로 한다.
이는 mid값을 기준으로 각각의 경우에 해가 되는 right값은 mid의 왼쪽, 해가 되는 left값은 mid의 오른쪽에 위치하기 때문이다.
right가 left보다 작아질 때 까지 반복한다. 최대시간(right)이 최소시간(left)보다 작아졌다는 것은 이전 시행의 결과가 해라는 의미이다.
이진탐색
이진탐색은 기준을 정해놓고 범위를 줄여나가는 것이 핵심인 것 같다.
이 문제의 경우 n명을 검사해야 하므로 n명을 검사할 수 있는 범위를 구해 기준으로 하고 범위를 줄여나가는 방식으로 풀어야 했다.
정리
나와는 상성이 좋지 않지만 비슷한 유형의 문제를 풀다보면 풀 수 있을 것이라고 생각한다..!
// Set up the interval. useEffect(() => { functiontick() { savedCallback.current(); } if (delay !== null) { let id = setInterval(tick, delay); return() =>clearInterval(id); } }, [delay]); }
setInterval + clearInerval의 단점
임피던스 불일치라는 용어를 쓴다. 리액트 프로그래밍 모델은 state를 기반으로 렌더링되고 기타 변수들을 관리한다.
하지만 setInterval은 일단 설정하고 나면 없애는 것 외에는 변경할 수 없다. 또한 react의 state 기반으로 동작하지도 않는다.
state나 props가 변하더라도 교체하기 전까지는 내부의 props와 state를 참조할 것이다.
ref의 사용
위에서 알아본 것 처럼 setInterval은 react의 동작과 다르게 동작한다. 이로 인해 발생하는 문제점은 다음과 같다.
첫 렌더에서 callback1을 가진 setInterval(callback1,delay)를 수행한다.
다음 렌더에서 새로운 props와 state를 거쳐서 만들어지는 callback2가 있다. 하지만 시간을 재설정하지 않고서는 callback을 대체할 수 없다.
이를 해결하려면 useRef를 사용하면 된다.
useRef는 hooks에서 렌더링과 관련없는 변수를 담는데에 이용되는 하나의 상자이다.
솔루션은 다음과 같다.
setInterval(fn,delay)에서 함수가 savedCallback을 호출하게 만든다.
// callback에 변경사항이 있을 경우 가장 최근의 함수를 저장한다 // 최근의 state나 props의 변경사항을 반영한 callback이다. useEffect(() => { savedCallback.current = callback; }, [callback]);
// 타이머를 교체하거나 하는 작업 없이 제일 최근에 들어온 함수를 실행한다. useEffect(() => { functiontick() { savedCallback.current(); } if (delay !== null) { let id = setInterval(tick, delay); return() =>clearInterval(id); } }, [delay]); }
Interval 일시정지하기
위의 useInterval hook에선 null을 delay에 전달하는 것으로 interval을 일시 정지할 수 있다. delay가 null이 아닐경우 타이머를 설정하기 떄문이다..!
cancelToken = axios.CancelToken.source(); // 토큰을 생성 axios.get(url, { cancelToken: cancelToken.token }); // 요청에 토큰을 넣어서 전송 cancelToken.cancel(); // 토큰의 cancel메서드를 이용하여 취소
토큰을 생성하여 axios의 config에 넣어주면 된다. 그 후 토큰의 cancel()메서드를 호출하면 된다.