ํ, 211008
๋ฌธ์
N์ฅ์ ์นด๋๊ฐ ์๋ค. ๊ฐ๊ฐ์ ์นด๋๋ ์ฐจ๋ก๋ก 1๋ถํฐ N๊น์ง์ ๋ฒํธ๊ฐ ๋ถ์ด ์์ผ๋ฉฐ, 1๋ฒ ์นด๋๊ฐ ์ ์ผ ์์, N๋ฒ ์นด๋๊ฐ ์ ์ผ ์๋์ธ ์ํ๋ก ์์๋๋ก ์นด๋๊ฐ ๋์ฌ ์๋ค.
์ด์ ๋ค์๊ณผ ๊ฐ์ ๋์์ ์นด๋๊ฐ ํ ์ฅ ๋จ์ ๋๊น์ง ๋ฐ๋ณตํ๊ฒ ๋๋ค. ์ฐ์ , ์ ์ผ ์์ ์๋ ์นด๋๋ฅผ ๋ฐ๋ฅ์ ๋ฒ๋ฆฐ๋ค. ๊ทธ ๋ค์, ์ ์ผ ์์ ์๋ ์นด๋๋ฅผ ์ ์ผ ์๋์ ์๋ ์นด๋ ๋ฐ์ผ๋ก ์ฎ๊ธด๋ค.
์๋ฅผ ๋ค์ด N=4์ธ ๊ฒฝ์ฐ๋ฅผ ์๊ฐํด ๋ณด์. ์นด๋๋ ์ ์ผ ์์์๋ถํฐ 1234 ์ ์์๋ก ๋์ฌ์๋ค. 1์ ๋ฒ๋ฆฌ๋ฉด 234๊ฐ ๋จ๋๋ค. ์ฌ๊ธฐ์ 2๋ฅผ ์ ์ผ ์๋๋ก ์ฎ๊ธฐ๋ฉด 342๊ฐ ๋๋ค. 3์ ๋ฒ๋ฆฌ๋ฉด 42๊ฐ ๋๊ณ , 4๋ฅผ ๋ฐ์ผ๋ก ์ฎ๊ธฐ๋ฉด 24๊ฐ ๋๋ค. ๋ง์ง๋ง์ผ๋ก 2๋ฅผ ๋ฒ๋ฆฌ๊ณ ๋๋ฉด, ๋จ๋ ์นด๋๋ 4๊ฐ ๋๋ค.
N์ด ์ฃผ์ด์ก์ ๋, ์ ์ผ ๋ง์ง๋ง์ ๋จ๊ฒ ๋๋ ์นด๋๋ฅผ ๊ตฌํ๋ ํ๋ก๊ทธ๋จ์ ์์ฑํ์์ค.
์ ๋ ฅ
์ฒซ์งธ ์ค์ ์ ์ N(1 โค N โค 500,000)์ด ์ฃผ์ด์ง๋ค.
์ถ๋ ฅ
์ฒซ์งธ ์ค์ ๋จ๊ฒ ๋๋ ์นด๋์ ๋ฒํธ๋ฅผ ์ถ๋ ฅํ๋ค.
์์ ์ ๋ ฅ 1
6
์์ ์ถ๋ ฅ 1
4
My solution
์ฃผ์ด์ง ์ค๋ช
๋๋ก ๋ก์ง์ ์ง๋ฉด ์๋์ ๊ฐ์ด ์์ฃผ ์ฝ๊ฒ ์งค ์ ์๋ค.
function solution(i) {
let nums = i.toString().trim().split("\n");
let cards = Array.from({ length: nums }).map((_, i) => (i + 1).toString());
while (cards.length > 1) {
cards.shift();
cards.push(cards.shift());
}
console.log(cards[0]);
return cards[0];
}
test("solution", () => {
expect(solution("6")).toBe("4");
});
๊ทธ๋ฐ๋ฐ ์ ์ถํ๋ฉด ์๊ฐ ์ด๊ณผ๊ฐ ๋์จ๋ค.
ย
์๋ ๊ธ์ ๋ณด๊ณ ํํธ๋ฅผ ์ป์๋ค. ์ผ๋จ์ ์ฑ๋ฅ ๊ณ ๋ ค๋ฅผ ์ํ๊ณ ํต๊ณผํ๋ฉด ๊ทธ๋๋ถํฐ ๋ฆฌํฉํฐ๋งํ๋ฉด์ ๊ณ ๋ คํ๋ ํธ์ธ๋ฐ ์์ ์๊ฐ์ด๊ณผ๋ก ํต๊ณผ๋ฅผ ์ํค์ง ์์ผ๋ ๊ฒ์ํด๋ณด์๋ค.
์ด๋ด ๋๋ ๊ท์น์ฑ ๋ฐ๊ฒฌ์ผ๋ก ์์ง ์ผ์ด์ค ์ฒ๋ฆฌ๋ฅผ ํ๋ ๊ฒ์ด ์ข๋ค๊ณ ํ๋ค.
1234๊ฐ ์์ ๋ 1์ ๋ฒ๋ฆฌ๊ณ 2๋ฅผ ๋ค๋ก ๋ณด๋ด๊ณ 3์ ๋ฒ๋ฆฌ๊ณ ๋๋๋ค.
12345๊ฐ ์์ผ๋ฉด 1์ ๋ฒ๋ฆฌ๊ณ 2๋ฅผ ๋ค๋ก ๋ณด๋ด๊ณ 3์ ๋ฒ๋ฆฌ๊ณ 4๋ฅผ ๋ค๋ก ๋ณด๋ธ๋ค์ 5๋ฅผ ๋ฒ๋ฆฌ๊ณ ๋๋๋ค.
์ฆ, ํ์๋ฒ์งธ(0๋ถํฐ ์์์ด์ง๋ง)์ ์๋ ์นด๋๋ค์ ๋ฒ๋ ค์ง๊ฒ ๋๋ค.
๋ฐ๋ผ์ ์๋์ ๊ฐ์ด ์งค ์ ์๋ค.
function solution(i) {
let nums = i.toString().trim().split("\n");
let cards = Array.from({ length: nums })
.map((_, i) => i + 1)
.filter((_, i) => !((i + 1) % 2));
console.log(cards);
while (cards.length > 1) {
cards.shift();
cards.push(cards.shift());
}
console.log(cards.pop());
return;
} ...
์ฌ์ ํ ์๊ฐ ์ด๊ณผ๊ฐ ๋์จ๋ค.
ย
๊ทธ๋ผ ๋ฐฐ์ด์ shift() ์ฐ์ฐ์ ์๊ฐ๋ณต์ก๋๊ฐ O(n)์ธ ์ด์ ๋ฐ์ ์์ ๊ฒ ๊ฐ๋ค. ๋ฐฐ์ด ๋งจ ์์ ๋ฝ์ผ๋ฉด ๋ค์ ์์๋ค์ ํ์นธ์ฉ ๋ค ์๋น๊ฒจ์ค์ผํ๊ธฐ ๋๋ฌธ์ด๋ค. ํ๋ ๋ํํ ๋ ์๊ฐ๋ณต์ก๋๊ฐ O(1)๋ก ์๊ณ ์๋ค. ์ฑ๋ฅ์ ์ฐพ์๋ณด๋
๊ฒฐ๋ก ๋ง ๋ณด๋ฉด ์๋์ ๊ฐ๋ค.
ํ๋ก ๊ตฌํํด์ผ๋ง ํต๊ณผํ๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์๋ค. js์์ ํ ๊ตฌํ์ ๊ฐ์ ํ๊ธฐ ์ํ ๊ฒ ์๋์์๊น ์ถ๋ค.
ย
๊ทธ๋ฐ๋ฐ ํ๋ฅผ ์ฐ๊ฒฐ๋ฆฌ์คํธ์ ๋ฐฐ์ด๋ก ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ด ์๋๋ฐ ์ฒ์์๋ ์ฐ๊ฒฐ๋ฆฌ์คํธ๋ก ๊ตฌํํ๋ ๊ฒ์ ๋จผ์ ์ฐพ์์ ๊ทธ๊ฑธ๋ก ํ๋ ค๊ณ ํ๋ค๊ฐ ์ฐ๊ฒฐ๋ฆฌ์คํธ๋ ์ผ๋ฐ์ ์ผ๋ก ๋ฐฐ์ด๋ณด๋ค ๋๋ฆฌ๋ค๋ ๋ง์ ๋ฃ๊ณ ์ฐ๊ฒฐ๋ฆฌ์คํธ์ ๋ฐฐ์ด์ด ์ด๋ค ์ฑ๋ฅ์์ ์ฐจ์ด๊ฐ ์๋ ๊ฒ์ธ์ง ์ฐพ์๋ดค๋ค.
์ด์์ฒด์ ๊ฐ์๋ฅผ ๋ค์ผ๋ฉด์ ๋ฐฐ์ ๋ ๋ด์ฉ์ธ๋ฐ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉํ๋ ค๋ ๋ฉ๋ชจ๋ฆฌ ๊ฐ๋ค์ ์บ์ฑํด๋๊ณ ๊ด๋ จ๋ ๊ฐ๊น์ง ๊ฐ์ด ์บ์ฑ๋์ด ์์ด ๋น ๋ฅด๊ฒ ์ ๊ทผํด ์ฌ์ฉํ ์ ์์ผ๋ ๋ง์ฝ ์บ์ฑ๋์ด ์์ง ์์ ๊ฐ์ ์๊ตฌํ๋ฉด ๋ฉ๋ชจ๋ฆฌ์ ๋ค์ ์ ๊ทผํด์ ๊ฐ์ ๊ฐ์ ธ์ค๊ฒ ๋๋ฏ๋ก ๋ ๋ง์ ์๊ฐ์ด ์์๋๋ค๋ ๊ฒ์ด๋ค. ์ด๋ฅผ Cache locality์ Cache hit์ ์๋ฉด ์ดํดํ ์ ์๋ค.
ย
cache hit: 1๊ณผ ๊ฐ์ด ์ง์ญ์ฑ์ ํ์ฉํ๊ธฐ ์ํด ์บ์ฌ์ ์ ์ฅํด๋์ ๋ฉ๋ชจ๋ฆฌ์ CPU๊ฐ ์ฐธ์กฐํ๊ณ ์ ํ๋ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์๋ค๋ฉด cahce hit, ์บ์ฌ ์ ์ค์ด๋ผ๊ณ ํ๋ค. ๋ฐ๋์ ๊ฐ๋
์ cache miss.
cache locality: ์ด์์ฒด์ ์์ ๋ฌผ๋ฆฌ์ ์ผ๋ก ๊ทผ์ ํ ์์น์ ๋ฐ์ดํฐ๊ฐ ์ฃผ๋ก ํ์ฉ๋๊ธฐ ๋๋ฌธ์ ๋ฏธ๋ฆฌ ์บ์ฌ์ ๋ฃ์ด๋ ์ผ๋ก์จ CPU์ ์ฑ๋ฅ์ ํฅ์์ํจ๋ค. ๋ฐฐ์ด์ ๋ฌผ๋ฆฌ์ ์ผ๋ก ์ฐ์๋ ๊ณต๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ locality๋ฅผ ์ ํ์ฉํ ์ ์๋ค.
ย
๋ฐ๋ผ์ ๋ฐฐ์ด๋ก ํ๋ฅผ ๊ตฌํํด๋ณด๊ธฐ ์ํด์ ์๋์ ์ฌ์ดํธ๋ค์ ์ฐธ๊ณ ํ๋ค.
ย
deque ํ๋ ๋ถ๋ถ์ด ์ผ๋ฐ ๋ฐฐ์ด๊ณผ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ์ ์ดํดํด์ผ ํ๋ค. ๋น์ด์์ ๋๋ null์ ๋ฆฌํดํ๊ณ ,
๋น์ด์์ง ์์ผ๋ฉด ๋จผ์ ํ์นธ ์ด๋์ํจ๋ค.
๋ง์ง๋ง์๋ _element์ ๋งจ ์์ ๊ฐ์ ์ ์ธํ๊ณ ๋ค์ ๋ง๋ ๋ค. ์ด ๋ฐฐ์ด์ ๊ธฐ์ค์ผ๋ก ํ๋ฉด ๋งจ ์์ ๊ฐ์ ๊ฐ๋ฆฌํค๋ ์ธ๋ฑ์ค์ธ _offset์ 0์ผ๋ก ๋ค์ ์ด๊ธฐํ๋๋ค. ์ด ๋ฐฉ์๋ง ์ฌ์ฉํ๊ฒ ๋๋ฉด ๋๋ฌด ๋๋ ค์ ์ถ๊ฐ ์ฒ๋ฆฌ๊ฐ ํ์ํ๋ค.
ย
์ฑ๋ฅ ๊ฐ์ ์ ์ํด ํ์ํ ๋ก์ง์ ์ฐจ๋ก๋๋ก ๋ณด๋ฉด,
deque : ๋ง์ฝ ํ์ 5๊ฐ๊ฐ ๋ค์ด์๊ณ offset์ด 0์ด๊ณ 1๋งํผ ๋ํด์ ธ์ 1์ด ๋์์ ๋ if(this.offset * 2 < this._element.length)์์ 2 < 5๊ฐ ๋๋ฉด ๋งจ ์์ ๊ฐ๋ง ๋ฐํํ๊ณ ํ๋ฅผ ๋ค์ ๋ง๋ค์ง ์๋๋ค.
deque : ๊ณ์ ํ์ 5๊ฐ๊ฐ ๋ค์ด์๊ณ offset์ด 1์ด๊ณ 1๋งํผ ๋ํด์ ธ์ 2๊ฐ ๋์์ ๋ if(this.offset * 2 < this._element.length)์์ 4 < 5๊ฐ ๋๋ฉด ๋งจ ์์ ๊ฐ๋ง ๋ฐํํ๊ณ ํ๋ฅผ ๋ค์ ๋ง๋ค์ง ์๋๋ค.
deque : offset์ ์ด์ 2๊ฐ ๋ ์ํ์ด๊ณ first๋ ํ์ฌ offset์ธ 2์ ์์น์ ์๋(๊ฐ์ฅ ์์ ์๋) ๊ฐ์ด ๋๋ค. offset์ 3์ผ๋ก ์ฆ๊ฐ์ํค๊ณ ์ด๋ if(this.offset * 2 < this.element.length) ์์ 3 * 2 < 5 ๋ก false๊ฐ ๋๋ค.
์ฆ, ํ์ ์ค๊ฐ๊น์ง๋ ์์ ๋ฐฉ์์ผ๋ก ์ฑ๋ฅ์์ ์ด๋์ ๋ณผ ์ ์๊ณ ๊ทธ ๋ค์๋ถํฐ๋ slice๋ฅผ ํตํด ๋ฐฐ์ด์ ์๋ผ์ ์ฌ์ ๋นํ๋ค.
ย
class Queue {
constructor(elements) {
// * : ์ฒ์์ ๋ฐฐ์ด์ ๋ฃ์ด์ค ์ ์๋ค.
this._elements = Array.isArray(elements) ? elements : [];
// * : _offsset์ ํ์ ๋งจ ์์ ๊ฐ์ ์ธ๋ฑ์ค๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
this._offset = 0;
}
enqueue(element) {
this._elements.push(element);
return this;
}
dequeue() {
if (this.isEmpty()) return null;
// ๋งจ ์์ ๊ฐ์ ๊ฐ์ง๊ณ _offset์ ํ์นธ ์ด๋
const first = this.front();
this._offset += 1;
// ํ์ ์ค๊ฐ๊น์ง๋ offset ๋ง์ผ๋ก ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ค. ์ฑ๋ฅ๊ฐ์ , ์ด์ฐจํผ ๋ฉค๋ฒ๋ณ์๋ ์ ๋ณด์๋์ผ๋ก ์ ๊ทผ๋ถ๊ฐ
if (this._offset * 2 < this._elements.length) return first;
// only remove dequeued elements when reaching half size
// to decrease latency of shifting elements.
this._elements = this._elements.slice(this._offset);
this._offset = 0;
return first;
}
front() {
return this.size() > 0 ? this._elements[this._offset] : null;
}
back() {
return this.size() > 0
? this._elements[this._elements.length - 1]
: null;
}
size() {
return this._elements.length - this._offset;
}
isEmpty() {
return this.size() === 0;
}
clear() {
this._elements = [];
this._offset = 0;
}
}
๊ทธ๋ฐ๋ฐ ๋ฉ๋ชจ๋ฆฌ ์ด๊ณผ๊ฐ ๋ฌ๋ค.
ํ ๊ตฌํํ ๋ ๋จผ์ ํ๋ ค๊ณ ํ๋ ์ฐ๊ฒฐ๋ฆฌ์คํธ๋ฅผ ์จ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ๊ฒ ๋ค์ฌ์ผ ๋๋ค. ํ๋ฒ์ ๋ง์ถ๋ฉด ํธํ๊ธด ํ๋ฐ ํ๋ฆฐ ๊ธธ๋ง ๋ค ์ฐพ์๋ณธ ๋๋ถ์ ๋ชจ๋ ๊ฑธ ๋ค ๊ฒช์ผ๋ฉด์ ์ฑ์ฅํ๊ฒ ๋์๋ค.
ย
๋ฐฐ์ด ์ด์ฉ์ผ๋ก ์๊ฐ ์ด๊ณผ๊ฐ ๋ ํ ํ ๊ตฌํ์ ๋ค์ ๊ฑฐ๋ฆฌ๋ค๊ฐ Single Linked List๋ฅผ Queue๋ผ๋ ์ด๋ฆ์ผ๋ก ํด๋์ค๋ก ๊ตฌํํด๋์๋๋ฐ ๊ฒฐ๋ก ์ ์ผ๋ก Queue๋ณด๋ค Single Linked List๋ฅผ ๋ ์ฌ๋ฆฌ๋ ๊ฒ ๋ ํ์ํ๋ค.
ย
์์ค์ฝ๋
class Node {
constructor(value) {
this.value = value;
this.next = null;
this.prev = null;
}
}
class LinkedList {
constructor() {
this.head = null;
this.tail = null;
this._size = 0;
}
add(value) {
const newNode = new Node(value);
if (!this.head) {
this.head = newNode;
} else {
this.tail.next = newNode;
newNode.prev = this.tail;
}
this.tail = newNode;
this._size++;
return newNode;
}
getHead() {
return this.head.value;
}
removeHead() {
this.head = this.head.next;
this.head.prev = null;
this._size--;
}
getSize() {
return this._size;
}
}
function solution(i) {
let nums = i.toString().trim().split("\n");
// console.log(cards);
const cards = new LinkedList();
for (let i = 1; i <= nums; i++) {
cards.add(i);
}
let q = new LinkedList(cards);
while (cards.getSize() !== 1) {
cards.removeHead();
cards.add(cards.getHead());
cards.removeHead();
}
console.log(cards.getHead());
return;
}
test("solution", () => {
expect(solution("6")).toBe("4");
});