DSA Interview Prep · Lektion

Tidsbegrænset prøveinterview: Nemme og mellemsvære problemer

Løs tre problemer inden for 45 minutter, forklar Deres tankeproces, som De ville gøre i et rigtigt interview, og gennemgå de optimale løsninger bagefter.

Lektion 2 af 413 trin

Tidsbegrænset prøveinterview: Nemme og mellemsvære problemer er en gratis DSA Interview Prep-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i DSA Interview Prep, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. DSA Interview Prep-kurset indeholder 4 lektioner i alt.

Sådan bruger du dette prøveinterview

Denne lektion simulerer en rigtig kodningssamtale. For hvert problem skal du: (1) læse det én gang, (2) identificere mønstret inden for 60 sekunder, (3) forklare din tilgang og kompleksiteten, (4) skrive løsningen og (5) teste med eksempler. Sæt en timer. Et let problem bør tage 10-15 minutter; et mellemsvært problem 20-25 minutter.

Se ikke på løsningen på forhånd — så forsvinder formålet. Hvis du er gået i stå efter 5 minutter, skal du læse problemformuleringen igen og lede efter det signalord, der afslører mønstret (sorteret? minimum? alle kombinationer? delarray?). Evnen til selv at komme videre er lige så vigtig som evnen til at løse problemet hurtigt.

# Mock interview timer simulation
import time

class InterviewTimer:
    def __init__(self, total_minutes):
        self.total = total_minutes * 60
        self.start = None

    def begin(self, problem_name):
        self.start = time.time()
        print(f'TIMER STARTED: {problem_name}')
        print(f'You have {self.total//60} minutes. Go!')

    def checkpoint(self, label):
        if self.start:
            elapsed = time.time() - self.start
            remaining = self.total - elapsed
            print(f'[{label}] Elapsed: {elapsed:.0f}s, Remaining: {remaining:.0f}s')

# Usage in real practice:
timer = InterviewTimer(15)  # 15-minute easy problem
timer.begin('Two Sum')
time.sleep(1)
timer.checkpoint('Identified pattern')

Let problem 1: Gyldige parenteser

Problem: Givet en streng, der kun indeholder '(', ')', '{', '}', '[', ']', skal du afgøre, om inputstrengen er gyldig. En streng er gyldig, hvis hver åben parentes lukkes af samme type parentes i den korrekte rækkefølge.

Signal: Matchende par, rækkefølgen er vigtig, den senest åbnede parentes skal lukkes først → Stack. Læg åbningsparenteser på stacken; tag dem af igen, og kontrollér dem, når der kommer lukkende parenteser. Hvis stacken er tom, når vi forsøger at tage et element af, eller der er elementer tilbage til sidst, er strengen ugyldig. Tid O(n), plads O(n).

def is_valid(s):
    stack = []
    matching = {')': '(', '}': '{', ']': '['}

    for char in s:
        if char in '({[':
            stack.append(char)
        else:
            if not stack or stack[-1] != matching[char]:
                return False
            stack.pop()
    return len(stack) == 0

# Test cases
test_cases = [
    ('()', True),
    ('()[]{}'  , True),
    ('(]', False),
    ('([)]', False),
    ('{[]}', True),
    ('', True),        # empty string is valid
    ('(((', False),    # unmatched opens
    (')]', False),     # close without open
]
for s, expected in test_cases:
    result = is_valid(s)
    status = 'PASS' if result == expected else 'FAIL'
    print(f'{status}: is_valid({repr(s)}) = {result} (expected {expected})')

Let problem 2: Bedste tidspunkt at købe og sælge aktier

Problem: Givet et array prices, hvor prices[i] er aktiekursen på dag i, skal du finde den maksimale fortjeneste ved ét køb og ét salg (køb skal ske før salg). Returnér 0, hvis ingen fortjeneste er mulig.

Signal: Maksimal forskel, hvor venstre side skal komme før højre → Hold styr på det løbende minimum, mens du går fra venstre mod højre. Hver dag er den mulige fortjeneste current_price - min_so_far. Opdatér den maksimale fortjeneste. Dette er O(n)/O(1) og et specialtilfælde af Kadane's algorithm.

