List 2

2024. 1. 31. 23:26알고리즘

  • 배열 : 2차원 배열

1차원 list를 묶어놓은 List

2차원 이상의 다차원 리스트는 차원에 따라 인덱스를 선언한다.

2차원 리스트의 선언 → 세로 길이 (행의 개수), 가로 길이(열의 개수)를 필요로 한다.

ex) arr = [[0,1,2,3],[4,5,6,7]] → (2행 4열의 2차원 list)

  • 2차원 배열을 할당하는 코드 예시

3

1 2 3

4 5 6

7 8 9

N = int(input())
arr = [list(map(int, input().split())) for _ in range(N)]

3

123

456

789

N = int(input())
arr = [list(map(int, input())) for _ in range(N)]

4

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

N = int(input())
arr = [[0] * N for _ in range(N)]

[[0] * N] * N]

이런 코드는 쓰면 안된다!

얕은 복사가 돼서 한 행의 요소만 바꿔도 모든 행의 요소가 다 바뀌기 때문이다.

  • 배열 순회

n * m 배열의 모든 원소를 조사하는 방법

  • 행 우선 순회
# i 행의 좌표
# j 열의 좌표
for i in range(n):
    for j in range(m):
        f(array[i][j])
  • 열 우선 순회
# i 행의 좌표
# j 열의 좌표
for j in range(m):
    for i in range(n):
        f(array[i][j])
  • 지그재그 순회
# i 행의 좌표
# j 열의 좌표
for i in range(n):
    for j in range(m):
        f(array[i][j + (m - 1 - 2*j) * (i % 2)])

만약 지그재그 방향을 반대로 하고 싶으면 맨 끝 (i % 2)를 (i + 1) % 2 나 1 - (i % 2) 등으로 바꾸면 된다.

  • 델타를 이용한 2차 배열 탐색

2차 배열 좌표에서 4 방향의 인접 배열 요소를 탐색하는 방법이다.

(i, j) 인덱스를 가지는 칸의 상하좌우 칸 (ni, nj)

0 : 오른쪽

1 : 아래

2 : 왼쪽

3 : 위

일 경우

di = [0, 1, 0, -1]

dj = [1, 0, -1, 0]

번호 별로 이동하면서 바뀌는 행과 열의 값을 두 델타 리스트의 번호 인덱스에 맞춰놓은 것!

가령 이동하는 번호가 k 일 경우 원래 인덱스 i, j에 대해 이동한 ni, nj의 인덱스는 다음과 같다.

ni = i + di [ k ]

nj = j + dj [ k ]

→ arr [ ni ] [ nj ]

이동하는 것을 짝 지어서 표현할 수도 있다.

ni, nj = (i + di [ k ]), (j + dj [ k ])

  • 델타를 이용한 행렬에서의 4 방향 이동 코드 예시 (주변 4개 값과의 차, 절댓값 합 구하기)
T = int(input())
for tc in range(1, T+1):
    N = int(input())
    arr = [list(map(int, input().split())) for _ in range(N)]
    result = 0
    dr = [0, 1, 0, -1]
    dc = [1, 0, -1, 0]
    for r in range(N):
        for c in range(N):
            for k in range(4):
                nr = r + dr[k]
                nc = c + dc[k]
                if 0 <= nr <= N-1 and 0 <= nc <= N-1:
                    result += abs(arr[r][c] - arr[nr][nc])
    print(f'#{tc} {result}')
  • 전치 행렬

행과 열의 인덱스 값이 같은 대각선 라인을 기준으로 위 아래의 좌표값을 반대로 바꾸는 것!

arr [ i ] [ j ], arr[ j ] [ i ] = arr[ j ] [ i ], arr[ i ] [ j ]

근데 이것만 사용하면 대각선을 기준으로 2번 바꾸게 돼서 결국 처음과 똑같이 돌아가버리고 만다.

따라서 if i < j 같은 조건을 걸어주어야 한다.

  • 비트 연산자

& : 비트 단위로 and 연산을 한다.

| : 비트 단위로 or 연산을 한다.

<< : 피연산자의 비트 열을 왼쪽으로 이동시킨다.

>>: 피연산자의 비트 열을 오른쪽으로 이동시킨다.

<< 연산자 : 1 << n → 2**n 즉, 원소가 n개일 경우의 모든 부분집합 수를 의미한다.

& 연산자 : i & (1 << j) → i 의 j 번째 비트가 1인지 아닌지를 검사한다.

bit : 0과 1로 상태를 나타낼 수 있는 최소 단위

8 bit = 1 byte

  • for 문과 while 문의 차이

→ 다른 언어에서는 문법만 다르고 작동원리는 동일하나 파이썬에서는 둘이 차이가 있다.

while 종료 조건 : (보통 종료 조건에 변수가 있어야 한다. 그래야 값이 변하고 조건이 달성가능)

(반복할 내용)

+ 종료 조건에 사용할 변수가 while 문 전에 생성되어있어야 한다.

while i < 5:
    i += 2

for i in range(5):
    i += 2

# 위 코드에서 while과 for문의 차이?
# while에서는 반복하는 과정에서 i 변수에 가해진 변화가 다음 반복 이후로도 반영된다.
# for 문에서는 반복하는 한 과정 안에서만 i 변수에 가해진 변화가 유지된다.
# 다음 반복부터는 리스트에서 꺼내는 다음 값으로 i 변수가 초기화 되어버린다.

 

'알고리즘' 카테고리의 다른 글

String  (1) 2024.02.05
알고리즘 문제 풀이  (1) 2024.02.05
List 2 (2)  (0) 2024.02.01
List 1 (2)  (1) 2024.01.30
List 1  (0) 2024.01.30