Έτσι λοιπόν είσαι. Ανακουφισμένος. Εξαντλημένος. Έχετε επιτέλους καταλήξει σε μια προσέγγιση για την επίλυση της δύσκολης κωδικοποίησης που σας ζητά ο συντάκτης. Ίσως το γράψατε και στον πίνακα, γραμμής ανά γραμμή. Και κάνατε καλό χρόνο! Είστε μόνο 20 λεπτά στη συνεδρίαση. Ο ερωτημένος πρέπει να εντυπωσιαστεί.
Σωστά?
"Αυτό θα λειτουργήσει, αλλά τυχόν ιδέες για το πώς να το κάνουμε πιο αποτελεσματικά;"
Η καρδιά σου βυθίζεται. Σκεφτήκατε ότι ολοκληρώσατε το δύσκολο κομμάτι του αλγορίθμου! Προσπαθείτε να σκεφτείτε περισσότερους τρόπους για την επίλυση του προβλήματος, αλλά το μόνο που μπορείτε να σκεφτείτε είναι η μία προσέγγιση που έχετε ήδη καταλήξει.
Αυτό συμβαίνει σχεδόν σε όλους. Και δεν είναι επειδή είναι ηλίθιοι. Είναι επειδή οι περισσότεροι άνθρωποι δεν έχουν μια μέθοδο για τη βελτίωση της αποτελεσματικότητας των αλγορίθμων τους.
Αλλά η αλήθεια είναι ότι υπάρχουν πολλά. Την επόμενη φορά που θα βρεθείτε αντιμέτωπος, δοκιμάστε να εφαρμόσετε αυτές τις τρεις κοινές προσεγγίσεις.
1. Χρησιμοποιήστε έναν χάρτη Hash
Σωστά. Hash χάρτες / συσσωματικές συστοιχίες / λεξικά (που πηγαίνουν με πολλά ονόματα, ανάλογα με τη γλώσσα προγραμματισμού που χρησιμοποιείτε) έχουν μια μαγική ικανότητα να μειώσουν το χρόνο εκτέλεσης των αλγορίθμων.
Για παράδειγμα, ας υποθέσουμε ότι η ερώτηση ήταν να βρούμε τον πιο επαναλαμβανόμενο αριθμό σε μια σειρά αριθμών.
Η πρώτη σας σκέψη ίσως είναι να πηδήσετε σε κάποια βρόχους. Για κάθε έναν από τους αριθμούς μας, υπολογίστε τον αριθμό του και δείτε αν είναι ο μεγαλύτερος. Πώς θα πάρουμε την καταμέτρηση για κάθε αριθμό; Βγείτε μέσω της συστοιχίας, υπολογίζοντας πόσες φορές εμφανίζεται! Γι 'αυτό μιλάμε για δύο ένθετους βρόχους. Σε ψευδοκώδικα:
def get_mode (nums): max_count = 0 mode = null για το δυναμικό_μέγεθος σε nums: count = 0 για τον αριθμό στο our_array: count + = 1 if count = = max_count: mode = potential_mode max_count =
Αυτή τη στιγμή, βγάζουμε το σύνολο της συστοιχίας μας για κάθε στοιχείο στη σειρά - αλλά μπορούμε να κάνουμε καλύτερα. Στη μεγάλη εγγραφή O, αυτό είναι O (n 2 ) χρόνος συνολικά.
Εάν αποθηκεύουμε τις μετρήσεις μας σε έναν χάρτα κατακερματισμού (χαρτογράφηση των αριθμών στις μετρήσεις τους), μπορούμε να λύσουμε το πρόβλημα σε μία μόνο βόλτα μέσω του πίνακα (O (n) time!):
def get_mode (nums): max_count = 0 mode = null counts = new HashMap, ξεκινώντας κάθε τιμή στο 0 για δυναμικό_μονάδα σε nums: counts = = 1 αν μετράει> max_count: mode = potential_mode max_count =
Πολύ πιο γρήγορα!
2. Χρησιμοποιήστε τη Χειρισμ
Αυτό θα σας ξεκαθαρίσει πραγματικά από το πακέτο. Δεν ισχύει για κάθε πρόβλημα, αλλά αν κρατήσετε αυτό στην πίσω τσέπη σας και θα την αποβάλλετε την κατάλληλη στιγμή, θα μοιάζετε με ένα rockstar.
Ακολουθεί ένα παράδειγμα: Ας υποθέσουμε ότι είχαμε μια σειρά αριθμών, όπου κάθε αριθμός εμφανίζεται δύο φορές, εκτός από έναν αριθμό που εμφανίζεται μόνο μία φορά. Γράφουμε μια λειτουργία για να βρούμε τον μοναχικό, μη επαναλαμβανόμενο αριθμό.
Το πρώτο ένστικτό σας μπορεί να είναι να χρησιμοποιήσετε έναν χάρτη κατακερματισμού, αφού μόλις μιλήσαμε γι 'αυτό. Αυτό είναι ένα καλό ένστικτο! Και θα λειτουργήσει για αυτό. Μπορούμε να κάνουμε έναν πολύ παρόμοιο "μετράει" χάρτη, και να το χρησιμοποιήσουμε για να δούμε ποιο αριθμό καταλήγει με έναν αριθμό 1.
Αλλά υπάρχει ένας ακόμα καλύτερος τρόπος. Εάν είστε εξοικειωμένοι με τη χειραγώγηση bit, μπορεί να είστε εξοικειωμένοι με το XOR. Ένα πράγμα που είναι ξεχωριστό για το XOR είναι ότι αν XOR έναν αριθμό με τον εαυτό του, τα bits "ακυρώνουν" στο 0. Για αυτό το πρόβλημα, αν XOR κάθε αριθμός στη συστοιχία μαζί, θα μείνει με τον έναν αριθμό που didn 't ακυρώσετε:
def find_unrepeated (nums): unrepeated = 0 για num σε nums: unrepeated = unrepeated XOR num επιστρέφει unrepeated
3. Πηγαίνετε από κάτω προς τα πάνω
Γράψτε μια συνάρτηση που εξάγει τον "nth" αριθμό Fibonacci, δεδομένου ενός αριθμού n. Αυτό είναι ένα κλασικό, και προσφέρεται πολύ ωραία στην επανάληψη:
def νν (η): αν το n είναι 0 ή 1: επιστροφή 1 ινώδους επιστροφής (n-1) + fib (n-2)
Αλλά η απλή αναδρομική απάντηση δεν είναι η μόνη! Σκεφτείτε προσεκτικά τι κάνει αυτή η λειτουργία. Ας υποθέσουμε ότι το n είναι 5. Για να πάρουμε την απάντηση, καλείται αναδρομικά fib (4) και fib (3). Τώρα, τι κάνει αυτό το κάλεσμα στο fib (4); Καλεί το ινώδες (3) και το fib (2). Αλλά είπαμε ότι είχαμε ήδη καλέσει στο fib (3)! Αυτή η χαριτωμένη αναδρομική λειτουργία κάνει πολλές επαναλαμβανόμενες εργασίες. Το συνολικό κόστος χρόνου προκύπτει ότι είναι O (2 n ). Αυτό είναι κακό τρόπο χειρότερο από το O (n 2 ).
Αντί να πηγαίνουμε από n αναδρομικά κάτω σε 1, ας πάμε "από κάτω προς τα πάνω", από 1 σε n. Αυτό μας επιτρέπει να παραλείψουμε την επανάληψη:
def def (n): προηγούμενο = 0 προηγούμενο_προηγούμενο = 1 για i στην περιοχή 1 έως n: τρέχουσα = προηγούμενη + previous_previous previous_previous = previous previous = τρέχουσα τρέχουσα επιστροφή
Ο κώδικας είναι μεγαλύτερος, αλλά είναι πολύ πιο αποδοτικός! Μέχρι την ώρα O (n). Ως πρόσθετο μπόνους με ξετυλίγοντας τους αναδρομικούς αλγόριθμους, εξοικονομούμε χώρο. Όλες αυτές οι αναδρομικές κλήσεις συσσωρεύονται στη στοίβα κλήσεων, η οποία βρίσκεται στη μνήμη και μετράει προς το κόστος του χώρου μας. Η αναδρομική μας λειτουργία είχε ένα κόστος O (n), αλλά αυτή η επαναληπτική λαμβάνει O (1) χώρο.
Την επόμενη φορά που ο ερευνητής σας ζητάει να βελτιώσετε την αποτελεσματικότητα της λύσης σας, προσπαθήστε να περάσετε από αυτές τις στρατηγικές και να δείτε αν αυτές βοηθούν. Με αρκετή πρακτική, πιθανότατα θα βρεθείτε να πηδήσετε κατευθείαν στη βελτιστοποιημένη λύση, παρακάμπτοντας την πιο αφελής λύση. Και αυτό είναι ένα μεγάλο πράγμα. Δεν σημαίνει μόνο ότι γίνεσαι καλύτερος συνέντευξη-σημαίνει ότι είσαι καλύτερος μηχανικός.