1. Remova os elementos da lista vinculada
Descrição do título:
Dado um nó principal de uma lista encadeada head
e um inteiro val
, exclua todos Node.val == val
os nós satisfeitos na lista encadeada e retorne um novo nó principal .
Ideias:
Traversal normal, encontre o valor do valor e o mesmo nó no título para liberar, existem duas situações:
A primeira é que o nó principal é o valor, apontando diretamente o nó principal para o próximo;
O segundo caso é que o segundo nó começa com valor e precisa haver um nó anterior apontando para o próximo nó de valor.
Código fonte:
struct ListNode* removeElements(struct ListNode* head, int val)
{
//链表本身为空
if(head==NULL)
return NULL;
struct ListNode* prev = NULL;
while(1)//头节点开始就是值
{
if(head->val==val)
{
prev=head;
head=head->next;
free(prev);
if(head==NULL)
{
return NULL;
}
}
else
{
break;
}
}
struct ListNode* cur = head;
while(cur)//从第二个开始才是value,可以使用prev,因为第一个不是value,可以存储
{
//这一部分卡了好久
if(cur->val==val)
{
prev->next=cur->next;
struct ListNode* del=cur;
free(del);
cur=prev->next;
}
else
{
prev=cur;
cur=cur->next;
}
}
return head;
}
Em segundo lugar, o nó intermediário da lista encadeada
Descrição do título:
Dado o nó principal da lista encadeada individualmente head
, encontre e retorne o nó do meio da lista encadeada.
Se houver dois nós intermediários, retorne o segundo nó intermediário.
Ideias:
Use o método de ponteiro rápido e lento .
Execute um ciclo, primeiro deixe o ponteiro rápido dar dois passos, então deixe o ponteiro lento dar um passo , até que o ponteiro rápido aponte para vazio ou o próximo ponteiro rápido aponte para vazio, então o ponteiro lento aponte para o nó do meio , e também satisfaz o segundo Node.
código:
struct ListNode* middleNode(struct ListNode* head)
{
//快慢指针,快指针走两步,慢指针走一步
struct ListNode* slow = head;
struct ListNode* fast = head;
while(fast&&fast->next)
{
fast=fast->next->next;
slow=slow->next;
}
return slow;
}
3. O penúltimo nó k na lista encadeada
Descrição do título:
Insira uma lista encadeada e imprima o k-ésimo último nó na lista encadeada.
Ideias:
É também a ideia de ponteiros rápidos e lentos .
Deixe o ponteiro rápido percorrer k etapas primeiro e, em seguida, deixe o ponteiro rápido e o ponteiro lento caminharem juntos até que o ponteiro rápido esteja vazio .
Esta questão tem alguns pontos para prestar atenção aos detalhes, como k é maior que o número de nós da lista encadeada, k==0, mas esses são pequenos detalhes, a ideia principal ainda é o ponteiro de velocidade ~
código:
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
// write code here
if(pListHead==NULL||k==0)//k=0和链表为空的情况
{
return NULL;
}
struct ListNode* fast=pListHead;
struct ListNode* slow=pListHead;
while(k--)//先让快指针走k步
{
fast=fast->next;
if(fast==NULL)
{
break;
}
}
if(k>0)//k大于链表结点的个数的情况
{
return NULL;
}
while(fast)
{
fast=fast->next;
slow=slow->next;
}
return slow;
}
Quarto, inverta a lista encadeada
Descrição do título:
Dado o nó principal da lista encadeada individualmente head
, inverta a lista encadeada e retorne a lista encadeada invertida.
Ideias:
Atravesse a lista encadeada sequencialmente, começando do primeiro nó para a inserção da cauda . Observe que a inserção da cauda aqui não é a função de pushback na lista encadeada individualmente rasgada à mão, mas os nós devem ser removidos um por um.
Equivale a aprender outra forma de inserção de cauda, ao invés de alterar diretamente o valor do nó de cabeça, mas apontar o nó de cabeça original para o novo nó de cabeça.
código:
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* newhead=NULL;
struct ListNode* next=NULL;
//头插
while(head)
{
next=head->next;
head->next=newhead;
newhead=head;
head=next;
}
return newhead;
}
5. Mescle duas listas encadeadas ordenadas
Descrição do título:
Mescla duas listas ascendentes em uma nova lista ascendente e retorna. A nova lista encadeada é formada unindo todos os nós das duas listas encadeadas dadas.
Ideias:
Compare a ordem dos primeiros nós das duas listas encadeadas, pegue a cauda menor e insira-a em um novo nó de cabeça , se um terminar antes, insira o outro diretamente na nova lista encadeada
código:
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
if(list1==NULL)
{
return list2;
}
if(list2==NULL)
{
return list1;
}
//取小的尾插
//为何这题可以直接定义一个尾结点?
struct ListNode* newhead=NULL;
struct ListNode* tail=NULL;
while(list1 && list2)
{
if(list1->val <= list2->val)
{
if(newhead==NULL)
{
newhead=tail=list1;
//tail=newhead->next;
}
else
{
tail->next=list1;
//tail=list1->next;
tail=tail->next;
}
list1=list1->next;
}
else
{
if(newhead==NULL)
{
tail=newhead=list2;
//tail=newhead->next;
}
else
{
tail->next=list2;
tail=tail->next;
}
list2=list2->next;
}
}
if(list1)//剩余直接尾插
{
//tail=list1;
tail->next=list1;
}
if(list2)
{
//tail=list2;
tail->next=list2;
}
return newhead;
}
Tomar cuidado:
No novo capítulo de estrutura de dados, há mais pequenos detalhes a serem observados, é melhor considerar todas as situações que podem ser consideradas, caso contrário, será mais trabalhoso depurar. Geralmente, somente quando o nó principal está vazio, a atribuição direta é igual a e o restante geralmente precisa ser o próximo vinculado.