2008-11-10 8 views
11

Tengo esta matriz. Escribí una función MostFreq que toma una matriz de enteros y devuelve 2 valores: el número más frecuente en la matriz y su frecuencia comprueba este código. ¿Qué crees? ¿Hay una mejor manera de hacerlo?El número más frecuente en una matriz

static void Main() 
{ 
    int [] M={4,5,6,4,4,3,5,3}; 
    int x; 
    int f=MyMath.MostFreq(M,out x); 
    console.WriteLine("the most Frequent Item = {0} with frequency = {1}",x,f); 
} 

=====

en el MyMath clase

public static int MostFreq(int[] _M, out int x) 
{ 
    //First I need to sort the array in ascending order 
    int Max_Freq, No_Freq, i, k; 
    Array.Sort(_M);       
    k = _M[0]; 
    Max_Freq = 0; i = 0; x = 0; 
    while (i < _M.Length) 
    { 
     //No_Freq= the frequency of the current number 
     No_Freq = 0; 
     //X here is the number which is appear in the array Frequently 
     while (k == _M[i]) 
     { 
      No_Freq++; 
      i++; 
      if (i == _M.Length) 
       break; 
     } 
     if (No_Freq > Max_Freq) 
     { 
      //so it will be printed the same 
      Max_Freq = No_Freq; 
      x = k; 
     } 
     if (i < _M.Length) k = _M[i]; 
    } 
    return (Max_Freq); 
} 
+0

¿Por qué se ha declinado y se ha calificado ofensivo? – FlySwat

+0

@Brandon ¿Qué versión de C# estás usando? –

+0

Acabo de editar las etiquetas para que la gente sepa a qué versión apuntar. –

Respuesta

7

LINQ para arriba. Sé que esto es en VB, pero usted debería ser capaz de convertirlo en C#:

Dim i = From Numbers In ints _ 
      Group Numbers By Numbers Into Group _ 
      Aggregate feq In Group Into Count() _ 
      Select New With {.Number = Numbers, .Count = Count} 

EDIT: Ahora en C# también:

var i = from numbers in M 
       group numbers by numbers into grouped 
       select new { Number = grouped.Key, Freq = grouped.Count()}; 
+0

Me gustas por eso :) –

3

Desde un punto de vista de la ingeniería de software, que se puede esperar una función llamada Most Freq devolverá el elemento con la frecuencia más alta, no la frecuencia en sí misma. Cambiaría tus valores de ida y vuelta.

5

Suponiendo que no se puede utilizar LINQ, probablemente me acerco al algoritmo de la siguiente manera:

  • Crear diccionario de clave/valor
  • Iterar la matriz, agregue una clave del diccionario para cada elem único, incrementa el valor cada vez que se repite ese elemento.
  • Acceda a las teclas del diccionario y devuelva el elemento con el valor más alto.

Esta no es una gran solución, pero es simple, ContainsKey es una búsqueda O (1), por lo que será como mucho iterar dos veces.

+0

sí, eso es genial Lo intentaré gracias –

1

Puede eliminar la clasificación que hace al inicio iterando toda la matriz una vez, manteniendo un recuento de cuántas veces se encuentra con cada valor en una matriz temporal, y luego iterando la matriz temporal para el número más alto. También puede mantener el conteo de frecuencia más alto y el ítem más frecuente en todo momento.

Diferentes tipos tienen diferentes eficiencias en diferentes tipos de datos, por supuesto, pero este sería el peor caso de solo dos iteraciones.

Editar: Disculpas por la repetición ... 'Tweren't allí cuando comenzaron :)

0
int count = 1; 
int currentIndex = 0; 
for (int i = 1; i < A.Length; i++) 
{ 
    if (A[i] == A[currentIndex]) 
     count++; 
    else 
     count--; 
    if (count == 0) 
    { 
     currentIndex = i; 
     count = 1; 
    } 
} 

int mostFreq = A[currentIndex]; 
+2

Incluso con un algoritmo simple, es una buena práctica explicar lo que hace y lo más importante por qué lo haces de esa manera. Cuáles son las ventajas, desventajas, etc. :) – ForceMagic

0
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace MostFrequentElement 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      int[] array = new int[] { 4, 1, 1, 4, 2, 3, 4, 4, 1, 2, 4, 9, 3, 1, 1, 7, 7, 7, 7, 7 }; 
      Array.Sort(array, (a, b) => a.CompareTo(b)); 
      int counter = 1; 
      int temp=0 ; 

      List<int> LOCE = new List<int>(); 
      foreach (int i in array) 
      { 
       counter = 1; 
       foreach (int j in array) 

{ 
        if (array[j] == array[i]) 
        { 
         counter++; 
        } 
        else { 
        counter=1; 
        } 
        if (counter == temp) 
        { 
         LOCE.Add(array[i]); 
        } 
        if (counter > temp) 
        { 
         LOCE.Clear(); 
         LOCE.Add(array[i]); 
         temp = counter; 

        } 
       } 

      } 
      foreach (var element in LOCE) 
      { 
       Console.Write(element + ","); 
      } 
      Console.WriteLine(); 
      Console.WriteLine("(" + temp + " times)"); 
      Console.Read(); 
     } 
    } 
} 
0

He aquí un ejemplo de cómo se podría hacer sin LINQ y no hay diccionarios y listas , sólo dos bucles anidados simples:

public class MostFrequentNumber 
{ 
    public static void Main() 
    { 
     int[] numbers = Console.ReadLine().Split(' ').Select(int.Parse).ToArray(); 

     int counter = 0; 
     int longestOccurance = 0; 
     int mostFrequentNumber = 0; 

     for (int i = 0; i < numbers.Length; i++) 
     { 
      counter = 0; 

      for (int j = 0; j < numbers.Length; j++) 
      { 
       if (numbers[j] == numbers[i]) 
       { 
        counter++; 
       } 
      } 

      if (counter > longestOccurance) 
      { 
       longestOccurance = counter; 
       mostFrequentNumber = numbers[i]; 
      } 
     } 

     Console.WriteLine(mostFrequentNumber); 
     //Console.WriteLine($"occured {longestOccurance} times"); 
    } 
} 

se obtiene el valor del número que ocurre con mayor frecuencia, y (comentado) se puede conseguir también el número de las ocurrencias. Sé que tengo un "uso de Linq;", eso es solo para convertir la cadena de entrada inicial a una matriz int y para ahorrar un par de líneas y un ciclo de análisis. Algoritmo está bien, incluso sin él, si llena la matriz de la forma "larga" ...

Cuestiones relacionadas