n으로 나눌 수있는 최대 합 요소를 고유하게 할 필요는 없습니다). 추천 O

StackOverflow 에서이 질문 했지만 여기에 더 적절한 장소가 있다고 생각합니다.

이것은 알고리즘 소개 과정 에서 발생하는 문제입니다 .

양의 정수 가 n 인 배열 가 있습니다 (배열을 정렬하거나 요소를 고유하게 할 필요는 없습니다). 추천 O ( N ) 로 나누어 소자의 가장 큰 합을 찾는 알고리즘 N을 .

a

n

O(n)

n

예 : . 답은 56입니다 (요소 6 , 13 , 4 , 8 , 25 포함 )

a=[6,1,13,4,9,8,25],n=7

56

6,13,4,8,25

동적 프로그래밍을 사용하고 나머지 0 , 1 , 2 , 와 함께 가장 큰 합계를 저장하여 에서 비교적 쉽게 찾을 수 있습니다 . . . , n 1 .

O(n2)

0,1,2,...,n−1

또한 연속 된 요소 시퀀스에주의를 제한하면 부분 합 모듈로 n 을 저장 하여 시간 에 최적의 시퀀스를 쉽게 찾을 수 있습니다 . let S [ i ] = a [ 0 ] + a [ 1 ] + + a [ i ] , 각 나머지 r 에 대해 S [ j ] r이 되도록 가장 큰 인덱스 j를 기억하십시오

O(n)

n

S[i]=a[0]+a[1]+⋯+a[i]

r

j

, 다음의 각 I 고려해야 S [ J ] S가 [ I ] 여기서, J는 에 대응하는 인덱스이고 , R = S [ I ] 개조 N .

S[j]≡r(modn)

i

S[j]−S[i]

j

r=S[i]modn

그러나 일반적인 경우에 시간 솔루션이 있습니까? 모든 제안을 부탁드립니다! 나는 이것이 선형 대수를 다루는 것으로 생각하지만 정확히 무엇인지 모르겠습니다.

O(n)

또는 시간 내에이 작업을 수행 할 수 있습니까?

O(nlog⁡n)


답변

다음은 몇 가지 임의의 아이디어입니다.

  • 동적 프로그래밍 알고리즘을 뒤집어 가장 큰 합계 대신 가장 작은 합계를 찾을 수 있습니다. 당신은 하나의 합동에 0 대신에, 전체 배열의 나머지에 합한 합을 찾는다. 요소를 오름차순으로 처리하면 전체 배열을 처리하기 전에 동적 알고리즘이 종료 될 수 있습니다.

    k 개의 요소를 처리하면 비용은 입니다. 있다 없다 의 하한 Ω ( N 로그 N ) 우리는 모든 요소를 정렬 할 필요가 없기 때문에이 알고리즘에. k 개의 가장 작은 요소 를 얻는 데 O ( n log k ) 시간 만 걸립니다 .

    O(nk)

    k

    Ω(nlog⁡n)

    O(nlog⁡k)

    k
  • 가장 큰 크기의 집합 대신 큰 크기의 집합을 염두에두면 빠른 푸리에 변환 기반 다항식 곱셈을 사용하여 시간. 도메인 범위가 제한 될 때 3SUM 에서 수행 한 것과 유사합니다 . (참고 : 사용은 다른 당신이 얻을 것이다, 이진 검색을 할 제곱 반복 O ( N K ( 로그 N ) ( 로그 로그 N ) ) K

    O(n(log⁡n)2(log⁡log⁡n))

    O(nk(log⁡n)(log⁡log⁡n))

    k

    생략 된 요소의 수입니다.)

  • 복합이며, 거의 모든 나머지 중 하나의 배수이다 N 의 요인 상당한 시간이 그 요소의 배수가 아닌 나머지에 초점을 맞춤으로써 저장 될 수 있습니다.

    n

    n
  • 잔차 r가 매우 흔하거나 잔재가 거의없는 경우 ‘여기에서 시작하면 다음 열린 슬롯을 추적하고 r정보를 계속 사용하여 정보를 계속 유지 ‘하면 많은 점프 스캔 대 오픈 스팟을 저장할 수 있습니다. 시각.

  • 도달 가능성 만 추적하고 플립 된 동적 알고리즘에서 비트 마스크를 사용한 다음 대상 나머지에 도달하면 역 추적 하여 로그 요소면도 할 수 있습니다 .

  • 동적 프로그래밍 알고리즘은 병렬로 실행될 수 있습니다. 각 버퍼 슬롯에 대한 프로세서를 사용하면 까지 내려갈 수 있습니다 . 또는 O ( n 2 ) 폭을 사용하고 반복 집계 대신 집계를 분할 및 정복함으로써 회로 깊이 비용을 O ( log 2 n ) 까지 줄일 수 있습니다 .

    O(n)

    O(n2)

    O(log2⁡n)
  • (메타) 나는 당신이 겪은 문제가 연속적인 합 에 관한 것이라고 강력히 의심합니다 . 실제 문제와 연결되어 있으면 쉽게 확인할 수 있습니다. 그렇지 않으면이 문제가 “알고리즘 소개”라는 과정에서 배정 된 것을 감안할 때이 문제가 얼마나 어려운지 매우 놀랐습니다. 그러나 어쩌면 당신은 그것을 사소하게 만드는 트릭을 다루었습니다.


