[코딩 테스트 합격자 되기 C++ 편] 04 코딩 테스트 필수 문법

2024. 12. 27. 10:28·책 정리/코딩 테스트 합격자 되기 C++ 편

04-1 빌트인 데이터 타입

C++에서 많이 사용하는 빌트인 데이터 타입은 정수형(int), 부동소수형(float or double), 논리형(boo), 문자형(char)가 있다. 그리고 같은 타입의 기본 자료형 변수들을 연속된 메모리에 저장할 수 있는 배열(array)도 있다.

정수형

양의 정수, 음의 정수, 0을 포함한다. 정수형은 더하기,빼기,곱하기,나누기와 같은 사칙 연산을 수행할 수 있다.

 

정수형 변수 선언 및 산술 연산

int a = 13;
int b = 4;

a + b;	// 덧셈, 17
a - b;	// 뺄셈, 9
a * b;	// 곱셈, 52
a / b;	// 나눗셈, 몫인 3
a % b;	// 나눗셈, 나머지인 1
-a;	// 부호 반전, -13

 

정수형 비교 연산

int a = 13;
int b = 4;

a == b;	// 같은 값인지 비교
a != b;	// 같지 않은 값인지 비교
a > b;	// 왼쪽 값이 더 큰지 비교
a < b;	// 오른쪽 값이 더 큰지 비교
a >= b;	// 왼쪽 값이 더 크거나 같은지 비교
a <= b;	// 오른쪽 값이 더 크거나 같은지 비교

정수형 비트 연산

int a = 13;
int b = 4;

a & b; // AND 연산
a | b; // OR 연산
a ^ b; // XOR 연산

부동소수형

부동소수형 사칙 연산

double d = 2.5;
float f = 1.5f;

sizeof(d);	// 8
sizeof(f);	// 4
d + f;		// 4.0
d - f;		// 1.0
d * f;		// 3.75
d / f;		// 1.66667

C++에서 부동소수형은 float와 double이 있다. 이 둘의 다른 점은 유효한 소수점의 자릿수이다.(정밀도가 차이난다)

double은 8바이트, float은 4바이트이므로 double의 유효한 소수점의 자릿수가 더 많다. double은 15자리, float은 7자리이다.

코딩 테스트에는 이 정도만 기억해도 크게 지장은 없다.

 

형 변환

C++은 변수를 선언하는 순간 타입이 결정된다. 형 변환은 타입이 서로 다른 변수간 연산을 하여 발생하는 암시적 형 변환(implicit conversion)과 사용자가 임의로 변경하는 명시적 형 변환(explicit conversion)이 있다.

int i = 65;
float f = 5.2f;

// 암시적 형 변환(메모리가 더 큰 float으로 변환됨, 이후 double로 변환된 값이 대입됨)
double d = i + f;
cout << d << endl;

// 명시적 형 변환(double -> int)
cout << static_cast<int>(d) << endl;

// 명시적 형 변환(int -> char)
cout << static_cast<char>(i) << endl;

 

문자열

문자열은 string 표준 헤더를 추가하여 사용할 수 있고, 문자열 작업을 쉽고 효율적으로 할 수 있는 다양한 메서드를 제공한다.

 

문자열 선언 및 초기화

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string str1;
    string str2 = "Hello, World!";
    string str3(str2);
    string str4(str2, 0, 5);
    string str5(10, '*');
    
    return 0;
}

 

문자열 찾기

특정 문자나 문자열을 찾을 때는 find() 메서드를 사용한다. find() 메서드는 다음과 같이 오버로딩되어 있다.

  • find(찾으려는 문자열)
  • find(찾으려는 문자열, 탐색 시작 위치)

find() 메서드를 이용해서 찾으면 해당 문자열이 시작하는 인덱스를 반환하고, 찾지 못하면 string::npos를 반환한다.

그리고 탐색하는 문자열의 길이가 N일 때, find() 메서드는 O(N)으로 동작한다.

 

문자열 추가, 수정

문자열의 추가는 '+' 연산자 혹은 '+='연산자를 사용한다.

특정 문자를 수정하려면 '[ ]' 연산자를 활용해서 임의 접근 후 수정하거나 replace() 메서드를 활용할 수 있다.

