반응형

개념

다익스트라(dijkstra)알고리즘은 다이나믹 프로그래밍(dp)를 활용한 대표적인 최단 경로 탐색 알고리즘이다. 다익스트라 알고리즘은 하나의 정점에서 다른 모든 정점으로 가는 최단 경로를 알려준다.

참고: https://blog.naver.com/PostView.naver?blogId=ndb796&logNo=221234424646&redirect=Dlog&widgetTypeCall=true&directAccess=false

 

23. 다익스트라(Dijkstra) 알고리즘

  다익스트라(Dijkstra) 알고리즘은 다이나믹 프로그래밍을 활용한 대표적인 최단 경로(Shortest P...

blog.naver.com

2차원 배열로 간선의 정보를 저장한다. 서로 연결되어 있지 않은 경우는 무한의 수로 설정한다.

  1. 음의 간선 정보는 포함 할 수 없다.
  2. 방문하지 않은 노드중 가장 비용이 적은 노드를 선택

구현 방법

  1. 간선 정보 2차원 배열로 생성, 최단 거리 배열 생성
#define INF 1e9 //엄청 큰 값인 10억

vector<pair<int,int>> v[10001]; // 비용, 연결점
int d[10001];
fill(d, d+10001, INF);

최단 거리 배열은 가장 작은 값을 나타내야 하기 때문에 우선은 가장 큰 값으로 초기화해 놓는다.

  1. priority_queue를 이용하여 최소비용 순서로 다익스트라 알고리즘 적용
void dijkstra(int start) {
	priority_queue<pair<int,int>> pq;
	pq.push({0,start});
	d[start] = 0;
	
	while(!pq.empty()) {
		int dist = -pq.top().fist; // 현재 노드까지의 비용, 작은것부터 뽑기위해 -로 저장해놨음
		int now = pq.top().second; // 현재 노드
		pq.pop();
	
		if(d[now] < dist) continue; // 현재 노드까지의 비용이 더 크면 볼 것도 없음
	
		for(int i = 0; i < v[now].size(); i++) {
			int cost = dist + v[now][i].first; //현재노드까지의 비용 + 다음 노드로 가는 비용
			if(cost < d[v[now][i].second]) {
				d[v[now][i].second] = cost
				pq.push(make_pair(-cost, v[now][i].second));
			}
		}
	}
}

현재까지의 비용이 가장 적은 노드 선택 후 그 노드와 연결된 노드들의 비용 값을 구한 후 만약 구한 값이 원래의 값보다 더 작다면 값을 업데이트 해 준 후 우선순위 큐에 해당 노드를 넣는다.

전체 코드

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정

// 노드의 개수(N), 간선의 개수(M), 시작 노드 번호(Start)
// 노드의 개수는 최대 100,000개라고 가정
int n, m, start;

vector<pair<int, int> > graph[100001]; // 각 노드에 연결되어 있는 노드에 대한 정보를 담는 배열
int d[100001]; // 최단 거리 테이블 만들기

void dijkstra(int start)
{
    priority_queue<pair<int,int>>pq; // 거리, 노드 인덱스
    
    pq.push({0,start}); //시작 노드로 가기위한 최단 경로는 0으로 설정하여, 큐에 삽입.
    d[start]=0;
    
    while(!pq.empty())
    {
        int dist = -pq.top().first; //현재 노드까지의 비용
        int now = pq.top().second; // 현재 노드
        pq.pop();
        
        if(d[now]<dist) // 이미 최단경로를 체크한 노드인 경우 패스
            continue;
        
        for(int i=0; i<graph[now].size(); i++)
        {
            int cost = dist+graph[now][i].second; // 거쳐서 가는 노드의 비용을 계산
                                                  // 현재노드까지 비용 + 다음 노드 비용
            if(cost<d[graph[now][i].first]) // 비용이 더 작다면 최단경로 테이블 값을 갱신.
            {
                d[graph[now][i].first]=cost;
                pq.push(make_pair(-cost,graph[now][i].first));
            }
        }
    }
}

int main(void)
{
    cin >> n >> m >> start;
    
    // 모든 간선 정보를 입력받기
    for (int i = 0; i < m; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        // a번 노드에서 b번 노드로 가는 비용이 c라는 의미
        graph[a].push_back({b, c});
    }
    
    // 최단 거리 테이블을 모두 무한으로 초기화
    fill(d, d + 100001, INF);
    
    // 다익스트라 알고리즘을 수행
    dijkstra(start);
    
    // 모든 노드로 가기 위한 최단 거리를 출력
    for (int i = 1; i <= n; i++)
    {
        // 도달할 수 없는 경우, 무한(INFINITY)이라고 출력
        if (d[i] == INF) {
            cout << "INFINITY" << '\\n';
        }
        // 도달할 수 있는 경우 거리를 출력
        else {
            cout << d[i] << '\\n';
        }
    }
}

시간 복잡도

O(N * logN)

 

반응형

'코딩 낙서' 카테고리의 다른 글

카카오기출 - 순위 검색  (0) 2023.06.23
알고리즘 - 인덱스 트리(Index Tree)  (0) 2023.06.21
알고리즘 - 크루스칼(Kruskal)  (0) 2023.06.21
알고리즘 - 누적합(Prefix Sum)  (0) 2023.06.21
알고리즘 - Union & Find  (0) 2023.06.21
반응형

개념

가장 적은 비용으로 모든 노드를 연결하기 위해 사용하는 알고리즘이다. 최소 비용 신장 트리를 만들기 위한 대표적인 알고리즘으로 흔히 여러개의 도시가 있을 때 각 도시를 도로를 이용해 연결하고자 할 때 비용을 최소로 하기 위해 실제로 적용되는 알고리즘이다.

노드 = 정점 = 도시

간선 = 거리 = 비용

일단 모든 노드를 최대한 적은 비용으로 연결 시켜야하기 때문에 간선 정보를 오름차순으로 정렬 한 후 비용이 적은 간선부터 차근차근 그래프에 포함시킨다. 단 이때 사이클을 형성하게 될 경우 간선을 포함하지 않는다.

 

조건

  1. 간선 정보를 오름차순으로 정렬
  2. 사이클이 형성되지 않게 연결

사용하기 좋은 경우

  1. 모든 노드를 최소 비용으로 연결할 경우
  2. 연결되어있는 그룹의 수를 구하는 경우 → 크루스칼 알고리즘으로 다 연결 한 후 최상단 부모의 개수가 그룹의 수이다.

구현 방법

  1. 비용, 출발, 도착의 정보를 갖는 노드들을 비용을 기준으로 오름차순 정렬하기
typedef pair<int, int> pii;
for(int i = 0; i < m; i++) { //a: 출발지점, b: 도착지점, c: 비용
        scanf("%d%d%d", &a, &b, &c);
        v.push_back(pair<int, pii>(c, pii(a,b)));
    }
    int p = 0;
    sort(v.begin(), v.end()); //비용 기준으로 정렬
  1. 최상단 부모 찾기
int parent[10001];

int findParent(int child) {
    if(parent[child] == 0) {
        return child;
    }
    return parent[child] = findParent(parent[child]);
}

parent 배열의 인덱스는 자기 자신을 나타내고 값은 자신의 부모를 나타낸다. 값이 0일경우 부모가 존재하지 않는 것으로 최상단 노드를 의미하기 때문에 값이 0일때를 찾아서 return 한다.

  1. 부모 자식 관계 설정하기, 최소 비용 구하기
int unionSet(pair<int, pii> xy) {
    int xp = findParent(xy.second.first); //출발 지점의 부모 찾기
    int yp = findParent(xy.second.second); //도착 지점의 부모 찾기
    
    if(xp == yp) return xp; //부모가 같으면 이미 연결되어 있는 것이므로 종료
    else { //부모가 다르면 서로 다른 선에 연결되어 있기 때문에 한 쪽의 부모를 다른 쪽 부모에 연결
        cost[xp] += cost[yp] + xy.first; //연결 후 최상단 노드의 비용을 더해줌
        parent[yp] = xp; //한 쪽의 최상단 부모를 다른 쪽 최상단 부모로 설정
    }
    return xp; //새로운 연결선의 최상단 노드
}

부모가 같으면 이미 연결되어있는 상태이고 다르면 서로의 최상단 부모를 연결해준다.

전체 코드

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
typedef pair<int, int> pii;
int n, m, a, b, c, answer;

vector<pair<int, pii>> v;

int parent[10001];
int cost[10001];

int findParent(int child) {
    if(parent[child] == 0) {
        return child;
    }
    return parent[child] = findParent(parent[child]);
}

int unionSet(pair<int, pii> xy) {
    int xp = findParent(xy.second.first);
    int yp = findParent(xy.second.second);
    
    if(xp == yp) return xp;
    else {
        cost[xp] += cost[yp] + xy.first;
        parent[yp] = xp;
    }
    return xp;
}

int main(int argc, const char * argv[]) {
    scanf("%d", &n);scanf("%d", &m);
    for(int i = 0; i < m; i++) {
        scanf("%d%d%d", &a, &b, &c);
        v.push_back(pair<int, pii>(c, pii(a,b)));
    }
    int p = 0;
    sort(v.begin(), v.end());
    for(int i = 0; i < v.size(); i++) {
        p = unionSet(v[i]);
    }
    answer = cost[p];
    printf("%d", answer);
    
    return 0;
}

시간복잡도

O(logN)

반응형
반응형

개념

말 그대로 구간의 누적의 합을 구하는 알고리즘이다. 배열에 값을 저장하고 하나씩 더해가는 방식은 O(n^2)의 시간 복잡도를 갖는다. 하지만 누적합 알고리즘을 사용한다면 O(n)으로 시간복잡도를 줄일 수 있다. 보통 누적합은 부분 합을 구하기 위해서 사용하는데 만약 a부터 b까지의 합을 구한다고 하면 먼저 누적합을 만들고, b번째 요소에서 a-1번째 요소를 빼주면 구할 수 있다.

사용 하면 좋은 경우

  1. 리스트에 일정 구간의 값의 합을 구할 때
  2. 리스트에 일정 구간에 값을 넣어야 할 경우(시작과 끝 부분에 값 넣어놓고 누적합)

사용 방법

  1. 구간의 합 구하기
import itertools

a = [3,2,1,6,8,4]
result = list(itertools.accumulate(a))

print(result)

🖨️ [3, 5, 6, 12, 20, 24]

  1. 부분 합 구하기
import itertools

a = [3,2,1,6,8,4]
start = 3
end = 5
acc = list(itertools.accumulate(a))

result = acc[end] - acc[start-1]

🖨️ 18

누적합을 우선 구한 후 마지막 부분의 누적합 값에서 시작부분 전의 누적합을 빼서 부분 합을 구할 수 있다,

시간 복잡도

  • O(N)
반응형
반응형

개념

그룹을 지을 때 사용할 수 있는 알고리즘이다. 처음에 자기 자신을 부모로 설정하고 조건에 따라 부모를 설정한다. Find는 자신의 최상위 부모를 찾는 역할을 한다. Union은 두 변수의 부모가 다르다면 하나의 최상위 부모를 다른 하나의 최상위 부모의 자식으로 만들어 두개의 그룹이 합쳐지는 기능을 수행한다.

  • Union by Rank : 트리가 균형이 맞도록 한다. 각 집합에 대해 이 집합을 나타내는 트리의 높이를 rank 변수에 저장한다. 그리고 두 집합을 합칠 때 rank가 작은 집합을 rank가 큰 집합 아래에 붙힌다.
  • Path Compression : 경로 압축(path compression)은 find 과정 가운데 경로 상의 모든 점들을 곧바로 루트 정점에 연결하는 방법이다. 이렇게 하면 위 그림과 같은 구조로 시간 복잡도가 훨씬 줄어들게 된다.

조건

  • Cycle 구조가 생기면 안된다. 따라서 Union은 서로의 부모가 다를때만 해야한다.

사용하기 좋은 경우

  1. 서로 중복되지 않는 부분 집합들로 나눌 때
  2. 그룹의 수를 구할 때

구현 방법

  1. Find
parent = [x for x in range(10)] # 자기 자신이 부모로 초기화

def find_parent(x, parent):
	if parent[x] == x: # x가 최상위 부모
			return x
	#x의 부모중 최상위 부모 찾기
	parent[x] = find_parent(parent[x], parent)
	return parent[x]

  1. Union
def union_parent(a, b, parent):
	pa = find_parent(a)
	pb = find_parent(b)
	if pa == pb :
		pass
	elif pa < pb : # 더 큰애가 부모가 되게 설정
		parent[pa] = pb
	else:
		parent[pb] = pa

시간 복잡도

  • O(M)+O(Mlog⋆N)+O(Nlog⋆N)=O((M+N)log⋆N)
  • (M : find 연산 수, N : 트리가 바뀌는 횟수)
반응형

'코딩 낙서' 카테고리의 다른 글

알고리즘 - 크루스칼(Kruskal)  (0) 2023.06.21
알고리즘 - 누적합(Prefix Sum)  (0) 2023.06.21
알고리즘 - 이진 탐색(이분 탐색)  (0) 2023.06.21
[LINUX] 기본 명령어 정리  (0) 2023.06.20
Linux  (0) 2023.06.14
반응형

개념

이진 탐색이란 데이터가 정렬돼 있는 배열에서 특정한 값을 찾아내는 알고리즘이다. 배열의 중간에 있는 임의의 값을 선택하여 찾고자 하는 값 X와 비교한다. X가 중간 값보다 작으면 중간 값을 기준으로 좌측의 데이터들을 대상으로, X가 중간값보다 크면 배열의 우측을 대상으로 다시 탐색한다. 동일한 방법으로 다시 중간의 값을 임의로 선택하고 비교한다. 해당 값을 찾을 때까지 이 과정을 반복한다.

https://blog.hexabrain.net/246 참고

 

알고리즘 2-2강. 탐색 알고리즘 - 이진 탐색(Binary Search)

[탐색 알고리즘 강좌] 데이터를 찾아보자! 이진 탐색(Binary Search) 이번에는 순차 탐색에 이어 이진 탐색(Binary Search)에 대해 알아보도록 할텐데, 이 '이진 탐색(Binary Search)'이 왜 이진인지 짐작이 가

blog.hexabrain.net

조건

  • 수들이 오름차순 또는 내림차순으로 정렬 되어 있어야 한다.
  • 원하는 값을 찾으면 종료한다. (종료 조건1) → 값을 찾음
  • 왼쪽값이 오른쪽 값보다 커지면 종료한다. (종료조건2) → 값이 없음

사용 하면 좋은 경우

  1. 리스트에서 값을 찾을 때 시간을 단축해야 하는 경우
    • list에서 find() 함수를 사용하거나 반목문으로 값을 찾을 시 O(N)의 시간이 필요하기 때문에 이진 탐색을 사용하면 시간 효율성을 증가 시킨다.
  2. 조건에 맞는 최소 또는 최대값을 찾아야 하는 경우
    • 이러한 경우에는 index를 left, right로 두지 않고 left = 가장 작은 값, right = 가장 큰 값 으로 설정하여 배열에서의 위치가 아닌 조건에 맞는 값을 구 할 수 있도록 한다.

구현 방법

기본 이진 탐색

  1. 반복문
#include <iostream>
#include <vector>

using namespace std;

int BinarySearch(vector<int> num, int target) {
    int left = 0, right =(int) num.size(), mid = 0;
    sort(num.begin(), num.end()); //숫자 오름차순 정렬
    //num : {1, 2, 4, 5, 15, 56, 123, 125, 199, 3215}
    while(left <= right) { //종료 조건
        mid = (left + right) / 2;
        if(num[mid] == target) {// target을 찾았을 때
            return mid;
        }
        else if(num[mid] > target) { //target보다 클 때 -> 왼쪽 수들을 확인
            right = mid - 1;
        }
        else { //target보다 작을 때 -> 오른쪽 수들을 확인
            left = mid + 1;
        }
    }
    return -1;
}

  1. 재귀 함수
#include <iostream>
#include <vector>

using namespace std;
//재귀 함수는 num을 정렬 해서 함수 호출
int RecurBinarySearch(vector<int> num, int target, int left, int right) {
    if(left > right) return -1; //종료 조건
    int mid = (left + right) / 2;
    if(num[mid] == target) { //target을 찾았을 때
        return mid;
    }
    else if(num[mid] > target) { // target보다 클 때
        return RecurBinarySearch(num, target, left, mid-1);
    }
    else { //target보다 작을 때
        return RecurBinarySearch(num, target, mid+1, right);
    }
}

int main(int argc, const char * argv[]) {
    vector<int> num {1,5,2,199,56,3215,125,123,15,4};
    sort(num.begin(), num.end());
    int left = 0, right = (int)num.size();
    cout << RecurBinarySearch(num, 199, left, right) << endl;
    return 0;
}

UpperBound

목표값보다 큰 값이 처음 발견되는 곳 찾기

int UpperBound(vector<int> num, int target) {
    int left = 0, right = (int) num.size(), mid = 0;
    sort(num.begin(), num.end());
    int ans = 0;
    while(left <= right) {
        mid = (left + right) / 2;
        if(num[mid] <= target) { // 목표보다 작거나 같으면 오른쪽 보기
            left = mid + 1;
        }
        else { // 목표보다 크면 답의 후보로 두고 왼쪽 보기
            ans = mid;
            right = mid - 1;
        }
    }
    return ans;
}

LowerBound

목표값보다 작은 값이 처음 발견되는 곳 찾기

int LowerBound(vector<int> num, int target) {
    int left = 0, right = (int) num.size(), mid = 0;
    sort(num.begin(), num.end());
    int ans = 0;
    while(left <= right) {
        mid = (left + right) / 2;
        if(num[mid] >= target) { //목표보다 크거나 같으면 왼쪽 보기
            right = mid - 1;
        }
        else { // 목표보다 작으면 답의 후보로 두고 오른 쪽 보기
            ans = mid;
            left = mid + 1;
        }
    }
    return ans;
}

결과

int main(int argc, const char * argv[]) {
    vector<int> num {1,5,2,199,56,3215,125,123,15,4};
    sort(num.begin(), num.end());
    int left = 0, right = (int)num.size();
    for(int i = 0; i < num.size(); i++) {
        cout << num[i] << " ";
    }
    cout << endl;
    cout << "재귀 : " << RecurBinarySearch(num, 199, left, right) << endl;
    cout << "반복문 : " << BinarySearch(num, 199) << endl;
    cout << "UpperBound : " << UpperBound(num, 199) << endl;
    cout << "LowerBound : " << LowerBound(num, 199) << endl;
    return 0;
}
1 2 4 5 15 56 123 125 199 3215
재귀 : 8
반복문 : 8
UpperBound : 9
LowerBound : 9

시간 복잡도

  • O(logN)
반응형

'코딩 낙서' 카테고리의 다른 글

알고리즘 - 크루스칼(Kruskal)  (0) 2023.06.21
알고리즘 - 누적합(Prefix Sum)  (0) 2023.06.21
알고리즘 - Union & Find  (0) 2023.06.21
[LINUX] 기본 명령어 정리  (0) 2023.06.20
Linux  (0) 2023.06.14
반응형

안녕하세요. 오늘은 개발자 자기소개서 2편, 자소서 작성하기 시작하겠습니다. 1편은 하기 링크에서 참고해주시면 감사하겠습니다.

https://nakco.tistory.com/entry/%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A1%9C-%EC%B7%A8%EC%97%85%ED%95%98%EA%B8%B0-%EC%9E%90%EA%B8%B0%EC%86%8C%EA%B0%9C%EC%84%9C-1%ED%8E%B8

 

개발자로 취업하기 - 자기소개서 1편

자기소개서 1편 - 시작하기 안녕하세요. 여태까지는 가볍게 SPEC UP 할 수 있는 자격증, 교육에 대해서 다뤘었는데요. 이번에는 취업의 시작이라고 할 수 있는 자기소개서에 대해서 다뤄보겠습니

nakco.tistory.com

 

모든 개발자가 그런것은 아니지만, 저는 글을 굉장히 못쓰고 써본적도 거의 없습니다... 그래서 처음에 쓸 때 정말 막막했고 많은 사람들의 것을 찾아보며 참고하면서 썼는데, 그러다 보니 너무 평범한 자기소개서가 됐었고, 저의 강점을 잘 나타내지도 못했던 것 같습니다. 따라서 이번 포스팅을 보고 그대로 하려고 하지 말고, 꼭 자신에게 맞게 변형할 수 있는 방법에 대해 생각해보시길 권합니다.

 

자기소개서 2편 - 작성하기

이전 포스팅을 보았다면, 어느정도 무슨 내용을 적을지 구상을 하셨을 것이라고 믿습니다. 그렇다면 해당 내용들을 어떻게 작성해야할까요? 많은 개발자 분들이 사실 글을 쓰는데 익숙치 않을 것이기 때문에, 정말 막막할 수 있습니다. 하지만 거창하게 쓸 필요 없습니다. 있는 그대로, 간결하고 정확하게 필요한 정보만을 넣는 것이 좋은 자기소개서라고 생각합니다. 좋은 자기소개서를 쓰기 위해서는 꼭 해야할 것과, 하지 말아야할 것이 있습니다.

 

꼭 하지 말아야 할 것

1. 추상적인 표현

추상적인 표현을 쓰면 안된다는 것은 여러분 중 대부분이 알고 있을 것입니다. 하지만 다른 사람들의 자기소개서를 보다보면 추상적인 표현이 굉장히 많습니다. 추상적인 표현을 사용하게 되면, 신뢰도가 떨어지고, 자소서의 칸만 차지하여 정작 써야할 내용은 못쓰게 될 수 있습니다. 간단한 예시를 들어보겠습니다.

 

예시) 저는 복학을 한 후, 꾸준히, 남들보다 열심히 공부하여 성적 향상을 이뤄냈습니다.

 

