작성
·
42
0
안녕하세요!!
누적합 공부하면서 좀 헷갈리는 부분과 예시코드랑 다른 부분이 있어서 이 두개에 대해서 질문하려고합니다.
http://boj.kr/88f78b9449fb462e99bbed15e9875b5f
이게 제가 작성한 코드인데요,
피자가원형이고, 예를 들어 7,2,2,2,1 이 있다고 치면 확장해서 7,2,2,2,1,7,2,2,2,1 이렇게 만드는 과정이 2*m 즉 2배 확장하는걸로 이해했는데요, (2*m)-1 만 확장해도 상관은 없는거죠? 선택할 수 잇는 시작점의 마지막 위치가 1이고 그 뒤로 넘어가 7을 선택하게되면 결국 맨 처음 선택했던 시작점과 동일해지기 때문에 이런것같은데, Chatgpt를 통해서 의견을 묻는데 반드시 2*M 의 구간확장이 필요하다해서 의미가 있나 싶어 질문드립니다.
또한 map에다가 누적합들을 더하는 과정이 예시 코드에서는
interval개를 선택할거고, start지점을 interval과 같게 설정하는 부분이 잘 이해가 안됩니다. 저는 i~j까지의 합을 size만큼 펼쳐가면서 더햇는데요, 예시 코드에서 start를 꼭 interval로하는 이유가 있나요? 물론 코드가 정상적으로 동작해서 같은 결과를 내는건 알겠는데, start = 1; start<= n 으로 하지 않는 이유가 궁금합니다.
답변 2
0
안녕하세요 정현님 ㅎㅎ
7,2,2,2,1,7,2,2,2,1
->
네 맞습니다.
예시를 들어 보면은... 여기서 보면 저희가 해야할 부분이
7,2,2,2,1,7,2,2,2,1
이렇게 가다가...
7,2,2,2,1,7,2,2,2,1
여기까지의 범위를 확인하는 것이라
2m - 1까지만 확인하는게 맞습니다.
실제로 이부분은 제 코드내에도 다음처럼 break를 걸어 2m 부분의 확인을 막습니다.
if(interval == n) break;
2번질문::
for(int interval = 1; interval <= n; interval++){
for(int start = interval; start <= n + interval - 1; start++){
이 코드와
for(int i = 1; i<=size; i++){
for(int j = i; j<=i + size -2; j++){
이 코드가 다른 부분을 말씀하시는거 맞을까요?
근데 저거 변수명 말고는 다른 부분은 -2까지인지 -1까지인지 말고는 없습니다.
for(int start = interval; start <= n + interval - 1; start++){
이부분이 정현님은
for(int start = interval; start <= n; start++)
이렇게 되어야 한다고 생각하시는것이죠?
자 전체코드를 잠깐 볼게요.
for(int interval = 1; interval <= n; interval++){
for(int start = interval; start <= n + interval - 1; start++){
int sum = psum[start] - psum[start - interval];
여기서 중요한 부분은 바로 psum[start] - psum[start - interval]; 이부분이죠?
우리는 뭘 확인하고 싶은 걸까요?
바로 길이가 1부터 n까지인 모든 연속 구간의 합을 계산하는 것입니다. 여기서 interval은 구간의 길이입니다. 1 ~ n이어야 합니다.
그리고 그 다음 루프는 해당 길이에 맞춰서 -> 구간의 모든 경우의 수를 구해야 합니다.
예를 들어 구간의 길이가 3이라고 했을 때
1, 2, 3, 4, 5, 6
1, 2, 3, 4, 5, 6
1, 2, 3, 4, 5, 6
1, 2, 3, 4, 5, 6
이런 경우의 수를 뽑아야 하기 때문에 start는 interval(3)부터 시작합니다. 그리고 나서
...
결국 여기까지 뽑아야 하기 때문에 n 까지가 아니라 n + interval - 1까지 뽑아야 합니다.
1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6
만약 n까지 뽑게 되면 그 이전의 경우의 수 까지밖에 못뽑게 되서 -> 모든 경우의 수를 생각하지 못하게 됩니다.
또 질문 있으시면 언제든지 질문 부탁드립니다.
좋은 수강평과 별점 5점은 제게 큰 힘이 됩니다. :)
감사합니다.
강사 큰돌 올림.
안녕하세요 정현님ㅎㅎ
int sum = psum[start] - psum[interval -1];
-> 이렇게 하시면 원형배열에 대한 경우의 수를 구할 때 잘못 구해지게 됩니다.
여기서 psum[interval]의 경우 interval에 의한 상수가 되어버리죠?
이 때 n이 8이라면 psum[7] - psum[1] 이런식으로 계산이 되는 경우가 생기는데 이 경우는 나오면 안되는 수입니다.
예를 들어 1, 2, 3, 4, 1, 2, 3, 4 에서 1, 2, 3, 4, 1, 2, 3, 4 이런식으로 되어버리니까요.
이런 반례가 있기 때문에 변수화해서 풀어야 합니다.
물론 앞으로 prefix sum 문제가 나오면 예시 코드처럼 풀 생각이지만 차이가 있을까 해서 질문드립니다.
-> 무조건적인 수용보다는 이렇게 질문주시는게 더 좋습니다. ㅎㅎ 좋은 생각이십니다.
또 질문 있으시면 언제든지 질문 부탁드립니다.
좋은 수강평과 별점 5점은 제게 큰 힘이 됩니다. :)
감사합니다.
강사 큰돌 올림.
0
안녕하세요, 인프런 AI 인턴입니다.
이정현님께서 주신 질문은 누적합과 피자원형 문제에서의 구간 확장 방식에 관한 내용입니다. 질문의 핵심은 피자 원형 배열을 확장하는 과정과 예시 코드에서 사용된 start
변수의 설정 방식입니다.
원형 배열 확장:
7, 2, 2, 2, 1
을 7, 2, 2, 2, 1, 7, 2, 2, 2, 1
로 확장합니다.Start 변수의 설정:
start
를 interval
로 설정한 이유는, 특정 길이만큼 확장한 배열을 다루기 위해 초기 위치를 조절한 것입니다.interval
로 잡습니다. 이 방식은 중복 계산을 피하고, 알고리즘의 복잡도를 줄이려는 의도가 포함되어 있습니다.start = 1; start <= n
으로 설정하는 것도 가능하겠지만, 이렇게 하면 처리하는 방식에 차이가 생길 수 있습니다. 예시에서는 효율적인 계산을 위해 이와 같이 구성한 걸로 보입니다.추가적으로 관련된 게시물들을 참조하셔서 더 풍부한 정보를 얻으시면 좋겠습니다. 도움이 될 만한 링크를 리스트로 드리겠습니다:
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
안녕하세요, interval 즉 구간의 크기만큼 start가 해당 크기에서 시작해야 하는 이유는 위 답변을 통해서 이해했습니다!!
이 과정에서 추가로 질문점이 생겨 죄송하지만 다시 한번 질문 드립니다!!!
int sum = psum[start] - psum[interval -1];
저는 예시 코드 기반 변수명으로 적용하면 이렇게 작성했는데요, 즉
psum[interval -1]
으로 고정해서, 피자 조각으로 들어온 첫번째 조각 의 index를 1이라고 했을때,1 / 1,2 / 1,2,3 / .... /1,2,...n-1 이렇게 계산을 하고자 했습니다. 구간의 길이를 1~n 순으로 순회한것이 아닌, 시작지점을 순회하고, 크기를 1~n-1까지 순회했습니다.
(이후는 2 / 2, 3 / ... /2,3,...n 이런 방식으로)
즉 interval이 아닌 시작 지점으로 생각을 해서 작성을 했는데요, 이런 방식은 문제가 있을까 궁금합니다!! 물론 앞으로 prefix sum 문제가 나오면 예시 코드처럼 풀 생각이지만 차이가 있을까 해서 질문드립니다.