replace() 메서드의 시간 복잡도는 대체할 문자열의 길이가 N일 때, O(N)이다.

04-2 STL

cplusplus.com의 표준 C++ 라이브러리 정리를 캡쳐한 모습

STL

STL(Standard Template Library) : C++에서 제공하는 템플릿 기반의 표준 라이브러리

템플릿(Template) : C++에서 함수나 클래스를 구현할 때 어떤 타입에서도 동작할 수 있도록 하는 문법

따라서 STL 역시 특정 타입에 한정하지 않고 라이브러리를 사용할 수 있다.

STL은 크게 데이터를 담을 수 있는 컨테이너(Container), 데이터를 처리하고 제어할 수 있는 여러 가지 알고리즘(Algorithm), 컨테이너에 접근 및 순회할 수 있게 하는 반복자(Iterator)로 이루어져 있다.

 

STL과 자주 사용하는 필수 문법

STL과 자주 사용하는 문법이니 아래 내용은 간단히 익힐 필요가 있다.

 

상수 레퍼런스

C++에서는 함수의 인수로 값을 전달할 때 값을 복사한다.(Call by Value)

이는 함수가 호출될 때마다 함수의 인수로 값이 전달되면서 복사하는 비용이 들게 된다.

함수의 인수로 STL 컨테이너 같은 객체 혹은 구조체 등을 전달하게 되면 이 복사 비용이 성능에 영향을 줄 수 있다.

#include <iostream>

using namespace std;

void modify(int value)
{
    value = 10;					// 새 공간의 value 변경
    cout << "주소 : " << &value << endl;	// 주소 : 0x7fff74f16e5c
    cout << "값 : " << value << endl;
}

int main()
{
    int value = 5;
    cout << "주소 : " << &value << endl;	// 주소 : 0x7fff74f16e74
    cout << "값 : " << value << endl;
    modify(value);
    cout << "값 : " << value << endl;
    
    return 0;
}

위와 같이 새로운 공간에서 값을 변경하기 때문에 원본의 값이 변경되는 결과를 원하지 않는다면 다른 방식을 택해야 한다.

또한, '크기가 1,000만인 정수형 배열을 포함한 객체'와 같이 규모가 큰 객체를 함수의 인수로 넘길 때는 굳이 객체 전체를 복사하지 않고 레퍼런스를 활용해서 넘기기도 한다.(Call by Reference)

레퍼런스는 &라는 문법을 사용한다. 이를 활용하면 변수 자체를 복사하지 않고 참조자를 통해 변수에 접근하고 수정할 수 있다.

#include <iostream>

using namespace std;

void modify(int& value)
{
    value = 10;				//main()의 value값 자체 변경
    cout << "주소 : " << &value << endl;// 주소 : 0x7fff6272fc34
    cout << "값 : " << value << endl;	// 값 : 10
}

int main()
{
    int value = 5;
    cout << "주소 : " << &value << endl;// 주소 : 0x7fff6272fc34
    cout << "값 : " << value << endl;	// 값 : 5
    modify(value);
    cout << "값 : " << value << endl;	// 값 : 10
    
    return 0;
}

 

참조값 전달과 주소값 전달의 공통점과 차이점은?

참조값(레퍼런스 사용)이 아니라 주소값을 전달(포인터 사용)하여 함수 호출 시 전달된 인수를 수정하는 방식도 있다.

  • 공통점
    1. 실 인수값을 변경할 수 있다.
  • 차이점
    1. 참조값을 전달하면 참조 변수와 참조 대상 변수의 주소값이 일치하므로 메모리의 값을 읽고 쓰기 위한 추가 문법이 필요 없다.
    2. 주소값을 전달하면 주소값을 전달받은 변수의 주소와 실제 변수의 주소값이 다르다. 그래서 주소값을 받기 위한 포인터 변수를 사용해야 한다.(즉, 포인터 문법이 필요하게 된다.)

정리하면, 두 방식은 '실 인수값을 변경한다.'라는 목적에는 차이가 없으나, 포인터 문법을 사용할 것인가에 대한 차이가 있다.

 

