알고리즘 및 코테

손코딩 문제 유형 연습 (작성 중)

luminous_dev 2025. 4. 4. 11:21

이번에 보는 손코딩 코테 시험을 대비하기 위해 연습이 더 필요할 것 같아서

손코딩에 도움될 만한 블로그 글을 찾아보았다..!

 

이번 글은 아래 블로그 글을 공부하는 글이당

내가 확실하게 알지 못했던 부분들을 정리해볼 예정이다.

 

참조 URL : 

 

https://velog.io/@rhdguswlx/ofjwsqq0

 

손코딩 테스트 대비

Math.random() 함수 랜덤함수는 기본형이 Double형이기에 (int) 로 정수화시켜줘야함0~1(1은 미포함) 구간에서 부동소수점의 난수를 생성1부터의 값을 뽑고 싶다면 랜덤함수는 0부터 나오기때문에 +1을

velog.io


시작 전

손코딩 시작할 기초

 

아래 틀을 작성하고 시작할 것!! 

이때 solution 메소드의 반환 타입과 매개변수, answer 변수의 데이터타입은 달라질 수 있음 

 

Solution 함수 

class Solution{
    public int solution(int n){
        int answer = 0;
        
        return answer;
    }
}

 

 

 

메인 함수 

public class Main {
	public static void main(String[] args) {
		
		
	}
		
}

4/4

배열 문제

배열의 최대값 최소값 찾기

 

방법 1. Arrays.stream(arr).max().getAsInt();  // Arrays.stream(arr).min().getAsInt();

int [] arr = {1,2,3,4,5};
	int max = Arrays.stream(arr).max().getAsInt();
    int min = Arrays.stream(arr).min().getAsInt();
    
    System.out.println(max);    
    System.out.println(min);

 

최댓값 : int max = Arrays.stream(arr).max().getAsInt();

최솟값 : int min = Arrays.stream(arr).min().getAsInt();

 

알게된 점: 

Q. Arrays.stream(arr).max().getAsInt(); 에서 getAsInt();를 해야하는 이유?
.max()의 반환 타입이 OptionalInt이기 때문

* 왜 OptionalInt로 반환할까?: 배열이 빈 배열일 수도 있기 때문

* OptionalInt는 "int일 수도 있고, 아닐 수도 있는 값"  / 
빈 배열 같은 예외 상황을 안전하게 처리하기 위한 래퍼 타입

 

 

방법 2. 반복문 활용

int[] arr = {1, 2, 3, 4, 5};
int max = arr[0];
int min = arr[0]

	for(int i = 1; i< arr.length; i++){
    	if(arr[i] > max){
        	max = arr[i]
        }
    	
        if(arr[i]<min){
        	min = arr[i]
        }
    }
알게된 점
else if를 쓰는 건 안될까?
x → min의 검사에서 값이 max보다 크기만 하면 min의 검사를 건너뜀 

 


중복된 값 찾기

이중 for 문 사용하기

//이중 for문으로 비교
int[] arr = { 1, 2, 3, 3, 4, 4, 5 };
	for(int i = 0; i< arr.length; i++){
            for(int j=i; j < arr.length; j++){
                if(arr[i] == arr[j]){
                    System.out.println("중복된 값:" + arr[i]);  
                }
            }
    }

 

 


배열 뒤집기

//★Arrays.reverse(arr); (x) 이런 메소드 없음 

//방법 1. List로 변환 후 Collections.reverse(); 사용 

 

//방법 2. 직접 구현하기 (for문 사용)

 

**Arrays.asList()는 참조형에 쓰일 수 있음

String[] arr = {"apple", "banana", "cherry"};
List<String> list = Arrays.asList(arr);

for(String fruit : list) {
    System.out.println(fruit);
}

 

방법 1. 

int[] arr = { 1, 2, 3, 3, 4, 4, 5 };

List<Integer> list = Arrays.stream(arr) // IntStream
        .boxed()                        // int → Integer 
        .collect(Collectors.toList()); // List<Integer>
        
        
/* 대체 가능

for (int num : arr) {
    list.add(num); // int → Integer (오토박싱)
}

*/
        
        
Collections.reverse(list);
System.out.println(list); // [5, 4, 4, 3, 3, 2, 1]

 

알게된 것
List<String> list = Arrays.stream(arr).collect(Collectors.toList());

 

 

 

방법 2. 

int[] arr = { 1, 2, 3, 3, 4, 4, 5 };


int left = 0; //첫 인덱스 
int right = arr.length -1; //마지막 인덱스

while(left<right){
	int tmp = arr[left];
    arr[left] = arr[right];
    arr[right]= tmp;
    left++;
	right--;
}