def max_profit(prices):
    if not prices:
        return 0
    min_price = float('inf')
    max_profit = 0

    for price in prices:
        if price < min_price:
            min_price = price
        elif price - min_price > max_profit:
            max_profit = price - min_price
    return max_profit

# Test cases
test_cases = [
    ([7, 1, 5, 3, 6, 4], 5),   # buy at 1, sell at 6
    ([7, 6, 4, 3, 1], 0),      # monotonically decreasing: no profit
    ([2, 4, 1], 2),             # buy at 2, sell at 4
    ([1], 0),                   # single price: no transaction possible
    ([3, 3, 3], 0),             # flat: no profit
]
for prices, expected in test_cases:
    result = max_profit(prices)
    status = 'PASS' if result == expected else 'FAIL'
    print(f'{status}: max_profit({prices}) = {result} (expected {expected})')

Mellemsvært problem 1: Tre sum

Problem: Givet et array skal du finde alle unikke tripletter, der summerer til nul. Løsningen må ikke indeholde duplikerede tripletter.

Mønster: To pointere udvidet til tre elementer. Sortér arrayet. For hvert element nums[i] skal du bruge to pointere left = i+1, right = n-1 til at finde par, der summerer til -nums[i]. Spring dubletter over ved at gå forbi identiske værdier. Tid O(n²), plads O(1) eksklusive resultatet. Sorteringen gør håndteringen af dubletter enkel.

def three_sum(nums):
    nums.sort()
    result = []
    n = len(nums)

    for i in range(n - 2):
        # Skip duplicate values for the first element
        if i > 0 and nums[i] == nums[i - 1]:
            continue
        left, right = i + 1, n - 1
        while left < right:
            total = nums[i] + nums[left] + nums[right]
            if total == 0:
                result.append([nums[i], nums[left], nums[right]])
                while left < right and nums[left] == nums[left + 1]:
                    left += 1      # skip duplicate lefts
                while left < right and nums[right] == nums[right - 1]:
                    right -= 1     # skip duplicate rights
                left += 1; right -= 1
            elif total < 0:
                left += 1
            else:
                right -= 1
    return result

print(three_sum([-1, 0, 1, 2, -1, -4]))  # [[-1,-1,2],[-1,0,1]]
print(three_sum([0, 0, 0, 0]))            # [[0,0,0]]
print(three_sum([]))                       # []
print(three_sum([1, 2, -2, -1]))           # []

Mellem-svær opgave 2: Længste delstreng uden gentagne tegn

Opgave: Givet en streng skal du finde længden af den længste delstreng uden gentagne tegn.

Mønster: Glidende vindue med et sæt (eller en dict med seneste positioner). Vedligehold et vindue [left, right]. Udvid right ved at inkludere hvert tegn. Hvis et tegn gentages (allerede i vinduet), skal du formindske fra venstre, indtil dubletten er fjernet. Hold styr på den største vinduesstørrelse, der er set. Tidsforbrug O(n), pladsforbrug O(min(n, alphabet_size)).

def length_of_longest_substring(s):
    char_index = {}    # character -> last seen index
    left = 0
    max_len = 0

    for right, char in enumerate(s):
        if char in char_index and char_index[char] >= left:
            left = char_index[char] + 1  # shrink window past duplicate
        char_index[char] = right
        max_len = max(max_len, right - left + 1)
    return max_len

# Test cases
test_cases = [
    ('abcabcbb', 3),   # 'abc'
    ('bbbbb', 1),       # 'b'
    ('pwwkew', 3),      # 'wke'
    ('', 0),            # empty string
    ('au', 2),          # full string
    ('dvdf', 3),        # 'vdf' (skip the first d)
]
for s, expected in test_cases:
    result = length_of_longest_substring(s)
    status = 'PASS' if result == expected else 'FAIL'
    print(f'{status}: len_longest({repr(s)}) = {result} (expected {expected})')

Mellem-svær opgave 3: Møntveksling

Opgave: Givet møntværdier og et målbeløb skal du finde det mindste antal mønter, der kræves for at nå beløbet. Returnér -1, hvis det er umuligt.