추가적으로 포인터 문법을 사용하면 다음과 같은 2가지의 불편함이 생긴다.

  1. 포인터를 사용하면 의도하지 않은 예외가 발생할 수 있다.(ex) 잘못된 주소 접근)
  2. 포인터 문법은 간접 참조를 하므로 주소를 얻을 때와, 값을 얻을 때의 문법이 다르다. 따라서, 상대적으로 포인터의 문법이 좀 더 복잡하다.

 

auto문

STL은 어떤 타입이라도 사용할 수 있도록 잘 구현되어 있다. 하지만, 타입이 복잡해지면 사용할 때 실수하기 쉽고 코드가 길어지므로 가독성이 떨어질 수 있다. 이럴 때, auto 키워드를 사용하면 변수의 타입을 자동으로 추론하기 때문에 코드가 더 간결해지고 유지 관리하기 쉬워진다.

#include <map>
#include <iostream>

void PrintMap(const std::map<int, int>& Numbers)
{
    std::map<int, int>::const_iterator IterBegin = Numbers.begin();
    auto IterEnd = Numbers.end();
    
    while(IterBegin != IterEnd)
    {
        std::cout << IterBegin->first << " " << IterBegin->second << std::endl;
        ++IterBegin;
    }
}

int main()
{
    std::map<int, int> Numbers;
    Numbers.insert(std::pair<int, int>(1, 1));
    Numbers.insert(std::pair<int, int>(2, 2));
    Numbers.insert(std::pair<int, int>(3, 3));
    Numbers.insert(std::pair<int, int>(4, 4));
    Numbers.insert(std::pair<int, int>(5, 5));

    PrintMap(Numbers);    
    
    return 0;
}

 

범위 기반 반복문

배열이나 컨테이너의 모든 원소를 순회할 때 사용한다. 기본 반복문보다 구현이 쉽고, 가독성이 좋다.

for (타입 변수명 : 컨테이너)
{
    // 코드
}

STL 컨테이너와 사용할 때는 값을 수정할 필요가 없으므로 auto 대신 상수 레퍼런스를 적용한 const auto&를 사용해도 된다.

컨테이너를 반복문에서 사용하거나 함수의 인수로 넘길 때는 항상 복사하는 비용을 고려해야 한다. 수정해야 할 때는 레퍼런스를, 수정하지 않아야 할 때는 상수 레퍼런스 적용을 고려해보면 좋다.

 

반복자

반복자(Iterator)는 C++에서 컨테이너(벡터, 셋, 맵 등)의 종류와 관계없이 원소들을 순회하고 접근할 수 있게 해준다.

모든 컨테이너에 같은 방식으로 원소를 순회하거나 접근할 수 있으므로 컨테이너가 바뀌더라도 반복자로 접근하는 코드는 수정할 필요가 없게 된다(유지보수&재사용성 향상)

 

순방향 반복자

순방향 반복자(Forward Iterator)는 컨테이너의 원소를 순차적으로 순회할 수 있게 해준다. begin()과 end()가 쌍으로 나오

는 경우가 많다.

 

begin() : 컨테이너의 첫 원소 위치를 나타낸다.

end() : 컨테이너의 마지막 원소 위치의 다음을 나타낸다.

 

컨테이너를 순회하는 과정이 있는 STL은 다음과 같은 2가지 특징을 지닌다.

  1. 대부분 시작 위치와 끝 위치를 받고, 이때 시작 위치는 begin(), 끝 위치는 end()로 넘기는 경우가 많다. 이는 begin()부터 end() 바로 직전까지 순회하라는 의미이다.
  2. 특정 원소를 탐색하거나 조건에 맞는 원소를 찾는 STL의 경우에는 해당 원소를 찾으면 위치를 반환하고, 그렇지 않으면 end()를 반환한다.

역방향 반복자

컨테이너의 끌에서 시작으로 이동하고 기본적인 개념은 순방향 반복자와 같다. 순방향 반복자와 다른 점은 ++연산자를 쓸 때, 역방향 반복자는 이전 원소로 위치가 바뀐다는 점이다.

역방향 반복자는 rbegin()과 rend()를 사용한다.

 

rbegin() : 맨 마지막 원소의 위치

rend() : 맨 처음 원소의 바로 직전 위치

 

04-3 STL의 컨테이너

STL의 컨테이너는 데이터를 저장하는 객체를 말한다.

