如何确定数组中哪个数字最常出现?
How to determine which number occurs most often in an array?
在用 100 个介于 1 和 11 之间的随机值填充数组后,如何确定哪个值出现次数最多?
这是一个示例代码:
procedure TForm1.Button1Click(Sender: TObject);
function Calculate: Integer;
var
Numbers: array [1..100] of Byte;
Counts: array [1..11] of Byte;
I: Byte;
begin
// Fill the array with random numbers
for I := Low(Numbers) to High(Numbers) do
Numbers[I] := Random(11) + 1;
// Count the occurencies
ZeroMemory(@Counts, SizeOf(Counts));
for I := Low(Numbers) to High(Numbers) do
Inc(Counts[Numbers[I]]);
// Identify the maximum
Result := Low(Counts);
for I := Low(Counts) + 1 to High(Counts) do
if Counts[I] > Counts[Result] then
Result := I;
end;
begin
ShowMessage(Calculate.ToString);
end;
It is a simple question [...]
是
but I can't seem to find any straight answers online.
您不应该搜索解决方案 on-line;相反,您应该开始考虑如何设计能够解决问题的算法。为此,您可能需要笔和纸。
首先,我们需要一些数据来处理:
const
ListLength = 100;
MinValue = 1;
MaxValue = 11;
function MakeRandomList: TArray<Integer>;
begin
SetLength(Result, ListLength);
for var i := 0 to High(Result) do
Result[i] := MinValue + Random(MaxValue - MinValue + 1);
end;
MakeRandomList
函数创建一个动态整数数组。根据需要,数组包含 ListLength = 100
个整数,范围从 MinValue = 1
到 MaxValue = 11
。
现在,给定这样一个整数列表,
var L := MakeRandomList;
我们如何找到最频繁的值?
好吧,如果我们在没有计算机的情况下仅使用笔和纸来解决这个问题,我们可能会计算列表中每个不同值 (1, 2, ..., 11) 出现的次数, 没有?
那么我们只需要找到频率最大的值即可。
例如,给定数据
2, 5, 1, 10, 1, 5, 2, 7, 8, 5
我们会数数以找到频率
X Freq
2 2
5 3
1 2
10 1
7 1
8 1
然后我们从顶行到底行读取table,找到频率最高的那一行,不断跟踪当前的赢家。
既然我们知道如何解决这个问题,写一段执行这个算法的代码就很简单了:
procedure FindMostFrequentValue(const AList: TArray<Integer>);
type
TValueAndFreq = record
Value: Integer;
Freq: Integer;
end;
var
Frequencies: TArray<TValueAndFreq>;
begin
if Length(AList) = 0 then
raise Exception.Create('List is empty.');
SetLength(Frequencies, MaxValue - MinValue + 1);
// Step 0: Label the frequency list items
for var i := 0 to High(Frequencies) do
Frequencies[i].Value := i + MinValue;
// Step 1: Obtain the frequencies
for var i := 0 to High(AList) do
begin
if not InRange(AList[i], MinValue, MaxValue) then
raise Exception.CreateFmt('Value out of range: %d', [AList[i]]);
Inc(Frequencies[AList[i] - MinValue].Freq);
end;
// Step 2: Find the winner
var Winner: TValueAndFreq;
Winner.Value := 0;
Winner.Freq := 0;
for var i := 0 to High(Frequencies) do
if Frequencies[i].Freq > Winner.Freq then
Winner := Frequencies[i];
ShowMessageFmt('The most frequent value is %d with a count of %d.',
[Winner.Value, Winner.Freq]);
end;
Delphi有一个TDictionary
class,可以用来实现频率映射,eg:
uses
..., System.Generics.Collections;
function MostFrequent(Arr: array of Integer) : Integer;
var
Frequencies: TDictionary<Integer, Integer>;
I, Freq, MaxFreq: Integer;
Elem: TPair<Integer, Integer>;
begin
Frequencies := TDictionary<Integer, Integer>.Create;
// Fill the dictionary with numbers
for I := Low(Arr) to High(Arr) do begin
if not Frequencies.TryGetValue(Arr[I], Freq) then Freq := 0;
Frequencies.AddOrSetValue(Arr[I], Freq + 1);
end;
// Identify the maximum
Result := 0;
MaxFreq := 0;
for Elem in Frequencies do begin
if Elem.Value > MaxFreq then begin
MaxFreq := Elem.Value;
Result := Elem.Key;
end;
end;
Frequencies.Free;
end;
var
Numbers: array [1..100] of Integer;
I: Integer;
begin
// Fill the array with random numbers
for I := Low(Numbers) to High(Numbers) do
Numbers[I] := Random(11) + 1;
// Identify the maximum
ShowMessage(IntToStr(MostFrequent(Numbers)));
end;
我也在学习中,因此觉得我处理这个问题的方式可能更接近于我应该做的方式:
procedure TForm1.GetMostOccuring;
var
arrNumbers : array[1..100] of Integer;
iNumberWithMost : Integer;
iNewAmount, iMostAmount : Integer;
I, J : Integer;
begin
for I := 1 to 100 do
arrNumbers[I] := Random(10) + 1;
iMostAmount := 0;
for I := 1 to 10 do
begin
iNewAmount := 0;
for J := 1 to 100 do
if I = arrNumbers[J] then
inc(iNewAmount);
if iNewAmount > iMostAmount then
begin
iMostAmount := iNewAmount;
iNumberWithMost := I;
end;
end;
ShowMessage(IntToStr(iNumberWithMost));
end;
我希望这不是完全没用。
这只是对一个简单问题的简单回答。
在用 100 个介于 1 和 11 之间的随机值填充数组后,如何确定哪个值出现次数最多?
这是一个示例代码:
procedure TForm1.Button1Click(Sender: TObject);
function Calculate: Integer;
var
Numbers: array [1..100] of Byte;
Counts: array [1..11] of Byte;
I: Byte;
begin
// Fill the array with random numbers
for I := Low(Numbers) to High(Numbers) do
Numbers[I] := Random(11) + 1;
// Count the occurencies
ZeroMemory(@Counts, SizeOf(Counts));
for I := Low(Numbers) to High(Numbers) do
Inc(Counts[Numbers[I]]);
// Identify the maximum
Result := Low(Counts);
for I := Low(Counts) + 1 to High(Counts) do
if Counts[I] > Counts[Result] then
Result := I;
end;
begin
ShowMessage(Calculate.ToString);
end;
It is a simple question [...]
是
but I can't seem to find any straight answers online.
您不应该搜索解决方案 on-line;相反,您应该开始考虑如何设计能够解决问题的算法。为此,您可能需要笔和纸。
首先,我们需要一些数据来处理:
const
ListLength = 100;
MinValue = 1;
MaxValue = 11;
function MakeRandomList: TArray<Integer>;
begin
SetLength(Result, ListLength);
for var i := 0 to High(Result) do
Result[i] := MinValue + Random(MaxValue - MinValue + 1);
end;
MakeRandomList
函数创建一个动态整数数组。根据需要,数组包含 ListLength = 100
个整数,范围从 MinValue = 1
到 MaxValue = 11
。
现在,给定这样一个整数列表,
var L := MakeRandomList;
我们如何找到最频繁的值?
好吧,如果我们在没有计算机的情况下仅使用笔和纸来解决这个问题,我们可能会计算列表中每个不同值 (1, 2, ..., 11) 出现的次数, 没有?
那么我们只需要找到频率最大的值即可。
例如,给定数据
2, 5, 1, 10, 1, 5, 2, 7, 8, 5
我们会数数以找到频率
X Freq
2 2
5 3
1 2
10 1
7 1
8 1
然后我们从顶行到底行读取table,找到频率最高的那一行,不断跟踪当前的赢家。
既然我们知道如何解决这个问题,写一段执行这个算法的代码就很简单了:
procedure FindMostFrequentValue(const AList: TArray<Integer>);
type
TValueAndFreq = record
Value: Integer;
Freq: Integer;
end;
var
Frequencies: TArray<TValueAndFreq>;
begin
if Length(AList) = 0 then
raise Exception.Create('List is empty.');
SetLength(Frequencies, MaxValue - MinValue + 1);
// Step 0: Label the frequency list items
for var i := 0 to High(Frequencies) do
Frequencies[i].Value := i + MinValue;
// Step 1: Obtain the frequencies
for var i := 0 to High(AList) do
begin
if not InRange(AList[i], MinValue, MaxValue) then
raise Exception.CreateFmt('Value out of range: %d', [AList[i]]);
Inc(Frequencies[AList[i] - MinValue].Freq);
end;
// Step 2: Find the winner
var Winner: TValueAndFreq;
Winner.Value := 0;
Winner.Freq := 0;
for var i := 0 to High(Frequencies) do
if Frequencies[i].Freq > Winner.Freq then
Winner := Frequencies[i];
ShowMessageFmt('The most frequent value is %d with a count of %d.',
[Winner.Value, Winner.Freq]);
end;
Delphi有一个TDictionary
class,可以用来实现频率映射,eg:
uses
..., System.Generics.Collections;
function MostFrequent(Arr: array of Integer) : Integer;
var
Frequencies: TDictionary<Integer, Integer>;
I, Freq, MaxFreq: Integer;
Elem: TPair<Integer, Integer>;
begin
Frequencies := TDictionary<Integer, Integer>.Create;
// Fill the dictionary with numbers
for I := Low(Arr) to High(Arr) do begin
if not Frequencies.TryGetValue(Arr[I], Freq) then Freq := 0;
Frequencies.AddOrSetValue(Arr[I], Freq + 1);
end;
// Identify the maximum
Result := 0;
MaxFreq := 0;
for Elem in Frequencies do begin
if Elem.Value > MaxFreq then begin
MaxFreq := Elem.Value;
Result := Elem.Key;
end;
end;
Frequencies.Free;
end;
var
Numbers: array [1..100] of Integer;
I: Integer;
begin
// Fill the array with random numbers
for I := Low(Numbers) to High(Numbers) do
Numbers[I] := Random(11) + 1;
// Identify the maximum
ShowMessage(IntToStr(MostFrequent(Numbers)));
end;
我也在学习中,因此觉得我处理这个问题的方式可能更接近于我应该做的方式:
procedure TForm1.GetMostOccuring;
var
arrNumbers : array[1..100] of Integer;
iNumberWithMost : Integer;
iNewAmount, iMostAmount : Integer;
I, J : Integer;
begin
for I := 1 to 100 do
arrNumbers[I] := Random(10) + 1;
iMostAmount := 0;
for I := 1 to 10 do
begin
iNewAmount := 0;
for J := 1 to 100 do
if I = arrNumbers[J] then
inc(iNewAmount);
if iNewAmount > iMostAmount then
begin
iMostAmount := iNewAmount;
iNumberWithMost := I;
end;
end;
ShowMessage(IntToStr(iNumberWithMost));
end;
我希望这不是完全没用。 这只是对一个简单问题的简单回答。