Recursiv procedure ?
HejJeg postede dette spørgsmål igår
http://www.eksperten.dk/spm/804059
og fandt en løsning på problemet umiddelbart derefter
Nu vil jeg meget gerne have hjælp til optimering, fordi det kører lidt langsomt
Her er spørgsmålet fra tidligere:
Hej
Jeg har en talrække fx
16 , 6 , 3 , 4 , 5 , 21 , 22 , 7 , 9 , 10 , 11 , 12 , 13 , 14 , 15
Tallene i rækken gentages ikke, dvs det samme tal optæder ikke to gange i rækken.
Tallenes rækkefølge er fast, dvs jeg må ikke udskifte placering på to tal med hinanden. Det eneste jeg må er at slette nogle tal fra rækken.
Jeg vil gerne finde den længste sekvens, hvori tallene vil stå i stigende rækkefølge. For den givne talrække vil den længste sekvens være:
3 , 4 , 5 , 7 , 9 , 10 , 11 , 12 , 13 , 14 , 15
Jeg har således slettet tallene 16, 6, 21 og 22
Jeg fandt en løsning som ser sådan her ud:
//==========================================================================
{fast delete taken from about.delphi}
procedure DelFromArray(var A: TIntArr; const Idx: Integer);
begin
//if Idx>High(A) then Exit;
//if Idx<Low(A) then Exit;
if Idx=High(A) then
begin
SetLength(A, Length(A)-1);
Exit;
end;
Finalize(A[Idx]);
System.Move(A[Idx+1], A[Idx], (Length(A)-Idx-1)*SizeOf(Integer)+1 );
SetLength(A, Length(A)-1);
end;
//==========================================================================
function IndexOfMin(const A: TIntArr):Integer;
var MinVal, I: Integer;
begin
Result:= Low(A);
for I:=Low(A)+1 to High(A) do
if A[I]<A[Result] then Result:=I;
end;
//==========================================================================
{Each number in array must be present only once. 0's must therefor be deleted}
function FindLargestSeq(const A: TIntArr): TIntArr;
var I, MinIdx: Integer;
IsAscending: boolean;
A1, A2, T: TIntArr;
begin
{if the whole array is in ascending order then we are done}
IsAscending:= True;
if Length(A)>1 then
for I:=Low(A)+1 to High(A) do
if A[I]<A[I-1] then
begin
IsAscending:=False;
Break;
end;
if IsAscending then
Result:= A
else
begin
{if array is not ascending then something needs deletion}
MinIdx:= IndexOfMin(A); {Find index of lowest num in array}
{Either the sequense before this MinIdx needs to be deleted,
or MinIdx
itself needs to be deleted. They cant both be members of
largest sequence}
{Delete MinIndex itself and call recursively}
A1:= Copy(A);
DelFromArray(A1, MinIdx);
if Length(A1)>1 then {If length is 1 then that is largest sequence}
A1:= FindLargestSeq(A1);
{To see if largest seq can be made starting with minIndex do:
1.Take MinVal out
2.Delete sequence upto and including MinIndex
3.Call recursively
4.Add MinVal back to start of retrieved array}
A2:= Copy(A, MinIdx+1, Length(A)-MinIdx-1);
case Length(A2) of
0: SetLength(A2, 1);
1: begin
SetLength(A2, 2);
A2[1]:= A2[0];
end;
else {If length is 1 or less then that is largest sequence}
T:= FindLargestSeq(A2);
SetLength(A2, Length(T)+1);
System.Move(T[0], A2[1], Length(T)*SizeOf(Integer) );
end;
A2[0]:= A[MinIdx];
if Length(A1)>Length(A2) then
Result:= A1
else
Result:= A2;
end;
{no need to set dynamic arrays to nil}
end;
Problemet nu er følgende:
1) Jeg kan ikke finde ud af at beregne tidskomplexiteten for sådan en rutine. Jeg vil meget gerne vide hvor langt tid det kommer til at tage i værste fald
2) proceduren skal køre ca 50000 pr bruger, og det kan tage på til 20-30 dek selv på en hurtig pc (efter hvad jeg selv kunne teste), så det er lidt uacceptabelt
Hvis der er nogle som har foreslag til forbedringer eller evt en hel anden måde at gøre det på må I meget gerne hjælpe. Det vil jeg sætte stor pris på
VH