문제

을 오름차순으로 목록 번호,무엇이 가장 효율적인 알고리즘의 생각할 수 있을 얻을 오름차순으로 목록 합계는 모든 두 번호에서는 목록이다.중복된 결과 목록에서 무관을 제거할 수 있습니다 그들 또는 그들을 피하기 좋아하는 경우.

수명,내가 관심있어하는 알고리즘이 있습니다.게시 코드에서 어떤 언어와 패러다임기..........

도움이 되었습니까?

해결책

편집으로의 2018:당신은 아마 이 읽기를 중지 합니다.(그러나 나는 삭제할 수 없습니다 그것이 허용됩니다.)

당신이 쓰는 경우 밖으로 합계 다음과 같다:

1 4  5  6  8  9
---------------
2 5  6  7  9 10
  8  9 10 12 13
    10 11 13 14
       12 14 15
          16 17
             18

는 것을 알 수 있기 때문에 M[i,j] <=M[i,j+1]M[i,j] <=M[i+1,j],그 다음 당신만을 검사하 왼쪽 상단에"코너"를 선택 최저 하나입니다.

예:

  • 1,왼쪽 상단 모서리를 선택 2
  • 만 1 선택 5
  • 6,8,6
  • 7 또는 8,선택 7
  • 9 또는 8,선택 8
  • 9 9,모두를 선택:)
  • 10 10 10,모두 선택
  • 12 또는 11,선택 11
  • 12 또는 12 일에 모두 선택
  • 13 13,두 선택
  • 14 14,두 선택
  • 15,16,선택 15
  • 만 1 선택 16
  • 만 1 선택 17
  • 1,선택 18

물론 할 때,당신 의 왼쪽 상단 모서리 이 솔루션 devolves.

는데 문제는 Ω(n2),기 때문에 당신을 계산한 금액에 대한 각 M[i,j]--지 않으면 누군가가 더 잘 알고리즘에 대한 요약:)

다른 팁

보다는 코딩,이것은 그림이 나는 의사 코드에서는 단계를 설명은 나의 논리,그래서는 더 나은 프로그래머 수 있습에 구멍을 내고 나의 논리를 필요한 경우입니다.

첫 번째 단계에서 시작하는 목록 숫자의 길 n.각 번호에 대한 우리 목록을 만들의 길이는 n-1 기 때문에 우리가 추가하지 않 수니다.에 의해 결국 우리의 목록에 대 n 로 정렬된 목록을 생성된 O(n^2)시간입니다.

step 1 (startinglist) 
for each number num1 in startinglist
   for each number num2 in startinglist
      add num1 plus num2 into templist
   add templist to sumlist
return sumlist 

2 단계에서이기 때문에 목록을 정렬에 의해 디자인(추가 수하는 각 요소에 정렬된 목록 이 목록은 여전히 분류)우리는 단순히 할 mergesort 병합하여 각 목록 함께 보다는 오히려 mergesorting 니다결국 이 O(n^2)시간입니다.

step 2 (sumlist) 
create an empty list mergedlist
for each list templist in sumlist
   set mergelist equal to: merge(mergedlist,templist)
return mergedlist

병합 방법을 병합하는 단계와 확인에 없는 중복된 금액입니다.내가 쓰지 않습니다 이 때문에 사람을 볼 수 있습 mergesort.

그래서 저의 솔루션입니다.전체 알고리즘 O(n^2)시간입니다.지적하여 주시기 바랍에 어떤 과오나 개선.

당신이 할 수 있는 이 두 라인에서는 파이썬

allSums = set(a+b for a in X for b in X)
allSums = sorted(allSums)

의 비용은 이 n^2(아마도 추가 로그인 요소이트에 대한?) 에 대한 반복 s*로그(s)에 대한 정렬이 어디 s 는 크기의 집합입니다.

의 크기가 설정으로 큰 수 n*(n-1)/2 는 경우 예를 들어 X=[1,2,4,...,2^n].그래서 당신이 원하는 경우를 생성하는 이 목록에 걸릴 것입니다 적어도 n^2/2 최악의 경우에는 이 때문에 크기의 출력 합니다.

그러나 그 선택하려면 첫 번째 k 요소의 결과에 이를 수행할 수 있습니 O(kn)을 이용하여 선택 알고리즘에 대한 정 X+Y 행렬에 의해 Frederickson 과 존슨(여기를 참조하십시오 처참한 상세정보).하지만 이것은 아마 수정을 생성하는 온라인에 그들을 다시 사용하여 계산하고 효율적 발전기를 위한 이 설정합니다.