자기소개서를 쓸때 흔히 쓰는 추상적인 표현이 바로 꾸준히, 열심히, 성실히 등입니다. 예시 문장을 보시면 어떤 느낌이 드시나요? 꾸준히, 열심히? 내가 그걸 어떻게 믿지? 뭐 어떻게 했다는거지? 라는 생각이 드시지 않으신가요? 그렇게 느껴지시지 않으시더라도, 위와 같은 표현은 자제하시길 바랍니다. 그렇다면 어떻게 쓰는게 좋을까요? 마찬가지로 간단한 예시를 들어보겠습니다.

 

예시) 저는 복학을 한 후, 전공 지식이 거의 없었기에 진도를 따라가기 조차 버거웠습니다. 하지만 포기하지 않았고, 개발 언어에 대한 지식이 먼저 필요하다고 느껴, 언어책을 사서 먼저 익히고 ~~ , 어떤 방법으로 공부를 하였고 ~~ 성적이 잘 나왔고 ~~ 이를 통해 자신감이 생겨 과 수석까지 했습니다.

 

이런 식으로 추상적인 표현보다는 구체적인 자신의 경험을 토대로 쓰시는 것을 추천드립니다. 

 

2. 뻔한 내용

컴퓨터 공학과를 나왔다면 사실 학교에서 배운 수업, 프로젝트 등의 내용은 거의 비슷할 것입니다. 공모전이나, 대회, 인턴같은것을 하지 않았다면 모두 비슷하겠지만, 그렇다고해서 남들 다 갖고 있는 이런 내용들을 적으면 변별력이 떨어질 것입니다. 비슷한 수업을 들었어도, 비슷한 프로젝트를 했어도 모두 갖고있는 경험은 다를 것입니다. 예시를 통해 보도록 하겠습니다.

 

