le mie informazioni di contatto
Posta[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
💎 欢迎各位大佬互三:la mia home page
206. Elenco concatenato inverso
Riflessione: se non si libera spazio aggiuntivo e si modifica solo l'elenco collegato originale, quale metodo dovrebbe essere utilizzato?
Basta partire dal secondo elemento ed eseguire in sequenza l'inserimento della testa.
Quindi modifica semplicemente il riferimento e punta l'ultimo elemento su null
- class Solution {
- public ListNode reverseList(ListNode head) {
- //head为null,直接返回
- if(head == null){
- return head;
- }
-
- ListNode cur = head.next;
- //head变为了末尾元素,指向null
- head.next = null;
- while(cur!=null){
- //curn为cur的next节点,便于往后移动
- ListNode curn = cur.next;
- cur.next = head;
- head = cur;
- //更新cur
- cur = curn;
- }
- return head;
- }
- }
876. Nodo intermedio di lista concatenata
Il primo metodo che mi viene in mente per questa domanda è sicuramente quello di definire un cnt, attraversare una volta l'elenco collegato, quindi trovare il numero centrale e quindi attraversare il valore restituito. Questo metodo è molto semplice, ma cosa succede se è necessario attraversare il elenco collegato solo una volta per trovare il nodo intermedio?
Ecco una nuova idea: usa i puntatori veloci e lenti, partendo da head. Il puntatore veloce si sposta di due nodi ogni volta e il puntatore lento si sposta di un nodo ogni volta. Questo raggiunge l'obiettivo finale?
Quindi implementiamolo:
- class Solution {
- public ListNode middleNode(ListNode head) {
- if(head == null){
- return null;
- }
- ListNode fast = head;
- ListNode slow = head;
- while(fast!= null&&fast.next!= null){
- fast = fast.next.next;
- slow = slow.next;
- }
- return slow;
- }
- }
Sarebbe più efficiente?
Domanda dell'intervista 02.02. Restituisce il k-esimo nodo dall'ultimo
La prima cosa che mi viene in mente per questa domanda è attraversarlo una volta per ottenere la lunghezza totale, quindi trovare il k-esimo nodo dall'ultimo. Tuttavia, sulla base della domanda precedente, puoi pensare a un altro metodo: Allo stesso modo,Utilizzando i puntatori veloce e lento, lascia andare prima i nodi fast k-1, quindi vai lento e veloce allo stesso tempo. Quando il successivo di fast è nullo, significa che fast ha raggiunto l'ultimo nodo e slow in questo momento è il k-esimo nodo dal basso.
Questa domanda indica che l'input k è legale, quindi non è necessario alcun giudizio aggiuntivo. Come giudicare se k è illegale ed è necessario che la lunghezza dell'elenco collegato non possa essere trovata direttamente, quindi è necessario giudicare lentamente mentre si cammina.
- class Solution {
- public int kthToLast(ListNode head, int k) {
- if (head == null) {
- return -1;
- }
- ListNode fast = head;
- ListNode slow = head;
- int cnt = 0;
- while (cnt != k - 1) {
- //判断k的合法性,虽然本题不用判断
- fast = fast.next;
- if(fast == null){
- return;
- }
- cnt++;
- }
- //slow和fast同时移动
-
- while (fast.next != null) {
- fast = fast.next;
- slow = slow.next;
- }
- return slow.val;
- }
- }
21. Unisci due elenchi collegati ordinati
Idea:Devi solo definire un nuovo nodo newH, quindi confrontare il val di headA e headB. Per trovare finalmente il nodo head dell'elenco collegato unito, devi anche definire un tmp = newH, e quindi chi ha il più piccolo. tmp.next lo indicherà.
- class Solution {
- public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
- ListNode head = new ListNode();
- ListNode tmp = head;
-
- while(list1!=null&&list2!=null){
- if(list1.val < list2.val){
- tmp.next = list1;
- list1 = list1.next;
- tmp = tmp.next;
- }else{
- tmp.next = list2;
- list2 = list2.next;
- tmp = tmp.next;
- }
- }
- //判断剩余的情况
- if(list1!=null){
- tmp.next = list1;
- }else if(list2!=null){
- tmp.next = list2;
- }
- return head.next;
- }
- }
Divisione dell'elenco collegato CM11
Questa è una domanda per un'intervista su Niuke. Il significato della domanda è dividere l'elenco collegato. Il lato sinistro di x è minore di x e il lato destro è maggiore di x. L'ordine originale non può essere modificato.
Idea: definire un nuovo nodo cur per attraversare l'elenco collegato originale (per evitare che l'elenco collegato originale venga modificato), inserire tutto ciò che è più grande di x in un elenco collegato, inserire tutto ciò che è più piccolo di x in un elenco collegato e infine connettere i due elenchi collegati.
- public class Partition {
- public ListNode partition(ListNode pHead, int x) {
- ListNode bs = null;
- ListNode be = null;
- ListNode as = null;
- ListNode ae = null;
- ListNode cur = pHead;
- while (cur != null) {
- if (cur.val < x) {
- //处理刚开始为null的情况
- if (bs == null) {
- bs = be = cur;
- }else{
- be.next = cur;
- be = be.next;
- }
- }else{
- if(as == null){
- as = ae = cur;
- }else{
- ae.next = cur;
- ae = ae.next;
- }
- }
- cur = cur.next;
- }
- //都是比x大的情况
- if(bs == null){
- return as;
- }
- be.next = as;
- //最后都要置为null,不然可能会报错
- if(as!=null){
- ae.next = null;
- }
- return bs;
- }
- }
Va notato che se sono maggiori di x, cioè bs = null, allora verrà restituito direttamente as e se as.next viene infine impostato su null
OR36 struttura palindroma della lista concatenata
Questa è una domanda di Niuke, perché ha requisiti di complessità temporale e di complessità spaziale, il che significa che non è possibile aprire un array aggiuntivo, altrimenti la complessità spaziale non verrà superata e l'attraversamento normale avrà una complessità di O(n)
L'idea è questa: prima trova il nodo centrale lento dell'elenco collegato, quindi inverti la parte dal centro alla fine. Il nodo principale viene attraversato all'indietro e anche il nodo lento viene attraversato all'indietro i valorisono diversi, significa che non restituiscono la struttura del testo
L'inversione dell'elenco collegato e la ricerca del nodo intermedio sono già stati praticati in precedenza
- public class PalindromeList {
- public boolean chkPalindrome(ListNode head) {
- if (head == null) {
- return true;
- }
- //找到中间节点
- ListNode fast = head;
- ListNode slow = head;
- while (fast != null && fast.next != null) {
- fast = fast.next.next;
- slow = slow.next;
- }
- //从slow开始到末尾反转
- ListNode cur = slow.next;
- while (cur != null) {
- ListNode curn = cur.next;
- cur.next = slow;
- slow = cur;
- cur = curn;
- }
- //判断回文
- while (head != slow) {
- if (head.val != slow.val) {
- return false;
- }
- //判断偶数节点
- if (head.next == slow) {
- return true;
- }
- head = head.next;
- slow = slow.next;
- }
- return true;
- }
- }
Va notato che esiste anche una differenza nel giudizio della lista concatenata di nodi con numeri dispari e della lista concatenata di nodi con numeri pari.
Se il nodo con numero pari viene spostato in alto, causerà un ciclo infinito, quindi è necessaria un'ulteriore valutazione per il nodo con numero pari.
160. Elenchi concatenati intersecati
La lista concatenata che si interseca è una trasformazione simile a "Y", come mostrato in figura
Anche l’immagine nella domanda qui sotto è molto chiara.
Idea: perché se A è corto o B è corto, la differenza tra loro è la parte prima dell'intersezione. Devi solo spostare la lunga lista concatenata di una differenza, quindi i due nodi della lista concatenata si spostano indietro contemporaneamente nodi identici devono intersecare il nodo di
- public class Solution {
- public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
- ListNode pl = headA;
- ListNode ps = headB;
- int cnta = 0,cntb = 0;
- //计算两个链表的长度
- while(pl!=null){
- pl = pl.next;
- cnta++;
- }
- while(ps!=null){
- ps = ps.next;
- cntb++;
- }
- //如果链表b长,就更新pl,ps
- int len = cnta - cntb;
- //上面求长度时pl,ps都为空了,所以这里再重新指向
- pl = headA;
- ps = headB;
- if(len < 0){
- pl = headB;
- ps = headA;
- len = cntb - cnta;
- }
- //移动差值
- while(len!=0){
- pl = pl.next;
- len--;
- }
- //找到相交节点
- while(pl!=ps){
- pl = pl.next;
- ps = ps.next;
- }
- //链表不相交的情况
- if(pl == null) return null;
- return pl;
- }
- }
Infine, dobbiamo aggiungere la situazione disgiunta Anche se possiamo superare questa domanda senza aggiungerla, dobbiamo comunque aggiungerla per motivi di rigore.
141. Elenco circolare collegato
Come determinare se un elenco collegato ha un ciclo:Usa ancora il puntatore di velocità, proprio come due persone che corrono nel parco giochi, una persona corre veloce e l'altra persona corre lentamente Poiché il parco giochi è un anello, quello veloce può sicuramente superare quello lento. In questo momento si sono incontrati , ma se non fosse stato per Tamaki, non sarebbero mai riusciti a incontrarsi, proprio come una dea che non puoi catturare, non importa quanto duramente la insegui.
Ma c'è un'altra situazione. Se si tratta di un anello con due nodi, e il puntatore veloce definito fa 3 passi alla volta e il puntatore lento fa 1 passo alla volta, allora non si incontreranno mai.
Pertanto, i puntatori definiti devono valutare quanti passi compiere ogni volta. Se uno fa 2 passi e l'altro ne fa 1, si incontreranno sicuramente.
- public class Solution {
- public boolean hasCycle(ListNode head) {
- ListNode fast = head;
- ListNode slow = head;
- while(fast!=null&&fast.next!=null){
- fast = fast.next.next;
- slow = slow.next;
- if(fast == slow) return true;
- }
- return false;
- }
- }
142. Lista Circolare Collegata II
Questa volta devi scoprire il punto di ingresso nell'anello dopo aver giudicato se si tratta di un anello nella domanda precedente. Puoi fare il seguente ragionamento
- public class Solution {
- public ListNode detectCycle(ListNode head) {
- ListNode fast = head;
- ListNode slow = head;
- //判断环
- while(fast!=null&&fast.next!=null){
- fast = fast.next.next;
- slow = slow.next;
- if(fast == slow) break;
- }
- if(fast == null||fast.next == null) return null;
- slow = head;
- //寻找环
- while(slow!=fast){
- slow = slow.next;
- fast = fast.next;
- }
- return slow;
- }
- }
Ciò che occorre aggiungere è:
Quando l'anello è molto piccolo il risultato finale della semplificazione diventa quello sopra, ma il codice originale va comunque bene.