Radix-Sortierung und Verwendung von Arrays zur Vereinfachung der Problemlösung

Der Anblick von Hongdou ist unerträglich, ihre Augen sind voller Liebeskummertränen

Fügen Sie hier eine Bildbeschreibung ein

 Dieser Artikel soll Ihnen hauptsächlich dabei helfen, sich mit der Verwendung von Arrays zur Urteilsbildung vertraut zu machen. Nachdem Sie diesen Artikel gelesen haben, können Sie diese Idee in zukünftigen Fragen verwenden. Natürlich ist die Verwendung dieser Methode für die Fragen im Beispiel möglicherweise nicht die optimale Lösung, aber Es ist definitiv so. Sie können sehen, wie Sie das Problem lösen können, ohne zu viel nachzudenken. Natürlich werde ich auch andere Methoden der aufgeführten Probleme vorstellen, damit jeder darüber nachdenken kann. Kommen wir ohne weitere Umschweife zur Sache.

Radix-Sortierung
Idee: Es wurde ein Array angegeben, und das Array ist die Sequenz, die wir sortieren müssen. Öffnen Sie dann ein Array, und die Zahl n des Arrays ist die Zahl sortiert werden. Die größte Zahl ist +1 und alle werden auf 0 initialisiert. Sortieren Sie die Zahlen im Array nach Bedarf, suchen Sie die tiefgestellte Position der Zahl im neu geöffneten Array und ++ die Zahl an dieser Position.
Zum Beispiel:
Fügen Sie hier eine Bildbeschreibung ein
 Die Logik ist sehr einfach und wir sprechen direkt über die Optimierung. Es ist auf einen Blick ersichtlich, dass diese Art der Denkanordnung auch verschwindet In einigen Fällen ist viel Platz erforderlich, z. B. Wenn die sortierten Zahlen alle zwischen 1000 und 2000 liegen und wir beginnen, den Platz bei 0 zu öffnen, werden die ersten 1000 Leerzeichen vergebens verwendet, was zu einer enormen Platzverschwendung führt.
Wir können zuerst den Maximalwert und den Minimalwert im zu sortierenden Array durchlaufen und ermitteln. Die Differenz zwischen den beiden plus 1 ist der Platz, den wir öffnen müssen.
Der Code lautet wie folgt

//基数排序
void CountSort(int* a, int n)
{
    
    
	int min = a[0], max = a[0];
	for (int i = 0; i < n; i++)
	{
    
    
		if (a[i] < min)
		{
    
    
			min = a[i];
		}
		if (a[i] > max)
		{
    
    
			max = a[i];
		}
	}
	int range = max - min + 1;
	int* count = (int*)malloc(sizeof(int) * range);
	if (count == NULL)
	{
    
    
		perror("malloc fail");
		return;
	}
	memset(count, 0, sizeof(int) * range);
	//统计数据出现的次数
	for (int i = 0; i < n; i++)
	{
    
    
		count[a[i] - min]++;//开的空间是减去min的,所以排序数组中的数在存储时也要减去min。
	}
	int j = 0;
	for (int i = 0; i < range; i++)
	{
    
    
		while (count[i]--)
		{
    
    
			a[j++] = i + min;//该位置的数出现几次,就统计出几次
		}
	}
}

Zusammenfassung der Radix-Sortierung

  1. Die Zählsortierung ist sehr effizient, wenn der Datenbereich konzentriert ist, ihr anwendbarer Umfang und ihre Szenarien sind jedoch begrenzt. Was ist, wenn es eine Dezimalzahl ist? Sie können nicht mit Indizes speichern.
  2. Zeitkomplexität: O(N(Bereich))
  3. Raumkomplexität: O(N)

OK, stellen Sie 5 Fragen vor, die diese Idee nutzen, um jedem zu helfen, diese Methode zur Beantwortung von Fragen zu meistern
1, Fehlersammlung
Fügen Sie hier eine Bildbeschreibung ein
Es gibt viele Lösungen für dieses Problem
 Idee 1: Am einfachsten ist es, zuerst zu sortieren, dann können Sie die fehlenden Zahlen leicht finden, und wir wissen es bereits Enthält 1 bis n, können Sie alle Elemente im Array, in dem der Fehler aufgetreten ist, direkt summieren und subtrahieren. Kopieren Sie beispielsweise 5 in 7, und das Ergebnis nach der Subtraktion ist -2, dann ist die wiederholte Zahl 5 plus 2 bis 7.
 Idee 2: Nutzen Sie direkt die Idee der Radix-Sortierung. Öffnen Sie ein Array erneut (initialisieren Sie alle auf 0), ohne zu sortieren, und fügen Sie direkt die tiefgestellten Positionen hinzu, die allen Zahlen im angegebenen Satz entsprechen. Wenn eine bestimmte Zahl nicht angezeigt wird, wird natürlich die Zahl an dieser Position im neuen hinzugefügt Das geöffnete Array ist 0, das wiederholte ist 1.