예시) 저는 프로젝트 수업에서, 팀장을 맡아 ~~를 주제로 프로젝트를 진행했습니다. 팀원들을 잘 이끌어 성공적으로 프로젝트를 마무리했고 좋은 성적을 받았습니다.

 

 저는 동기들이나 취업스터디를 했던 다른 개발자분들의 자소서를 엄청 많이 봤었는데, 대부분의 사람들이 위와같은 내용이 있었습니다. 누구나 다 팀장이였고, 누구나 다 성공적으로 프로젝트를 마쳤습니다. 저보다 훨씬 더 많은 자소서를 본 취업담당자 분들은 해당 내용을 보고 어떤 느낌이 들까요? 지루할 것이고, 또한 신뢰도 가지않고 변별력도 없을 것입니다.  똑같은 경험이더라도, 자신만의 경험을 녹이는 것이 중요하다고 생각합니다.

 

예시) 저는 ~~를 주제로 프로젝트를 진행했습니다.  해당 프로젝트는 어떤 기술을 사용해야했는데 해당 기술에 대한 정보가 거의 없어 난처했습니다. 해당 기술을 파헤치기 위해 하루동안 공식 영문 기술서를 모두 읽어보았고 ~~ 

 

이런식으로 자신의 구체적인 경험을 적어보는 것이 어떨까요?

 

