코딩테스트
[level 1] 행렬의 덧셈 - 12950
https://school.programmers.co.kr/learn/courses/30/lessons/12950
[level 1] 행렬의 덧셈 - 12950 - 풀이코드
더보기
#include <string>
#include <vector>
#include <iostream>
using namespace std;
vector<vector<int>> solution(vector<vector<int>> arr1, vector<vector<int>> arr2) {
vector<vector<int>> answer(arr1.size(), vector<int>(arr1[0].size())); // -> 중요
// vector<vector<int>> answer; -> 초기화를 안해주면 에러 발생
// signal: illegal instruction (core dumped) -> 잘못된 인덱스 접근, 초기화되지 않은 변수 사용 등
for (int i = 0; i < arr1.size(); ++i) {
for (int j = 0; j < arr1[i].size(); ++j) {
answer[i][j] = arr1[i][j] + arr2[i][j];
}
}
return answer;
}
[level 1] 직사각형 별 찍기 - 12969
https://school.programmers.co.kr/learn/courses/30/lessons/12969
[level 1] 직사각형 별찍기 - 12969 - 풀이코드
더보기
#include <iostream>
#include <vector>
using namespace std;
int main(void) {
int a;
int b;
cin >> a >> b;
for(int i = 0; i < b; i++) {
for(int j = 0; j < a; j++) {
cout << "*";
}
cout << endl;
}
return 0;
}
[level 1] 최대공약수와 최소공배수 - 12940
https://school.programmers.co.kr/learn/courses/30/lessons/1294
[level 1] 최대공약수와 최소공배수 - 12940 - 풀이코드
더보기
#include <string>
#include <vector>
using namespace std;
vector<int> solution(int n, int m) {
vector<int> answer(2);
for (int i = 1; i <= n + m; i++) {
if (n % i == 0 && m % i == 0) {
answer[0] = i;
answer[1] = (n / i) * (m / i) * i;
}
}
return answer;
}
RValue vs LValue
RValue란?
오른쪽에만 올 수 있는 값
즉, 임시로 만들어지는 값이거나, 한 번 쓰고 사라지는 값이다.
LValue란?
왼쪽에 올 수 있는 값
즉, 변수처럼 이름이 있고, 메모리에 저장된 값이다.
int x = 10; // 여기서는 x는 LValue, 10은 RValue이다.
x = 20; // LValue는 값이 바뀔 수 있다.
int y = x + 5; // x + 5의 결과도 RValue이다. → 이름이 없는 임시 값
RValue는 주소가 없는 물건, 상점에서 받은 영수증처럼 잠깐 쓰고 버리는 것(임시로 만들어지는 값)
LValue는 주소가 있는 물건, 집처럼 주소가 있어서 찾아갈 수 있다.(메모리에 저장되어 있는 값)
C++에서는 RValue를 LValue에 넣을 수 있지만, LValue를 RValue처럼 사용할 때는 조심해야 한다.
ios_base::sync_with_stdio(false);
- C++ 표준 입출력(stream)(cin, cout)과 C의 표준 입출력(scanf, printf)은 기본적으로 동기화(sync)되어 있다.
- 이 동기화는 C와 C++ 입출력을 함께 사용할 때 데이터 순서를 보장하지만, 동기화를 유지하면 성능이 떨어질 수 있다.
- 위에 있는 ios_base::sync_with_stdio(false) 메서드는 이 동기화를 해제해서 성능을 개선한다.
- 하지만, 이 설정 이후에는 C++의 cin, cout과 C의 scanf, printf를 혼용하면 예상치 못한 동작이 발생할 수 있다.
cin.tie(NULL);
- 기본적으로 cin과 cout은 연결되어 있어서, cin을 호출하면 자동으로 cout의 버퍼가 비워져 출력 순서를 보장한다.
- 이 연결을 해제하면 cout의 버퍼를 자동으로 비우지 않아서 성능이 더 빨라질 수 있다.
- 하지만, 출력이 지연될 수 있으므로 순서가 중요하다면 주의해야 한다.
cout.tie(NULL);
- cout은 원래 연결이 없기 때문에 이 설정은 필요하지 않다.
set vs multiset
C++의 STL에서 제공되는 컨테이너로, 정렬된 상태로 데이터를 저장하지만 몇 가지 차이점이 있다.
공통점
- 정렬된 상태로 저장
- 두 컨테이너 모두 삽입된 데이터가 항상 정렬된 상태를 유지합니다.
- 기본적으로 오름차순 정렬이지만, 사용자 정의 비교자를 통해 정렬 기준을 변경할 수 있습니다.
- 탐색 속도
- set과 multiset 모두 내부적으로 이진 탐색 트리(주로 레드-블랙 트리)로 구현되어, 삽입, 삭제, 탐색의 시간 복잡도는 O(log N)입니다.
- 중복된 데이터에 대한 탐색
- find(), lower_bound(), upper_bound()등의 함수 사용이 가능합니다.
차이점
특징 | set | multiset |
중복 허용 여부 | 중복 요소를 허용하지 않음 | 중복 요소를 허용 |
요소 삽입 | 중복된 값을 삽입하려고 하면 무시 | 동일한 값을 여러 번 삽입 가능 |
삽입 함수 반환값 | insert()는 std::pair를 반환: 삽입 여부를 알려준다. | insert()는 iterator를 반환: 삽입된 위치 |
요소 삭제 | 특정 값을 삭제하면 해당 값이 모두 삭제 | 특정 값을 삭제하면 한 번에 한 개씩 삭제 |
#include <iostream>
#include <set> // -> set, multiset를 사용하기 위해 <set> 선언
using namespace std;
int main() {
set<int> s;
multiset<int> ms;
// 1부터 4까지 값을 두 번씩 추가하는 로직
for (int i = 1; i < 4; i++) {
s.insert(i);
s.insert(i);
ms.insert(i);
ms.insert(i);
}
cout << "set" << endl;
for (auto i : s) {
cout << i << " ";
}
cout << endl;
// set
// 1 2 3
cout << "multiset" << endl;
for (auto j : ms) {
cout << j << " ";
}
cout << endl;
cout << "ms.count(2) : " << ms.count(2) << endl; // -> 특정 원소의 빈도수계산 가능
// multiset
// 1 1 2 2 3 3
// ms.count(2) : 2
}
주요 사용 사례
- set: 중복 요소를 허용하지 않는 집합 데이터가 필요할 때
- 고유한 ID저장, 중복 제거 기능 구현
- multiset: 중복 데이터가 허용되며, 정렬된 상태가 유지되어야 할 때
- 빈도 기반 데이터 처리(카운팅), 정렬된 중복 데이터 저장