Teknologian jakaminen

Valitut Likou, Niukelian pintatestikysymykset

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

💎 欢迎各位大佬互三:kotisivuni

1. Käänteinen linkitetty luettelo

206. Käänteinen linkitetty luettelo

Ajatteleminen: Jos et avaa lisätilaa ja muokkaa vain alkuperäistä linkitettyä luetteloa, mitä menetelmää tulisi käyttää?

Aloita vain toisesta elementistä ja suorita pään lisäys järjestyksessä.

Muokkaa sitten viittausta ja osoita viimeinen elementti tyhjäksi

  1. class Solution {
  2. public ListNode reverseList(ListNode head) {
  3. //head为null,直接返回
  4. if(head == null){
  5. return head;
  6. }
  7. ListNode cur = head.next;
  8. //head变为了末尾元素,指向null
  9. head.next = null;
  10. while(cur!=null){
  11. //curn为cur的next节点,便于往后移动
  12. ListNode curn = cur.next;
  13. cur.next = head;
  14. head = cur;
  15. //更新cur
  16. cur = curn;
  17. }
  18. return head;
  19. }
  20. }

2. Linkitetyn luettelon keskisolmu

876. Linkitetyn luettelon välisolmu

Ensimmäinen menetelmä, joka tulee mieleen tälle kysymykselle, on ehdottomasti määrittää cnt, kulkea linkitetyn luettelon läpi kerran, etsiä sitten keskimmäinen luku ja sitten kulkea paluuarvo. Tämä menetelmä on hyvin yksinkertainen, mutta entä jos sinun on käytävä läpi linkitetty luettelo vain kerran löytääksesi välisolmun?

Tässä on uusi idea: käytä nopeita ja hitaita osoittimia, alkaen päästä. Nopea osoitin siirtää joka kerta yhtä solmua. Saavuttaako tämä lopullisen tavoitteen?

Toteutetaan se sitten:

  1. class Solution {
  2. public ListNode middleNode(ListNode head) {
  3. if(head == null){
  4. return null;
  5. }
  6. ListNode fast = head;
  7. ListNode slow = head;
  8. while(fast!= null&&fast.next!= null){
  9. fast = fast.next.next;
  10. slow = slow.next;
  11. }
  12. return slow;
  13. }
  14. }

Olisiko tämä tehokkaampaa?

3. Palauta k:s solmu viimeisestä

Haastattelukysymys 02.02. Palauta k:s solmu viimeisestä

Ensimmäinen asia, joka tulee mieleen tälle kysymykselle, on kulkea se kerran, jotta saadaan kokonaispituus, ja sitten löytää k:s solmu edellisestä kysymyksestä. Voit kuitenkin ajatella toista menetelmää edellisen kysymyksen perusteella: Samalla lailla,Nopeaa ja hidasta osoittimia käyttämällä anna nopea mennä k-1 solmulle ja sitten hidas ja nopea mennä samanaikaisesti on k:s solmu alhaalta.

Tämä kysymys osoittaa, että syöte k on laillinen, joten lisäarviointia ei tarvita, kuinka arvioida, onko k laiton, ja vaaditaan, että linkitetyn listan pituutta ei voida löytää suoraan, joten hitaan on arvioitava kävellessä.

  1. class Solution {
  2. public int kthToLast(ListNode head, int k) {
  3. if (head == null) {
  4. return -1;
  5. }
  6. ListNode fast = head;
  7. ListNode slow = head;
  8. int cnt = 0;
  9. while (cnt != k - 1) {
  10. //判断k的合法性,虽然本题不用判断
  11. fast = fast.next;
  12. if(fast == null){
  13. return;
  14. }
  15. cnt++;
  16. }
  17. //slow和fast同时移动
  18. while (fast.next != null) {
  19. fast = fast.next;
  20. slow = slow.next;
  21. }
  22. return slow.val;
  23. }
  24. }

4. Yhdistä linkitetyt luettelot

21. Yhdistä kaksi järjestettyä linkitettyä luetteloa