3. 거짓말

네, 물론 어느정도의 과장은 필요하다고 생각합니다. 하지만 지나친 거짓말은 화를 부르게 되어 있습니다. 운이좋게 잘 포장하여 자기소개서를 합격 할 순 있지만, 저희에겐 면접이 남아있습니다. 면접에서 해당 거짓말을 걸리게 되면 어떻게 될까요? 혹은 거짓말한 부분을 답변하기 위해, 안그래도 없는 시간을 쪼개어 준비를해야하고 자신의 강점에 집중할 수 없게 됩니다. 자신이 없는 부분은 과감히 버리길 바랍니다.

 

예시) 저는 시스템프로그래밍 수업을 들으며 어셈블리어를 익혔고, 이러한 경험을 통해 프로그래밍을 좀 더 효율적으로 하는 습관을 갖게 되었습니다.

 

저는 실제로 위의 내용과 비슷하게 자소서에 쓴 적이 있습니다... 내용 자체가 거짓말은 아니였으나, 어셈블리어는 2학년 때 배우고 한번도 접한적이 없었고, 저런 습관도 없었습니다. 면접 전에 갑자기 어셈블리어를 공부하려니 시간이 많이 모자랐고 결국 질문하지 않기를 바라며 대충 공부하고 면접에 참여했습니다. 결국 면접관님이 어셈블리에 대해 물었고, 대답을 못하자 힌트까지 주면서 대답을 요구했지만, 저는 대답하지 못했습니다. 정말 쪽팔렸고, 면접 분위기도 그대로 망쳤습니다. 여러분은 저와같은 실수를 하지 마시고, 면접까지 생각하며 자기소개서를 작성하시길 바랍니다.

 

 

