๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

์•Œ๊ณ ๋ฆฌ์ฆ˜/LEETCODE

Maximum Frequency Stack | LeetCode 895

๋ฐ˜์‘ํ˜•

๐Ÿค” ๋ฌธ์ œ : Maximum Frequency Stack | LeetCode 895

๋ฌธ์ œ : https://leetcode.com/problems/maximum-frequency-stack/

๋ฌธ์ œ์—์„œ ๋งŒ๋“ค๊ณ ์ž ํ•˜๋Š” Frequncy Stack์€

  • ๊ธฐ์กด stack๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ๊ฐ™์ง€๋งŒ
  • pop ํ•  ๋•Œ ๋‹จ์ˆœํžˆ ๊ฐ€์žฅ ์œ„์— ์žˆ๋Š” ์›์†Œ๊ฐ€ ์•„๋‹Œ
  • ๊ฐ€์žฅ ๋งŽ์ด ๋“ค์–ด์žˆ๋Š” ์›์†Œ๋“ค ์ค‘ ๊ฐ€์žฅ ์œ„์— ์žˆ๋Š” ์›์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•จ
    => ๊ฐ ์›์†Œ๊ฐ€ ๋ช‡ ๋ฒˆ ๋‚˜์™”๋Š”์ง€๋ฅผ ํšจ์œจ์ ์œผ๋กœ countํ•˜๊ณ  cachingํ•  ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•จ

๐Ÿ’ก ํ’€์ด

1. Popํ•  ๋•Œ Stack ๋‚ด ๋ชจ๋“  ์›์†Œ๋ฅผ ์„ธ์–ด ๊ฐ€์žฅ ๋งŽ์ด ๋‚˜์˜จ ์›์†Œ๋ฅผ ๋ฐ˜ํ™˜

์ฒ˜์Œ์—๋Š” Time Limit Exceed ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š๊ณ , ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ํ’€์ด๋กœ ํ’€์–ด๋ด…๋‹ˆ๋‹ค.

  • push ๋Š” ๊ธฐ์กด stack๊ณผ ๋™์ผํ•˜๊ณ 
  • pop ์€ ์ „์ฒด stack์„ ๋Œ๋ฉฐ ๊ฐ ์›์†Œ์˜ ๊ฐฏ์ˆ˜๋ฅผ countํ•˜์—ฌ ๊ฐ€์žฅ ๋งŽ์ด ๋‚˜์˜จ ์›์†Œ ๋ฐ˜ํ™˜
var FreqStack = function() {
    this.array = []; // stack
};

/**
 * push operation์€ ๊ธฐ์กด Stack๊ณผ ๊ฐ™์Œ
 */
FreqStack.prototype.push = function(val) {
    this.array.push(val)
};

/**
 * pop operation์€ ๋ฐ˜ํ™˜ ์ „์— ์ „์ฒด array๋ฅผ iterationํ•˜๋ฉฐ ๊ฐ element๊ฐ€ ๋ช‡ ๋ฒˆ ๋“ฑ์žฅํ•˜๋Š”์ง€ count ํ•œ ํ›„
 * ๊ฐ€์žฅ ๋งŽ์ด ๋‚˜์˜จ element์˜ ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ๋“ค์–ด์˜จ ์œ„์น˜๋ฅผ pop
 */
FreqStack.prototype.pop = function() {
  var max = 0; // ๊ฐ€์žฅ ๋งŽ์ด ๋‚˜์˜จ element์˜ ๋นˆ๋„
  var maxPosition = 0; // ๊ฐ€์žฅ ๋งŽ์ด ๋‚˜์˜จ element์˜ ๋งˆ์ง€๋ง‰ position
  const cache = [];

  for(const index in this.array){
    const i = this.array[index];
    // i๊ฐ€ ๋ช‡ ๋ฒˆ ๋‚˜์™”๋Š”์ง€ count
    if(!cache[i]) 
      cache[i] = 1;
    else cache[i]++;
    
    // ๊ฐ€์žฅ ๋งŽ์ด ๋‚˜์˜จ ๋นˆ๋„๋ณด๋‹ค ํด ๊ฒฝ์šฐ max๊ฐ’ update
    if(cache[i] >= max){
      max = cache[i];
      maxPosition = index;
    }
  }

  const result = this.array[maxPosition];
  this.array.splice(maxPosition, 1);
  return result;
};

