Um teste escrito por dia - 2020-9-19

Um teste escrito por dia - 2020-9-19

leetCode: 21. Mesclar duas listas vinculadas ordenadas (simples)

Os dois se fundiram em uma nova lista em ordem crescente de lista crescente e retornos. A nova lista vinculada é composta pela emenda de todos os nós das duas listas vinculadas fornecidas.

Exemplo:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

Método 1: recursão

Ideias

Podemos definir recursivamente a operação de mesclagem em duas listas vinculadas da seguinte maneira (ignorando as condições de limite, como listas vinculadas vazias etc.):

Insira a descrição da imagem aqui

Em outras palavras, um nó com o menor valor de cabeça das duas listas vinculadas é mesclado com o resultado da operação de mesclagem dos elementos restantes.

algoritmo

Modelamos diretamente o processo recursivo acima e precisamos considerar as condições de contorno.

Se l1 ou l2 for uma lista vinculada vazia desde o início, não há operação a ser mesclada, portanto, só precisamos retornar uma lista vinculada não vazia. Caso contrário, temos que determinar qual de l1 e l2 o nó principal da lista encadeada tem o menor valor e, então, decidir recursivamente o próximo nó a ser adicionado ao resultado. Se uma das duas listas vinculadas estiver vazia, a recursão termina.

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    
    
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    
    
  	  if (l1 == null) {
    
    
            return l2;
        } else if (l2 == null) {
    
    
            return l1;
        } else if (l1.val < l2.val) {
    
    
            l1.next = mergeTwoLists(l1.next, l2);
            return l1;
        } else {
    
    
            l2.next = mergeTwoLists(l1, l2.next);
            return l2;
        }

    }
}

Análise de complexidade:

时间复杂度:O(n+m)O(n + m)O(n+m),其中 nnn 和 mmm 分别为两个链表的长度。因为每次调用递归都会去掉 l1 或者 l2 的头节点(直到至少有一个链表为空),函数 mergeTwoList 至多只会递归调用每个节点一次。因此,时间复杂度取决于合并后的链表长度,即 O(n+m)O(n+m)O(n+m)。

空间复杂度:O(n+m)O(n + m)O(n+m),其中 nnn 和 mmm 分别为两个链表的长度。递归调用 mergeTwoLists 函数时需要消耗栈空间,栈空间的大小取决于递归调用的深度。结束递归调用时 mergeTwoLists 函数最多调用 n+mn+mn+m 次,因此空间复杂度为 O(n+m)O(n+m)O(n+m)。

Insira a descrição da imagem aqui

Método 2: Iteração

Ideias

Podemos implementar o algoritmo acima de forma iterativa. Quando l1 e l2 não são listas vinculadas vazias, determine qual de l1 e l2 tem o menor valor de nó principal e adicione o nó com o menor valor ao resultado. Quando um nó é adicionado ao resultado, ele corresponderá à lista vinculada O nó de é movido um bit para trás.

algoritmo

Primeiro, definimos uma pré-cabeça do nó sentinela, o que nos permite retornar à lista vinculada mesclada mais facilmente no final. Mantemos um ponteiro anterior, e o que precisamos fazer é ajustar seu próximo ponteiro. Em seguida, repetimos o seguinte processo até l1 ou l2 apontar para nulo: Se o valor do nó atual de l1 for menor ou igual a l2, conectamos o nó atual de l1 à parte de trás do nó anterior e movemos o ponteiro de l1 um bit para trás. Caso contrário, fazemos o mesmo para 12. Independentemente de qual elemento seguimos, precisamos mover o anterior um pouco para trás.

No final do loop, no máximo um de l1 e l2 não está vazio. Como as duas listas vinculadas de entrada estão em ordem, não importa qual lista vinculada não está vazia, todos os elementos que ela contém são maiores do que todos os elementos da lista vinculada previamente mesclada. Isso significa que precisamos apenas conectar a lista vinculada não vazia ao final da lista vinculada mesclada e retornar à lista vinculada mesclada.

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    
    
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    
    
  	 ListNode prehead = new ListNode(-1);

        ListNode prev = prehead;
        while (l1 != null && l2 != null) {
    
    
            if (l1.val <= l2.val) {
    
    
                prev.next = l1;
                l1 = l1.next;
            } else {
    
    
                prev.next = l2;
                l2 = l2.next;
            }
            prev = prev.next;
        }

        // 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
        prev.next = l1 == null ? l2 : l1;

        return prehead.next;
    }
}

Insira a descrição da imagem aqui

Acho que você gosta

Origin blog.csdn.net/qq_37924905/article/details/108683007
Recomendado
Clasificación