꼭 해야할 것

1. 경험 위주로 작성

 앞에서도 말씀드렸지만, 변별력있는 자소서를 쓰기 위해서는 모든 내용을 자신의 경험을 토대로 작성해야합니다. 그래야 자소서 읽는 분도 재밌게 보고 남들과는 다른 자소서가 탄생할 것 입니다. 모든 내용이 자신의 경험으로 작성되야 신뢰도가 높아집니다. 모든 문항에 자신의 경험을 1~2개 정도 넣어주시길 바랍니다.

 

예시)  회사에 지원한 동기에 대해 기술하세요.

 저는 이 회사에 이 직무에서는 ~~역량이 필요하다고 생각합니다. 학교를 다닐 때 ~ 수업에서 ~를 했던 경험이 있습니다. 이 경험이 이 회사에 제가 지원한 직무에 적합하다고 생각합니다. 해당 경험으로 저는 ~~를 얻었고, 이를 회사에 ~~에 어떻게 사용하여 도움이 되겠습니다.

 

간략하게 적었지만 위와같이 자신의 경험으로 적어야합니다. 이 회사는 어느분야 1등 기업이고~, 요새 ~~를 하고 있고, 뭐 이런것도 쓸 수 있겠지만, 쓰더라도 자신의 경험은 꼭 한두개 넣길 바랍니다.

 

