这样一个循环:list:Tstringlist;

  假设list已经创建好,有30000个元素,每个元素都是4位数的随机数,
  并且List不能排序,可以有相同的。
}procedure TestFor;
var
  i,j:Integer;
begin
  for i:=0 to list.count-1 do begin
    for J:=0 to list.count-1 do begin
      if i <> j then begin
        //OtherHandle;做其他处理
      end;
    end;
  end; 
end;
要求:求出list里面相同元素的个数。
从要求开看代码很简单,明显不能用List.Find和List.indexof这两个函数(因为不能排序并且有相同的);
可以这样做要两层For循环逐一对比就可以得到正确的答案,
但是效率却很低,这样要做30000²次的运算,如果数据再大的话就更恐怖了n²次运算。
有没有其他更快的方法或者算法进行改良提高效率?先谢谢大家。

解决方案 »

  1.   


    var
      i , n : integer;
      Buf : array [0..9999] of SmallInt;
    begin
      FillChar(Buf , SizeOf(Buf) , 0);
      for i:=0 to list.count-1 do begin
        n := StrToInt(List.Strings[i]);
        Inc(Buf[n]);
      end;
      //循环 Buf得到每个数的重复次数,Buf[0..n]分别保存了这个数出现的次数,如果>1表示重复
    end;由于默认的StrToInt效率不高,可以自己写一个专用的来提高效率.
      

  2.   

    这么循环确实效率很低。
    随机数都是4位,那就是1000到9999?怎么会有30000个。
    重复得太严重吧。能不能创建list的时候不要这么多重复啊。(仅供参考)
      

  3.   

    学习一楼,如果只是为了统计出重复的次数的话,可以优化下,减少10000次循环program Project1;{$APPTYPE CONSOLE}{$R *.res}uses
      System.SysUtils,
      System.Classes;var
      List: TStrings;procedure BuildRandomList(AList: TStrings);
    var
      I: Integer;
    begin
      Randomize;
      AList.Clear;
      for I := 0 to 30000 - 1 do
        AList.Add(IntToStr(Random(9999)));
    end;function CountRepeat(AList: TStrings): Integer;
    var
      I, J: Integer;
      LBuffer: array [0..9999] of Byte;
    begin
      FillChar(LBuffer, SizeOf(LBuffer), 0);
      Result := 0;
      for I := 0 to AList.Count - 1 do
      begin
        J := StrToInt(AList[I]);
        Inc(LBuffer[J]);
        if LBuffer[J] > 1 then
        begin
          Inc(Result);
          Writeln(Format('%d  %d', [J, LBuffer[J]]));
        end;
      end;
    end;begin
      List := TStringList.Create;
      BuildRandomList(List);  Writeln(IntToStr(CountRepeat(List)));  List.Free;  Sleep(100000);
    end.