Der Code lautet wie folgt

int* findErrorNums(int* nums, int numsSize, int* returnSize)
{
    
    
    int *array1,*array2,i;
    array1=(int*)calloc(numsSize,sizeof(int));
    array2=(int*)malloc(sizeof(int)*2);
    for(i=0;i<numsSize;i++)
    {
    
    
        array1[nums[i]-1]+=1;
    }
    for(i=0;i<numsSize;i++)
    {
    
    
        if(array1[i]==2)
        array2[0]=i+1;
        else if(array1[i]==0)
        array2[1]=i+1;
    }
    *returnSize=2;
    return array2;    
}

 Die Logik ist klar, die Zeitkomplexität ist O(N) und die Raumkomplexität ist O(N). Natürlich können Sie auch eine Beurteilung hinzufügen, um direkt nach dem Finden von zwei Zahlen aus der Schleife zu springen und so die Anzahl der Schleifen zu reduzieren.


2,Anzahl der Zeichen
Fügen Sie hier eine Bildbeschreibung ein

 Ebenso müssen wir noch herausfinden, ob eine bestimmte Zahl in einem Bereich existiert oder wie oft eine bestimmte Zahl vorkommt. Zeichen sind auch Ganzzahlen. Sie können die durch Zeichen dargestellten Ganzzahlen verwenden. Oder Sie können trotzdem lösen Das Problem entspricht der obigen Idee. Sie müssen nur die Konvertierung erzwingen. Die anderen Ideen sind alle gleich.
Der Code lautet wie folgt

#include <stdio.h>
int main() {
    
    
    int i = 0;
    int count = 0;
    char arr1[500];
    int arr[127] = {
    
     0 };

    scanf("%s", arr1);
    while (arr1[i] != '\0')
    {
    
    
        arr[(int)arr1[i]] = 1;
        i++;
    }
    for (int j = 0; j < 127; j++)
    {
    
    
        if (arr[j] == 1)
        {
    
    
            count++;
        }
    }
    printf("%d", count);
    return 0;
}

 Solange diese Idee verwendet wird, beträgt die Zeitkomplexität im Allgemeinen O (N). Wie in der Frage angegeben, liegt der Bereich zwischen 0 und 127. Es ist so cool, diese Idee zu verwenden.


3,Die meisten Elemente
Fügen Sie hier eine Bildbeschreibung ein
 Bei einem gegebenen Array findet die Anzahl der Vorkommen im Array größer als numsSize/2 Number, wir können diese Methode auch verwenden, aber dieses Problem kann mit dieser Methode nicht gelöst werden, obwohl wir bereits wissen, wie viel Platz wir öffnen möchten (Zeitkomplexität ist O(1) ), aber der Unterschied zwischen dem Maximal- und dem Minimalwert im Array beträgt 2*10^9. Diese Zahl ist zu groß, was bedeutet, dass der Raum, den wir öffnen müssen, auch sehr groß ist. Wenn wir dieses Problem lösen wollen , die Zeitkomplexität ist O(N) , es ist unmöglich, diese Methode zu verwenden. Aber man kann schummeln und Punkte sammeln. Wie oben erwähnt ist das nur eine Idee. Natürlich wird es auch andere Lösungen geben.
Der Code für die Verwendung von Array-Indizes lautet wie folgt