2.  두괄식으로 작성

두괄식이란, 글의 중심 내용을 맨 앞에서 한번 언급해주는 것입니다. 즉 질문에 대한 답변을 먼저 한 후에 이야기를 풀어나가는 것입니다. 위의 질문에서 안좋은 답변을 보여드리겠습니다.

 

나쁜 예시)  회사에 지원한 동기에 대해 기술하세요.

 저는 ~프로젝트를 진행했던 경험이 있습니다. 해당 프로젝트는 ~~였는데 저는 거기서 ~~를 했고 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

이러한 경험이 회사에 도움이 될 것이라 생각합니다.

 

내용 자체는 자신의 경험을 토대로 썼기 때문에 나쁘지 않습니다. 하지만, 읽는 사람 입장에서 생각해보면 '나는 지원 동기를 물었는데 얘는 왜 갑자기 지 프로젝트 얘기를 하고 있어' 라고 생각할 것입니다. 따라서 해당 내용을 적기 전에 앞에서 한문장 정도로 전체 내용을 요약해서 먼저 작성한 후 스토리를 이어나가길 바랍니다.

 

좋은 예시)  회사에 지원한 동기에 대해 기술하세요.

 해당 직무에서는 ~를 하고있는 것으로 알고 있고, 저의 ~프로젝트 경험이 도움이 될 것이라 생각했습니다. . 해당 프로젝트는 ~~였는데 저는 거기서 ~~를 했고 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

이러한 경험을 바탕으로 ~~를 하며 같이 성장해 나가겠습니다.

 

3.  소제목 쓰기

소제목도 두괄식과 비슷한 개념이지만 훨씬 더 어렵습니다. 전체 내용을 요약하면서도, 뻔하면 안되고, 흥미를 유발해야합니다. 인사과 사람들은 많게는 수만장의 자기소개서를 읽어야 할텐데, 소제목이 없거나 딱봐도 지루해보이면 읽기 싫을 것입니다. 따라서 흥미를 유발하는 것이 중요합니다. 

 

나쁜 예시) 회사에 지원한 동기에 대해 기술하세요. 

[한국 1등 기업]

[꾸준한 공부, 지속적인 성적 향상]

[자연어 처리 모델링 구현 경험]

[도전 정신]

.

.

.

 

위의 소제목들을 보고 어떤 생각이 드시나요? '한국 1등 기업', '도전 정신'. 네 물론 해당 소제목을 보고 대충 어떤 내용이겠구나 생각 할 순 있을것입니다. 하지만, 너무 뻔하지 않나요? 흥미롭지가 않습니다. '자연어 처리 모델링 구현 경험' 이건 어떤가요? 인사과분들은 대부분 컴공이 아닐 확률이 큽니다. 그렇다면 저 소제목만 봐도 아주 한숨이 푹푹 쉬어질 것입니다. 흥미가 매우 떨어지겠죠. 그렇다면 어떻게 쓰는 것이 좋을까요?

 

좋은 예시) 회사에 지원한 동기에 대해 기술하세요. 

 

[최고 지향, 목표 달성을 위한 나만의 원칙]  

[꼴등에서 일등으로, 성장하며 배운 것]

[새로운 자연어 처리 모델로 내가 이뤄낸 것]

[한 번의 성공을 위한 네 번의 도전]

 