Mønster: Klassisk 1D-DP (variant af det ubundne rygsækproblem). dp[i] = det mindste antal mønter for beløb i. Initialisér dp[0] = 0 og alle andre værdier til uendelig. For hvert beløb fra 1 til målet skal du prøve alle møntværdier. dp[i] = min(dp[i], dp[i - coin] + 1) for hver gyldig mønt. Tidsforbrug O(amount × len(coins)), pladsforbrug O(amount).

def coin_change(coins, amount):
    dp = [float('inf')] * (amount + 1)
    dp[0] = 0   # 0 coins to make amount 0

    for i in range(1, amount + 1):
        for coin in coins:
            if coin <= i and dp[i - coin] + 1 < dp[i]:
                dp[i] = dp[i - coin] + 1

    return dp[amount] if dp[amount] != float('inf') else -1

# Test cases
test_cases = [
    ([1, 5, 11], 15, 3),      # 11+1+1+1+1... wait: 11+1+1+1+1=5 coins? No: 5+5+5=3
    ([2], 3, -1),              # impossible (only even coins)
    ([1], 0, 0),               # 0 coins for amount 0
    ([1, 2, 5], 11, 3),        # 5+5+1
    ([186, 419, 83, 408], 6249, 20),  # stress test
]
for coins, amount, expected in test_cases:
    result = coin_change(coins, amount)
    status = 'PASS' if result == expected else 'FAIL'
    print(f'{status}: coin_change({coins}, {amount}) = {result} (expected {expected})')

Problemløsningsarbejdsgang under tidspres

Når tiden er ved at løbe ud, skal du prioritere i denne rækkefølge: (1) en fungerende brute-force-løsning med korrekt resultat frem for en ufuldstændig optimal løsning, (2) håndtér kanttilfælde tydeligt, (3) skriv ren og letlæselig kode frem for smarte enkeltlinjer. Interviewere foretrækker en ren O(n²)-løsning, der består alle testtilfælde, frem for en O(n)-løsning med en subtil fejl.

Hvis du opdager, at din O(n²)-løsning er forkert, skal du ikke opgive den halvvejs — færdiggør den, afprøv den, og tilbyd derefter at optimere den, hvis der er tid tilbage. En halvt skrevet optimal løsning giver mindre anerkendelse end en komplet, men ikke-optimal løsning.

# Priority order when time runs out
priority = [
    ('First priority',  'Correct brute-force that passes all test cases'),
    ('Second priority', 'Optimal solution with bugs is WORSE than suboptimal correct'),
    ('Third priority',  'Edge cases handled visibly (empty input, single element, negatives)'),
    ('Fourth priority', 'Clean variable names and readable code'),
    ('Fifth priority',  'Add complexity statement as a comment at the top'),
]
print('Under time pressure, prioritise:')
for priority_level, desc in priority:
    print(f'  {priority_level}: {desc}')

# Adding complexity as a comment
def two_sum_commented(nums, target):
    # Time: O(n), Space: O(n)
    seen = {}
    for i, n in enumerate(nums):
        complement = target - n
        if complement in seen:
            return [seen[complement], i]
        seen[n] = i
    return []

Gennemgang af din løsning: Fem spørgsmål

Før du siger 'Jeg er færdig', spørg dig selv om disse fem ting:

  1. Håndterer den tomt input? [], '', None, n=0
  2. Håndterer den et enkelt element? Arrays med størrelse 1, træer med én node
  3. Håndterer den elementer, der alle er ens? [5, 5, 5, 5], 'aaaa'
  4. Håndterer den mindste og største værdier? Negative tal, meget store heltal, 0
  5. Har jeg angivet tids- og pladsforbruget? Big-O med en kort begrundelse

Disse fem kontroller afslører størstedelen af fejlene i interviewløsninger. Interviewere forventer, at kandidater afprøver deres løsninger selv — de fortæller dig ikke, at din løsning har en fejl, medmindre du beder om tilbagemelding.

