알고리즘
[Java] 알고리즘 Day2
Jaemin0604
2024. 7. 2. 15:54
1. 델타 delta
- 상하좌우를 이동하는 기법
static int dy[] = { -1, 1, 0, 0};
static int dx[] = { 0, 0, -1, 1};
주의할 점
상하좌우 이동하면서 배열의 인덱스 값 범위에서 벗어나는지 검사
델타 활용 예시
static void print(int y, int x) {
for (int d = 0; d < 4; d++) {
int ny = y;
int nx = x;
while(true) {
ny = ny + dy[d];
nx = nx + dx[d];
if( ny < 0 || nx < 0 || ny >= 5 || nx >= 5 ) break; //인덱스 범위 검사
System.out.print(map[ny][nx]);
}
}
System.out.println();
}
- dx, dy를 조절하여 대각선 이동도 가능
static int dy[] = { -1,-1, 1, 1};
static int dx[] = { -1, 1, -1, 1};
- 8방향 이동
static int dy[] = { -1, 1, 0, 0, -1,-1, 1, 1};
static int dx[] = { 0, 0, -1, 1, -1, 1, -1, 1};
2. 재귀(Recursive)
- 함수가 자기 자신을 호출하는 프로그래밍 기법
주의할 점
재귀가 끝나는 조건을 항상 명시할 것
예시 - 팩토리얼
static int factorial(int n) {
if (n==1) return 1; // 재귀 종료 조건
else return n*factorial(n-1); // 재귀 호출
}
static void factorial(int n, int result) {
if (n==1) {
System.out.println(result);
return;
}
factorial(n-1, result*n);
}
3. 정렬(Sort)
배열(array) vs 컬렉션(collection)
- 배열은 크기가 정해져있을 때 -> 배열의 크기는 고정
- 컬렉션은 크기를 모를 때 -> 컬렉션은 동적으로 크기 변경
- 속도 자체는 배열이 빠름
- 컬렉션이 유연성을 가짐
배열(Array) 사용
정수 정렬
int[] intArray = { 3, 5, 2, 7, 9, 4 };
Arrays.sort(intArray); // intArray 오름차순정렬
System.out.println(Arrays.toString(intArray));
문자열 정렬
String[] strArray = {"Hello", "ABC", "World"};
Arrays.sort(strArray, Collections.reverseOrder());
Arrays.sort(strArray);
정렬
방법1: Comparable interface 구현
static class Item implements Comparable<Item>{
int itemId;
String itemNm;
Item(int itemId, String itemNm){
this.itemId = itemId;
this.itemNm = itemNm;
}
@Override
public String toString() {
return "Item [itemId=" + itemId + ", itemNm=" + itemNm + "]";
}
@Override
public int compareTo(Item o) {
// itemId 우선 비교 같으면 itemNm 비교
return this.itemId == o.itemId ? this.itemNm.compareTo(o.itemNm) : this.itemId - o.itemId;
}
}
방법2: Comparator 객체 전달
Arrays.sort(itemArray, new Comparator<Item>() {
@Override
public int compare(Item o1, Item o2) {
return o1.itemNm.compareTo(o2.itemNm);
}
});
System.out.println(Arrays.toString(itemArray));
- 익명 클래스를 사용하여 Comparator 인터페이스를 구현
- itemNm을 기준 오름차순 정렬
방법3: 람다활용
Arrays.sort(itemArray, [정렬 조건]);
Arrays.sort(itemArray, (o1, o2) -> o2.itemId - o1.itemId );
System.out.println(Arrays.toString(itemArray));
- itemId 기준 오름차순 정렬
컬렉션(Collection) 사용
-> ArrayList
List<Item> list = new ArrayList<>();
list.add(new Item(3, "666"));
list.add(new Item(2, "777"));
list.add(new Item(5, "444"));
list.add(new Item(3, "111"));
ArrayList<String> list = new ArrayList<>();
list.add("Banana");
list.add("Apple");
list.add("Cherry");
// 기본 정렬 (자연 순서)
Collections.sort(list);
ArrayList<String> list = new ArrayList<>();
list.add("Banana");
list.add("Apple");
list.add("Cherry");
// 사용자 정의 Comparator로 정렬 (문자열 길이 순)
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
}
});
ArrayList<String> list = new ArrayList<>();
list.add("Banana");
list.add("Apple");
list.add("Cherry");
// 람다 표현식을 사용하여 정렬 (문자열 길이 순)
Collections.sort(list, (s1, s2) -> Integer.compare(s1.length(), s2.length()));
4. 순열(Permuatation)
n개의 원소를 가지는 집합에서 순서를 고려하여 r개를 선택
- 모든 순열 조합 출력 예시(n = 5, r = 3)
static int[] src = {1, 2, 3, 4, 5};
static int[] tgt = new int[3]; // 선택된 원소들로 만든 순열을 담을 배열
static boolean[] select = new boolean[src.length]; // 선택되었는지 알려주는 배열
public static void main(String[] args) {
perm(0);
}
static void perm(int tgtIdx) {
if (tgtIdx == tgt.length) {
System.out.println(Arrays.toString(tgt));
return;
}
for (int i = 0; i < src.length; i++) {
if (select[i]) continue;
tgt[tgtIdx] = src[i];
select[i] = true;
perm(tgtIdx + 1);
select[i] = false;
}
}
5. 조합(Combination)
n개의 원소를 가지는 집합에서 순서를 고려하지 않고 r개를 선택
static int[] src = {1, 2, 3, 4, 5};
static int[] tgt = new int[3];
// 조합은 select 필요 X
// 맨 앞에서부터 tgt 의 각자를 순차적으로 고려하면서 채움
public static void main(String[] args) {
comb(0, 0);
}
static void comb(int srcIdx, int tgtIdx) {
if( tgtIdx == tgt.length ) {
System.out.println(Arrays.toString(tgt));
return;
}
// src 배열을 모두 확인한 경우
if( srcIdx == src.length) return;
// 선택된 경우 (현재 srcIdx의 원소를 tgt 배열에 추가)
tgt[tgtIdx] = src[srcIdx];
comb(srcIdx + 1, tgtIdx + 1); // 다음 위치를 채우기 위해 재귀 호출
// 선택되지 않은 경우 (현재 srcIdx의 원소를 무시)
comb(srcIdx + 1, tgtIdx); // 다음 원소를 고려하기 위해 srcIdx를 증가시키고 tgtIdx는 그대로 유지
}
6. 집합(Subset)
가질 수 있는 모든 부분 집합의 목록을 출력
static int[] src = {1, 2, 3, 4, 5};
static boolean[] select = new boolean[src.length];
public static void main(String[] args) {
subset(0);
}
static void subset(int srcIdx) {
// 모든 원소를 확인한 경우
if (srcIdx == src.length) {
printSubset();
return;
}
// srcIdx 원소를 선택하는 경우
select[srcIdx] = true;
subset(srcIdx + 1); // 다음 원소를 고려하기 위해 재귀 호출
// srcIdx 원소를 선택하지 않는 경우
select[srcIdx] = false;
subset(srcIdx + 1); // 다음 원소를 고려하기 위해 재귀 호출
}
static void printSubset() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < select.length; i++) {
if (select[i] ) sb.append(src[i]).append(" ");
}
System.out.println(sb);
}