책에서는 벡터, 셋, 맵, 우선순위 큐를 소개한다. 실제 STL은 더 많은 컨테이너를 지원하지만, 책은 코딩 테스트에 꼭 필요한 STL에만 집중한다.

컨테이너를 공부할 때는 데이터를 저장한다는 특성도 중요하지만, 어떤 방식으로 저장하고 접근하는지를 아는 게 중요하다.

배열처럼 임의 접근을 해야 한다면 벡터를, '키-값' 형태로 저장한다면 맵을 선택해야 함을 유념하자.

잘못된 컨테이너 선택은 구현 코드 분량의 증가와 알고리즘의 저효율을 야기한다.

 

벡터

벡터(Vector)는 배열과 매우 유사한 컨테이너이다. 데이터를 순차적으로 저장하고, 인덱스를 통해서 특정 위치의 원소에 쉽게 접근할 수 있다. 문제를 풀 때 배열 대신 벡터를 사용하는 경우가 많다.

 

벡터의 선언 및 초기화

벡터를 사용하려면 #include <vector>로 벡터 헤더를 포함해야 한다.

STL은 템플릿 기반으로 구현되어 있기에 초기화 코드에서 int 대신, char, double, string, 사용자 정의형 모두 사용할 수 있다.

 

벡터의 원소 변경

벡터에서 원소를 변경하는 방법은 여러 가지가 있지만 '[ ]'연산자를 활용하는 방법만 알면 충분하다. 방법은 배열과 완전히 같고 시간 복잡도는 O(1)이다.

 

벡터의 삽입과 삭제

벡터의 내부는 배열로 구성되어 있다. 따라서 맨 뒤에서는 삽입, 삭제 연산을 효율적으로 할 수 있지만, 맨 앞에서 원소를 삽입, 삭제 연산을 할 때는 매우 비효율적이다. 맨 앞의 원소를 삽입, 삭제하면 뒤의 원소들을 한 칸씩 이동해야 하기 때문이다. 벡터에 데이터가 N개 있으면 해당 연산은 시간 복잡도가 O(N)이 된다. 만약 문제 해결 시에 맨 앞에 원소를 삽입, 삭제하는 일이 빈번하다면 다른 컨테이너로 해결할 수는 없는지 고민해보는 게 좋다. 맨 앞의 원소를 효율적으로 삽입, 삭제할 수 있는 자료구조는 덱(Deque)이 있으며 시간 복잡도는 O(1)이다.

 

벡터로 맨 뒤에 원소를 삽입 삭제 : push_back() / pop_back()

 

내부가 배열로 구성되어 있으므로 맨 뒤의 삽입, 삭제는 저장된 다른 값에 전혀 영향을 미치지 않는다. 따라서 이 두 메서드의 시간 복잡도는 O(1)이다.

 

셋

셋(Set)은 중복을 허용하지 않고, 저장된 데이터를 자동으로 정렬하는 컨테이너이다. 집합이라고 표현하기도 한다.

 

셋의 선언 및 초기화

셋을 사용하려면 #include <set>으로 셋 헤더를 포함시켜야 한다.

 

선언 : set<자료형> 변수명

초기화 : set<자료형> 변수명 = {값1, 값2, ... , 값n};

다른 셋을 사용하여 초기화 : set<자료형> 변수명(다른 set의 변수명);

 

셋은 원소를 대입할 때, 동시에 내부에서 정렬을 수행한다. 여기서 정렬이 되었다는 의미는 배열처럼 작은 원소부터 메모리에 순차적으로 저장된다는 의미가 아니라 트리 구조를 통해 정렬 상태를 유지한다는 의미이다.

 

셋에서의 원소 탐색

셋에 특정 원소가 있는지 확인하려면 find()메서드를 사용하면 된다.

만약 찾는 원소가 있으면 원소의 위치를 반환하고 없으면 end 반복자를 반환한다.

셋의 크기가 N일 때, find()메서드의 시간 복잡도는 O(logN)이다.

 

셋의 삽입과 삭제

셋은 모든 삽입, 삭제의 시간 복잡도가 O(logN)이다. 삽입, 삭제 후에도 정렬된 상태를 유지하기 때문이다.

구현할 때 삽입은 insert(), 삭제는 erase()메서드를 활용한다.

