[알고리즘]기초 코드 작성 요령

모든 내용은 다음 내용을 참고해서 작성되었습니다.

1. STL과 함수인자

함수인자

  • 첫번째, int를 함수 인자로 보내면 값이 복사돼서 넘어갑니다. 그러니까 함수에서 값을 바꾸더라도 main의 변수 t에는 아무런 영향을 주지 않습니다.

  • 두번째, arr[0]이 바뀌게 되는데, func에 int 배열 arr를 인자로 주는게 arr의 주소를 넘겨주는 것이니 arr[0]을 func 함수에서 바꾸면 원본의 값도 자연스럽게 바뀌게 됩니다.

  • 마지막으로, 구조체의 경우에는 int랑 비슷하게 그냥 값이 다 복사되기 때문에 func 함수에서 값을 바꿔도 원본에는 영향을 주지 않습니다.

참조자


C++에서는 포인터외에 해결법이 한 개 더 있는데, 바로 참조자(reference)입니다. swap3 함수를 보면 함수 인자인 a와 b의 type이 int가 아니고, int 뒤에 &가 붙어있는 것을 볼 수 있습니다. 그러니까 a와 b는 int reference인 것입니다.

저렇게 a와 b를 참조자로 만들면 함수 내의 코드에서는 그냥 int를 쓰듯이 tmp에 a를 대입하고, a에 b를 대입하고 하는데 저게 다 원본을 바꾸는 것입니다.

STL(Standard Template Library)

vector

//#include <vector>
vector<int> v(100);
v[20] = 10;
v[60] = -4;

STL을 함수인자로 넘길 때


STL도 구조체랑 비슷하게 함수 인자로 실어 보내면 복사해서 보낸다는 걸 유의하셔야 합니다.

cmp1은 두 vector를 인자로 넘겨받아 idx번째 원소의 값을 비교한 결과를 반환하는 함수입니다. v1, v2를 인자로 실어서 보낼 때 원본으로부터 복사본을 만드는 비용이 발생합니다. v1, v2의 크기가 N이니까 N개의 원소들을 하나하나 복사하는 과정은 O(N)이 듭니다. 그래서 이 함수는 의도하지 않게 시간복잡도가 O(N)이 됩니다.

cmp2에서는 v1, v2의 type을 vector의 reference로 만들었습니다. 그러면 cmp2가 호출될 때 복사본을 따로 만들어내지 않고 참조 대상의 주소 정보만 넘어가기 때문에 시간복잡도는 의도한대로 O(1)이 됩니다.

표준입출력

C: scanf/printf, Cpp: cin/cout

cin << num;
cout >> "hello";

+) scanf/printf에서 단 한 가지 아쉬운 점이라고 한다면, C++ string을 처리할 수가 없습니다. 아시다시피 C에서는 char으로 문자열을 다루는데 사실 char보다 C++ string이 월등하게 편합니다. 그래서 scanf/printf를 쓰면서도 C++ string을 활용하고 싶으면 일단 char*으로 입력을 받고 string으로 형 변환을 해서 원하는 작업을 다 끝낸 후에 c_str() 메소드를 이용해 출력하면 됩니다.

cin/cout 입출력으로 인한 시간초과 방지

ios::sync_with_stdio(0);
cin.tie(0);

scanf/printf와 다르게 cin/cout은 입출력으로 인한 시간초과를 막기 위해서 위 두 명령을 실행시켜야 합니다. 이걸 안해두면 입/출력의 양이 많을 때 시간초과가 날 수 있습니다.

  • sync_with_stdio(0) : C++ stream만 쓸거면 동기화를 끊어버려서 프로그램 수행 시간에서 이득을 챙길 수 있습니다. 대신 절대 cout과 printf를 섞어쓰면 안됩니다. 섞어쓰면 순서가 꼬이게 됩니다.
  • cin.tie(0) : cin 명령을 수행하기 전에 cout 버퍼를 비우지 않도록 하는 코드

endl 금지

endl은 개행문자("\n")를 출력하고 출력 버퍼를 비워라는 명령입니다. 앞에서도 얘기했지만 어차피 저지는 프로그램이 종료될 때 출력이 어떻게 생겼는지를 가지고 채점을 진행하니까 중간 중간 버퍼를 비우라고 명령을 줄 필요가 전혀 없습니다. 줄바꿈이 필요하면 endl 말고 그냥 개행문자(\n)를 출력하시면 됩니다.

2. 코드 작성팁

코딩테스트와 개발은 다르다.

코딩테스트에서는 내가 헷갈리지 않는 범위 안에서 어떻게든 타이핑을 아끼는게 최고입니다. 그래서 저는 오른쪽 위와 같이 짤 것입니다.

코딩테스트의 목표는 남이 알아볼 수 있는 클린코드를 작성하는게 아닙니다. 어떻게든 제한된 시간 안에 정답을 받아야합니다. 그렇기 때문에 코드를 거의 책에 예제로 실어도 될 정도로 깔끔하게 만들기 위해 노력하기 보다는, 좀 더럽더라도 내가 빠르게 짤 수 있는 방식으로 빠르게 구현하는게 훨씬 더 중요합니다.

사실 문제 상황을 보면 배열 자체가 필요없기 때문에 저는 더 줄여서 오른쪽 아래와 같이 짤 것입니다.

출력 맨 마지막에 공백 혹은 줄바꿈이 추가로 있어도 상관이 없다.

디버거는 굳이 사용하지 않아도 된다.

구현을 끝냈는데 예제에 대해 답이 올바르게 나오지 않을 때 코드의 어디가 잘못됐는지 알고 싶어서 디버거를 이용하는 경우가 간혹 있는데 사실 코딩테스트의 코드는 끽해야 100줄 전후 길이일 것입니다.

그럴 때 디버거를 켜면 뭔가 꼬이고 늪에 빠져드는 것과 같은 느낌을 받을 때가 있어서 차라리 중간 변수를 보고 싶으면 cout이나 printf로 출력을 찍어서 확인하고 디버거는 굳이 사용을 안하는 것을 권장합니다. 하지만 이건 권장일 뿐이고 아무리 생각해도 디버거를 쓰는게 낫다 싶으면 쓰셔도 상관은 없습니다.

좋은 웹페이지 즐겨찾기