답변

내가 제안한 알고리즘은 다음과 같습니다.

n의 배수 인 summand 만 추가하면 합은 n으로 나눌 수 있습니다.

시작하기 전에 int를 키로, 인덱스 목록을 값으로 사용하여 해시 맵을 작성하십시오. 또한 색인이 포함 된 결과 목록을 만듭니다.

그런 다음 배열을 반복하고 mod n이 0 인 모든 인덱스를 결과 목록에 추가합니다. 다른 모든 색인에 대해 다음을 수행하십시오.

이 인덱스의 값 mod n을 n에서 뺍니다. 이 결과는 필요한 값을 가진 요소의 인덱스를 저장하는 해시 맵의 핵심입니다. 이제이 색인을 해시 맵의 목록에 추가하고 계속 진행하십시오.

배열을 반복 한 후 출력을 계산합니다. 인덱스가 가리키는 값에 따라 해시 맵의 각 목록을 정렬하면됩니다. 이제 해시 맵의 모든 쌍이 n까지 합산되는 것을 고려하십시오. 따라서 n = 7이면 해시 맵에서 3과 4를 검색합니다. 둘 다에 항목이 있으면 두 개의 가장 큰 값을 가져 와서 목록에서 제거하고 결과 목록에 추가합니다.

마지막 권장 사항 : 여전히 알고리즘을 테스트하지 않았고 무차별 강제 알고리즘을 사용하여 테스트 케이스를 작성하십시오.


답변

이 DP 방법을 사용하십시오 ( /programming/4487438/maximum-sum-of-non-consecutive-elements?rq=1 ) :

배열 A [0..n]이 주어지면 인덱스 0..i를 갖는 요소를 사용하여 M (i)을 최적의 솔루션으로 만드십시오. 그런 다음 M (-1) = 0 (반복에 사용됨), M (0) = A [0] 및 M (i) = max (M (i-1), M (i-2) + A [i ])에 대해 i = 1, …, n입니다. M (n)은 우리가 원하는 솔루션입니다. 이것은 O (n) 입니다. 다른 배열을 사용하여 각 하위 문제에 대해 선택한 항목을 저장할 수 있으므로 선택한 실제 요소를 복구 할 수 있습니다.

재귀를 M (i) = max (M (i-1), M (i-2) + A [i])로 변경하여 N으로 나눌 수있는 경우에만 저장합니다.