을 효율적으로 정 합의로 정렬된 목록
-
08-06-2019 - |
문제
을 오름차순으로 목록 번호,무엇이 가장 효율적인 알고리즘의 생각할 수 있을 얻을 오름차순으로 목록 합계는 모든 두 번호에서는 목록이다.중복된 결과 목록에서 무관을 제거할 수 있습니다 그들 또는 그들을 피하기 좋아하는 경우.
수명,내가 관심있어하는 알고리즘이 있습니다.게시 코드에서 어떤 언어와 패러다임기..........
해결책
편집으로의 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
이제 병합 과정을 복용해야하는 두 개의 목록 i
고 i+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,및 다른 사람입니다.