LeetCode[70/83/88] Treppen steigen, doppelte Elemente in sortierten verknüpften Listen löschen, zwei geordnete Arrays zusammenführen C/C++ – Tag 6

70. Steigen Sie die Treppe hinauf

Titelbeschreibung [einfach]:
Angenommen, Sie steigen Treppen. Es dauert n Schritte, bis Sie die Spitze des Gebäudes erreichen können.

Sie können 1 oder 2 Stufen gleichzeitig erklimmen. Auf wie vielen verschiedenen Wegen kann man zur Spitze des Gebäudes gelangen?

Beispiel 1:
Eingabe: n = 3
Ausgabe: 3
Erläuterung: Es gibt drei Möglichkeiten, auf die Spitze des Gebäudes zu klettern.

  1. Stufe 1 + Stufe 1 + Stufe 1
  2. Stufe 1 + Stufe 2
  3. 2. Stufe + 1. Stufe

Idee [Dynamische Programmierung]:

Tatsächlich ähnelt er der Fibonacci-Folge etwas , außer dass F[2]=2 ist.
Dies ist ein typisches Problem der dynamischen Programmierung .

Der Lösungsprozess der dynamischen Programmiermethode besteht aus drei Schritten :

  1. Teilprobleme aufteilen ; das ursprüngliche Problem in mehrere überlappende Teilprobleme zerlegen
  2. Bestimmen Sie die dynamische Programmierfunktion . Analysieren Sie, ob das Problem das Optimalitätsprinzip erfüllt, und ermitteln Sie die rekursive Formel der dynamischen Programmierfunktion.
  3. Füllen Sie das Formular aus . Entwerfen Sie eine Tabelle, berechnen Sie mithilfe der Rekursion die Lösung jedes Teilproblems von unten nach oben und füllen Sie die Tabelle aus, um den dynamischen Programmierprozess zu realisieren.

1. Teilprobleme aufteilen

Die Anzahl der Teilprobleme, die wir teilen = die Anzahl der Möglichkeiten, die n-te Treppenstufe zu erklimmen = Summe von 2 Teilen

  1. Die Anzahl der Möglichkeiten, n-1 Stufen zu erklimmen, denn wenn Sie eine weitere Stufe erklimmen, gelangen Sie zur n-ten Stufe
  2. Die Anzahl der Möglichkeiten, n-2 Treppen zu erklimmen, da das Erklimmen von 2 weiteren Stufen zur n-ten Stufe führt

2. Bestimmen Sie die dynamische Programmierfunktion.
Es ist nicht schwer herauszufinden, dass das Klettern von n Treppenstufen letztendlich zu einer Anzahl von Möglichkeiten zum Klettern von n-1 Treppenstufen und einer Anzahl von Möglichkeiten zum Klettern von n-1 Treppenstufen führt.
Daher kann die folgende dynamische Programmierfunktion abgeleitet werden:
dp[ i ]=dp[ i - 1 ] + dp[ i - 2 ] (genau dann, wenn i>2 ist, ist die Gleichung aufgestellt)

Bestimmen Sie den Anfangswert:
dp[1] = 1 ; dp[2] = 2 ;

Wenn Sie jedoch nur darum bitten, zur ersten oder zweiten Ordnung zu wechseln, können wir den ursprünglichen Wert direkt zurückgeben. Die dynamische Programmierfunktion beginnt bei 3, dh sie tritt bei 3 in den Zyklus ein. Aber im Array müssen wir noch die Werte von dp[1] und dp[2] festlegen.

C++-Code:

class Solution {
    
    
public:
    int climbStairs(int n) {
    
    
        if(n<=2)
        return n;
        int* dp = new int[n+1] ; //使用 new 来创建动态数组
        dp[1] = 1 ;
        dp[2] = 2 ;
        for(int i = 3 ; i <= n ; i++){
    
    
            dp[i] = dp[i - 1] + dp[i - 2] ;
        }
        return dp[n] ;
    }
};

Das Clevere an der Verwendung von C++ in dieser Frage ist, dass new zum Erstellen dynamischer Arrays verwendet werden kann.

Zeitkomplexität: O(n);

83. Löschen Sie doppelte Elemente in der sortierten Liste

Titelbeschreibung [Einfach]:
Löschen Sie anhand des Kopfes einer sortierten verknüpften Liste alle doppelten Elemente, sodass jedes Element nur einmal vorkommt. Gibt eine sortierte verknüpfte Liste zurück.

Beispiel 1:
Eingabe: head = [1,1,2]
Ausgabe: [1,2]

Idee [Merkmale des verknüpften Listenzeigers]:

