해쉬란?

해쉬는 입력 데이터를 고정된 길이의 데이터로 변환된 값을 말한다. 다른 말로는 해시 값이라고한다.

 

 

사용하는경우 

배열의 인덱스위치, 위치, 데이터 값을 저장하거나 검색할때 활용된다.

 

특징 

키(KEY)에 데이터(VALUE)를 매핑할 수 있는 데이터 구조

해쉬 함수를 통해 키의 데이터를 배열에 저장할 수 있는 주소(인덱스 번호)를 계산

 

 

 

 

 

장단점

장점

데이터 저장/ 읽기 속도가 빠름 (검색속도가 빠름)

해시는 키에 대한 데이터가 있는지 확인이 쉬움

 

단점

일반적으로 저장곤간이 많이 필요

여러 키에 해당하는 주소(인덱스)가 동일한 경우 충돌을 해결하기 위한 별도 자료구조 필요

 

 

 

 

 

 

 

코드

class hashTable{
    constructor(size){
        this.storage = [];
        if(size){
            this.size = size;
        }
        else{
            this.size = 100;
        }
    }
    insert = (key,value) => {               
        let index = this.hash(key);
        
        if(this.storage[index] === undefined){
            this.storage[index] = [[key, value]];
        }
        else{
            let storageFlag = false;
            for(let i = 0; i < this.storage[index].length; i++){
                if(this.storage[index][i][0] === key){
                    this.storage[index][i][1] = value;
                    storageFlag = true;
                }
            }
            if(!storageFlag){
                this.storage[index].push([key,value]);
            }
        }
    }
    delete = (key) => {
        let index = this.hash(key);
        if(this.storage[index] === undefined){
            return false;
        }
        else if(this.storage[index].length === 1 && this.storage[index][0][0] === key){
            this.storage.splice(index,1);
            return true;
        }
        else{
            for(let i = 0; i < this.storage[index].length; i++){
                if(this.storage[index][i][0] === key){
                    this.storage[index].splice(i,1)
                    return true;
                }
            }
            return false;
        }
    }
    search = (key) => {
        let index = this.hash(key);
        if(this.storage[index] === undefined){
            return false;
        }
        else if(this.storage[index].length === 1 && this.storage[index][0][0] === key){
            return this.storage[index][0][1];
        }
        else{
            for(let i = 0; i < this.storage[index].length; i++){
                if(this.storage[index][i][0] === key){
                    return this.storage[index][i][1];
                }
            }
            return false;
        } 
    }

    hash = (key) => {
        let hash = 0;
        for(let i = 0; i < key.length; i++){
            hash += key.charCodeAt(i);
        }
        return hash % this.size;
    }

    getTable(){
        return this.storage;
    }

}

let data = new hashTable(100);
data.insert(1,5);
data.insert('asd', 12);
data.insert(213,14);
data.insert('a', 'b');
data.insert('213', '12');
console.log(data.search(1));
console.log(data.search(213));
data.delete(1);
console.log(data.search(1));
data.insert(1,10)
data.delete('a');
console.log(data.search(1));
console.log(data.getTable())

그리디 알고리즘이란? 

최적의 값을 구해야하는 상황에서 사용되는 방법으로

' 매선택에서 지금 이순간 당장 최적인 답을 선택하여 적합한 결과를 도출하자'  가 모토이다.

 

비유하자면 마시멜로 실험을 생각하면된다 -> 그리디 알고리즘을 사용한다는것은 당장 눈앞에있는 마시멜로를 먹는것이다.

하지만 이방법을 사용하는것은 기다렸다가 2개를 먹는다라는 최적해를 보장해주지 못한다

 

 

사용하는이유

항상 최적의 선택을하기때문에 앞서봤던 깊이우선탐색(dp) 보다 빠른 속도를 낸다

 

특징

최적부분 구조이다. -> 한번의 선택이 다음선택에는 전혀 무관한 값이며 매순간의 최적해가 문제에대한 최적해야여한다는의미이다.

 

 

 

 

그리디의 에니메이션 출처 : 위키피디아

 

 

원리

위의 그림을 보면서 아래 설명의 봐보자. 

1. 시작 정점을 7로 설정 (최대값을 구할때)

2. 3과 12중에 하나를 골라! 당장! 12가 크네 선택

3. 5과 6중에 하나를 골라! 당장! 6이 크네

 

이런식으로 탐색을 한다. 당장의 선택에만 선택하므로. 당장의이익만보는 그리디 알고리즘이라 하는것이다.

 

장단점

장점

간단하고 직관적인 방법이다.

또한 원리를 나열할때 3번에 끝난것을보아 계산 시간이 짧아서 대용량 데이터에도 적용이 가능하다

 

 

단점

최적화가 보장되지 않는다는 것이다. 위의 에니메이션을 보면 

맨아래노드의 최대값이 99인 큰값이 존재해서   7 ->3 -> 99 로 진행한다면 더 큰 최대값을 도출할수있는데

당장의 큰값만 선택하다보니 보다 작은 값이 도출되었음을 알 수 있다.

 

 

코드