나쁜 예시와 비교했을 때 호기심을 자극하고, 더 흥미롭다는 것을 느낄 수 있을 것입니다. 저는 본문 쓰는 것보다 소제목 쓰는 것이 훨씬 오래 걸렸었는데, 소제목이 시작이니만큼 중요도를 깊게 고민하고 작성해보시길 바랍니다.

 

마무리

이번 포스팅에서는 크게 꼭 해야할 것과, 하지 말아야할 것에 대해 다뤄봤습니다. 이 외에도 맞춤법 검사, 목표 3분할 (초기 / 중기 / 장기) 등등 여러가지 꿀팁이 많지만 분량 상 여기서 마무리하겠습니다. 저는 취업을 한 후에도 동기나 후배들의 취업을 돕기 위해 자소서 첨삭을 많이 해줬었는데, 제가 정답은 아니지만 그래도 필요하신 분들은 댓글 남겨주시면 최선을 다해 도움드리겠습니다. 개발자, 취준생 여러분 모두 화이팅입니다.

반응형
반응형

Linux에서 자주 쓰는 기본 명령어에 대해 간단히 정리해보겠습니다.
우선 ls, cd, mkdir, rm, cp, mv 등의 명령어를 사용하여 파일 시스템을 탐색하고 파일 및 디렉토리를 관리하는 방법에 대해 알아보았습니다.

다음은 일반적으로 사용되는 몇 가지 기본 명령어입니다.

ls: 현재 디렉토리의 파일 및 디렉토리 목록을 표시합니다.
cd: 디렉토리를 변경합니다.
mkdir: 새로운 디렉토리를 생성합니다.
rm: 파일이나 디렉토리를 삭제합니다.
cp: 파일이나 디렉토리를 복사합니다.
mv: 파일이나 디렉토리를 이동하거나 이름을 변경합니다.
pwd: 현재 작업 중인 디렉토리의 경로를 표시합니다.
cat: 파일의 내용을 터미널에 표시합니다.
grep: 텍스트에서 패턴을 찾습니다.
chmod: 파일이나 디렉토리의 권한을 변경합니다.

리눅스 명령어는 다양한 옵션을 제공하여 보다 구체적인 작업을 수행할 수 있다고합니다. 같이 한번 알아보도록 하겠습니다!

각 명령어마다 다양한 옵션이 있으며, 옵션은 주로 하이픈(-)과 함께 사용됩니다. 명령어의 옵션을 사용하면 명령어의 동작을 변경하거나 추가 기능을 활용할 수 있습니다.

여기에 몇 가지 일반적으로 사용되는 명령어와 해당 명령어의 일부 옵션을 예시로 나열하겠습니다:

ls (목록 보기):
-l: 자세한 파일 정보 표시
-a: 숨겨진 파일 및 디렉토리 포함하여 모두 표시
-h: 파일 크기 등을 보기 좋게 사람이 읽을 수 있는 형식으로 표시

cd (디렉토리 변경):
..: 상위 디렉토리로 이동
-: 이전 작업 디렉토리로 이동

mkdir (디렉토리 생성):
-p: 중간 디렉토리가 없으면 자동으로 생성

rm (파일 및 디렉토리 삭제):
-r: 디렉토리와 그 내용을 재귀적으로 삭제 (주의: 신중히 사용)

cp (파일 복사):
-r: 디렉토리와 그 내용을 재귀적으로 복사 (디렉토리 복사 시)

mv (파일 이동 및 이름 변경):
-i: 대상 파일이 이미 존재할 경우 덮어쓰기 전 확인

cat (파일 내용 표시):
-n: 줄 번호 표시

grep (패턴 검색):
-i: 대소문자 구분 없이 검색
-r: 디렉토리 내의 파일에서 재귀적으로 검색

chmod (파일 권한 변경):
u: 소유자(user)에 대한 권한 변경
g: 그룹(group)에 대한 권한 변경
o: 기타 사용자(other)에 대한 권한 변경
+: 권한 추가
-: 권한 제거
=: 권한 설정

반응형

'코딩 낙서' 카테고리의 다른 글

알고리즘 - 크루스칼(Kruskal)  (0) 2023.06.21
알고리즘 - 누적합(Prefix Sum)  (0) 2023.06.21
알고리즘 - Union & Find  (0) 2023.06.21
알고리즘 - 이진 탐색(이분 탐색)  (0) 2023.06.21
Linux  (0) 2023.06.14
반응형

자기소개서 1편 - 시작하기

안녕하세요. 여태까지는 가볍게 SPEC UP 할 수 있는 자격증, 교육에 대해서 다뤘었는데요. 이번에는 취업의 시작이라고 할 수 있는 자기소개서에 대해서 다뤄보겠습니다. 처음 취업을 준비한다면 자기소개서를 어떻게 써야할지 매우 답답할텐데, 제가 경험하고 느꼈던 꿀팁들을 공유하겠습니다.

 저는 처음에 자소설 닷컴 사이트에서 IT 관련 공고 중 제가 들어봤던 기업은 모두 자기소개서를 작성했었습니다. 총 20개 정도를 넣었고, 처음에 쓴 SK 하이닉스를 제외하고는 모두 서류에서 합격했었습니다. 지금부터 제가 생각하는 자소서에서 중요한 점들에 대해 말씀드리겠습니다.

 

https://jasoseol.com/

 

일 잘하는 당신의 파트너, 자소설닷컴 | 대기업, 공기업 채용 플랫폼