이 때, erase()메서드에는 삭제할 원소의 값이 올 수도 있고, 삭제할 원소의 주소가 올 수도 있다.

주의할 점으로는 end 반복자를 사용해서 erase() 메서드를 사용하면 안된다는 점이다.

end 반복자가 가지고 있는 주소가 셋의 마지막 원소의 다음 주소를 가지고 있기 때문이다.

만약 end 반복자를 사용해서 erase()를 호출하면 예외가 발생하게 된다.

 

맵

맵(Map)은 키와 값을 쌍으로 갖는 컨테이너이다. 여기서 키와 값의 쌍을 entry라고 한다. STL에서는 이를 std::pair 타입으로 표현한다. 내부는 균형 이진 탐색 트리로 구성되어 있다. 따라서 항상 키 값을 기준으로 데이터가 자동 정렬된다. N개의 키가 있다면 키를 기준으로 검색, 삽입, 삭제를 하는데 이 때, 시간 복잡도가 O(logN)이다.

추가로 맵의 키값은 중복되지 않고 유일하다는 특징이 있다.

일반적인 배열은 인덱스를 통해 원하는 값을 찾지만 맵은 배열과 같이 정수형 인덱스로 한정되지 않고, 키 자체를 통해 원하는 값을 찾을 수 있다.

 

맵의 선언 및 초기화

맵을 사용하려면 #include <map>을 통해 맵 헤더를 포함시켜야 한다.

맵 선언 : map<키 타입, 값 타입> 변수명;

맵 초기화 : map<키 타입, 값 타입> 변수명 = {{키1 값, 값1 값}, {키2 값, 값2 값}, ... , {키n 값, 값n 값}};

 

맵에서 특정 키에 접근

특정 키에 접근하는 방법으로 다음 2가지가 존재한다.

  • [ ] 연산자 활용하기
  • find() 메서드 활용하기

[ ] 연산자는 표현상 배열과 비슷할 뿐더러 가독성도 좋으므로 많이 활용한다. 단, 배열과 다르게 [ ] 연산자를 통해 접근하려는 키가 맵에 없으면 맵에 현재 키를 추가한다는 점이다. 즉, 맵에 없는 키에 접근하면 오류는 발생하지 않고 새로운 키가 만들어진다. [ ] 연산자의 시간 복잡도는 O(logN)이다.

 

만약 특정 키를 검색할 때, 키가 없고, 맵에 새로운 키를 추가하는 것이 아니라 키가 없는 상태를 유지해야 하면, find() 메서드를 사용하면 된다. find() 메서드는 키가 맵에 있으면 해당 키의 위치를 반환하고, 없으면 end 반복자를 반환한다.

find() 메서드의 시간 복잡도는 O(logN)이다. 각 원소는 pair 객체이므로 멤버 변수로 first와 second를 갖는다. first는 맵의 키 정보를, second는 맵의 값 정보를 담고 있다.

 

맵의 값 변경

맵의 값을 변경할 때는 벡터와 마찬가지로 '[ ]'연산자를 활용한다. 인덱스가 숫자가 아닐 수도 있다는 것만 기억하면 된다.

 

맵의 삽입과 삭제

맵에 원소를 삽입하는 방법은 2가지이다.

  • insert() 메서드를 활용하여 아래의 두 방법으로 원소를 삽입한다. 두 방법 모두 시간 복잡도는 O(logN)이다.
    • insert( make_pair(키, 값) );
    • insert( {키, 값} );

삭제할 때는 erase() 메서드를 사용한다. 인수로 키값 혹은 키의 위치를 넣으면 해당 키 혹은 위치의 원소가 삭제된다. 

인수로 값을 넘길 때의 시간 복잡도는 O(logN), 위치를 넘길 때 시간 복잡도는 O(1)이 된다.

 

정렬되지 않은 셋과 맵

C++ STL의 셋과 맵은 내부 구조가 이진 탐색 트리이기 때문에 정렬 상태를 유지한다. 하지만, 자동으로 정렬되는 것이 무조건 좋은 것만은 아니다. 문제를 풀 때 굳이 필요 없는데 정렬을 하면 성능 저하를 야기시키기 때문이다.

 

이 때, 사용할 수 있는 것이 정렬되지 않은 셋(unordered_set)과 정렬되지 않은 맵(unordered_map)이다.