Time Complexity
push : O(1) stack์˜ ๊ฐ€์žฅ top์— push
pop :O(N) stack ์ „์ฒด๋ฅผ ๋Œ๋ฉฐ ๊ฐ ์›์†Œ์˜ ๋นˆ๋„๋ฅผ count
Space Complexity
O(N) ๊ฐ ์›์†Œ๋ฅผ ํ•œ๋ฒˆ์”ฉ๋งŒ ์ €์žฅํ•˜๋ฉด ๋จ

์ •๋‹ต์€ ์›ํ•˜๋Š”๋Œ€๋กœ ๋‚˜์˜ค์ง€๋งŒ (์—ญ์‹œ๋‚˜..) TLE ์ž…๋‹ˆ๋‹ค.
pop operation์„ O(N)๋ณด๋‹ค ๋น ๋ฅด๊ฒŒ ํ•  ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•ด ๋ณด์ด๋„ค์š”.

 

2. Double Stack ๊ตฌ์กฐ๋กœ ๊ฐ ์›์†Œ์˜ ๋นˆ๋„ caching

๊ฐ ์›์†Œ๊ฐ€ ๋ช‡๋ฒˆ ๋‚˜์™”๋Š”์ง€๋ฅผ ๋งค๋ฒˆ countํ•˜์ง€ ์•Š์•„๋„ ๋˜๋„๋ก
ํšจ์œจ์ ์œผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ๋– ์˜ฌ๋ ค์•ผ ํ–ˆ๋Š”๋ฐ์š”,

์ œ๊ฐ€ ๊ณ ๋ฏผํ•œ ํ˜•ํƒœ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ์ด์ค‘ stack์ž…๋‹ˆ๋‹ค.
stack์ด ์ธต ๋ณ„๋กœ ๋‚˜์›Œ์ง„ ํ˜•ํƒœ์ธ๋ฐ, ๊ฐ N์ธต์˜ stack์€ N๋ฒˆ์งธ๋กœ ๋“ค์–ด์˜จ ์›์†Œ๋“ค๋ผ๋ฆฌ์˜ stack์ด๋ผ๊ณ  ๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค.
(ํ•ด๋‹น ์›์†Œ์˜ ๋นˆ๋„์— ํ•ด๋‹นํ•˜๋Š” ์ธต์— push)

์˜ˆ๋ฅผ๋“ค์–ด 5 7 5 7 4 5 ์ˆœ์œผ๋กœ ๊ฐ’์ด ๋“ค์–ด์˜จ๋‹ค๋ฉด, ์•„๋ž˜ ์ˆœ์„œ๋กœ stack์˜ ๋ชจ์Šต์ด ๊ทธ๋ ค์ง‘๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๋˜๋ฉด ๊ฐ€์žฅ ๋†’์€์ธต์—๋Š” ์ง€๊ธˆ๊นŒ์ง€ ์ค‘ ๊ฐ€์žฅ ๋นˆ๋„๊ฐ€ ๋†’์€ ์ˆซ์ž๋“ค์ด ๋“ค์–ด๊ฐ€ ์žˆ์œผ๋ฉฐ,
๊ฐ ์ธต์—์„œ๋„ ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ๋“ค์–ด์˜จ ์ˆซ์ž๋Š” stack์˜ top์— ์žˆ๋Š” ๊ตฌ์กฐ๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ pop์„ ํ•  ๋•Œ๋Š” ๊ฐ€์žฅ ๋†’์€์ธต์˜ stack์—์„œ ํ•˜๋‚˜์”ฉ Pop์„ ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

var FreqStack = function() {
    this.doubleStack = []; // ์–ด๋–ค ์ˆซ์ž๊ฐ€ ๋ช‡ ๋ฒˆ์งธ์— ๋‚˜์™”๋Š”์ง€
    /** ex)
    * [, [1, 2, 5], [2, 1], [1]] => 1์€ 3๋ฒˆ 2๋Š” 2๋ฒˆ 5๋Š” 1๋ฒˆ ๋‚˜์˜ด
    **/
};

