diff --git a/level-3/N-Queen.js b/level-3/N-Queen.js
new file mode 100644
index 0000000..8d36ad5
--- /dev/null
+++ b/level-3/N-Queen.js
@@ -0,0 +1,39 @@
+//https://github.com/codeisneverodd/programmers-coding-test
+//완벽한 정답이 아닙니다.
+//정답 1 - codeisneverodd
+function solution(n) {
+    /*
+    1. 0번째 행에 0번째 queen을 놓는다.
+    2. 그 다음 행의 퀸은 이전 퀸들의 범위와 겹치지 않는 곳에 놓는다. 퀸은 한 행에 반드시 하나 두어야한다.
+    3. 마지막 열까지 도달하면 성공으로 간주하고 answer에 1을 더한다.
+    4. 0번째 queen의 위치를 바꿔가며 모두 시도한다.
+    4. 단, 체스판은 일차원 배열로 선언하고 index = 행, 값 = 열 로 생각한다.
+    */
+    let answer = 0;
+    const canBePlacedOn = (chess, currentRow) => {
+        //해당 행에 둔 queen이 유효한지
+        for (let prevRow = 0; prevRow < currentRow; prevRow++) {
+            const onDiagonal = currentRow - prevRow === Math.abs(chess[currentRow] - chess[prevRow])
+            const onStraight = chess[prevRow] === chess[currentRow]
+            if (onDiagonal || onStraight) return false
+        }
+        return true
+    }
+    const placeQueen = (chess, currentRow) => {
+        //queen을 배치하다가 끝 행에 도착하면 1을 리턴, 도착하지 못하면 0을 리턴하여, 재귀적으로 모든 경우를 합하여 리턴
+        let count = 0
+        if (currentRow === chess.length) return 1
+        for (let currentQueen = 0; currentQueen < n; currentQueen++) {
+            //queen을 우선 배치한 후 가능한지 살펴본다.
+            chess[currentRow] = currentQueen
+            if (canBePlacedOn(chess, currentRow)) count += placeQueen(chess, currentRow + 1)
+        }
+        return count
+    }
+    for (let firstQueen = 0; firstQueen < n; firstQueen++) {
+        const chess = new Array(n).fill(-1)
+        chess[0] = firstQueen
+        answer += placeQueen(chess, 1)
+    }
+    return answer;
+}
\ No newline at end of file
diff --git "a/level-4/\353\213\250\354\226\264-\355\215\274\354\246\220.js" "b/level-4/\353\213\250\354\226\264-\355\215\274\354\246\220.js"
new file mode 100644
index 0000000..475cc45
--- /dev/null
+++ "b/level-4/\353\213\250\354\226\264-\355\215\274\354\246\220.js"
@@ -0,0 +1,34 @@
+//https://github.com/codeisneverodd/programmers-coding-test
+//완벽한 정답이 아닙니다.
+//정답 1 - codeisneverodd
+//코드 참고자료: https://velog.io/@longroadhome/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-LV.4-%EB%8B%A8%EC%96%B4-%ED%8D%BC%EC%A6%90
+function solution(strs, t) {
+  const tLength = t.length; //자주 쓰는 값 미리 계산
+  //Infinity 로 선언을 해야 조합이 불가능한 영역의 값을 무한으로 두고, 그 영역에 하나를 더해도 불가능하다는 것을 Infinity로 표현할 수 있게 된다.
+  const minCountToIndex = new Array(tLength).fill(Infinity);
+  for (let currentIndex = 0; currentIndex < tLength; currentIndex++) {
+    //내가 검사할 부분은 t의 0~currentIndex 영역
+    const currentSlice = t.slice(0, currentIndex + 1);
+    for (const str of strs) {
+      //현재 영역이 strs에 있는 조각들 중 하나로 끝난다면
+      if (currentSlice.endsWith(str)) {
+        //frontLength 는 str 조각을 제외한 앞 쪽의 남은 조각의 길이
+        const frontLength = currentIndex - str.length + 1;
+        if (frontLength === 0) {
+          //앞쪽에 남은 것이 없다면, 현재 검사중인 영역 = strs에 있는 조각
+          minCountToIndex[currentIndex] = 1;
+        } else {
+          //앞쪽에 남은 것이 있다면, 현재 검사중이 영역까지 필요한 조각 수는, 지금까지 구한 최소 값과 지금 구한 값 중 최소값
+          minCountToIndex[currentIndex] = Math.min(
+            minCountToIndex[currentIndex],
+            minCountToIndex[frontLength - 1] + 1
+          );
+        }
+      }
+    }
+  }
+  //마지막 영역이 Infinity 이면 만들기 불가능한 단어, 아니라면 마지막 영역의 값을 리턴
+  return minCountToIndex[tLength - 1] === Infinity
+    ? -1
+    : minCountToIndex[tLength - 1];
+}