# The five edge-case categories with examples
edge_cases = {
    'Empty input':     ['[] empty array', '"" empty string', 'None / null'],
    'Single element':  ['[42]', 'single node tree', 'n=1'],
    'All same':        ['[3,3,3,3]', '"aaaa"', 'uniform grid'],
    'Extreme values':  ['[-10^9, 10^9]', 'INT_MAX + 1 overflow check', '0 as input'],
    'Already sorted':  ['ascending + descending', 'already optimal input'],
}
for category, examples in edge_cases.items():
    print(f'{category}:')
    for ex in examples:
        print(f'  - {ex}')
    print()

# Template for self-testing:
def test_my_solution(fn, test_cases):
    for inputs, expected in test_cases:
        result = fn(*inputs) if isinstance(inputs, tuple) else fn(inputs)
        status = 'PASS' if result == expected else 'FAIL'
        print(f'{status}: {inputs} => {result} (expected {expected})')

Håndtering af opfølgende spørgsmål

Efter du har løst opgaven, stiller interviewere typisk opfølgende spørgsmål. Almindelige typer:

  • 'Kan du gøre det med O(1) pladsforbrug?' → Se efter ændring direkte i inputtet eller matematiske kneb
  • 'Hvad hvis n er meget stor?' → Diskutér strømbehandling, sideinddeling eller stikprøvebaserede tilgange
  • 'Hvad hvis arrayet allerede er sorteret?' → Der findes ofte en enklere algoritme
  • 'Kan du parallelisere dette?' → Identificér uafhængige delproblemer, og diskutér MapReduce eller parallelisering af opgaver

Opfølgende spørgsmål afprøver din faglige dybde og omstillingsevne. Sig 'Lad mig tænke et øjeblik' i stedet for straks at gætte. En velovervejet pause er bedre end et forkert svar, der bliver leveret selvsikkert.

# Follow-up answers for classic problems
follow_ups = [
    {
        'problem': 'Find duplicate in array 1..n (space O(n) solution uses set)',
        'follow_up': 'Can you do it in O(1) space without modifying input?',
        'answer': 'Floyd cycle detection: treat array as linked list (slow/fast pointer)',
    },
    {
        'problem': 'Reverse a string (space O(n) with new array)',
        'follow_up': 'Can you do it in-place?',
        'answer': 'Two pointers from both ends, swap until they meet: O(n) time O(1) space',
    },
    {
        'problem': 'Find max in array: O(n) single pass',
        'follow_up': 'What if the array is streamed one element at a time?',
        'answer': 'Same algorithm works! Running maximum handles infinite streams',
    },
    {
        'problem': 'Merge sorted arrays O(n+m)',
        'follow_up': 'What if you have K sorted arrays?',
        'answer': 'Use a min-heap of (value, array_idx, element_idx): O(n log k)',
    },
]
for fu in follow_ups:
    print(f'Problem: {fu["problem"]}')
    print(f'Follow-up: {fu["follow_up"]}')
    print(f'Answer: {fu["answer"]}\n')

Øvelsesopgave: Gruppér anagrammer

Opgave: Givet en array af strenge skal du gruppere anagrammerne sammen. Returnér en liste med grupper.

Mønster: Brug et frekvensmap som nøgle. For hver streng skal du sortere dens tegn (eller beregne en tegnfrekvenstuple) som den kanoniske nøgle. Gruppér strenge efter denne nøgle ved hjælp af et hash map med lister. Tidsforbrug O(n × m log m), hvor m er den maksimale strenglængde, pladsforbrug O(n × m). Der er ikke brug for indlejrede løkker — én gennemgang af arrayet.

from collections import defaultdict

def group_anagrams(strs):
    # Method 1: sort each string as key
    groups = defaultdict(list)
    for s in strs:
        key = ''.join(sorted(s))   # canonical form
        groups[key].append(s)
    return list(groups.values())

def group_anagrams_v2(strs):
    # Method 2: character count tuple as key (avoids sorting)
    groups = defaultdict(list)
    for s in strs:
        count = [0] * 26
        for c in s:
            count[ord(c) - ord('a')] += 1
        key = tuple(count)   # immutable, hashable
        groups[key].append(s)
    return list(groups.values())

test = ['eat', 'tea', 'tan', 'ate', 'nat', 'bat']
result = [sorted(g) for g in group_anagrams(test)]
result.sort()
print('Groups:', result)
# [['ate','eat','tea'], ['bat'], ['nat','tan']]