이 둘은 앞에서 정리한 셋과 맵과 같은 방법으로 사용할 수 있다. 다만, 내부 구조가 이진 탐색 트리가 아닌 해시 기반이기 때문에 데이터를 자동으로 정렬하지 않는다. 따라서 삽입, 삭제, 탐색의 시간 복잡도가 O(1)이다. 최악의 경우 O(N)이지만 이런 경우는 거의 발생하지 않는다.

기존에 제공하는 셋과 맵이 O(logN)이었던 것에 비해 빠르다.

 

정렬되지 않은 셋 사용 시 : #include <unordered_set>

정렬되지 않은 맵 사용 시 : #include <unordered_map>

 

나머지 사용법은 set, map과 동일하다.

04-4 STL의 알고리즘

count() 함수로 횟수 세기

컨테이너 내에서 특정 값이 나타나는 횟수를 센다.

3개의 인수를 받는다. 시작 반복자, 끝 반복자, 그리고 나타나는 횟수를 확인해야 하는 값이다.

시간 복잡도는 범위로 지정한 원소의 개수가 N개일 때, O(N)이다.

 

sort() 함수로 정렬하기

컨테이너를 정렬하는 함수이다. 다음과 같이 오버로딩되어 있다.

  • sort(시작 반복자, 끝 반복자)
  • sort(시작 반복자, 끝 반복자, 비교 함수)

첫 번째는 오름차순으로 정렬을 하고 두 번째는 비교 함수를 기준으로 범위 내 원소를 정렬한다.

sort()함수의 시간 복잡도는 O(NlogN)이다.

 

sort(STL container.begin(), STL container.end()) 가 오름차순 정렬이라면 내림차순으로 하고 싶다면

sort(STL container.rbegin(), STL container.rend())를 사용해서 간단하게 내림차순으로 할 수 있다.

 

next_permutation() 함수로 순열 생성하기

next_permutation()함수는 가능한 모든 순열을 생성한다. 인수는 시작 반복자와 끝 반복자 두 개를 받는다.

순열은 사전 순으로 생성하며 실제 범위 내 원소들의 위치가 변경된다. 가능한 순열이 있으면 true를 반환하며, 더 이상 가능한 순열이 없으면 false를 반환한다.

가능한 모든 순열을 생성할 때 이 함수를 주로 사용하며 while 내에서 함수를 호출하는 패턴이 많다.

데이터가 N개라면 각 순열을 생성할 때 최대 N/2번 만큼 원소의 위치를 맞바꿀 수 있고, 순열은 최대 N!개 있으므로 모든 순열을 생성할 때 연산 횟수를 기준으로 시간 복잡도는 O(N*N!)이다.

 

next_permutation()에서 가능한 모든 순열을 생성하려면 데이터가 사전순으로 정렬된 상태여야 한다. 만약 데이터가 사전순으로 정렬된 상태가 아니라면 정렬을 한 후에 next_permutation()을 호출해야 한다.

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

using namespace std;

int main()
{
    vector<int> v = {1, 2, 3};
    
    do{
    	for(int i : v)
        {
            cout << i << " ";
        }
        cout << endl;
    } while(next_permutation(v.begin(), v.end()));
    
    return 0;
}

 

unique() 함수로 중복 정리하기

unique() 함수는 컨테이너 내 중복되는 원소들을 뒤로 밀어내고 중복되지 않은 원소들만 남겨 새로운 범위의 끝 반복자를 반환한다. 인수는 시작 반복자와 끝 반복자 2개를 받는다. 시간 복잡도는 데이터의 개수가 N개일 때, O(N)이다.

 

binary_search() 함수로 이진 탐색하기

binary_search()함수는 컨테이너에서 주어진 범위 내 원소에 이진 탐색을 수행한다. 인수는 시작 반복자, 끝 반복자, 찾을 값으로 3개를 받는다. 탐색을 수행하고 원소가 있으면 true 없으면 false를 반환한다. 시간 복잡도는 데이터의 개수가 N이면 O(logN)이다.

이진 탐색의 특성상 원소가 이미 정렬되어 있어야 정상 동작한다. 데이터가 이미 정렬되어 있고, 원소를 자주 탐색해야 한다면 이진 탐색이 배열을 순차 탐색하는 것보다 유용하다.(이로 인해, 정렬이 필요하다면 선형 탐색보다 많은 시간 복잡도를 필요로 하게 된다.)

 