Idea:Sinun tarvitsee vain määrittää uusi solmu newH ja sitten verrata headA:n ja headB:n valuutta. Jotta voit lopulta löytää yhdistetyn linkitetyn luettelon pääsolmun, sinun on myös määritettävä tmp = newH ja sitten se, jolla on pienempi. tmp.next viittaa siihen.

  1. class Solution {
  2. public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
  3. ListNode head = new ListNode();
  4. ListNode tmp = head;
  5. while(list1!=null&&list2!=null){
  6. if(list1.val < list2.val){
  7. tmp.next = list1;
  8. list1 = list1.next;
  9. tmp = tmp.next;
  10. }else{
  11. tmp.next = list2;
  12. list2 = list2.next;
  13. tmp = tmp.next;
  14. }
  15. }
  16. //判断剩余的情况
  17. if(list1!=null){
  18. tmp.next = list1;
  19. }else if(list2!=null){
  20. tmp.next = list2;
  21. }
  22. return head.next;
  23. }
  24. }

5. Linkitetty luettelo jaettu

CM11 linkitetty luettelo jaettu

Tämä on haastattelukysymys Niukessa. Kysymyksen tarkoitus on jakaa linkitetty lista x:n vasen puoli on pienempi kuin x. Alkuperäistä järjestystä ei voi muuttaa.

Idea: Määritä uusi solmukäyrä, joka kulkee alkuperäisen linkitetyn luettelon läpi (jotta estät alkuperäisen linkitetyn luettelon muuttamisen), laita kaikki x:tä suuremmat asiat linkitettyyn luetteloon, lisää kaikki x:tä pienempi linkitettyyn luetteloon ja yhdistä lopuksi nämä kaksi. linkitetyt luettelot.

  1. public class Partition {
  2. public ListNode partition(ListNode pHead, int x) {
  3. ListNode bs = null;
  4. ListNode be = null;
  5. ListNode as = null;
  6. ListNode ae = null;
  7. ListNode cur = pHead;
  8. while (cur != null) {
  9. if (cur.val < x) {
  10. //处理刚开始为null的情况
  11. if (bs == null) {
  12. bs = be = cur;
  13. }else{
  14. be.next = cur;
  15. be = be.next;
  16. }
  17. }else{
  18. if(as == null){
  19. as = ae = cur;
  20. }else{
  21. ae.next = cur;
  22. ae = ae.next;
  23. }
  24. }
  25. cur = cur.next;
  26. }
  27. //都是比x大的情况
  28. if(bs == null){
  29. return as;
  30. }
  31. be.next = as;
  32. //最后都要置为null,不然可能会报错
  33. if(as!=null){
  34. ae.next = null;
  35. }
  36. return bs;
  37. }
  38. }

On huomattava, että jos ne ovat suurempia kuin x, eli bs = null, niin as palautetaan suoraan, ja jos as.next asetetaan lopulta tyhjäksi.

6. OR36 linkitetyn luettelon palindromirakenne

Linkitetyn luettelon OR36 palindromirakenne

Tämä on kysymys Niukelta, koska sillä on aikamonimutkaisuus ja tilan monimutkaisuusvaatimukset, mikä tarkoittaa, että et voi avata ylimääräistä taulukkoa, muuten avaruuden monimutkaisuus ei selviä ja normaalin läpikäynnin monimutkaisuus on O(n)

Idea on seuraava: etsi ensin linkitetyn listan keskisolmu ja sen jälkeen käännä osa keskeltä loppuun arvot ovat erilaisia, se tarkoittaa, että ne eivät palauta tekstirakennetta

Linkitetyn listan kääntämistä ja välisolmun löytämistä on harjoitettu aiemmin

  1. public class PalindromeList {
  2. public boolean chkPalindrome(ListNode head) {
  3. if (head == null) {
  4. return true;
  5. }
  6. //找到中间节点
  7. ListNode fast = head;
  8. ListNode slow = head;
  9. while (fast != null && fast.next != null) {
  10. fast = fast.next.next;
  11. slow = slow.next;
  12. }
  13. //从slow开始到末尾反转
  14. ListNode cur = slow.next;
  15. while (cur != null) {
  16. ListNode curn = cur.next;
  17. cur.next = slow;
  18. slow = cur;
  19. cur = curn;
  20. }
  21. //判断回文
  22. while (head != slow) {
  23. if (head.val != slow.val) {
  24. return false;
  25. }
  26. //判断偶数节点
  27. if (head.next == slow) {
  28. return true;
  29. }
  30. head = head.next;
  31. slow = slow.next;
  32. }
  33. return true;
  34. }
  35. }

On huomattava, että myös linkitetyn parittomien solmujen luettelon ja parillisten solmujen linkitetyn luettelon arvioinnissa on ero.

Jos parillinen solmu siirretään huipulle, se aiheuttaa äärettömän silmukan, joten parillisen solmun kohdalla tarvitaan lisäarviointia.