function getChange(value) {
  let changes = [10000, 5000, 1000, 500, 100, 50, 10];
  let won = Math.floor(value / 10) * 10; // 1의 자리 원화 반내림
  let i = 0;
  let counts = [];

  while (true) {
    if (won >= changes[i]) {
      let count = Math.floor(won / changes[i]);
      won = won - changes[i] * count;
      counts[i] = count;
    } else {
      counts[i] = 0;
    }

    i++;
    if (won === 0) {
      for (let j = 0; j < changes.length - i; j++) {
        counts.push(0);
      }
      break;
    }
  }

  changes.map((change, index) => {
    console.log(`${change.toLocaleString()}원 ${counts[index]}개`);
  });
}

 

 

 

'프로그래밍 > algorithm' 카테고리의 다른 글

[알고리즘] Hash (해쉬)이란  (0) 2024.02.12
[알고리즘] DFS (깊이 우선탐색)이란  (1) 2024.02.11
Codewars 사용  (0) 2022.03.21

 

깊이 우선탐색 (Depth-Firtst Search)

 

깊이우선 탐색이란?

루트노드에서 시작해서 다음 분기로 넘어가기 전에 해당 분기를 완벽하게 탐색하는 방법이라고한다.

즉, 깊게 탐색, 완벽탐색

 

사용하는경우 

모든 노드를 방문 하고자 하는 경우에 이방법을 선택한다.

 

특징 

1. 자기자신을 호출하는 순환 알고리즘의 형태를 가지고있다.

2. 어떤 노드를 방문했었는지 여부를 반드시 검사해야한다.

 

 

 

DFS의 애니메이션 출처 : 위키피디아

 

원리

위의 그림을 보면서 아래 설명을 봐보자.

1. 시작 정점을 1로 설정

2. 1번 탐색 시작 1번과 연결되었고 방문 안한 정점이 어디지? 2번이 있네. 2번으로 가자.

3. 2번과 연결되었고, 방문 안한것? 3번이네. 3번으로 가자.

4. 3번은? 4번이 있네. 4번으로 가자.

5. 4번은? 없는데..?? 그러면 3번으로 다시 올라가자.

6. 3번은? 방문 안한곳이 없네.. 다시 2번... 다시 1번

7. 1번은? 5번이 있네. 5번으로 가자.

-> 이런 식으로 방문 안한 곳이 없을때까지 반복

 

이런식으로 쭉 탐색을 한다. 이런식으로하면 한길로 깊이 있게 파고들어가게 된다. 이래서 깊이 우선탐색이라는 말이 나온것이다.

 

 

장단점

장점

코드가 직관적이고, 구현하기 쉽다.
-> 사실 일정행동을 계속 반복하는데, 이를 만들어놓고 끝까지 계속 돌려 쓰는 것이기 때문에 비교적 간단하게 코드를 구현할 수 있다.

 

단점

깊이가 엄청 깊어지면, 메모리 비용을 예측하기 어렵다.
-> 앞서 설명한 것처럼 깊이가 깊어질수록 함수가 하나씩 쌓이는 구조이다. 이 때문에 깊이가 엄청 깊어진다면 스택 메모리가 지나치게 커질 수 있다.

 

또한 최단 경로를 알 수 없다.

 

코드

const graph = {
  A: ["B", "C"],
  B: ["A", "D"],
  C: ["A", "G", "H", "I"],
  D: ["B", "E", "F"],
  E: ["D"],
  F: ["D"],
  G: ["C"],
  H: ["C"],
  I: ["C", "J"],
  J: ["I"]
};

const DFS = (graph, startNode) => {
  const visited = []; // 탐색을 마친 노드들
  let needVisit = []; // 탐색해야할 노드들

  needVisit.push(startNode); // 노드 탐색 시작

  while (needVisit.length !== 0) { // 탐색해야할 노드가 남아있다면
    const node = needVisit.shift(); // queue이기 때문에 선입선출, shift()를 사용한다.
    if (!visited.includes(node)) { // 해당 노드가 탐색된 적 없다면
      visited.push(node); 
      needVisit = [...graph[node], ...needVisit];
    }
  }
  return visited;
};

console.log(DFS(graph, "A"));
// ["A", "B", "D", "E", "F", "C", "G", "H", "I", "J"]

 

 

'프로그래밍 > algorithm' 카테고리의 다른 글

[알고리즘] Hash (해쉬)이란  (0) 2024.02.12
[알고리즘] Greedy Algorithm (탐욕알고리즘) 이란  (1) 2024.02.12
Codewars 사용  (0) 2022.03.21

https://kwiki.devserum.com/ko/articles/tech-articles/2021-05-31-518-consecutive-days-algorithm-challenge

 

518일동안 단 하루도 빠지지 않고 알고리즘을 풀었다.

 

kwiki.devserum.com

 

코드워즈를 사용해보려고한다.

그이유라면 이블로그에올린게 멋있었기때문이다. ㅋㅋ

 

꾸준히 할진 모르겠지만

풀고 이블로그에 계속올려보려고한다.

 

문제를 보고 틈틈히 그문제를 생각해보고 저녁에는 커밋하는방식?

 

알고리즘을 공부하는이유라면 조금더 코딩에 친숙해지고 복붙보다 직접 코딩을해보고 싶은 마음에 배우기로했다.

 

 

+ Recent posts