Skip to content

Insert Delete GetRandom O(1)Β #59

@hsskey

Description

@hsskey

문제 μ„€λͺ… | Insert Delete GetRandom O(1)

RandomizedSet 클래슀λ₯Ό κ΅¬ν˜„ν•˜λŠ” 문제둜, 평균 O(1) μ‹œκ°„ λ³΅μž‘λ„λ‘œ μš”μ†Œμ˜ μ‚½μž…, 제거, 랜덀 선택을 μˆ˜ν–‰ν•  수 μžˆμ–΄μ•Ό ν•œλ‹€.

πŸ“ μ œμ•½μ‘°κ±΄

  • -2^31 <= val <= 2^31 - 1
  • insert, remove, getRandom ν•¨μˆ˜λŠ” μ΅œλŒ€ 2 * 10^5번 호좜됨
  • getRandom 호좜 μ‹œμ μ—λŠ” μ΅œμ†Œ ν•˜λ‚˜μ˜ μš”μ†Œκ°€ μ‘΄μž¬ν•¨μ„ 보μž₯
  • λͺ¨λ“  ν•¨μˆ˜λŠ” 평균 O(1) μ‹œκ°„ λ³΅μž‘λ„λ₯Ό κ°€μ Έμ•Ό 함

πŸ’‘ μ˜ˆμ‹œ

  • Input:
["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"]
[[], [1], [2], [2], [], [1], [2], []]
  • Output: [null, true, false, true, 2, true, false, 2]

문제 ν•΄κ²° κ³Όμ •

Step 1: 문제 μ΄ν•΄ν•˜κΈ°

  • RandomizedSet() - 빈 μ§‘ν•© 생성
  • insert(1) - 1 μ‚½μž…, μ—†μ—ˆμœΌλ―€λ‘œ true λ°˜ν™˜
  • remove(2) - 2 제거 μ‹œλ„, μ—†μœΌλ―€λ‘œ false λ°˜ν™˜
  • insert(2) - 2 μ‚½μž…, μ—†μ—ˆμœΌλ―€λ‘œ true λ°˜ν™˜
  • getRandom() - 1 λ˜λŠ” 2 쀑 ν•˜λ‚˜λ₯Ό λžœλ€ν•˜κ²Œ λ°˜ν™˜ (동일 ν™•λ₯ )
  • remove(1) - 1 제거, μžˆμ—ˆμœΌλ―€λ‘œ true λ°˜ν™˜
  • insert(2) - 2 μ‚½μž… μ‹œλ„, 이미 μžˆμœΌλ―€λ‘œ false λ°˜ν™˜
  • getRandom() - 2만 μžˆμœΌλ―€λ‘œ 2 λ°˜ν™˜

Step 2: μ ‘κ·Ό 방법

μ‹œκ°„λ³΅μž‘λ„ 뢄석:

  • insert: O(1)으둜 μš”μ†Œ 쑴재 유무 확인 및 μ‚½μž…
  • remove: O(1)으둜 μš”μ†Œ 쑴재 유무 확인 및 제거
  • getRandom: O(1)으둜 랜덀 μš”μ†Œ 선택

자료ꡬ쑰 선택:

  • Map: κ°’μ˜ 쑴재 여뢀와 λ°°μ—΄μ—μ„œμ˜ μœ„μΉ˜(인덱슀)λ₯Ό O(1)에 ν™•μΈν•˜κΈ° μœ„ν•¨
  • λ°°μ—΄: 랜덀 μš”μ†Œ 선택을 O(1)에 κ°€λŠ₯ν•˜κ²Œ ν•˜κΈ° μœ„ν•¨

핡심 아이디어:

  • λ°°μ—΄μ—μ„œ μš”μ†Œ μ œκ±°λŠ” 일반적으둜 O(n)μ΄μ§€λ§Œ, μ œκ±°ν•  μš”μ†Œλ₯Ό λ°°μ—΄μ˜ λ§ˆμ§€λ§‰ μš”μ†Œμ™€ κ΅μ²΄ν•œ ν›„ λ§ˆμ§€λ§‰ μš”μ†Œλ₯Ό μ œκ±°ν•˜λ©΄ O(1)에 κ°€λŠ₯