System.out.println(Arrays.toString(arr)); //배열을 출력하기 위하여 .toString으로 바꿔야 함
자꾸 깜빡하는 거 
배열은 출력하기 위하여 Arrays.toString()로 바꿔야 함
System.out.println(Arrays.toString(arr)); 

 


문자열 문제

문자열 뒤집기 

String str = "hello";

StringBuilder sb = new StringBuilder(str).reverse().toString();

 

 

 

String str = "hello";
	StringBuilder sb = new StringBuilder(str); //StringBuilder의 ()안에 str 바로 넣으면 변환됨 
    sb.reverse().toString(); //StringBuilder로 메소드 적용한 값은 .toString() 해줘야 함
    
    System.out.println(sb);
알게된 점 1
문자열을 StringBuilder로 변환하는 법
StringBuilder sb = new StringBuilder(str);


깜빡하는 점 2.
sb.reverse().toString();
StringBuilder 변수에 바로 .reverse() 메서드 
끝나면 .toString()

★ 중복된 문자열 제거

//만약 String으로 전달되면 String[] arr = str.split("");
String[] arr = { "p", "e", "o", "p", "l" ,"e" };
	arr = Arrays.stream(arr)  // 배열을 스트림으로 변환
    		.distinct()       //중복 제거 
            .toArray(String[]::new); // 다시 String[] 배열로 변환
    
    System.out.println(Arrays.toString(arr)); //결과 출력할 땐 배열은 .toString();

 

String[] arr = { "p", "e", "o", "p", "l" ,"e" };

 

Arrays.stream(arr).distinct().toArray(String[]arr::new);

 

알게된 점

.distinct(); : 중복 제거 

.toArray(String[]::new); : 새로운 String[] 객체로 반환


- 생성자 참조(Constructor reference)
- 자바에서 스트림(Stream)을 배열로 바꿀 때 어떤 타입의 배열을 만들지 지정 




배열은 출력 시 .toString();

 


 

팰린드롬

 

방법 1. StringBuilder 

//StringBuilder sb = new StringBuilder(str);

//.reverse() 바로

//끝나면 .toString();  

public static boolean isPalindrome(String str) {
    String reversed = new StringBuilder(str).reverse().toString();
    return str.equals(reversed);
}

 

방법 2. 

public static boolean isPalindrome(String str) {
    int left = 0;
    int right = str.length() - 1;
    
    while (left < right) {
        if (str.charAt(left) != str.charAt(right)) {
            return false;
        }
        left++;
        right--;
    }
    return true;
}

최대 공약수, 최소 공배수 

최대 공약수 : 원래 b는 a로, a에서 b를 나눈 것은 b로 - (a에서 b나눈 것이 0이면 a 반환) 

최소 공배수 : 두 수를 곱한 다음 최대공약수로 나눈 것

/* 최대 공약수 
b는 a로 , a는 a%b로 넣기*/

private int gcd (int a, int b){
	if(b==0){
    	return a;
    }
	return gcd(b, a%b);	    
}

-----------------------------------
/* 최소 공약수 
두 값을 곱한 후 최대공약수로 나누기*/

private int lcm(int a, int b){
	return a*b /gcd(a,b); //여기에서 최대 공약수를 호출
}

4/5

소수 구하기

소수 : 1가 자기 자신으로만 나누어지는 수 

★1은 소수에서 제외

 

이중 for문으로 돌렸을 때 i와 j 나눈 나머지가 0이면 count를 키우기

이때 count가 하나이면! -> 본인만 count되어 있으면 소수 출력 

0이랑 1은 소수 아님

class Solution {
    public int solution(int n) {
        
        boolean[] isComposit = new boolean[n+1]; //소수 = false
        int answer = 0;
        
        for(int i = 2; i < isComposit.length ; i++){
            if(!isComposit[i]){
                answer++;
                //i의 배수는 모두 true로 만들기
                for(int j = i*2; j<= n ; j+=i){ //i씩 증가
                    isComposit[j] =true;                    
                }
            }            
        }
        
        return answer;
    }
}

 

 

만약 어떤 소수인지 출력? 그럼 i를 출력하기 

 


 

 

팩토리얼 수중에 0인 것 

N!에서 뒤에서부터 처음 0이 아닌 숫자가 나올떄까지 0의 개수를 구하라

뒷자리가 0이 나오는 경우 2와 5가 곱해져있을 때

소인수분해를 해서 2와 5가 나오면 뒷자리는 0으로 끝남

public class Main{
	public static void main(String[]args){
    
 		Scanner sc = new Scanner(System.in);
        int num = sc.nextInt(); //sc.next() = 문자열
         sc.close(); // 리소스 누수 방지를 위해 Scanner 닫기
        
        int answer = 0;
        
        while(num>=5){
			answer+=num/5;
            num/=5;
        }
        
        System.out.println(answer);
    }
}

 

 

 

 

 

 

숫자 중에 7의 개수 

public class Main{
	public static void main(String[]args){
    	int answer = 0;
        int [] array = {7,77,17};
		
        for(int i = 0; i < array.length;i++){
        	//숫자를 문자로 바꾸기
            String num = Integer.toString(array[i]);
            String[]arr = num.split("");
            
            for(int j = 0; j< arr.length ; j++){
				if(arr[j].equals("7")){
					answer++;                
                }
            }
        }
        
        System.out.println(answer);
    }
}

 

알게된 것
숫자 -> 문자 변환
Integer.toString(숫자);

 

 

 

 

팩토리얼 : n! = n × (n-1) × (n-2) × ... × 1

피보나치 : f(n) = f(n-1) + f(n-2)

 


재귀 팩토리얼 

4면 4*3*2*1


int fact(int n){
	if(n==1){
    	return 1;
    }
	return n*fact(n-1);
}

 

 

★ 재귀 피보나치 수열 

피보나치 = 앞의 두 수를 더해서 다음 수를 만들어나감

private int fibo(int n){
	if(n<2){ //n이 2보다 작으면 1,0...
    	return n;
    }
	return fibo(n-1) + fibo(n-2);
}

 

 

 

 

로또 번호 뽑기 (Math.random());

import java.util.*;

public class Main{
	public static void main(String[]args){
		
        //랜덤 1부터 값 뽑기
        
        //로또 뽑을 배열 6개로 생성
        int[] arr= new int[6];
		
        for(int i = 0; i< arr.length; i++){
        //Math.random()은 Double형이라 int로 형변환
			int lotto = (int)(Math.random());        
        
        
        }
    }
}

 

 

 

 

 

구구단 출력(가로) 

 

 

 

구구단 출력(세로) 

 

 

구구단 3단에서 3의 배수 빼고 출력 

 

 

구구단 3의 배수단만 출력 

 

 

 

 

 

메모이제이션을 이용한 피보나치 수열 

 

 

반복문(동적계획법) 이용한 피보나치 수열

 

 

 

 

 

1~100 사이 수를 크기 10인 배열 arr에 담고 각각 정렬하기 

 


대표 알고리즘

 

선택 정렬 

최솟값과 비교해서 더 작으면 교체

이때 i 이후에 최솟값이 있으면 (i 하나마다 j를 다 돌고 변경) 

for (int i = 0; i < arr.length; i++) {
    int min = i; // 현재 위치를 최소값으로 가정

    // i 이후의 값 중 가장 작은 값을 찾는다
    for (int j = i + 1; j < arr.length; j++) {
        if (arr[min] > arr[j]) {
            min = j; // 더 작은 값이 있다면 min 인덱스 갱신
        }
    }

    // 현재 위치(i)와 가장 작은 값(min)을 교환
    int tmp = arr[i];
    arr[i] = arr[min];
    arr[min] = tmp;
}

 

 

 

버블 정렬 

i회차씩 돌릴 때마다 큰 수가 뒤로 보내짐

다음 j는 이미 정렬된 끝의 수를 제외하고 다시 정렬 

(바로 뒤와 비교해서 i보다 큰 수를 뒤로 보냄)

int[] arr = {1, 5, 6, 2, 3, 7, 8, 4, 9, 10};

// 버블 정렬 - 가장 큰 값을 오른쪽 끝으로 "거품처럼" 올린다
for (int i = 0; i < arr.length - 1; i++) {
    for (int j = 0; j < arr.length - 1 - i; j++) {
        if (arr[j] > arr[j + 1]) {
            int tmp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = tmp;
        }
    }
}

 

i 반복문이 필요한 이유

버블 정렬은 한 번 반복할 때마다 가장 큰 수가 맨 끝으로 가요.

  • 1회차(i=0): 가장 큰 수가 맨 끝으로
  • 2회차(i=1): 두 번째 큰 수가 그 앞에
  • ...
  • 이렇게 i가 커질수록, 비교할 범위가 점점 줄어듭니다.

 

i = 전체 몇 회 반복했는지 나타냄 (회차) 

j = 0부터 시작해서 인접한 값을 비교 (arr[j] vs arr[j+1])

j<arr.length -1 - i = 이미 정렬된 마지막 부분은 안 봐도 됨

 

 

 


삽입 정렬 (거꾸로 - 더 작은 값을 왼쪽으로 이동)

앞에서부터 차례대로 정렬된 부분에 "적절한 위치"를 찾아 삽입하는 방식

 

  • 마치 카드 게임에서 손에 카드를 한 장씩 끼워넣는 것처럼 동작
  • i=1부터 시작해서 arr[0...i] 구간을 항상 정렬된 상태로 유지함.

 

