일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 1차원 DP
- 2차원 dp
- 99클럽
- @BeforeAll
- @BeforeEach
- @Builder
- @Entity
- @GeneratedValue
- @GenericGenerator
- @NoargsConstructor
- @Query
- @Table
- @Transactional
- Actions
- Amazon EFS
- amazon fsx
- Android Studio
- ANSI SQL
- ApplicationEvent
- assertThat
- async/await
- AVG
- AWS
- Azure
- bind
- builder
- button
- c++
- c++ builder
- c03
- Today
- Total
기록
99클럽 코테 스터디 21일차 TIL C++ 정렬, 람다함수 본문
문제 소개
오늘 풀어본 문제는 LeetCode 문제 중 하나로, 각 행을 내림차순 정렬한 후 열별로 가장 큰 값을 합산하는 문제입니다. 이 문제를 풀면서 자연스럽게 정렬과 람다 함수를 어떻게 활용할 수 있는지에 대해 학습할 수 있었습니다.
이 글에서는 문제 풀이 과정에서 사용한 정렬 및 람다 함수에 대해 설명하고, 기존 풀이를 어떻게 더 간결하게 개선할 수 있는지 보여드리겠습니다.
문제 풀이: 열별로 최대값을 더하기
이 문제의 핵심은 다음과 같습니다:
- 각 행을 내림차순으로 정렬: 각 행에서 가장 큰 값을 쉽게 선택할 수 있도록 내림차순 정렬합니다.
- 각 열에서 가장 큰 값을 선택하여 합산: 열별로 가장 큰 값을 찾아 결과에 더하는 방식입니다.
전체 코드 풀이
우선 기본적인 풀이 방법을 살펴보겠습니다. C++에서 각 행을 내림차순으로 정렬한 뒤, 각 열에서 최대값을 찾아 더하는 방식으로 구현합니다.
#include <vector>
#include <algorithm>
#include <iostream>
class Solution {
public:
int deleteGreatestValue(std::vector<std::vector<int>>& grid) {
// 각 행을 정렬 (내림차순)
for (auto& row : grid) {
std::sort(row.begin(), row.end(), std::greater<int>());
}
int ans = 0;
int numColumns = grid[0].size();
// 각 열의 최대값을 선택
for (int col = 0; col < numColumns; ++col) {
int maxValue = 0;
for (auto& row : grid) {
// 각 행의 현재 열에서 값을 가져옴
maxValue = std::max(maxValue, row[col]);
}
ans += maxValue;
}
return ans;
}
};
이 코드에서는 각 행을 내림차순으로 정렬한 뒤, 각 열의 최대값을 더해주는 방식으로 ans
를 계산하고 있습니다.
람다 함수란?
람다 함수는 간단하고 임시적인 함수 로직을 작성할 때 유용합니다. C++에서는 C++11부터 람다 함수를 지원하기 시작했으며, 자바스크립트(JavaScript), Python, 자바(Java) 등 다양한 언어에서도 흔히 사용되고 있습니다.
람다 함수의 기본 구조
람다 함수의 기본적인 구조는 다음과 같습니다:
C++ 람다 함수
[capture](parameters) -> return_type {
// 함수 내용
};
capture
: 외부 변수(스코프)를 람다 내부로 가져오는 방법.[=]
: 외부 변수를 값으로 캡처합니다.[&]
: 외부 변수를 참조로 캡처합니다.[var]
: 특정 변수만 선택적으로 캡처할 수 있습니다.
parameters
: 함수의 매개변수.return_type
: 반환 타입 (생략 가능, 자동으로 추론됩니다).
JavaScript 람다 함수 (화살표 함수)
JavaScript에서는 람다 함수를 화살표 함수라고 부르며, 다음과 같은 구조를 가집니다:
(parameters) => {
// 함수 내용
};
- 매개변수가 하나일 경우 괄호를 생략할 수 있습니다.
- return 문이 하나인 경우 중괄호와 return 키워드를 생략할 수 있습니다.
예시:
const add = (a, b) => a + b;
Java 람다 함수
Java에서는 Java 8부터 람다 표현식을 지원하며, 기본적인 구조는 다음과 같습니다:
(parameters) -> {
// 함수 내용
};
- 람다는 주로 함수형 인터페이스와 함께 사용됩니다. 함수형 인터페이스는 하나의 추상 메소드만을 가지는 인터페이스를 의미합니다.
예시:
(int a, int b) -> a + b;
람다는 Stream API
와 같은 Java의 함수형 프로그래밍을 지원하는 다양한 기능과 결합하여 사용됩니다.
capture
: 외부 변수(스코프)를 람다 내부로 가져오는 방법.[=]
: 외부 변수를 값으로 캡처합니다.[&]
: 외부 변수를 참조로 캡처합니다.[var]
: 특정 변수만 선택적으로 캡처할 수 있습니다.
parameters
: 함수의 매개변수.return_type
: 반환 타입 (생략 가능, 자동으로 추론됩니다).
기존 코드의 개선: 람다 함수 사용하기
위에서 작성한 기존 코드를 개선해 보겠습니다. 이번에는 람다 함수와 STL 함수를 사용하여 코드를 더욱 간결하고 직관적으로 변경해 보았습니다.
개선된 코드
람다 함수와 STL 알고리즘(std::for_each
, std::max_element
)을 활용하여 각 행을 정렬하고 열의 최대값을 선택하는 방식으로 개선한 코드입니다:
#include <vector>
#include <algorithm>
#include <iostream>
class Solution {
public:
int deleteGreatestValue(std::vector<std::vector<int>>& grid) {
// 각 행을 정렬 (내림차순)
std::for_each(grid.begin(), grid.end(), [](std::vector<int>& row) {
std::sort(row.begin(), row.end(), std::greater<int>());
});
int ans = 0;
int numColumns = grid[0].size();
// 각 열의 최대값을 선택
for (int col = 0; col < numColumns; ++col) {
// 반복자를 이용해 각 열에서 최대값 선택
auto maxRowIt = std::max_element(
grid.begin(), grid.end(),
[col](const std::vector<int>& row1, const std::vector<int>& row2) {
return row1[col] < row2[col];
});
// 반복자에서 값을 추출하여 합산
ans += (*maxRowIt)[col];
}
return ans;
}
};
개선된 코드 설명
std::for_each
와 람다 함수 사용: 각 행을 내림차순으로 정렬할 때,std::for_each
와 람다를 사용하여 코드를 더 간결하게 만들었습니다.std::max_element
와 람다 함수 사용: 각 열의 최대값을 선택할 때, 람다를 이용한 커스텀 비교 연산을 통해 직관적으로 열의 최대값을 찾아낼 수 있도록 했습니다.
람다 함수의 장점과 단점
람다 함수는 다음과 같은 장점을 가집니다:
- 간결함: 코드가 짧고 직관적이기 때문에 반복적인 로직을 간단하게 작성할 수 있습니다.
- 지역성: 지역적으로 사용되는 간단한 로직을 쉽게 함수화할 수 있습니다.
- 캡처: 외부 변수에 쉽게 접근할 수 있어 유연한 코드를 작성할 수 있습니다.
- STL과의 결합: STL 함수(
std::for_each
,std::sort
,std::max_element
)와 결합하면 더욱 간결하고 유지보수하기 쉬운 코드를 작성할 수 있습니다.
하지만 람다 함수에도 단점이 있습니다:
- 특정 경우에는 람다 함수의 사용이 직접
for
문을 사용하는 것보다 성능 면에서 좋지 않을 수 있습니다.for
문은 람다에 비해 명확하고 컴파일러 최적화가 용이할 수 있기 때문에, 반복 횟수가 많거나 성능이 중요한 코드에서는for
문이 더 효율적입니다. - 복잡한 로직을 처리할 때는 가독성이 떨어질 수 있습니다.
- 캡처의 사용이 잘못될 경우, 의도치 않은 동작이나 메모리 누수와 같은 심각한 문제가 발생할 수 있습니다. 특히 참조로 캡처할 때는 캡처된 변수가 람다의 생명 주기보다 먼저 소멸될 수 있으므로 주의가 필요합니다. 동작이나 메모리 문제가 발생할 수 있습니다.
오늘의 회고
이번 학습을 통해 C++에서 람다 함수를 어떻게 활용할 수 있는지, 특히 STL 알고리즘과 결합했을 때 얼마나 코드가 간결해질 수 있는지를 배울 수 있었습니다.
- 코드의 간결성과 유연성: 람다 함수는 코드의 간결성을 높이기 위해 매우 유용한 도구입니다. STL과 결합하여 불필요한 반복을 줄이고, 더 직관적인 코드를 작성할 수 있습니다.
- 적절한 사용: 그러나, 람다 함수의 남용은 코드 가독성을 해칠 수 있기 때문에 복잡한 로직보다는 간단한 작업을 처리할 때 사용하는 것이 좋습니다.
- STL 활용의 중요성:
std::for_each
와std::max_element
같은 STL 함수는 반복문을 대체하여 가독성 높은 코드를 작성하는 데 큰 도움이 됩니다.
'코딩테스트 > cpp' 카테고리의 다른 글
99클럽 코테 스터디 23일차 TIL C++ 우선순위 큐(priority_queue와 multiset), 포인터와 참조변수(*it과 &it) (0) | 2024.11.24 |
---|---|
99클럽 코테 스터디 22일차 TIL C++ DP, LDS, lower_bound (0) | 2024.11.24 |
99클럽 코테 스터디 20일차 TIL C++ Priority Queue과 multiset, std::accumulate (0) | 2024.11.18 |
99클럽 코테 스터디 19일차 TIL C++ priority_queue, 약수탐색(sqrt) (0) | 2024.11.18 |
99클럽 코테 스터디 18일차 TIL C++ max_element (0) | 2024.11.17 |