λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

Algorithm

[Algorithm] 숫자 κ²Œμž„

πŸ“‹ 문제

xx νšŒμ‚¬μ˜ 2xNλͺ…μ˜ 사원듀은 Nλͺ…μ”© 두 νŒ€μœΌλ‘œ λ‚˜λˆ  숫자 κ²Œμž„μ„ ν•˜λ €κ³  ν•©λ‹ˆλ‹€. 두 개의 νŒ€μ„ 각각 AνŒ€κ³Ό BνŒ€μ΄λΌκ³  ν•˜κ² μŠ΅λ‹ˆλ‹€. 숫자 κ²Œμž„μ˜ κ·œμΉ™μ€ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  • λ¨Όμ € λͺ¨λ“  사원이 λ¬΄μž‘μœ„λ‘œ μžμ—°μˆ˜λ₯Ό ν•˜λ‚˜μ”© λΆ€μ—¬λ°›μŠ΅λ‹ˆλ‹€.
  • 각 사원은 λ”± ν•œ λ²ˆμ”© κ²½κΈ°λ₯Ό ν•©λ‹ˆλ‹€.
  • 각 κ²½κΈ°λ‹Ή AνŒ€μ—μ„œ ν•œ 사원이, BνŒ€μ—μ„œ ν•œ 사원이 λ‚˜μ™€ μ„œλ‘œμ˜ 수λ₯Ό κ³΅κ°œν•©λ‹ˆλ‹€. κ·Έλ•Œ μˆ«μžκ°€ 큰 μͺ½μ΄ μŠΉλ¦¬ν•˜κ²Œ 되고, μŠΉλ¦¬ν•œ 사원이 μ†ν•œ νŒ€μ€ μŠΉμ μ„ 1점 μ–»κ²Œ λ©λ‹ˆλ‹€.
  • λ§Œμ•½ μˆ«μžκ°€ κ°™λ‹€λ©΄ λˆ„κ΅¬λ„ μŠΉμ μ„ μ–»μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

전체 사원듀은 μš°μ„  λ¬΄μž‘μœ„λ‘œ μžμ—°μˆ˜λ₯Ό ν•˜λ‚˜μ”© λΆ€μ—¬λ°›μ•˜μŠ΅λ‹ˆλ‹€. κ·Έλ‹€μŒ AνŒ€μ€ λΉ λ₯΄κ²Œ μΆœμ „μˆœμ„œλ₯Ό μ •ν–ˆκ³  μžμ‹ λ“€μ˜ μΆœμ „ μˆœμ„œλ₯Ό BνŒ€μ—κ²Œ κ³΅κ°œν•΄λ²„λ ΈμŠ΅λ‹ˆλ‹€. BνŒ€μ€ 그것을 보고 μžμ‹ λ“€μ˜ μ΅œμ’… μŠΉμ μ„ κ°€μž₯ λ†’μ΄λŠ” λ°©λ²•μœΌλ‘œ νŒ€μ›λ“€μ˜ μΆœμ „ μˆœμ„œλ₯Ό μ •ν–ˆμŠ΅λ‹ˆλ‹€. μ΄λ•Œμ˜ BνŒ€μ΄ μ–»λŠ” μŠΉμ μ„ κ΅¬ν•΄μ£Όμ„Έμš”.
A νŒ€μ›λ“€μ΄ 뢀여받은 μˆ˜κ°€ μΆœμ „ μˆœμ„œλŒ€λ‘œ λ‚˜μ—΄λ˜μ–΄μžˆλŠ” λ°°μ—΄ A와 i번째 μ›μ†Œκ°€ BνŒ€μ˜ i번 νŒ€μ›μ΄ 뢀여받은 수λ₯Ό μ˜λ―Έν•˜λŠ” λ°°μ—΄ Bκ°€ μ£Όμ–΄μ§ˆ λ•Œ, B νŒ€μ›λ“€μ΄ 얻을 수 μžˆλŠ” μ΅œλŒ€ μŠΉμ μ„ return ν•˜λ„λ‘ solution ν•¨μˆ˜λ₯Ό μ™„μ„±ν•΄μ£Όμ„Έμš”.

 

μ œν•œ 사항

  • A와 B의 κΈΈμ΄λŠ” κ°™μŠ΅λ‹ˆλ‹€.
  • A와 B의 κΈΈμ΄λŠ” 1 μ΄μƒ 100,000 μ΄ν•˜μž…λ‹ˆλ‹€.
  • A와 B의 각 μ›μ†ŒλŠ” 1 μ΄μƒ 1,000,000,000 μ΄ν•˜μ˜ μžμ—°μˆ˜μž…λ‹ˆλ‹€.

 

μž…μΆœλ ₯ 예

[5,1,3,7] [2,2,6,8] 3
[2,2,2,2] [1,1,1,1] 0

 

✏️ 풀이

λͺ¨λ“  상황을 λΉ„κ΅ν•˜κΈ°μ—λŠ” 각 λ°°μ—΄μ˜ 길이가 크기 λ•Œλ¬Έμ— μ ˆλŒ€ λΆˆκ°€λŠ₯ν•  것이라고 μƒκ°ν–ˆλ‹€. BνŒ€μ΄ 많이 이기기 μœ„ν•΄μ„œλŠ” AνŒ€μ΄ 큰 수일 λ•Œ μ ˆλŒ€ 이기지 λͺ»ν•˜λŠ” κ²½μš°μ— 제일 μž‘μ€ 수λ₯Ό 이길 수 μžˆλŠ” κ²½μš°μ— μž‘μ€ 수둜 이길 수 μžˆλ‹€λ©΄ μž‘μ€ 수λ₯Ό 큰 수둜 이겨야 ν•œλ‹€λ©΄ 큰수λ₯Ό λ‚΄λŠ” 것이 큰 수λ₯Ό 아끼며 μ΅œμ„ μ˜ λ°©ν–₯으둜 κ°€λŠ” 것이라고 μƒκ°ν–ˆλ‹€.

 