for (int i = 1; i < arr.length; i++) {   // 두 번째 요소부터 시작
    for (int j = i; j > 0; j--) {       // 현재 값 j와 왼쪽 값들을 비교
        if (arr[j - 1] > arr[j]) {      // 왼쪽이 더 크면
            int tmp = arr[j];           // 오른쪽을 스와프해서 왼쪽으로 이동
            arr[j] = arr[j - 1];
            arr[j - 1] = tmp;
        } else break;                   // 아니면 멈춤(자리 찾았음)
    }
}

 

거꾸로 -> 만약 arr[j-1]이 arr[j]보다 큰 값일 때  서로 바꾸고 ( 아니면 ) break; 

이미 이전 것들은 정렬이 되었으니까 break

 


퀵 정렬 

“중간값 하나를 고르고, 그보다 작은 건 왼쪽, 큰 건 오른쪽으로 보내면서 나눠서 정리해나가는 방법!”

제일 첫번째 수(start) 를 pivot / 작은 건 왼쪽 , 큰 건 오른 ㅉ고 

public class Main {
    public static void main(String[] args) {
        int n = 10;
        int[] arr = {7, 5, 9, 0, 3, 1, 6, 2, 4, 8};

        quickSort(arr, 0, n - 1);
        System.out.println(Arrays.toString(arr)); // 정렬된 결과 출력은 여기서!
    }

    private static void quickSort(int[] arr, int start, int end) {
        if (start >= end) return;

        int pivot = start; // pivot = start 
        int left = start + 1; //left는 start보다 1큰 값
        int right = end; //right = end

        while (left <= right) { //start보다 1큰 값이 end값보다 작을 때 
        
            while (left <= end && arr[left] <= arr[pivot]) left++; //left가 end보다 작거나 같고, arr left가 arr start의 값보다 작거나 같으면 left++;
            
            
            
            while (right > start && arr[right] >= arr[pivot]) right--; //right가 start보다 크고 / arr right가 arr start보다 크거나 같으면 right--;

            if (left > right) { //만약 left와 right이 안 같으면 중앙값 기준으로 제대로 정렬 안됐다는 거니까 피벗과 작은 값 (right) 교체
                int tmp = arr[pivot];
                arr[pivot] = arr[right];
                arr[right] = tmp;
            } else {  // 제대로 정렬됐다면 작은 값과 큰 값 교체
                int tmp = arr[left];
                arr[left] = arr[right];
                arr[right] = tmp;
            }
        }

        // 분할 이후 왼쪽과 오른쪽 정렬
        quickSort(arr, start, right - 1);
        quickSort(arr, right + 1, end);
    }
}

 

start가 end보다 크면 끝냄

 

 

 

 

 

석차 구하기 

정수를 비교해 작은 점수의 등수를 증가 시키는 방식
10명의 학생의 점수를 임의로 설정하여 각 학생별로 등수를 매기시오

 

 

스택 LIFO

.push () / .pop () / .empty() /.peek()

Stack<Integer> s = new Stack<>();

public static void main(String[] args) {
		Stack<Integer> s = new Stack<>();
		
		// 삽입(5) - 삽입(2) - 삽입(3) - 삽입(7) - 삭제() - 삽입(1) - 삽입(4) - 삭제()
		s.push(5);
		s.push(2);
		s.push(3);
		s.push(7);
		s.pop();
		s.push(1);
		s.push(4);
		s.pop();	
	
		
		while(!s.empty()) { //비어있지 않으면
			System.out.println(s.peek());//스택의 맨앞에있는거 출력
			s.pop(); //하고 삭제
			
			
		}
	
	}

 

 

큐 FIFO

.offer(); / .poll()

Queue<Integer> q = new LinkedList<>():

import java.util.LinkedList;
import java.util.Queue;

public class Main {

	public static void main(String[] args) {
		Queue<Integer> q = new LinkedList<>();
		q.offer(5); //삽입
		q.offer(2);
		q.offer(3);
		q.offer(2);
		q.poll(); //삭제 
		//먼저 들어온 원소부터 추출
		while(!q.isEmpty()) {
			System.out.println(q.poll());
		}
		
	}
	}

 

 

추가

int 형 배열 내림차순 하기

1. Integer[] arr2 = Arrays.stream(arr).boxed().toArray(Integer[]::new);

2. Arrays.sort(arr2,Collections.reverseOrder());

 

 

 

 

 

 

그래프 탐색 알고리즘 : DFS/BFS 

소수문제, 길찾기 문제, 숫자중에 0이나, 7의 개수, 팩토리얼 수중에 0인것, 피보나치, 완전탐색 기초적인것(DFS, BFS), 달팽이문제, 배열돌리기, 해쉬맵으로 카운트해서 정렬하기 , 이진검색트리, 타켓숫자을 주고 배열중 두수로 타켓숫자 만들기