max_element(), min_element() 함수로 최댓값, 최솟값 위치 구하기

max_element()와 min_element() 함수는 컨테이너 내에서 최댓값, 최솟값의 위치를 반환한다. 두 함수는 시작, 끝 반복자 2개의 인수를 받는다. 시간 복잡도는 데이터의 개수가 N개일 때, O(N)이다.

 

04-5 함수

함수 정의

C++의 함수는 '반환타입 함수명 (인수1, 인수2, ...)'와 같은 방식으로 정의한다. 만약 반환하는 값이 없다면 반환 타입에 void를 사용하면 된다.

함수 호출

함수를 호출할 때 매개변수가 있으면 func(a, b)와 같이 인수를 함께 전달한다.

 

04-6 코딩 테스트 코드 구현 노하우

조기 반환

조기 반환(Early Return)은 코드 실행 과정이 함수 끝까지 도달하기 전에 반환하는 기법이다.

코드의 가독성을 높여줄 뿐 아니라 예외를 조금 더 깔끔하고 빠르게 처리할 수 있다.

보호 구문

보호 구문(Guard Clauses)은 본격적인 로직을 진행하기 전 예외 처리 코드를 추가하는 기법이다. 예를 들어 조건문을 이용하여 초기에 입력값이 유요한지 검사하고 그렇지 않으면 바로 함수를 종료하는 보호 구문을 쓸 수 있다.

'책 정리 > 코딩 테스트 합격자 되기 C++ 편' 카테고리의 다른 글

[코딩 테스트 합격자 되기 C++ 편] 06 스택  (1) 2024.12.27
[코딩 테스트 합격자 되기 C++ 편] 05 배열  (1) 2024.12.27
[코딩 테스트 합격자 되기 C++ 편] 03 알고리즘의 효율 분석  (1) 2024.12.27
[코딩 테스트 합격자 되기 C++ 편] 02 프로그래머스 완벽 활용 가이드  (3) 2024.12.27
[코딩 테스트 합격자 되기 C++ 편] 01 코딩 테스트 효율적으로 준비하기  (0) 2024.12.27
'책 정리/코딩 테스트 합격자 되기 C++ 편' 카테고리의 다른 글
  • [코딩 테스트 합격자 되기 C++ 편] 06 스택
  • [코딩 테스트 합격자 되기 C++ 편] 05 배열
  • [코딩 테스트 합격자 되기 C++ 편] 03 알고리즘의 효율 분석
  • [코딩 테스트 합격자 되기 C++ 편] 02 프로그래머스 완벽 활용 가이드
DevJoo1120
DevJoo1120
  • DevJoo1120
    Jin's Programming
    DevJoo1120
  • 전체
    오늘
    어제
    • 분류 전체보기 (142)
      • 포트폴리오 (7)
        • Castlevania: Aria of Sorrow.. (7)
        • [UE5] KILL Everything (0)
      • C++ (0)
      • 라이브러리 (1)
      • 다이렉트X11 (0)
      • Unreal Engine (11)
        • Unreal Document (1)
        • 이것 저것 (8)
        • UI (1)
      • 자료구조 및 알고리즘 (0)
      • 책 정리 (3)
        • 코딩 테스트 합격자 되기 C++ 편 (10)
      • 코딩 테스트 (32)
        • 프로그래머스 (32)
      • 스파르타 코딩 언리얼 1기 (9)
        • 특강 (0)
        • C++와 Unreal Engine으로 3D .. (2)
      • TIL(Today I Learned) (63)
      • 영어 공부 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    코딩 테스트 합격자 되기 c++ 편
    프로그래머스
    문자열
    Study
    코딩 테스트
    정리
    스파르타 코딩 클럽
    map
    반복문
    책 정리
    팀 프로젝트
    코딩테스트
    Til
    과제
    정렬
    배열
    C++
    Unreal Engine 5
    WINAPI
    이중 반복문
  • hELLO· Designed By정상우.v4.10.5
DevJoo1120
[코딩 테스트 합격자 되기 C++ 편] 04 코딩 테스트 필수 문법
상단으로

티스토리툴바