AνŒ€μ˜ μˆœμ„œλŠ” 상관없이 많이 μ΄κΈ°λŠ” 경우λ₯Ό μ°ΎλŠ” 것이기 λ•Œλ¬Έμ— λ¨Όμ € AνŒ€μ„ ν°μˆ˜λŒ€λ‘œ μ •λ ¬ν•΄μ£Όκ³  비ꡐ해야 ν–ˆλ‹€. μˆ˜κ°€ μ„žμ—¬μžˆλŠ” 경우 μ•žμ„œ μ„Έμš΄ μ „λž΅μ„ μ‚¬μš©ν•  수 μ—†κΈ° λ•Œλ¬Έμ΄λ‹€. 그리고 κ°€μž₯ μž‘μ€ μˆ˜μ™€ 큰 수λ₯Ό κ΄€λ¦¬ν•˜κΈ° μœ„ν•΄μ„œ max heap, min heap을 μ‚¬μš©ν–ˆλ‹€. μœ„μ—μ„œ μ„Έμš΄ μ „λž΅λŒ€λ‘œ μ •λ ¬λœ A의 μ›μ†Œμ™€ λΉ„κ΅ν–ˆλ‹€.

 

1. λ§Œμ•½ κ°€μž₯ μž‘μ€ 수둜 이길 수 μžˆλŠ” κ²½μš°μ—λŠ” min heapμ—μ„œ 값을 λΉΌκ³  μ΄κΈ°λŠ” κ²½μš°μ΄λ―€λ‘œ answerλ₯Ό μ¦κ°€μ‹œν‚¨λ‹€. 
2. κ°€μž₯ 큰 수둜 이길 수 μ—†λŠ” 경우 min heapμ—μ„œ 제일 μž‘μ€ 값을 λΉΌκ³  μ§€λŠ” 경우이기 λ•Œλ¬Έμ— answerλ₯Ό μ¦κ°€μ‹œν‚€μ§€ μ•ŠλŠ”λ‹€.
3. μœ„μ˜ 쑰건을 ν†΅κ³Όν•˜κ³  큰 수둜 이길 수 μžˆλŠ” κ²½μš°μ—λŠ” max heapμ—μ„œ 값을 λΉΌκ³  answerλ₯Ό μ¦κ°€μ‹œν‚¨λ‹€.

 

⌨️ μ½”λ“œ

class MinHeap {
  constructor() {
    this.heap = [];
    this.heap.push(-1e9);
  }

  insert(value) {
    this.heap.push(value);
    this.upheap(this.heap.length - 1);
  }

  upheap(pos) {
    let temp = this.heap[pos];

    while (temp < this.heap[parseInt(pos / 2)]) {
      this.heap[pos] = this.heap[parseInt(pos / 2)];
      pos = parseInt(pos / 2);
    }
    this.heap[pos] = temp;
  }

  get() {
    if (this.size() === 0) return;
    if (this.size() === 1) return this.heap.pop();
    const result = this.heap[1];
    this.heap[1] = this.heap.pop();
    this.downheap(1, this.heap.length - 1);
    return result;
  }

  show() {
    if (this.size() === 0) return;
    return this.heap[1];
  }

  downheap(pos, len) {
    let temp = this.heap[pos],
      child;
    while (pos <= parseInt(len / 2)) {
      child = pos * 2;
      if (child < len && this.heap[child] > this.heap[child + 1]) child++;
      if (temp <= this.heap[child]) break;
      this.heap[pos] = this.heap[child];
      pos = child;
    }
    this.heap[pos] = temp;
  }

  size() {
    return this.heap.length - 1;
  }
}

class MaxHeap {
  constructor() {
    this.heap = [];
    this.heap.push(1e9);
  }

  insert(value) {
    this.heap.push(value);
    this.upheap(this.heap.length - 1);
  }

  upheap(pos) {
    let temp = this.heap[pos];

    while (temp > this.heap[parseInt(pos / 2)]) {
      this.heap[pos] = this.heap[parseInt(pos / 2)];
      pos = parseInt(pos / 2);
    }
    this.heap[pos] = temp;
  }

  get() {
    if (this.size() === 0) return;
    if (this.size() === 1) return this.heap.pop();
    const result = this.heap[1];
    this.heap[1] = this.heap.pop();
    this.downheap(1, this.heap.length - 1);
    return result;
  }

  show() {
    if (this.size() === 0) return;
    return this.heap[1];
  }

  downheap(pos, len) {
    let temp = this.heap[pos],
      child;
    while (pos <= parseInt(len / 2)) {
      child = pos * 2;
      if (child < len && this.heap[child] < this.heap[child + 1]) child++;
      if (temp >= this.heap[child]) break;
      this.heap[pos] = this.heap[child];
      pos = child;
    }
    this.heap[pos] = temp;
  }

  size() {
    return this.heap.length - 1;
  }
}

function solution(A, B) {
  var answer = 0;

  const maxHeap = new MaxHeap();
  const minHeap = new MinHeap();

  A.sort((a, b) => b - a);

  for (const b of B) {
    maxHeap.insert(b);
    minHeap.insert(b);
  }

  for (const a of A) {
    if (a < minHeap.show()) {
      minHeap.get();
      answer += 1;
    } else if (a >= maxHeap.show()) {
      minHeap.get();
    } else {
      maxHeap.get();
      answer += 1;
    }
  }

  return answer;
}