/**
 * @param {number} val
 * @return {void}
 */
FreqStack.prototype.push = function(val) {
  for(var i=this.cache.length; i>0; i--){ // ๊ฐ€์žฅ ์œ—์ธต๋ถ€ํ„ฐ ๋Œ๋ฉด์„œ
    if(this.cache[i] && this.cache[i].includes(val)){ // ๊ทธ ์ธต์— val์ด ์žˆ์œผ๋ฉด
      if(this.cache[i+1]) this.cache[i+1].push(val) // ๊ทธ ์œ—์ธต์— val์„ push
      else this.cache[i+1] = [val]
      return;
    }
  }
  if(this.cache[1]) this.cache[1].push(val) // ๋ชจ๋“ ์ธต์— val์ด ์—†์œผ๋ฉด 1์ธต์— push
  else this.doubleStack[1] = [val]
  return;
};

/**
 * @return {number}
 */
FreqStack.prototype.pop = function() {
  const maxFrequency = this.doubleStack.length-1;
  const targetNum = this.doubleStack[maxFrequency].pop();
  if(this.doubleStack[maxFrequency].length === 0) this.doubleStack.pop();
  return targetNum;
};

Time Complexity
push : O(N) ์ „์ฒด stack์„ ๋Œ๋ฉฐ ํ•ด๋‹น ์›์†Œ๋ฅผ ์ฐพ์•„์•ผ ํ•จ
pop :O(1) stack์˜ ๊ฐ€์žฅ ์œ„์˜ ์›์†Œ๋ฅผ pop
Space Complexity
O(N) ๊ฐ ์›์†Œ๋ฅผ ํ•œ๋ฒˆ์”ฉ๋งŒ ์ €์žฅํ•˜๋ฉด ๋จ

์ œ์ถœํ•˜๋‹ˆ ํ†ต๊ณผ๋Š” ๋˜์—ˆ๋Š”๋ฐ์š”,
์ƒ๊ฐํ•ด๋ณด๋ฉด pushํ•  ๋•Œ stack์„ iterationํ•˜๋ฉฐ ๋ช‡๋ฒˆ์งธ ์ธต์— ๋‚˜์˜จ์ ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•˜๋‹ˆ push operation์˜ TC๋Š” ์—ฌ์ „ํžˆ O(N)์ด ๋˜๊ฒ ๋„ค์š”.
๊ฐ™์€ ์›์†Œ๊ฐ€ ์—ฌ๋Ÿฌ๋ฒˆ ๋ฐ˜๋ณตํ•ด์„œ ๋“ค์–ด์˜จ๋‹ค๋ฉด ์ด ๋ฐฉ๋ฒ•์ด ํšจ์œจ์ ์ด๊ฒ ์ง€๋งŒ, ์ƒˆ๋กœ์šด ์›์†Œ๊ฐ€ ๊ณ„์† ๋“ค์–ด์˜จ๋‹ค ์ƒ๊ฐํ•˜๋ฉด Stack ์ „์ฒด๋ฅผ iterationํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„์ง€๋ฏ€๋กœ 1๋ฒˆ ํ’€์ด์™€ ๋น„์Šทํ•œ ์†๋„๊ฐ€ ๋  ์ˆ˜๋„ ์žˆ๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ†ต๊ณผ๋œ ๊ฒƒ์„ ๋ณด๋ฉด ํ…Œ์ŠคํŠธ์ผ€์ด์Šค์—

  • ๊ฐ™์€ ์›์†Œ๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ pushํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๊ณ 
  • Stack์ด ์•„์ฃผ ํด ๋•Œ pop์„ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„

push๋ณด๋‹ค๋Š” pop์˜ ํšจ์œจ์„ฑ์ด ์ค‘์š”ํ•˜์ง€ ์•Š์•˜๋‚˜ ์ƒ๊ฐ์ด ๋“ญ๋‹ˆ๋‹ค.

3. 2๋ฒˆํ’€์ด push์˜ TC(Time Complexity)์ตœ์ ํ™”

