τα στοιχεία επικοινωνίας μου
Ταχυδρομείο[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
💎 欢迎各位大佬互三:την αρχική μου σελίδα
206.Αντίστροφη συνδεδεμένη λίστα
Σκέψη: Εάν δεν ανοίξετε επιπλέον χώρο και τροποποιήσετε μόνο την αρχική συνδεδεμένη λίστα, ποια μέθοδος θα πρέπει να χρησιμοποιήσετε;
Απλώς ξεκινήστε από το δεύτερο στοιχείο και εκτελέστε την εισαγωγή της κεφαλής με τη σειρά.
Στη συνέχεια απλώς τροποποιήστε την αναφορά και τοποθετήστε το τελευταίο στοιχείο σε 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. Ενδιάμεσος κόμβος συνδεδεμένης λίστας
Η πρώτη μέθοδος που έρχεται στο μυαλό για αυτήν την ερώτηση είναι οπωσδήποτε να ορίσετε ένα cnt, να διασχίσετε τη συνδεδεμένη λίστα μία φορά, μετά να βρείτε τον μεσαίο αριθμό και μετά να διασχίσετε την τιμή επιστροφής Αυτή η μέθοδος είναι πολύ απλή, αλλά τι γίνεται αν χρειαστεί να διασχίσετε την τιμή συνδεδεμένη λίστα μόνο μία φορά για να βρείτε τον ενδιάμεσο κόμβο;
Εδώ είναι μια νέα ιδέα: χρησιμοποιήστε τους γρήγορους και αργούς δείκτες, ξεκινώντας από το κεφάλι Ο γρήγορος δείκτης μετακινεί δύο κόμβους κάθε φορά και ο αργός δείκτης κινεί έναν κόμβο κάθε φορά.
Τότε ας το εφαρμόσουμε:
- 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;
- }
- }
Θα ήταν πιο αποτελεσματικό αυτό;
Ερώτηση συνέντευξης 02.02 Επιστρέψτε τον κ-ο κόμβο από τον τελευταίο
Το πρώτο πράγμα που έρχεται στο μυαλό για αυτήν την ερώτηση είναι να το διασχίσετε μία φορά για να λάβετε το συνολικό μήκος και στη συνέχεια να βρείτε τον κ-ο κόμβο από τον τελευταίο, ωστόσο, με βάση την προηγούμενη ερώτηση, μπορείτε να σκεφτείτε μια άλλη μέθοδο: Ομοίως,Χρησιμοποιώντας τους γρήγορους και αργούς δείκτες, αφήστε πρώτα τους κόμβους γρήγορα να πάνε και μετά να πάνε αργοί και γρήγοροι ταυτόχρονα είναι ο κ-ος κόμβος από κάτω.
Αυτή η ερώτηση υποδεικνύει ότι η είσοδος k είναι νόμιμη, επομένως δεν χρειάζεται πρόσθετη κρίση Πώς να κρίνουμε εάν το k είναι παράνομο και απαιτείται να μην μπορεί να βρεθεί άμεσα το μήκος της συνδεδεμένης λίστας, επομένως χρειάζεται να κριθεί αργά ενώ περπατάτε.
- 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. Συγχωνεύστε δύο ταξινομημένες συνδεδεμένες λίστες
Ιδέα:Χρειάζεται μόνο να ορίσετε έναν νέο κόμβο newH και, στη συνέχεια, να συγκρίνετε την val του headA και του headB Για να βρείτε τελικά τον κύριο κόμβο της συγχωνευμένης συνδεδεμένης λίστας, πρέπει επίσης να ορίσετε ένα tmp = newH και, στη συνέχεια, όποιος έχει το μικρότερο. tmp.next θα το δείχνει.
- 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;
- }
- }
Διαχωρισμός συνδεδεμένης λίστας CM11
Αυτή είναι μια ερώτηση συνέντευξης στο Niuke Το νόημα της ερώτησης είναι να διαιρέσετε τη συνδεδεμένη λίστα Η αριστερή πλευρά του x είναι μεγαλύτερη από το x.
Ιδέα: Ορίστε έναν νέο κόμβο για να διασχίσετε την αρχική συνδεδεμένη λίστα (για να αποτρέψετε την αλλαγή της αρχικής συνδεδεμένης λίστας), τοποθετήστε ό,τι μεγαλύτερο από x σε μια συνδεδεμένη λίστα, βάλτε οτιδήποτε μικρότερο από x σε μια συνδεδεμένη λίστα και, τέλος, συνδέστε τα δύο συνδεδεμένες λίστες.
- 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;
- }
- }
Πρέπει να σημειωθεί ότι εάν είναι μεγαλύτερα από x, δηλαδή bs = null, τότε το as θα επιστραφεί απευθείας και εάν το as.next οριστεί τελικά σε null
Δομή παλίνδρομου OR36 της συνδεδεμένης λίστας
Αυτή είναι μια ερώτηση από τη Niuke, επειδή έχει απαιτήσεις πολυπλοκότητας χρόνου και χώρου, πράγμα που σημαίνει ότι δεν μπορείτε να ανοίξετε έναν επιπλέον πίνακα, διαφορετικά η πολυπλοκότητα του χώρου δεν θα ξεπεραστεί και η κανονική διέλευση θα έχει πολυπλοκότητα O(n)
Η ιδέα είναι αυτή: πρώτα βρείτε τον μεσαίο κόμβο της συνδεδεμένης λίστας και μετά αντιστρέψτε το τμήμα από τη μέση προς το τέλος οι τιμές είναι διαφορετικές, σημαίνει ότι δεν επιστρέφουν δομή κειμένου
Η αντιστροφή της συνδεδεμένης λίστας και η εύρεση του ενδιάμεσου κόμβου έχουν εξασκηθεί στο παρελθόν
- 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;
- }
- }
Πρέπει να σημειωθεί ότι υπάρχει επίσης διαφορά στην κρίση της συνδεδεμένης λίστας περιττών κόμβων και της συνδεδεμένης λίστας των ζυγών κόμβων.
Εάν ο ζυγός κόμβος μετακινηθεί στην κορυφή, θα προκαλέσει έναν άπειρο βρόχο, επομένως απαιτείται πρόσθετη κρίση για τον ζυγό κόμβο.
160. Διασταυρούμενες συνδεδεμένες λίστες
Η τεμνόμενη συνδεδεμένη λίστα είναι ένας μετασχηματισμός παρόμοιος με το "Y", όπως φαίνεται στο σχήμα
Η εικόνα στην παρακάτω ερώτηση είναι επίσης πολύ σαφής.
Ιδέα: Επειδή το Α είναι σύντομο ή το Β, η διαφορά μεταξύ τους είναι το τμήμα πριν από τη διασταύρωση πανομοιότυποι κόμβοι πρέπει να τέμνουν τον κόμβο του
- 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;
- }
- }
Τέλος, πρέπει να προσθέσουμε την ασύνδετη κατάσταση Αν και μπορούμε να περάσουμε αυτήν την ερώτηση χωρίς να την προσθέσουμε, πρέπει ακόμα να την προσθέσουμε για λόγους αυστηρότητας.
141. Κυκλική συνδεδεμένη λίστα
Πώς να προσδιορίσετε εάν μια συνδεδεμένη λίστα έχει κύκλο:Χρησιμοποιήστε ακόμα τον δείκτη ταχύτητας, ακριβώς όπως δύο άτομα που τρέχουν στην παιδική χαρά, το ένα άτομο τρέχει γρήγορα και το άλλο άτομο τρέχει αργά , αλλά αν δεν ήταν το Tamaki, δεν θα μπορούσαν ποτέ να συναντηθούν, όπως μια θεά που δεν μπορείς να την πιάσεις όσο κι αν κυνηγήσεις.
Αλλά υπάρχει μια άλλη κατάσταση, εάν είναι ένας δακτύλιος με δύο κόμβους, και ο καθορισμένος γρήγορος δείκτης κάνει 3 βήματα τη φορά και ο αργός δείκτης κάνει 1 βήμα τη φορά, τότε δεν θα συναντηθούν ποτέ.
Επομένως, οι καθορισμένοι δείκτες πρέπει να κρίνουν πόσα βήματα κάνουν κάθε φορά, αν ο ένας κάνει 2 βήματα και ο άλλος 1 βήμα, σίγουρα θα συναντηθούν.
- 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. Κυκλική Συνδεδεμένη Λίστα II
Αυτή τη φορά πρέπει να μάθετε το σημείο εισόδου στο δαχτυλίδι αφού κρίνετε αν είναι δαχτυλίδι στην προηγούμενη ερώτηση Μπορείτε να κάνετε τον ακόλουθο συλλογισμό
- 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;
- }
- }
Αυτό που πρέπει να προστεθεί είναι:
Όταν ο δακτύλιος είναι πολύ μικρός, το τελικό αποτέλεσμα απλοποίησης γίνεται το παραπάνω, αλλά ο αρχικός κωδικός είναι ακόμα εντάξει.