print('V2:', [sorted(g) for g in sorted(group_anagrams_v2(test), key=len)])

Selvvurdering efter et prøveinterview

Efter hvert simuleret interview skal du vurdere dig selv på disse områder:

  • Hastighed i mønstergenkendelse: Identificerede du mønsteret på <60 sekunder?
  • Kodens korrekthed: Bestod din første løsning alle testtilfælde?
  • Håndtering af kanttilfælde: Afprøvede du tomt input, enkelt input og ekstreme input?
  • Kommunikation: Forklarede du dine overvejelser undervejs?
  • Forståelse af kompleksitet: Angav du tids- og pladsforbruget?
  • At komme videre: Hvis du gik i stå, skiftede du så smidigt strategi, eller frøs du?

Giv dig selv en vurdering fra 1 til 5 på hvert område. Fokuser den næste uges øvelse på det område, du vurderede lavest. De fleste kandidater har brug for at forbedre enten mønstergenkendelse eller kommunikation — sjældent begge dele.

# Self-assessment scoring template
def self_assess(pattern_speed, code_correctness, edge_cases,
                communication, complexity, recovery):
    scores = {
        'Pattern recognition (< 60s)': pattern_speed,
        'Code correctness (all tests pass)': code_correctness,
        'Edge case handling': edge_cases,
        'Communication (thinking aloud)': communication,
        'Complexity stated correctly': complexity,
        'Recovery when stuck': recovery,
    }
    total = sum(scores.values())
    max_total = len(scores) * 5
    print('Self-Assessment Results:')
    print('-'*50)
    for dim, score in scores.items():
        bar = '#' * score + '-' * (5 - score)
        print(f'{dim:45s} [{bar}] {score}/5')
    print(f'\nTotal: {total}/{max_total} ({total/max_total*100:.0f}%)')
    weak = min(scores, key=scores.get)
    print(f'Focus area: {weak}')

self_assess(4, 3, 4, 3, 5, 2)  # example scores

Hurtigt tjek

Afprøv din forståelse af begreberne fra denne lektion i Data Structures & Algorithms — Coding Interview Prep.

Opsummering af lektionen

I denne lektion har du lært: at gå til opgaver med en fast arbejdsgang — læs, identificér mønsteret på 60 sekunder, angiv kompleksiteten, kod, og afprøv derefter løsningen med fem kategorier af kanttilfælde, at en fungerende brute-force-løsning er bedre end en ufuldstændig optimal løsning, når tiden er ved at løbe ud, og at selvvurdering efter hver simulerede træningssession på seks områder (hastighed, korrekthed, kanttilfælde, kommunikation, kompleksitet og evnen til at komme videre) retter forbedringsarbejdet mod de rigtige områder. Næste gang gennemgår vi håndtering af kanttilfælde og bedste praksis for, hvordan du kommunikerer som interviewperson.

Gratis at komme i gang

Lær Python med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
30
Lektioner
120

Ofte stillede spørgsmål

Er lektionen “Tidsbegrænset prøveinterview: Nemme og mellemsvære problemer” gratis?

Ja — alle 3 lektioner i læringssporet DSA Interview Prep, inklusive “Tidsbegrænset prøveinterview: Nemme og mellemsvære problemer”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. DSA Interview Prep-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Tidsbegrænset prøveinterview: Nemme og mellemsvære problemer”?

Løs tre problemer inden for 45 minutter, forklar Deres tankeproces, som De ville gøre i et rigtigt interview, og gennemgå de optimale løsninger bagefter. Du øver dig i DSA Interview Prep med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på DSA Interview Prep?

Der kræves ingen tidligere erfaring. DSA Interview Prep på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.

Hvor lang tid tager lektionen “Tidsbegrænset prøveinterview: Nemme og mellemsvære problemer”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne DSA Interview Prep-lektion?

Ja. Alle DSA Interview Prep-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Oversigt over mønstergenkendelse
  2. Tidsbegrænset prøveinterview: Nemme og mellemsvære problemer
  3. Håndtering af kanttilfælde og kommunikation som interviewperson
  4. Gennemgang af svære problemer: Word Ladder II og Alien Dictionary
← Tilbage til DSA Interview Prep