2๋ฒˆ ํ’€์ด์˜ Push operation์„ ์ข€ ๋” ์ตœ์ ํ™”ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Stack์„ ๋Œ๋ฉฐ ๋ช‡์ธต์— pushํ• ์ง€ ์ •ํ•˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ, inFloor๋ผ๋Š” ์ด๋ฆ„์˜ cache๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ˜„์žฌ๊นŒ์ง€์˜ ๋นˆ๋„๋ฅผ ๋”ฐ๋กœ ์ €์žฅํ•ด๋‘๊ฒ ์Šต๋‹ˆ๋‹ค.
pushํ•  ๋•Œ๋Š” inFloor[val]+1 ์ธต์— pushํ•˜๋ฉด ๋˜๊ฒ ์ง€์š”

var FreqStack = function() {
    this.doubleStack = []; // ์–ด๋–ค ์ˆซ์ž๊ฐ€ ๋ช‡ ๋ฒˆ์งธ์— ๋‚˜์™”๋Š”์ง€
    /** ex)
    * [, [1, 2, 5], [2, 1], [1]] => 1์€ 3๋ฒˆ 2๋Š” 2๋ฒˆ 5๋Š” 1๋ฒˆ ๋‚˜์˜ด
    **/
  	this.inFloor = []; // ๊ฐ element์˜ ๋นˆ๋„ 
  	/** ex)
    * [, 3, 2, , , 1] => 1์€ 3๋ฒˆ 2๋Š” 2๋ฒˆ 5๋Š” 1๋ฒˆ ๋‚˜์˜ด
    **/
};

FreqStack.prototype.push = function(val) {
  if(!this.inFloor[val]) this.inFloor[val] = 0;
  this.inFloor[val]++;
  if(!this.doubleStack[this.inFloor[val]]) this.doubleStack[this.inFloor[val]] = []
  this.doubleStack[this.inFloor[val]].push(val)
};

FreqStack.prototype.pop = function() {
  const maxFrequency = this.doubleStack.length-1;
  const targetNum = this.doubleStack[maxFrequency].pop();
  this.inFloor[targetNum]--;
  if(this.doubleStack[maxFrequency].length === 0) this.doubleStack.pop();
  return targetNum;
};

Time Complexity
push : O(1) ์ „์ฒด stack์„ ๋Œ๋ฉฐ ํ•ด๋‹น ์›์†Œ๋ฅผ ์ฐพ์•„์•ผ ํ•จ
pop :O(1) stack์˜ ๊ฐ€์žฅ ์œ„์˜ ์›์†Œ๋ฅผ pop
Space Complexity
O(N) ๊ฐ ์›์†Œ๋ฅผ ํ•œ๋ฒˆ์”ฉ๋งŒ ์ €์žฅํ•˜๋ฉด ๋จ

๐Ÿ“– Learned

js๋กœ ํ‘ธ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ ์ค‘ ์ด๋ ‡๊ฒŒ ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•ด๋‚ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ๋Š” ์ƒ์†Œํ•ด์„œ, push์™€ popํ•จ์ˆ˜๋ฅผ ์–ด๋””์— ์ž‘์„ฑํ•ด์•ผํ•˜๋Š”์ง€, ํด๋ž˜์Šค ๋‚ด์˜ ๋ณ€์ˆ˜๋Š” ์–ด๋–ป๊ฒŒ ์„ ์–ธํ•ด์•ผ ํ•˜๊ณ , ํ•จ์ˆ˜ ๋‚ด์—์„œ ๊ทธ ๋ณ€์ˆ˜๋ฅผ ์–ด๋–ป๊ฒŒ ์ ‘๊ทผํ•ด์•ผ ํ•˜๋Š”์ง€ ์ข€ ํ—ค๋งธ์Šต๋‹ˆ๋‹ค..;;
์œ„์— ํ’€์ด์ฒ˜๋Ÿผ .prototype.ํ•จ์ˆ˜ ๋กœ ์ž‘์„ฑํ•ด๋„ ๋˜๊ณ 

์•„๋ž˜ ์ฒ˜๋Ÿผ๋„ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค

function FreqStack() { let m =[]; return { push, pop } function push(x) { m.push(x) ... } function pop() { m.pop(x) ... } }

 

๋ฐ˜์‘ํ˜•