## 배열 개념
### 배열 선언
```javascript
// 리터럴 이용하기
const arr1 = [0, 0, 0, 0, 0];
// 생성자 이용하기
const arr2 = new Array(5).fill(0);
```
### N차원 배열
배열은 차원과는 별개로 메모리에 저장될 때에는 모두 1차원 배열로 저장된다.
```javascript
// 1차원 배열
const arr1 = [0, 0, 0, 0];
```
2차원 배열은 1차원 배열을 원소로 갖는 배열을 만드는 방식으로 선언할 수 있다.
```javascript
const arr2 = [...new Array(3)].map((_, i) => new Array(4).fill(i));
console.log(arr2);
```
> [!tip]- `[...new Array(3)]` 이유
> net Array(3) 는 빈 요소를 3개 담고 있는 배열을 반환한다. `[ <3 empty items> ]`
> 이게 undefined랑은 별개의 값임.
> map 메서드는 빈 요소는 건너뛰기 때문에
> ```javascript
> const arr = new Array(3).map(() => 1);
> ```
> 이렇게 map으로 순회할 수 없다.
> 하지만 비어있는 배열에 스프레드 연산자를 사용하면 실제로 undefined 값이 채워진 배열로 변환되기 때문에 의도한 대로 map 메서드를 사용할 수 있다.
> - 비어 있는 배열 : sparse array
> - undefined 값이 채워진 배열 : dense array
## 배열의 효율성
배열은 임의 접근으로 배열의 원소에 접근한다. 따라서 **데이터에 접근하기 위한 시간 복잡도는 `O(1)`**이다.
### 원소 삽입
#### 맨 뒤에 삽입
맨 뒤에는 바로 접근해서 바로 삽입할 수 있으므로 시간 복잡도는 O(1)이다. (`Array.push()`)
![[342e3a68-382b-4b32-bf0e-5f3383e79704.png]]
#### 맨 앞에 삽입
맨 앞에 삽입하기 위해서는 뒤 원소들을 모두 한 칸씩 뒤로 밀어낸 뒤에 새로 확보된 자리에 삽입해야 하므로 맨 앞에 삽입하는 시간 복잡도는 `O(N)`이다. (`Array.unshift()`)
![[6dd959fa-41c3-4dc4-b36f-e28ab94b882f.png]]
#### 중간에 삽입
중간에 삽입하는 것도 맨 앞에 삽입하는 것과 동일하게 삽입 위치 뒤쪽의 원소들을 한 칸씩 밀어 자리를 확보한 뒤에 삽입하는 방식이 되므로 시간 복잡도는 밀어내야 하는 원소가 N개일 때 `O(N)`이 된다. (`Array.splice()`)
![[0bada834-bc16-4f47-8fc9-64bb1145954e.png]]
### 자료구조로 배열을 선택할 때 고려할 점
배열의 장점으로는 임의접근이 있다. 특히 그래프를 표현할 때 배열을 활용하면 좋다. 하지만 주의할 점이 2가지 있다.
1. **할당할 수 있는 메모리 크기를 확인해야 한다.**
너무 큰 배열을 할당하면 런타임에서 배열 할당에 실패할 수 있다. 운영체제마다 메모리의 한계치는 다르지만, 보통은 정수형 1차원 배열은 1000만개, 2차원 배열은 3000 * 3000 크기를 최대로 생각한다.
2. **중간에 데이터 삽입이 많은지 확인해야 한다.**
선형 자료구조기 때문에 맨 앞이나 중간에 데이터를 빈번하게 삽입하면 시간 복잡도가 높아져서 시간 초과가 발생할 수 있다.
## 자주 사용하는 배열 기법
자주 사용하는 배열 메서드와 구현 패턴 정리
> [!note] shift와 unshift
> 배열 특성상 배열 앞에서 원소를 추가하거나 삭제하는 경우에는 시간 복잡도가 O(N)이 되지만 배열 내 데이터가 작은 경우에는 자바스크립트 엔진이 최적화를 하기 때문에 조금 성능이 좋아진다.
### 배열에 데이터 추가
`const arr = [1, 2, 3]`
| 방식 | 설명 | 코드 |
| ----------- | ---------- | ----------------------------------------------- |
| `push()` | 끝에 원소 추가 | `arr.push(4); // [1, 2, 3, 4]` |
| `concat()` | 끝에 배열 추가 | `arr.concat([4, 5]); // [1, 2, 3, 4, 5]` |
| 스프레드 연산자 | 배열 추가 | `arr = [...arr, ...[4, 5]]; // [1, 2, 3, 4, 5]` |
| `unshift()` | 맨 앞에 원소 추가 | `arr.unshift(0); // [0, 1, 2, 3]` |
| `splice()` | 배열 중간에 추가 | `arr.splice(3, 0, 4, 5); // [1, 2, 3, 4, 5] ` |
### 배열에 데이터 삭제
`const arr = [1, 2, 3, 4];`
| 방식 | 설명 | 코드 |
| ---------- | -------- | ----------------------------- |
| `pop()` | 끝 원소 제거 | `arr.pop(); // [1, 2, 3]` |
| `shift()` | 앞 원소 제거 | `arr.shift(); // [2, 3, 4]` |
| `splice()` | 배열 중간 제거 | `arr.splice(1, 2); // [1, 4]` |
## 고차 함수 활용하기
모두 원본 배열은 유지하고 새로운 배열을 반환한다.
### 배열 원소 모두를 제곱하기 (map)
```javascript
const numbers = [1, 2, 3, 4];
const squares = numbers.map((number) => number * number);
console.log(squares); // [1, 4, 9, 16]
```
### 짝수 필터링 (filter)
```javascript
const numbers = [1, 2, 3, 4];
const evens = numbers.filter((number) => number % 2 === 0);
console.log(evens); // [2, 4]
```
### 총 합 구하기 (reduce)
```javascript
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((sum, number) => sum + number, 0);
console.log(sum); // 10
```
## 관련 프로그래머스 문제
- [[Lv1. 두 개 뽑아서 더하기]]
- [[Lv1. 모의고사]]
- [[Lv2. 행렬의 곱셈]]
- [[Lv1. 실패율]]
- [[Lv2. 방문 길이]]