int majorityElement(int* nums, int numsSize) {
    
    
    int min = nums[0], max = nums[0];
	for (int i = 0; i < numsSize; i++)
	{
    
    
		if (nums[i] < min)
		{
    
    
			min = nums[i];
		}
		if (nums[i] > max)
		{
    
    
			max = nums[i];
		}
	}
    int range=max-min+1;
    int*arr=(int*)malloc(sizeof(int)*(range));
    for (int k = 0; k < range; k++)
	{
    
    
		arr[k] = 0;
	}
    for (int i = 0; i < numsSize; i++)
	{
    
    
		arr[nums[i] - min]++;
	}
	for(int j=0;j<range;j++)
    {
    
    
        if(arr[j]>numsSize/2)
        {
    
    
            return j+min;
        }
    }
	return -1;
}

 Wenn Sie genau hinschauen, werden Sie feststellen, dass die Methode der vorherigen Radix-Sortiermethode sehr ähnlich ist, mit der Ausnahme, dass die Dinge, die nach Abschluss der Speicherung beurteilt oder erhalten werden sollen, unterschiedlich sind.
Wenn Sie diesen Code ausführen, wird er nicht erfolgreich sein, da einige Anwendungsfälle speziell darauf abzielen.
Fügen Sie hier eine Bildbeschreibung ein
Es kann festgestellt werden, dass die meisten Anwendungsfälle bestanden wurden.
Fügen Sie hier eine Bildbeschreibung ein
 Die verbleibenden Schätzungen enthalten diese beiden Zahlen. Ich weiß nicht, ob die Optimierung erfolgreich sein kann Und ich möchte nicht so viel Zeit damit verbringen. Wenn der Zahlenunterschied im Array im Anwendungsfall nicht so groß ist, beträgt die zeitliche Komplexität dieser Lösung O (N) und die räumliche Komplexität O (1). ).

OK, wir können hier nicht einfach eine unpassierbare Methode einfügen.

Sprechen Sie über die Abstimmungsmethode (sehr clever)
 Nutzen Sie die Tatsache, dass die Häufigkeit der meisten Elemente im Array definitiv größer als numsSIze/2 ist, also verwenden Sie different Elemente, um dieselben Objekte zu eliminieren. Dann sind die Elemente von unten bis zum Ende definitiv dieselben, dh die meisten Elemente, nach denen wir suchen.
Fügen Sie hier eine Bildbeschreibung ein
Der Code lautet wie folgt

int majorityElement(int*nums,int numsSize)
{
    
    
    int candidate=nums[0];
    int flag=1;
    for(int i=1;i<numsSize;i++)
    {
    
    
        if(nums[i]==candidate)
        {
    
    
            flag++;
        }
        else
        {
    
    
            flag--;
            if(flag<0)
            {
    
    
                candidate=nums[i];
                flag=1;
            }
        }
    }
    return candidate;
}

4,Alle fehlenden Daten im Array finden
Fügen Sie hier eine Bildbeschreibung ein

 In ähnlicher Weise bezieht sich diese Frage auch darauf,ob eine bestimmte Zahl im Array vorhanden ist oder wie oft eine bestimmte Zahl vorkommt, mit der gleich Die Idee kann ohne Sortierung gefunden werden und die zeitliche Komplexität ist O(N), aber wir haben zusätzlichen Platz geöffnet. Was die fortgeschrittene Schreibmethode betrifft, legen wir sie zunächst beiseite.
Der Code lautet wie folgt

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize){
    
    
    int k=0;
    int*arr=(int*)malloc(sizeof(int)*(numsSize));
    int*ret=(int*)malloc(sizeof(int)*(numsSize));
    //memset(arr,0,(sizeof(int)*(numsSize+1)));
    for(int l=0;l<numsSize;l++)
    {
    
    
        arr[l]=0;
    }
    for(int i=0;i<numsSize;i++)
    {
    
    
        arr[nums[i]-1]++;
    }
    for(int j=0;j<numsSize;j++)
    {
    
    
        if(arr[j]==0)
        {
    
    
            ret[k++]=j+1;
            //*returnSize++;
        }
    }
    *returnSize=k;
    return ret;
}

Zusammenfassung: Um die Anzahl der Vorkommen einer bestimmten Zahl (insbesondere ungeordneter) im Array zu bestimmen (um festzustellen, ob sie angezeigt wird oder nicht, ist die Anzahl der Vorkommen 0), können Sie diese Methode verwenden Dasselbe wie beim Radix-Sortierprinzip. Raum wird gegen Zeit ausgetauscht, was beim Öffnen von Raum ein Muss ist.
 Es ist vorbei, es ist vorbei, ich hoffe, Sie gewinnen etwas, das ist die größte Motivation für meine Kreation.

Guess you like

Origin blog.csdn.net/qq_75270497/article/details/134701619