Step 3: μ½”λ“œ 섀계

  1. μ΄ˆκΈ°ν™”: Map(κ°’->인덱슀)κ³Ό λ°°μ—΄(κ°’ μ €μž₯)을 μ„ μ–Έ
  2. insert ν•¨μˆ˜:
    • Map에 값이 μžˆλŠ”μ§€ 확인
    • μ—†μœΌλ©΄ Map에 (κ°’, λ°°μ—΄ 길이) μΆ”κ°€ν•˜κ³  배열에 κ°’ μΆ”κ°€
    • κ²°κ³Ό λ°˜ν™˜
  3. remove ν•¨μˆ˜:
    • Map에 값이 μžˆλŠ”μ§€ 확인
    • 있으면:
      • ν•΄λ‹Ή κ°’μ˜ 인덱슀λ₯Ό κ°€μ Έμ˜΄
      • λ°°μ—΄μ˜ λ§ˆμ§€λ§‰ 값을 κ°€μ Έμ˜΄
      • μ œκ±°ν•  κ°’μ˜ μœ„μΉ˜μ— λ§ˆμ§€λ§‰ 값을 λ„£μŒ
      • λ°°μ—΄μ—μ„œ λ§ˆμ§€λ§‰ 값을 제거(pop)
      • Mapμ—μ„œ λ§ˆμ§€λ§‰ κ°’μ˜ 인덱슀λ₯Ό μ—…λ°μ΄νŠΈ
      • Mapμ—μ„œ μ œκ±°ν•  κ°’ μ‚­μ œ
    • κ²°κ³Ό λ°˜ν™˜
  4. getRandom ν•¨μˆ˜:
    • λ°°μ—΄μ—μ„œ 랜덀 인덱슀 μƒμ„±ν•˜μ—¬ κ°’ λ°˜ν™˜

Step 4: μ½”λ“œ κ΅¬ν˜„

var RandomizedSet = function() {
    this.numMap = new Map(); // κ°’ -> 인덱슀 λ§€ν•‘
    this.numList = [];       // κ°’ μ €μž₯ λ°°μ—΄
};

/** 
 * @param {number} val
 * @return {boolean}
 */
RandomizedSet.prototype.insert = function(val) {
    let res = !this.numMap.has(val); // 값이 μ—†μœΌλ©΄ true
    if (res) {
        this.numMap.set(val, this.numList.length); // κ°’κ³Ό 인덱슀 μ €μž₯
        this.numList.push(val); // 배열에 κ°’ μΆ”κ°€
    }
    return res;
};

/** 
 * @param {number} val
 * @return {boolean}
 */
RandomizedSet.prototype.remove = function(val) {
    let res = this.numMap.has(val); // 값이 있으면 true
    if (res) {
        let idx = this.numMap.get(val); // μ œκ±°ν•  κ°’μ˜ 인덱슀
        let lastVal = this.numList[this.numList.length - 1]; // λ§ˆμ§€λ§‰ κ°’
        
        this.numList[idx] = lastVal; // μ œκ±°ν•  μœ„μΉ˜μ— λ§ˆμ§€λ§‰ κ°’ μ‚½μž…
        this.numList.pop(); // λ§ˆμ§€λ§‰ κ°’ 제거
        this.numMap.set(lastVal, idx); // λ§ˆμ§€λ§‰ κ°’μ˜ 인덱슀 μ—…λ°μ΄νŠΈ
        this.numMap.delete(val); // μ œκ±°ν•  κ°’ μ‚­μ œ
    }
    return res;
};

/**
 * @return {number}
 */
RandomizedSet.prototype.getRandom = function() {
    return this.numList[Math.floor(Math.random() * this.numList.length)];
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions