erase를 사용할 때는 erase로 반환되는 iterator를 변수에 대입해야 합니다. erase(it)를 했다고 it가 자동으로 갱신되는게 아니라 it = erase(it)로 대입을 해줘야 합니다. erase를 할 경우 iterator 변수는 empty 상태로 변경되기 때문입니다.
Visual Studio에서는 조사식으로 확인할 때 이 iterator의 값이 empty로 표기되지 않고 삭제한 결과에 맞게 자동으로 갱신된 것처럼 표기됩니다.
erase를 하기 전의 상태 it는 nums[1]을 가리키고 있는 상태이며, 조사식에도 it의 [ptr]이 &nums[1]과 같은 것을 볼 수 있습니다.
erase를 하고 난 후의 상태 it도 갱신되고 [ptr]도 &nums[1]의 것과 동일한 것으로 출력됩니다.
하지만 막상 iterator 변수를 참조하려고 하는 순간 런타임 에러가 발생합니다.
Leetcode 문제를 풀다 iterator 사용법을 헷갈려하여 잠시 헤맸던 상황이었고 혹시 저와 같은 문제로 고생 중인 분이 있을 수도 있기에 포스팅으로 남깁니다.
for (auto it = nums.begin() + 1; it != nums.end();)
{
if (*it == *(it - 1))
{
nums.erase(it); // 이러면 it 참조 시 에러 발생
it = nums.erase(it); // it를 계속 사용할 거라면 이렇게.
}
else
{
it++;
}
}
포도주 잔 n과 각 잔에 들어있는 포도주의 양이 주어질 때 최대로 마실 수 있는 포도주의 양을 출력한다. 단, 연속으로 놓여 있는 세 잔을 모두 마실 수는 없다.
테스트 케이스
6 6 10 13 9 8 1
33
6 8 2 0 0 2 8
20
문제 풀이
계단 오르기 문제와 비슷하지만 건너 뛰는 간격에 대한 제한이 없다는 차이가 있다. 즉, 2칸을 건너뛰지 않고 3칸을 건너뛸 수도 있다는 것. 이 때문에 점화식을 만든 후 값을 구하는 것은 계단오르기와 동일하나 dp[i - 2]와 dp[i-3]만 알면 되었던 계단오르기와 달리, dp[i - 3] 대신 dp[0] ~ dp[i - 3] 중에서 가장 큰 값을 알아야 한다. dp 중에서 가장 큰 값을 저장하는 변수를 만들고 새로운 dp 값을 구할 때마다 이 변수에 가장 큰 값을 입력해두는 식으로 진행하면 최대로 마실 수 있는 포도주의 양을 구할 수 있다.
풀이 코드
#include <iostream>
using namespace std;
void BAEKJOON_2156()
{
int n;
cin >> n;
uint32_t max;
if (n == 1)
{
cin >> max;
}
else
{
/*----------배열 할당 및 값 입력-----*/
uint32_t* pt = new uint32_t[n + 1];
uint32_t* dp = new uint32_t[n + 1];
pt[0] = 0;
for (int i = 1; i <= n; i++)
{
cin >> pt[i];
}
/*---------점화식-------------------*/
dp[0] = 0;
dp[1] = pt[1];
dp[2] = pt[1] + pt[2];
max = dp[2] > dp[1] ? dp[2] : dp[1];
uint32_t semiMax = 0;
/*---------값 구하기----------------*/
for (int i = 3; i <= n; i++)
{
semiMax = dp[i - 3] > semiMax ? dp[i - 3] : semiMax;
uint32_t before = dp[i - 2] + pt[i];
uint32_t other = semiMax + pt[i - 1] + pt[i];
dp[i] = before > other ? before : other;
if (dp[i] > max)
{
max = dp[i];
}
}
/*----------배열 할당 해제----------*/
delete[] pt;
delete[] dp;
}
cout << max << endl;
return;
}
아래 세 가지 규칙을 바탁으로 X를 1로 만드는데 필요한 최소한의 연산 횟수를 출력한다. 1. X가 3으로 나누어 떨어지면, 3으로 나눈다. 2. X가 2로 나누어 떨어지면, 2로 나눈다. 3. 1을 뺀다.
테스트 케이스
2
1
10
3
10000
14
문제 풀이
일정 범위까지 점화식을 만들고 점화식을 바탕으로 아래의 내용에 대해 판단한다. 1. m1, m2, m3 변수를 만들고 100만보다 큰 수로 초기화 한다. 2. n % 3 == 0인 경우 [n / 3]의 값을 구해 m1에 저장한다. 3. n % 2 == 0인 경우 [n / 2]의 값을 구해 m2에 저장한다. 4. [n - 1]의 값을 구해 m3에 저장한다. 5. m1, m2, m3의 값을 비교해 가장 작은 값 + 1을 [n]에 저장한다. 6. 1~5를 반복한다.
풀이 코드
#include <iostream>
using namespace std;
void BAEKJOON_1463()
{
int N;
cin >> N;
int* count = new int[N + 1];
count[0] = 0;
count[1] = 0;
for (int i = 2; i <= N; i++)
{
int d3 = 1000001;
int d2 = 1000001;
int m1 = 1000001;
if (i % 3 == 0)
{
d3 = 1 + count[i / 3];
}
if (i % 2 == 0)
{
d2 = 1 + count[i / 2];
}
m1 = 1 + count[i - 1];
count[i] = d3 < d2 ? d3 : d2;
count[i] = count[i] < m1 ? count[i] : m1;
}
cout << count[N] << endl;
delete[] count;
return;
}
계단을 올라갈 때마다 밟을 칸의 점수를 획득한다. 도착지점까지 오르면서 얻을 수 있는 최고 점수를 출력한다. 단, 계단은 한 칸 또는 두 칸 간격으로 올라갈 수 있으며 연속해서 세 개를 밟을 수는 없다.
테스트 케이스
6 10 20 15 25 10 20
75
1 10
10
2 10 20
30
3 10 20 30
50
6 10 15 20 10 25 20
80
문제 풀이
최대 이동 간격이 두 칸이라는 점, 연속해서 세 개의 계단을 밟을 수 없다는 점이 풀이의 핵심이다. N번째 위치에 도달하는 경우는 직전에서 올라오는 경우, 두 칸 전에서 올라오는 경우로 나뉜다. 직전에서 올라오는 경우에는 직전 칸 도달의 최대값을 현재 칸 값에 더하면 되고, 두 칸 전에서 올라오는 경우에는 세 칸 전 도달의 최대값 + 두 칸 전의 계단값에 현재 칸 값을 더하면 된다.
이미지로 표현하면 아래 두 가지 경우 중에 큰 값을 최대값 n에 넣는 것과 같다.
풀이 코드
#include <iostream>
using namespace std;
void BAEKJOON_2579()
{
int N;
cin >> N;
int stairs[301];
int dp[301] = { 0 };
for (int i = 1; i <= N; i++)
{
cin >> stairs[i];
}
/*-----------------점화식 및 계산------------------*/
dp[1] = stairs[1];
dp[2] = stairs[1] + stairs[2];
for (int i = 3; i <= N; i++)
{
int left = stairs[i] + dp[i - 2];
int right = stairs[i] + stairs[i - 1] + dp[i - 3];
dp[i] = left > right ? left : right;
}
/*-----------------출력--------------------*/
cout << dp[N] << endl;
return;
}
RGB거리와 비슷한 방식으로 풀 수 있는 문제다. 문제에서는 최대값만을 구하면 되므로 최하층에서 최상층으로 좁혀간 뒤 최상층에서 계산한 결과 값을 바로 출력해주면 된다. 최상층에서 최하층으로 넓혀가면서 구할 경우 최하층 계산이 끝난 후 N개의 배열에서 결과값을 찾는 연산을 추가로 해줘야 한다. 목적에 따라서는 최상층에서 최하층으로 이동하는 것이 적절할 수 있으나 문제에서 요구하는 것과는 관계가 없다.
풀이 코드
#include <iostream>
using namespace std;
void BAEKJOON_1932()
{
int n;
cin >> n;
/*--------------배열 할당 및 값 입력------------*/
int** arr = new int*[n];
for (int i = 0; i < n; ++i)
{
arr[i] = new int[i + 1];
for (int j = 0; j <= i; ++j)
{
cin >> arr[i][j];
}
}
/*-------------최대 합계 구하기----------------*/
for (int i = n - 2; i >= 0; --i)
{
for (int j = 0; j <= i; ++j)
{
arr[i][j] += arr[i + 1][j] > arr[i + 1][j + 1] ? arr[i + 1][j] : arr[i + 1][j + 1];
}
}
cout << arr[0][0] << endl;
/*----------------할당 해제--------------------*/
for (int i = 0; i < n; ++i)
{
delete[] arr[i];
}
delete[] arr;
return;
}
1. 집은 일렬로 쭉 늘어서 있다. 단, [0]과 [N - 1]은 인접하지 않았다. 2. 인접한 집의 색이 동일하지 않아야 한다. (RRG는 불가능, RGR은 가능) 3. 입력으로 각 집의 RGB에 대한 도색 비용이 주어진다. 위 조건에 맞춰 [0]부터 [N - 1]번째 집까지 도색하는 비용의 최소값을 출력한다.
테스트 케이스
3 26 40 83 49 60 57 13 89 99
96
1 26 40 83
26
문제 풀이
비용이 최소인 경로를 구하는 문제. 이런 종류의 문제는 각 출발지에서 목적지까지 도달한 후에 경로별 값을 비교하는 것으로 구할 수 있다. [1]의 R은 [0]의 G, B와 비교하여 작은 값과 더하고, [1]의 G는 [0]의 R, B와 비교, [1의 B는 [0]의 R, G와 비교하여 최소 값을 구하는 식으로 목적지인 [N-1]까지 최소 합계를 구하고, [N-1]의 R, G, B 중에서 가장 작은 값을 출력하는 것으로 해결할 수 있다.
풀이 코드
#include <iostream>
using namespace std;
// 배열을 사용한 풀이
void BAEKJOON_1149()
{
int N;
cin >> N;
int* R = new int[N];
int* G = new int[N];
int* B = new int[N];
/*----------------값 입력 받기-------------------*/
for (int i = 0; i < N; ++i)
{
cin >> R[i] >> G[i] >> B[i];
}
/*-----------------비용 계산----------------------*/
for (int i = 0; i < N - 1; ++i)
{
R[i + 1] += G[i] < B[i] ? G[i] : B[i];
G[i + 1] += R[i] < B[i] ? R[i] : B[i];
B[i + 1] += R[i] < G[i] ? R[i] : G[i];
}
int result = R[N - 1] < G[N - 1] ? R[N - 1] :G[N - 1];
result = result < B[N - 1] ? result : B[N - 1];
cout << result << endl;
/*-------------------메모리 해제------------------*/
delete[] R;
delete[] G;
delete[] B;
return;
}
#include <iostream>
using namespace std;
// 배열을 사용하지 않는 풀이
void BAEKJOON_1149()
{
int N;
cin >> N;
int R = 0;
int G = 0;
int B = 0;
for (int i = 0; i < N; ++i)
{
int r, g, b;
cin >> r >> g >> b;
r = G < B ? r + G : r + B;
g = R < B ? g + R : g + B;
b = G < R ? b + G : b + R;
R = r;
G = g;
B = b;
}
int minCost = R < G ? R : G;
minCost = minCost < B ? minCost : B;
cout << minCost << endl;
return;
}