@deuseldorf,Peter 일부에 대한 혼란(n!) 중 deuseldorf 의미"n 계승"하지만 단순히"n,(매우 흥분)!"

최고의 내에 오를 수 있을 만드는 것입니다 매트릭스의 총액의 각 쌍,다음을 병합하는 행 함께,라 병합니다.나는 같은 느낌이 나는 몇 가지 간단한 통찰력을 공개하는 훨씬 더 많은 효율적인 솔루션입니다.

나의 알고리즘,용:

matrixOfSums list = [[a+b | b <- list, b >= a] | a <- list]

sortedSums = foldl merge [] matrixOfSums

--A normal merge, save that we remove duplicates
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) = case compare x y of
    LT -> x:(merge xs (y:ys))
    EQ -> x:(merge xs (dropWhile (==x) ys))
    GT -> y:(merge (x:xs) ys)

내가 찾는 사소한 개선,하나 더 많은 의무 게으른 stream-based coding.대신 합병의 열한 쌍 병합,한 번에 모두.에 활용되고 있는 당신을 받기 시작한 요소의 목록을 즉시.

-- wide-merge does a standard merge (ala merge-sort) across an arbitrary number of lists
-- wideNubMerge does this while eliminating duplicates
wideNubMerge :: Ord a => [[a]] -> [a]
wideNubMerge ls = wideNubMerge1 $ filter (/= []) ls
wideNubMerge1 [] = []
wideNubMerge1 ls = mini:(wideNubMerge rest)
    where mini = minimum $ map head ls
          rest = map (dropWhile (== mini)) ls

betterSortedSums = wideNubMerge matrixOfSums

그러나,당신이 알고 있는 경우 당신이 이용하기 위하여 려고 하고 있는 모든 금액이 없는 장점을 얻는 그들 중 일부는 이전,이동과 함께'foldl merge []'으로,그것은 빠릅니다.

에서 SQL:

create table numbers(n int not null)
insert into numbers(n) values(1),(1), (2), (2), (3), (4)


select distinct num1.n+num2.n sum2n
from numbers num1
inner join numbers num2 
    on num1.n<>num2.n
order by sum2n

C#LINQ:

List<int> num = new List<int>{ 1, 1, 2, 2, 3, 4};
var uNum = num.Distinct().ToList();
var sums=(from num1 in uNum
        from num2 in uNum 
        where num1!=num2
        select num1+num2).Distinct();
foreach (var s in sums)
{
    Console.WriteLine(s);
}

상관없이 당신이 무엇을 하지 않고,추가적인 제약 조건에 입력 값을 수행할 수 없습니다 보다 더 O(n^2)기 때문에,단순히 당신을 반복하는 모든 쌍의 숫자가 있습니다.반복을 지배하게 될 것이 정렬(수행할 수 있는 O(n 로그 n)또는 빨리).

이 질문은 파괴 내 두뇌한다.굉장하다.

어쨌든,당신은에서 얻을 수 없 n^2 자연의 그것을 쉽게 하지만,당신이 할 수 있는 약간 더 나은 병합할 수 있기 때문에 바인딩된 범위의 각 요소를 삽입합니다.

에서 보면 모든 목록을 생성하고,그들은 다음과 같은 형식으로 제공합니다.

(a[i], a[j]) | j>=i

는 경우 플립을 90 도까지,당신이 얻을:

(a[i], a[j]) | i<=j

이제 병합 과정을 복용해야하는 두 개의 목록 ii+1 (에 해당하는 나열하는 첫 번째 멤버가 항상 a[i]a[i+1]다),당신할 수밖에 없는 범위를 삽입하는 요소 (a[i + 1], a[j]) 으로 목록 i 에 의해 위치 (a[i], a[j]) 위치 (a[i + 1], a[j + 1]).

이미 병합해야 합니다서 역방향의 측면에서 j.나도 몰라(아직)는 경우에 활용할 수 있는 이러 j 뿐만 아니라,하지만 그것이 가능한 것 같습니다.

찾고 있다면 진정한 언어 독립적 솔루션은 그 다음 당신은 몹시 실망한 내 생각에 있을 것이기 때문에 붙어에 대한 반복하고 몇 가지 조건.그러나 만약 당신이 그것을 열어하는 기능적인 언어나 기능 언어 기능(내가 당신을 보고 LINQ)다음 내 동료들이 여기를 채울 수 있는 이 페이지는 우아한 예제에서는 루비,Lisp,Erlang,및 다른 사람입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top