7. Leikkaavat linkitetyt luettelot

160. Leikkaavat linkitetyt luettelot

Leikkaava linkitetty lista on "Y":n kaltainen muunnos, kuten kuvassa näkyy

Myös alla olevan kysymyksen kuva on hyvin selkeä.

Idea: Koska onko A lyhyt tai B lyhyt, niiden välinen ero on leikkausta edeltävä osa. Sinun tarvitsee vain siirtää pitkää linkitettyä listaa, ja sitten kaksi linkitettyä listan solmua siirtyvät taaksepäin identtiset solmut leikkaavat solmun

  1. public class Solution {
  2. public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
  3. ListNode pl = headA;
  4. ListNode ps = headB;
  5. int cnta = 0,cntb = 0;
  6. //计算两个链表的长度
  7. while(pl!=null){
  8. pl = pl.next;
  9. cnta++;
  10. }
  11. while(ps!=null){
  12. ps = ps.next;
  13. cntb++;
  14. }
  15. //如果链表b长,就更新pl,ps
  16. int len = cnta - cntb;
  17. //上面求长度时pl,ps都为空了,所以这里再重新指向
  18. pl = headA;
  19. ps = headB;
  20. if(len < 0){
  21. pl = headB;
  22. ps = headA;
  23. len = cntb - cnta;
  24. }
  25. //移动差值
  26. while(len!=0){
  27. pl = pl.next;
  28. len--;
  29. }
  30. //找到相交节点
  31. while(pl!=ps){
  32. pl = pl.next;
  33. ps = ps.next;
  34. }
  35. //链表不相交的情况
  36. if(pl == null) return null;
  37. return pl;
  38. }
  39. }

Lopuksi meidän on lisättävä epäyhtenäinen tilanne. Vaikka voimme ohittaa tämän kysymyksen lisäämättä sitä, meidän on silti lisättävä se tarkkuuden vuoksi.

8. Pyöreä linkitetty luettelo

8.1 Selvitä, onko silmukkaa

141. Pyöreä linkitetty luettelo

Kuinka määrittää, onko linkitetyllä luettelolla sykli:Käytä silti nopeusosoitinta, aivan kuten kaksi ihmistä juoksee leikkikentällä, toinen juoksee nopeasti ja toinen juoksee hitaasti Koska leikkipaikka on rengas, nopea voi ehdottomasti ylittää hitaan , mutta ilman Tamakia, he eivät koskaan voisi tavata, aivan kuten jumalatar, jota et saa kiinni vaikka jahtaat kuinka lujasti.

Mutta on toinen tilanne, jos se on rengas, jossa on kaksi solmua ja määritetty nopea osoitin ottaa 3 askelta kerrallaan ja hidas osoitin 1 askeleen kerrallaan, ne eivät koskaan kohtaa.

Siksi määriteltyjen osoittimien on arvioitava, kuinka monta askelta he ottavat joka kerta. Jos toinen ottaa 2 askelta ja toinen 1 askeleen, ne kohtaavat varmasti.

  1. public class Solution {
  2. public boolean hasCycle(ListNode head) {
  3. ListNode fast = head;
  4. ListNode slow = head;
  5. while(fast!=null&&fast.next!=null){
  6. fast = fast.next.next;
  7. slow = slow.next;
  8. if(fast == slow) return true;
  9. }
  10. return false;
  11. }
  12. }

8.2 Palauta solmu renkaan sisäänkäynnin kohdalla

142. Pyöreä linkitetty luettelo II

Tällä kertaa sinun on selvitettävä kehän sisääntulokohta sen jälkeen, kun olet päättänyt, onko se rengas edellisessä kysymyksessä. Voit tehdä seuraavan päättelyn

  1. public class Solution {
  2. public ListNode detectCycle(ListNode head) {
  3. ListNode fast = head;
  4. ListNode slow = head;
  5. //判断环
  6. while(fast!=null&&fast.next!=null){
  7. fast = fast.next.next;
  8. slow = slow.next;
  9. if(fast == slow) break;
  10. }
  11. if(fast == null||fast.next == null) return null;
  12. slow = head;
  13. //寻找环
  14. while(slow!=fast){
  15. slow = slow.next;
  16. fast = fast.next;
  17. }
  18. return slow;
  19. }
  20. }

Mitä pitää lisätä, on:

Kun rengas on hyvin pieni, lopullinen yksinkertaistustulos tulee yllä olevaksi, mutta alkuperäinen koodi on edelleen kunnossa.