#include <stdio.h>
#include <stdlib.h>
void set(int** arr, int* data, int rows, int cols) {
for (int i = 0; i < rows * cols; ++i) {
arr[((i + 1) / rows) % rows][(i + 1) % cols] = data[i];
}
}
int main() {
int rows = 3, cols = 3, sum = 0, i;
int data[] = {5, 2, 7, 4, 1, 8, 3, 6, 9};
int** arr;
arr = (int**) malloc(sizeof(int*) * rows);
for (i = 0; i < rows; i++) {
arr[i] = (int*) malloc(sizeof(int) * cols);
}
set(arr, data, rows, cols);
for (i = 0; i < rows * cols; i++) {
sum += arr[i / cols][i % cols] * (i % 2 == 0 ? 1 : -1);
}
for(i=0; i<rows; i++) {
free(arr[i]);
}
free(arr);
printf("%d", sum);
return 0;
}
🖍️ 13
data
배열에 있는 값을 2차원 배열arr
에 특정 방식으로 저장 (set 함수)- 저장된 배열 값을 홀수 인덱스에서는 음수, 짝수 인덱스에서는 양수로 합산
- 최종적으로
sum
을 출력🧩 2차원 배열을 동적으로 할당:
arr = (int**) malloc(sizeof(int*) * rows);
arr
은int
포인터의 포인터, 즉int**
arr
을int*
배열로 만들고 싶음sizeof(int*) * rows
:int*
타입을rows
개 만큼 메모리 할당
즉, 행(row
) 개수만큼 포인터 공간을 확보arr │ ├───► arr[0] → ? ├───► arr[1] → ? └───► arr[2] → ?
for (i = 0; i < rows; i++) { arr[i] = (int*) malloc(sizeof(int) * cols); }
arr[i]
는 각 행에 해당하는 포인터sizeof(int) * cols
: 열(col
) 수만큼 정수 배열을 만듦
즉, 각 행에 실제 데이터를 저장할 공간을 할당arr │ ├───► arr[0] → [ int ][ int ][ int ] ├───► arr[1] → [ int ][ int ][ int ] └───► arr[2] → [ int ][ int ][ int ]
🧩 set() 함수
void set(int** arr, int* data, int rows, int cols) { for (int i = 0; i < rows * cols; ++i) { arr[((i + 1) / rows) % rows][(i + 1) % cols] = data[i]; } }
- 행 인덱스:
((i + 1) / rows) % rows
- 열 인덱스:
(i + 1) % cols
즉,i
가 0부터 8까지 순회하면서,data[i]
값을 위의 인덱스 계산으로arr
에 넣음
🧩 최종 arr 상태:
arr = { {9, 5, 2}, {7, 4, 1}, {8, 3, 6} };
🧩 sum 계산
for (i = 0; i < rows * cols; i++) { sum += arr[i / cols][i % cols] * (i % 2 == 0 ? 1 : -1); }
2차원 배열을 순서대로 탐색하면서:
- 짝수 인덱스
(i % 2 == 0)
→ 더함- 홀수 인덱스 → 뺌
➡︎
9 - 5 + 2 - 7 + 4 - 1 + 8 - 3 + 6 = 13
① 다른 모듈 내부에 있는 변수나 기능을 다른 모듈에서 사용하는 경우의 결합도
② 모듈 간의 인터페이스로 배열이나 오브젝트, 자료구조 등이 전달되는 경우의 결합도
③ 파라미터가 아닌 모듈 밖에 선언되어 있는 전역 변수를 참조하고 전역 변수를 갱신하는 식으로 상호작용하는 경우의 결합도
🖍️ ① 내용 결합도 ② 스템프 결합도 ③ 공통 결합도
상속(Inheritance), 메서드 오버라이딩(Method Overriding), 정적 변수(Static Variable), 변수 숨김(Variable Shadowing)
class parent{
static int total = 0;
int v = 1;
public parent(){
total += (++v);
show();
}
public void show(){
total += total;
}
}
class child extends parent{
int v = 10;
public child(){
v += 2;
total += v++;
show();
}
@Override
public void show(){
total += total*2;
}
}
class Main {
public static void main(String[] args) {
new child();
System.out.println(parent.total);
}
}
🖍️ 54
🩵 코드 시작:
new child();
1️⃣ 먼저 parent 생성자가 실행
int v = 1; ++v; // v는 2가 됨 total += v; // total = 0 + 2 = 2 show(); // 여기서 child의 show()가 호출됨
⚠️ 중요 포인트
show()
는parent
클래스의 메서드처럼 보이지만,child
클래스에서 오버라이딩했기 때문에, 실제로는child
의show()
가 실행됨// child의 show() 실행 total += total * 2; // 2 + (2 * 2) = 6
total
= 62️⃣ child 생성자가 실행
int v = 10; // child의 v (부모 v와는 다른 변수) v += 2; // v는 12 total += v++; // total = 6 + 12 = 18, v는 13이 됨 show(); // 다시 child의 show() 실행
total += total * 2; // 18 + (18 * 2) = 54
🔚 최종 결과
System.out.println(parent.total); // 결과: 54
- 동적 바인딩으로 인해 부모 생성자에서도 자식의 메서드가 호출됨
static
변수 덕분에 값이 누적되어 최종적으로 54가 출력됨
🖍️ adapter
정확하지 않음
int main() {
int a = 0;
while (조건문) {
if (B[a] < 0)
B[a] = -B[a];
a++;
}
return(1);
}
🖍️
순서: ➊→➋→➌→➍→➎→➋→➏
흐름도 구성 노드
[Start] --> [a = 0] | v [➊ while (조건문)] <------------------------ / \ | No Yes | | | | [➋ return 1] v | [➌ if (조건문)] | / \ | No Yes | | | | | v | | [➍ B[a] = -B[a]] | \ / | | | [➎ a++] ----------------------- | [➏ return 1]
public class Main {
static int comp(int[] a, int st, int end) {
if (st >= end) return 0;
int mid = (st + end) / 2;
return a[mid] + Math.max(comp(a, st, mid), comp(a, mid + 1, end));
}
public static void main(String[] args) {
int[] values = {3, 5, 8, 12, 17};
System.out.println(comp(values, 0, values.length - 1));
}
}
🖍️ 20
🧩 main 함수
public static void main(String[] args) { int[] values = {3, 5, 8, 12, 17}; System.out.println(comp(values, 0, values.length - 1)); }
comp
함수는values
배열을0
부터values.length - 1
(즉, 0부터 4까지)까지의 범위로 분할하여 실행comp
함수는 재귀적으로 배열을 나누고, 각 부분에서 가장 큰 값을 구해 반환🧩 comp 함수
static int comp(int[] a, int st, int end) { if (st >= end) return 0; int mid = (st + end) / 2; return a[mid] + Math.max(comp(a, st, mid), comp(a, mid + 1, end)); }
comp
함수는 배열a
와 인덱스st(start)
와end(end)
를 인자로 받아서 부분 배열의 합을 구하고, 그 중에서 최대값을 반환하는 함수
- 재귀 종료 조건:
st >= end
이면 0을 반환, 이 조건은 배열의 크기가 1 이하일 때 재귀가 종료- 분할: 배열을 두 부분으로 나눔,
mid
는 배열의 중간 인덱스- 부분합 계산:
comp(a, st, mid)
는st
부터mid
까지의 부분 배열을 처리하고,comp(a, mid + 1, end)
는mid + 1
부터end
까지의 부분 배열을 처리- 최대값 구하기: 두 부분의 결과를 비교한 후 더 큰 값을 선택하고,
a[mid]
값을 더해 최종 결과를 계산✅ comp(values, 0, 4) 실행 흐름 표
comp(0,4) → 8+12 ├── comp(0,2) → a[1]+3+0 = 8 │ ├── comp(0,1) → a[0]+0+0 = 3 │ │ ├── comp(0,0) → 0 │ │ └── comp(1,1) → 0 │ └── comp(2,2) → 0 ├── comp(3,4) → a[3]+0+0 = 12 │ ├── comp(3,3) → 0 │ └── comp(4,4) → 0
class TreeNode:
def __init__(self, value):
self.value = value
self.children = []
def build_tree(li):
nodes = [TreeNode(i) for i in li]
for i in range(1, len(li)):
nodes[(i - 1) // 2].children.append(nodes[i])
return nodes[0]
def calc(node, level=0):
return node.value if level % 2 else 0 + sum(calc(n, level + 1) for n in node.children) if node else 0
li = [3, 5, 8, 12, 15, 18, 20]
root = build_tree(li)
print(calc(root))
🖍️ 13
🩵 클래스 TreeNode 정의
class TreeNode: def __init__(self, value): self.value = value self.children = []
TreeNode
클래스는 트리의 각 노드를 나타냄__init__()
: 노드의 값을 설정, 자식 노드들을 담을children
리스트를 초기화🩵 build_tree 함수
def build_tree(li): nodes = [TreeNode(i) for i in li] for i in range(1, len(li)): nodes[(i - 1) // 2].children.append(nodes[i]) return nodes[0]
build_tree
함수는 입력 리스트li
를 이용해 트리를 만듦
먼저,li
의 각 값에 대해TreeNode
인스턴스를 만들어nodes
리스트에 저장- 이후
for
루프를 통해 각 노드의 부모 노드를 찾아서 자식으로 추가
nodes[(i - 1) // 2]
는 현재 노드i
의 부모 노드를 가리킴- 예를 들어,
i = 1
일 때,(i - 1) // 2 = 0
으로, 노드 1의 부모는 노드 0- 마지막으로 트리의 루트 노드(
nodes[0]
)를 반환
🌳 결과 트리 구조
nodes[0]: 3 ├── nodes[1]: 5 │ ├── nodes[3]: 12 │ └── nodes[4]: 15 └── nodes[2]: 8 ├── nodes[5]: 18 └── nodes[6]: 20
🩵 calc 함수
calc
함수는 트리의 각 노드를 깊이 우선 탐색(DFS) 방식으로 순회하며 계산한다.def calc(node, level=0): return node.value if level % 2 else 0 + sum(calc(n, level + 1) for n in node.children) if node else 0
level=0
: 루트(시작점)level
: 현재 노드가 트리의 몇 번째 레벨인지를 나타냄🔍 핵심: 조건부 삼항 연산자
return ( node.value if level % 2 # 👉 레벨이 홀수면 자기 값 반환 else 0 + sum(...) # 👉 짝수면 자기 값 무시하고 자식 노드들의 결과만 합침 if node # 👉 node가 None이면 무조건 0 반환 else 0 )
- True = 1 / False = 0
node.value
: 현재 노드 값- 기본적으로, 노드의 값은 깊이에 따라 다르게 처리됨
level % 2 == 1
: 홀수,node.value
+ 자식들 합level % 2 == 0
: 짝수, 자신의 값은 무시 + 자식들 합sum(calc(n, level + 1) for n in node.children)
현재 노드의 모든 자식 노드들에 대해calc()
를 호출해서 합산, 재귀 호출node == None
일 경우, 0을 반환nodes[0]: 3 → 무시 ├── nodes[1]: 5 → 포함 │ ├── nodes[3]: 12 → 무시 │ └── nodes[4]: 15 → 무시 └── nodes[2]: 8 → 포함 ├── nodes[5]: 18 → 무시 └── nodes[6]: 20 → 무시
🩵 실행
li = [3, 5, 8, 12, 15, 18, 20] root = build_tree(li) print(calc(root))
3 / \ 5 8 / \ / \ 12 15 18 20
- 5 + 8 = 13
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int value;
struct Node *next;
} Node;
Node* createNode(Node* head, int value) {
Node* new_node = (Node*)malloc(sizeof(Node));
new_node->value = value;
new_node->next = head;
return new_node;
}
Node* reconnect(Node* head, int disconnect_count) {
Node *prev = NULL, *curr = head;
while (curr && curr->value != disconnect_count) {
prev = curr;
curr = curr->next;
}
if (!curr || curr == head) return head;
prev->next = curr->next;
curr->next = head;
head = curr;
return head;
}
int main() {
Node *head = NULL, *curr, *temp;
for (int i = 1; i <= 5; i++)
head = createNode(head, i);
head = reconnect(head, 3);
for (curr = head; curr != NULL; curr = curr->next)
printf("%d", curr->value);
// 메모리 해제
curr = head;
while (curr != NULL) {
temp = curr;
curr = curr->next;
free(temp);
}
return 0;
}
🖍️ 35421
🧩 구조체 정의
typedef struct Node { int value; struct Node *next; } Node;
Node
라는 이름의 구조체를 정의value
: 노드가 가지고 있는 값 (int형).next
: 다음 노드를 가리키는 포인터, 이 포인터를 통해 연결된 리스트를 구성🧩 새 노드 생성 함수
Node* createNode(Node* head, int value) { Node* new_node = (Node*)malloc(sizeof(Node)); new_node->value = value; new_node->next = head; return new_node; }
createNode()
함수는 새로운 노드를 생성하여 리스트의 맨 앞에 추가하는 함수
malloc
을 사용하여 새로운 Node를 동적으로 할당- 할당된 새로운 노드의
value
를 주어진value
로 설정- 새로운 노드의
next
는 현재의head
를 가리키도록 설정하여, 리스트의 맨 앞에 이 노드를 추가- 함수는 생성된
new_node
를 반환🧩 연결 리스트에서 특정 노드를 맨 앞으로 이동시키는 함수
Node* reconnect(Node* head, int disconnect_count) { Node *prev = NULL, *curr = head; ... }
reconnect
함수는 특정 값(disconnect_count
)을 가진 노드를 리스트에서 찾아 맨 앞으로 이동시키는 함수
prev
: 현재 노드의 이전 노드를 가리키는 포인터curr
: 현재 노드를 가리키는 포인터, 초기에는head
로 설정됨while (curr && curr->value != disconnect_count) { prev = curr; curr = curr->next; }
while
루프를 통해 리스트를 탐색하여disconnect_count
값과 일치하는 노드를 찾음
prev
는 항상curr
의 이전 노드를 추적curr
는 현재 노드를 추적if (!curr || curr == head) return head;
curr
이NULL
이면 값을 찾지 못한 경우이고,curr == head
이면 이미 맨 앞에 있는 경우- 그런 경우에는 아무것도 하지 않고
head
를 그대로 반환prev->next = curr->next; curr->next = head; head = curr;
prev->next = curr->next
:prev
노드의next
가curr
의next
를 가리키도록 하여curr
노드를 리스트에서 분리curr->next = head
:curr
노드를 리스트의 맨 앞에 추가하기 위해curr->next
를 기존head
로 설정head = curr
:head
를curr
로 변경하여 리스트의 첫 번째 노드를curr
로 설정head ↓ [5] → [4] → [3] → [2] → [1] → NULL ↑ ↑ prev curr head ↓ [5] → [4] → [3] → [2] → [1] → NULL ↑ ↑ prev curr • prev->next = curr->next → 4 → 2 • curr->next = head → 3 → 5 • head = curr → 새로운 head는 3
🧩 main 함수
int main() { Node *head = NULL, *curr, *temp; for (int i = 1; i <= 5; i++) head = createNode(head, i); ... }
Node *head = NULL
: 리스트의 헤드를 NULL로 초기화(빈 리스트)for (int i = 1; i <= 5; i++)
: 1부터 5까지 숫자를 가진 노드들을 생성하여 연결 리스트를 만듦createNode
함수를 사용하여 각 숫자에 대한 노드를 리스트의 맨 앞에 추가
결과적으로head
는5 -> 4 -> 3 -> 2 -> 1
로 초기화됨head = reconnect(head, 3);
- 3을 리스트에서 찾아서 맨 앞에 이동시킴
- 결과적으로 리스트는
3 -> 5 -> 4 -> 2 -> 1
for (curr = head; curr != NULL; curr = curr->next) printf("%d", curr->value);
- 리스트의 모든 값을 출력하는 루프
head
부터 시작하여 각 노드를 출력
🧩 메모리 해제
curr = head; while (curr != NULL) { temp = curr; curr = curr->next; free(temp); }
동적으로 할당한 메모리를 해제하는 코드
curr
는 리스트의 현재 노드를 가리키고,temp
는 메모리 해제를 위한 임시 포인터curr
를 리스트를 따라 이동시키면서, 각 노드의 메모리를free
함수로 해제free(temp)
로curr
가 가리키는 노드를 해제한 후,curr
을 다음 노드로 이동시킴
#include <stdio.h>
typedef struct student {
char* name;
unsigned int score[3];
} Student;
int dec(int enc) {
return enc & 0xA5;
}
int sum(Student* p) {
return dec(p->score[0]) + dec(p->score[1]) + dec(p->score[2]);
}
int main() {
Student s[2] = { "Kim", {0xF0, 0xF5, 0xDB}, "Lee", {0xED, 0xD3, 0xF2} };
Student* p = s;
int result = 0;
for (int i = 0; i < 2; i++) {
result += sum(&s[i]);
}
printf("%d", result);
return 0;
}
🖍️ 908
🧩 구조체 정의
typedef struct student { char* name; int score[3]; } Student;
Student
구조체는 학생의 이름과 점수 3개를 저장score[3]
배열은 3개의 정수 점수를 저장
다만, 이 점수는 인코딩된 형태🧩 디코딩 함수
int dec(int enc) { return enc & 0xA5; }
&
연산자는 비트AND
연산0xA5
는 16진수로 10100101- 즉, 인코딩된 점수에서 특정 비트만 남겨서 "디코딩"하는 역할
Kim: 0xF0(11110000)` & 0xA5(10100101) = 0xA0(10100000) = 160 0xF5(11110101) & 0xA5 = 0xA5 = 165 0xDB & 0xA5 = 0x81 = 129 → Kim의 총합: 160 + 165 + 129 = 454 Lee: 0xED & 0xA5 = 0xA5 = 165 0xD3 & 0xA5 = 0x81 = 129 0xF2 & 0xA5 = 0xA0 = 160 → Lee의 총합: 165 + 129 + 160 = 454
🧩 합산 함수
int sum(Student* p) { return dec(p->score[0]) + dec(p->score[1]) + dec(p->score[2]); }
- 특정 학생 포인터
p
의 세 점수를 디코딩해서 더함🧩 main 함수
for (int i = 0; i < 2; i++) { result += sum(&s[i]); } printf("%d", result);
result
=sum[0] + sum[1]
= 454 + 454 = 908
public class Main {
public static void main(String[] args) {
System.out.println(calc("5"));
}
static int calc(int value) {
if (value <= 1) return value;
return calc(value - 1) + calc(value - 2);
}
static int calc(String str) {
int value = Integer.valueOf(str);
if (value <= 1) return value;
return calc(value - 1) + calc(value - 3);
}
}
🖍️ 4
🩵 main()
public class Mian { public static void main(String[] args) { System.out.println(calc("5")); }
main()
함수에서 "5"라는 문자열을calc()
함수에 넘김- 문자열이므로 호출되는 건
calc(String str)
🩵 메서드 오버로딩 (Overloading)
static int calc(String str) { int value = Integer.valueOf(str); if (value <= 1) return value; return calc(value - 1) + calc(value - 3); }
Integer.valueOf(str);
: 문자열을 정수로 변환- 재귀적으로
calc(int)
를 호출! (value - 1, value - 3)- ⚠️ 주의: 여기서 호출되는
calc(value - 1) + calc(value - 3)
은int
버전의calc()
🔍 동작 순서 분석
"5" → calc(String) 호출됨 value = 5 calc(5 - 1) + calc(5 - 3) = calc(4) + calc(2)
📌 calc(4) - static int calc(int value)
calc(4 - 1) + calc(4 - 2) = calc(3) + calc(2) = (calc(2) + calc(1)) + (calc(1) + calc(0)) = ((calc(1) + calc(0)) + 1) + (1 + 0) = ((1 + 0) + 1) + (1 + 0) = (1 + 1) + 1 = 2 + 1 = 3
📌 calc(2) - static int calc(int value)
calc(2 - 1) + calc(2 - 2) calc(1) + calc(0) = 1 + 0 = 1
🩵 최종 결과
calc("5") = calc(4) + calc(2) = 3 + 1 = 4