Da die verknüpfte Liste standardmäßig sortiert ist, ähnelt diese Frage dem vorherigen Vergleich zum Löschen doppelter Elemente im Array. Wir definieren zunächst einen Zeiger h so, dass er gleich dem Kopfzeiger head ist. Beim Durchlaufen der gesamten verknüpften Liste löschen wir das nächste Element, wenn das Element, auf das h zeigt, dem nächsten Element entspricht, auf das h zeigt. Wir verwenden die Eigenschaften der verknüpften Liste, um das nächste Element, auf das h zeigt, direkt auf das nächste Element zu verweisen, um den Zweck des Löschens desselben Elements zu erreichen. Lassen Sie h nach dem Löschen gleich dem nächsten Knoten sein, auf den h zeigt, dh beginnen Sie mit der Rückwärtsbewegung entlang der verknüpften Liste. Wenn wir durchlaufen, bis der nächste Punkt NULL ist, bedeutet dies, dass wir das Ende der verknüpften Liste erreicht haben und die Durchquerung endet.

Diese Frage besagt, dass Daten ein Wert sind. Unser Zeiger zeigt also nicht auf Daten, sondern auf einen Wert.

C++-Code:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */Oclass Solution {
    
    
public:
    ListNode* deleteDuplicates(ListNode* head) {
    
    
        ListNode* h = head ;
        while(h != NULL && h->next != NULL ){
    
    
        if(h->val == h->next->val )
            h->next = h->next->next;
        else h = h ->next;
        }
        return head;
    }
};

Erstellen Sie einen neuen Zeiger, um ihn mit dem Kopfzeiger gleichzusetzen, anstatt den Kopfzeiger direkt zu verwenden. Der Grund dafür ist: Um am Ende zum Kopfknoten zurückzukehren, müssen Sie ihn zuerst speichern, und die nachfolgende Schleife ändert die Position davon Knoten, daher ist es am besten, einen neuen Knoten zu erstellen

Kehren Sie schließlich zum Kopf zurück: Obwohl sich der Kopf nicht geändert hat, hat sich der nächste Kopf geändert, sodass sich die gesamte verknüpfte Liste geändert hat.
Anstatt h zurückzugeben: h kann hier als Arbeitsknoten verstanden werden: Er wird zum Durchlaufen der verknüpften Liste und zum Ändern der Struktur der verknüpften Liste verwendet. head stellt diese verknüpfte Liste dar, da es immer auf den Kopf der verknüpften Liste zeigt (unabhängig davon, ob Sie die verknüpfte Liste ändern oder nicht).

Zeitkomplexität: O(n);

88. Zwei sortierte Arrays zusammenführen

Titelbeschreibung [einfach]:
Sie erhalten zwei ganzzahlige Arrays nums1 und nums2, die in nicht absteigender Reihenfolge angeordnet sind, sowie zwei ganze Zahlen m und n, die die Anzahl der Elemente in nums1 bzw. nums2 darstellen.

Bitte führen Sie nums2 mit nums1 zusammen, damit das zusammengeführte Array ebenfalls in nicht absteigender Reihenfolge angeordnet wird.

Hinweis : Letztendlich sollte das zusammengeführte Array nicht von der Funktion zurückgegeben, sondern im Array nums1 gespeichert werden . Um dieser Situation gerecht zu werden, beträgt die Anfangslänge von nums1 m + n, wobei die ersten m Elemente Elemente darstellen, die zusammengeführt werden sollen, und die letzten n Elemente 0 sind und ignoriert werden sollten. nums2 hat die Länge n.

Beispiel 1:
Eingabe: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
Ausgabe: [1,2,2,3,5 ,6]
Erläuterung : [1,2,3] und [2,5,6] müssen zusammengeführt werden.
Das kombinierte Ergebnis ist [1,2,2,3,5,6], wobei die Elemente in nums1 kursiv und fett markiert sind.

Idee [umgekehrter Doppelzeiger]:

Vergleichen Sie zwei Arrays und wählen Sie das größte aus, um es am Ende von nums1 einzufügen. Nachdem nums2 in nums1 gestopft wurde, besteht keine Notwendigkeit, die Verarbeitung fortzusetzen.

C++-Code:

class Solution {
    
    
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
    
    
        int i = nums1.size() ;

        while (n > 0) {
    
    
            if (m > 0 && nums1[m-1] > nums2[n-1]) {
    
    
                nums1[--i] = nums1[--m];  //替代swap
            }else{
    
    
                nums1[--i] = nums2[--n]; 
            }
          
        }
    }
};

Guess you like

Origin blog.csdn.net/Lailalalala/article/details/126070760