Welcome to collectivesolver - Programming & Software Q&A with code examples. A website with trusted programming answers. All programs are tested and work.

Contact: aviboots(AT)netvision.net.il

Semrush - keyword research tool

Turn ChatGPT, Claude, Gemini, And CoPilot Into Your Personal Assistant, Business Coach, Content Creator, And More

AFFILIATE MARKETING Your all-in-one performance engine Manage affiliates, creators, and customer referrals in one unified platform—turning every partnership into measurable growth
Secure & Reliable Web Hosting, Free Domain, Free SSL, 1-Click WordPress Install, Expert 24/7 Support

Boost your online presence with premium web hosting and servers

Disclosure: My content contains affiliate links.

42,709 questions

55,473 answers

573 users

How to find the N smallest values in a 2D array in Pascal

1 Answer

0 votes
program NSmallest2DArray;

{$mode objfpc}{$H+}{$MODESWITCH ADVANCEDRECORDS}

uses
  SysUtils, Math;

type
  { Dynamic array type definitions for clarity and flexibility }
  T1DIntArray = array of Integer;
  T2DIntArray = array of array of Integer;

  {
    Bounded Max-Heap data structure.
    Used to track the N smallest elements encountered so far.
    The largest element among the current N smallest sits at the root (index 0),
    allowing O(1) comparison and O(log N) updates when a smaller value is found.
  }
  TBoundedMaxHeap = record
  private
    FItems: T1DIntArray;
    FCapacity: Integer;
    FCount: Integer;

    procedure SiftUp(Index: Integer);
    procedure SiftDown(Index: Integer);
    procedure Swap(I, J: Integer);
  public
    procedure Initialize(ACapacity: Integer);
    procedure PushOrReplace(Value: Integer);
    function ExtractSortedAscending: T1DIntArray;
    property MaxValue: Integer read FItems[0];
    property Count: Integer read FCount;
  end;

{ TBoundedMaxHeap Implementation }

procedure TBoundedMaxHeap.Swap(I, J: Integer);
var
  Temp: Integer;
begin
  Temp := FItems[I];
  FItems[I] := FItems[J];
  FItems[J] := Temp;
end;

procedure TBoundedMaxHeap.Initialize(ACapacity: Integer);
begin
  FCapacity := ACapacity;
  FCount := 0;
  SetLength(FItems, FCapacity);
end;

procedure TBoundedMaxHeap.SiftUp(Index: Integer);
var
  Parent: Integer;
begin
  while Index > 0 do
  begin
    Parent := (Index - 1) div 2;
    if FItems[Index] > FItems[Parent] then
    begin
      Swap(Index, Parent);
      Index := Parent;
    end
    else
      Break;
  end;
end;

procedure TBoundedMaxHeap.SiftDown(Index: Integer);
var
  LeftChild, RightChild, MaxChild: Integer;
begin
  while (2 * Index + 1) < FCount do
  begin
    LeftChild := 2 * Index + 1;
    RightChild := 2 * Index + 2;
    MaxChild := LeftChild;

    if (RightChild < FCount) and (FItems[RightChild] > FItems[LeftChild]) then
      MaxChild := RightChild;

    if FItems[MaxChild] > FItems[Index] then
    begin
      Swap(Index, MaxChild);
      Index := MaxChild;
    end
    else
      Break;
  end;
end;

procedure TBoundedMaxHeap.PushOrReplace(Value: Integer);
begin
  if FCapacity <= 0 then Exit;

  { If heap is not full, append and sift up }
  if FCount < FCapacity then
  begin
    FItems[FCount] := Value;
    Inc(FCount);
    SiftUp(FCount - 1);
  end
  { If full and incoming value is smaller than current max, replace root }
  else if Value < FItems[0] then
  begin
    FItems[0] := Value;
    SiftDown(0);
  end;
end;

function TBoundedMaxHeap.ExtractSortedAscending: T1DIntArray;
var
  I, OriginalCount: Integer;
begin
  SetLength(Result, FCount);
  OriginalCount := FCount;

  { Pop items from Max-Heap into the array from back to front }
  for I := OriginalCount - 1 downto 0 do
  begin
    Result[I] := FItems[0];
    FItems[0] := FItems[FCount - 1];
    Dec(FCount);
    SiftDown(0);
  end;
end;

{
  Finds the N smallest elements in a 2D integer array.
  Time Complexity: O(R * C * log N) where R is rows and C is columns.
  Space Complexity: O(N) auxiliary space for the bounded heap.
}
function FindNSmallest(const Matrix: T2DIntArray; N: Integer): T1DIntArray;
var
  Heap: TBoundedMaxHeap;
  Row, Col, TotalElements: Integer;
begin
  { Edge cases: empty matrix or non-positive N }
  if (Length(Matrix) = 0) or (N <= 0) then
  begin
    SetLength(Result, 0);
    Exit;
  end;

  { Count total elements across all rows }
  TotalElements := 0;
  for Row := 0 to High(Matrix) do
    Inc(TotalElements, Length(Matrix[Row]));

  { Clamp N to the total number of available elements }
  N := Min(N, TotalElements);

  Heap.Initialize(N);

  { Process every element in the 2D array }
  for Row := 0 to High(Matrix) do
  begin
    for Col := 0 to High(Matrix[Row]) do
    begin
      Heap.PushOrReplace(Matrix[Row][Col]);
    end;
  end;

  { Extract elements into ascending sorted order }
  Result := Heap.ExtractSortedAscending;
end;

{ Helper procedure to display a 1D array }
procedure Print1DArray(const Arr: T1DIntArray);
var
  I: Integer;
begin
  Write('[');
  for I := 0 to High(Arr) do
  begin
    Write(Arr[I]);
    if I < High(Arr) then
      Write(', ');
  end;
  Writeln(']');
end;

{ Helper procedure to display a 2D matrix }
procedure Print2DArray(const Matrix: T2DIntArray);
var
  Row, Col: Integer;
begin
  for Row := 0 to High(Matrix) do
  begin
    Write('  [');
    for Col := 0 to High(Matrix[Row]) do
    begin
      Write(Matrix[Row][Col]:4);
      if Col < High(Matrix[Row]) then
        Write(',');
    end;
    Writeln(' ]');
  end;
end;

var
  Grid: T2DIntArray;
  Smallest: T1DIntArray;
  N: Integer;
begin
  { Initialize a sample 2D array (4x4) }
  SetLength(Grid, 4, 4);

  Grid[0][0] := 42; Grid[0][1] := 12; Grid[0][2] := 85; Grid[0][3] :=  3;
  Grid[1][0] :=  7; Grid[1][1] := 99; Grid[1][2] := 15; Grid[1][3] := 23;
  Grid[2][0] := 64; Grid[2][1] :=  1; Grid[2][2] := 18; Grid[2][3] := 30;
  Grid[3][0] :=  3; Grid[3][1] := 55; Grid[3][2] := 11; Grid[3][3] := 90;

  Writeln('Input Matrix:');
  Print2DArray(Grid);
  Writeln;

  N := 5;
  Writeln(Format('Finding the %d smallest values:', [N]));
  Smallest := FindNSmallest(Grid, N);
  Print1DArray(Smallest);
end.


(*
run:

Input Matrix:
  [  42,  12,  85,   3 ]
  [   7,  99,  15,  23 ]
  [  64,   1,  18,  30 ]
  [   3,  55,  11,  90 ]

Finding the 5 smallest values:
[1, 3, 3, 7, 11]

*)

 



answered 5 days ago by avibootz
...