대기업 채용, 공기업 채용부터 자기소개서, 합격자 데이터랩, 스마트 채용 스케줄러, 실시간 정보 공유 익명 채팅방 솔루션으로 빠른 취업, 채용, 이직, 취직 성공하세요.

jasoseol.com

 

포트폴리오 만들기

자기소개서 쓰기도 바쁜데 포트폴리오를 만들으라니 황당 할 수 있지만, 포트폴리오를 만드는 것은 필수적입니다. 포트폴리오에는 자신의 SPEC, 개발 경험, 수상 경험, 코딩 Skill 등등 자신이 했던 모든 활동, 스킬들에 대해 정리해놓아야 합니다. 포트폴리오를 만들어 놓음으로서 자신을 더 잘 정리할 수 있고, 이를 통해 자기소개서를 쓰는데 많은 도움이 될 것입니다. 특히 네이버나 카카오 같은 경우는 포트폴리오를 제출하는 부분이 따로 있고, 면접때 자기소개서보다 해당 포트폴리오를 보고 질문을 많이 했었습니다. 갑자기 만들려면 쉽지 않으니 취업을 시작할때부터 미리미리 만들어 두는 것을 추천드립니다. 저는 Notion 이라는 템플릿을 이용했는데, 다른 사람들의 포트폴리오 양식을 복제하여 사용할 수 있고, 글을 적기에도 편리한 부분이 많아서 선택했습니다.

 

 다음 사진은 제 포트폴리오인데, 저는 2달가량 만들었고, 매일 저녁에 1시간정도 시간을 빼어 작성했습니다. 필요하신분들은 댓글을 달아주시면 사이트 공유해드리도록 하겠습니다. 

 

기업 핵심 가치 파악하기

 만약 포트폴리오를 작성했다면, 자신의 경험, 기술 등에 대해 잘 파악이 된 상황 일 것입니다. 그렇다면 해당 경험과 기술을 어느 문항에 적을지를 선택해야합니다. 자기소개서를 작성할때 주의해야할 점이 절대 생각나는대로 먼저 쓰기 시작하면 안된다는 것입니다. 

 첫번째로 기업의 가치를 파악합니다. 도전적인 기업이라면, 자신의 경험중 도전을 나타낼 수 있는 경험을, 성장을 추구하는 기업이면 꾸준히 성장했던 자신의 경험을, IT 전문 기업이라면 자신의 개발 Skill을 중점적으로 적는 것이 좋을 것입니다. 기업의 핵심 가치는 기업 공식 홈페이지에서 회사소개 화면으로 가면 보통 나와있습니다. 포트폴리오에 있는 자신의 경험들에 이러한 기업들의 핵심가치들을 연관지어 놓는다면, 다른 기업의 자기소개서를 쓸 때에도 큰 도움이 될 것입니다.

 

경험 / 기술 우선순위 정리하기

 자신의 경험 / 기술들의 가치에 대해 정리했다면, 이제는 자신의 최대 강점이 무엇인지 우선순위를 두어야합니다. 남들 다 하는 경험은 아무런 의미가 없습니다. 나만의 경험, 나의 강점을 살려 전달하는 것이 무엇보다 중요합니다. 특별한 경험이 없다고 해서 걱정하실 필요 없습니다. 당신만의 경험은 무조건 존재할테니까요. 해당 경험에 어떤 의미를 부여하고, 그 경험을 통해 무엇을 얻었는지를 정리해야합니다. 저같은 경우에는 가장 높은 우선순위를 공모전 수상, 학점 이 두가지로 뽑았고, 모든 자기소개서에 해당 내용을 넣었습니다. 

 학점 같은 경우에는 제가 1학년땐 공부를 안해서 거의 꼴찌였는데, 그 이후로 학점을 상당히 높이 올렸습니다. 해당 부분을 성장성과 꾸준함 등으로 어필하였습니다.

 공모전은 팀단위로 나갔던 공모전이였고, AI 관련이였습니다. 이러한 부분을 살려 팀워크와 도전 정신을 키워드로 삼았습니다. 대부분의 기업이 성실, 성장, 팀워크, 도전정신 같은 비슷한 핵심 가치를 두기 때문에 이를 바탕으로 자신의 높은 우선순위의 경험을 두는 것이 시작하기 편할 것입니다.

 

마무리

자기소개서는 무작정 시작부터하는 것이 아니라 자기 자신에 대해서 먼저 정리하는 것이 저에겐 큰 도움이 됐습니다. 처음에 하이닉스 자기소개서를 작성할땐 그냥 문항을 보고 바로 작성했었는데, 제가 뭘 쓰는지도 잘 이해가 안되고, 무엇을 적어야할지도 바로바로 생각하면서 쓰니, 계속 바꾸게 되고 결국엔 맞춤법 검사도 하지 못하고 제출했습니다. 여러분은 저와 같은 실수를 하지말고 꼭! 포트폴리오를 미리 작성해두고, 기업의 핵심 가치를 파악하고, 경험의 우선순위를 두어 핵심가치와 연결하여 자기소개서 작성을 시작하길 바랍니다. 이번 포스팅은 여기서 마치도록하고, 다음편에서 자기소개서2편 - 작성하기로 돌아오겠습니다. 취준생, 개발자 여러분 항상 응원하겠습니다.

반응형

+ Recent posts