-
구현
1. 랜덤으로 뽑고 중복체크
/*** 중복 없이 랜덤으로 숫자 뽑기* @param {Number} min 최소 숫자* @param {Number} max 최대 숫자* @param {Number} count 뽑을 개수* @returns {Number[]} 중복 없는 랜덤 숫자 배열*/function getUniqueRandomNums(min, max, count) {const result = [];const rangeCount = max - min + 1;let r;while (result.length < count) {r = Math.floor(Math.random() * rangeCount + min);if (result.includes(r) == false) {result.push(r);}}return result;}코드가 간결하지만 일단 랜덤으로 뽑은 후
배열을 순회해서 중복 체크를 하기 때문에
중복 없이 뽑을 확률이 낮을수록 오래 걸립니다.최소 연산 횟수는
(count + 1) * count / 2
라서
min, max 범위는 넓고 뽑을 개수 count가 적다면
대부분은 빠르게 실행됩니다.2. 배열에 넣고 랜덤으로 뽑기
/*** 중복 없이 랜덤으로 숫자 뽑기* @param {Number} min 최소 숫자* @param {Number} max 최대 숫자* @param {Number} count 뽑을 개수* @returns {Number[]} 중복 없는 랜덤 숫자 배열*/function getUniqueRandomNums(min, max, count) {const nums = [];const result = [];let rangeCount = max - min + 1;// min부터 max까지 nums배열에 넣음for (let i = 0; i < rangeCount; i++) {nums[i] = i + min;}// 중복없이 랜덤으로 count만큼 뽑음for (let i = 0, r; i < count; i++) {r = Math.floor(Math.random() * --rangeCount);result[i] = nums[r];nums[r] = nums[rangeCount];}return result;}배열에 min, max 범위만큼 넣어놓고
랜덤으로 고른 후, 제외하기 때문에
연산 횟수는 확률에 의존하지 않아서max - min + count + 1
고정입니다.O(n)
이라 빠를 거 같아 보이지만
min, max 범위가 넓으면 넓을수록
배열에 넣는 과정에서 고정 횟수가 있기 때문에
범위가 넓지 않을수록 빠릅니다.예제
로또 번호를 뽑고자 하면
최소 번호: 1
최대 번호: 45
뽑을 개수: 6getUniqueRandomNums(1, 45, 6);
콘솔에 출력하면 아래와 같이 나옵니다.
[19, 1, 36, 40, 10, 4]
getUniqueRandomNums(1, 45, 6).sort((a, b) => a - b);
sort 메서드를 통해 낮은 순으로 정렬하면
[1, 4, 10, 19, 36, 40]
이렇게 됩니다.