Amazon AI Engineer Interview Questions & Answers

amazon icon

Questions with Detailed ExplanationsWith Detailed Explanations

(Last Updated: August 28, 2026)

11. For an Amazon Bedrock Knowledge Base, n documents and their near-duplicate links form an undirected graph. Implement `count_components(n, edges)` to return the number of connected components so deduplication jobs can be batched per component.CodingMediumAmazon

Question Details

The implementation must validate node bounds, handle isolated vertices, duplicate and self edges, return the correct count at scale, state time and space complexity, and test both sparse and dense cases.

Short Interview Answer (30-60 seconds)

I would model the documents as an undirected graph and count connected components with iterative DFS. I first validate every node ID, then build an adjacency list. Self edges are skipped because they do not change connectivity. Duplicate edges are harmless because visited nodes are not explored again. I scan every node, so isolated documents are also counted. Each DFS started from an unvisited node adds one component. The time complexity is O(n + m), and the auxiliary space is O(n + m).

Detailed Explanation

See the Code while reading this explanation.

We have n documents. Some pairs of documents have near-duplicate links. A link means those documents belong to the same group, either directly or through other linked documents. We need to count how many separate groups exist. I build the links in both directions, then start from every document that has not already been reached. A stack lets me visit the full group. Each new start adds one to the answer. Because I check all n documents, documents with no links are counted too.

Useful Questions to Ask the Interviewer
  1. Are valid document IDs always integers from 0 through n - 1?
  2. Should the function raise an error when an edge contains an invalid node ID? The shown implementation raises ValueError.
  3. Can the input contain duplicate links and self links? The implementation safely handles both.
For an Amazon Bedrock Knowledge Base, n documents and their near-duplicate links form an undirected graph. Implement `count_components(n, edges)` to return the number of connected components so deduplication jobs can be batched per component. diagram
How to Explain It in an Interview
1. Understand the input and output

The function receives n and edges. Nodes are numbered from 0 through n - 1. Each pair (u, v) is an undirected edge, so the connection works both ways. The required output is one integer: the number of connected components. A connected component is one group of nodes where every node can reach the others through one or more edges. A node with no edges is still its own component.

2. Build and validate the graph

First, reject a negative n. Then read each edge. Both endpoints must be inside the range 0 through n - 1. If either endpoint is invalid, raise ValueError. A self edge such as (2, 2) does not connect two different nodes, so the code skips it. Every other edge is added in both directions to the adjacency list because the graph is undirected. Duplicate edges may appear more than once in the list, but they do not change the component count because already visited nodes are not explored again.

3. Initialize the traversal state

Create visited = [False] * n and count = 0. visited[i] tells us whether node i has already been assigned to a component found by an earlier DFS. The important invariant is that every visited node already belongs to a component that has been counted.

4. Walk through the sparse example

The diagram uses n = 7 and edges = [(0, 1), (1, 2), (3, 4)]. Start with all nodes unvisited. Node 0 is unvisited, so count becomes 1. DFS from 0 reaches 1 and 2. Nodes 1 and 2 are now already visited. Node 3 is the next unvisited node, so count becomes 2. DFS from 3 reaches 4. Node 5 has no links, so starting from 5 makes count 3. Node 6 is also isolated, so starting from 6 makes count 4. The final result is 4.

5. Explain why the result is correct

Whenever DFS starts from an unvisited node, it follows every reachable edge and marks that whole connected component visited. Because all nodes in that component become visited, no later start can count the same component again. If the outer loop reaches a node that is still unvisited, that node cannot belong to any component already explored. Therefore every new DFS start represents exactly one new connected component.

6. Explain the Python implementation

The adjacency list stores the neighbors of each node. The outer loop checks every node from 0 through n - 1, which is why isolated vertices are included. When an unvisited start node is found, the code increases count, places that node on a stack, and marks it visited. The iterative DFS pops one node at a time. For each neighbor that has not been visited, it marks the neighbor immediately and pushes it onto the stack. When the stack is empty, that component is complete.

7. Explain complexity and edge cases

Let n be the number of nodes and m be the number of supplied edges. Building the adjacency list and traversing it takes O(n + m) time. The adjacency list, visited array, and DFS stack use O(n + m) auxiliary space in the worst case. Important cases are isolated nodes, duplicate edges, self edges, an empty edge list, a one-node graph, dense graphs, and invalid node IDs. The dense complete-graph example with n = 6 has one connected component.

Key Insight / Why This Solution Works

The key idea is to count how many times we need to start a new graph traversal. The graph is stored as an undirected adjacency list. We then use iterative DFS with a stack to explore one complete connected component at a time. The central invariant is that every visited node already belongs to a component we have counted. Therefore, when the outer loop finds an unvisited node, that node must start a new component. DFS marks every node reachable from it before the outer loop continues. Checking every node also makes isolated documents count correctly.

Code
from collections import defaultdict
from typing import List, Tuple


def count_components(n: int, edges: List[Tuple[int, int]]) -> int:
    """Return the number of connected components in an undirected graph."""

    # A graph cannot have a negative number of nodes.
    if n < 0:
        raise ValueError("n must be non-negative")

    # Store each node's neighbors. Normal edges are added in both directions.
    adj: defaultdict[int, list[int]] = defaultdict(list)

    for u, v in edges:
        # Every edge endpoint must be a valid node from 0 through n - 1.
        if not (0 <= u < n and 0 <= v < n):
            raise ValueError(f"node out of bounds: ({u}, {v}) for n={n}")

        # A self edge does not connect this node to another node.
        if u == v:
            continue

        # Add both directions because the graph is undirected.
        # Duplicate edges are harmless because DFS checks visited before pushing.
        adj[u].append(v)
        adj[v].append(u)

    # visited[i] becomes True when node i is assigned to a discovered component.
    visited: List[bool] = [False] * n
    count = 0

    # Check all nodes so isolated vertices are counted as one-node components.
    for start in range(n):
        if visited[start]:
            continue

        # An unvisited start node means we found one new connected component.
        count += 1
        stack: List[int] = [start]
        visited[start] = True

        # Iterative DFS visits every node reachable from this component start.
        while stack:
            u = stack.pop()

            for v in adj[u]:
                # Mark before pushing so the same node is not added repeatedly.
                if not visited[v]:
                    visited[v] = True
                    stack.append(v)

    # Each DFS start represented exactly one connected component.
    return count


def main() -> None:
    # Sparse example from the diagram: {0,1,2}, {3,4}, {5}, and {6}.
    n = 7
    edges: List[Tuple[int, int]] = [(0, 1), (1, 2), (3, 4)]
    result = count_components(n, edges)
    print(result)  # Expected: 4
    assert result == 4

    # Dense example from the diagram: a complete graph has one component.
    dense_edges: List[Tuple[int, int]] = [(i, j) for i in range(6) for j in range(i + 1, 6)]
    assert count_components(6, dense_edges) == 1

    # With no edges, every node is isolated and forms its own component.
    assert count_components(5, []) == 5

    # Self and duplicate edges do not change the connectivity result.
    assert count_components(4, [(0, 0), (1, 2), (1, 2), (2, 1)]) == 2

    # A single isolated node is one connected component.
    assert count_components(1, []) == 1


if __name__ == "__main__":
    main()
Time & Space Complexity

Let n be the number of documents and m be the number of supplied edges. The time complexity is O(n + m). We examine the nodes, read the edges, and traverse the adjacency entries created from those edges. Duplicate input edges can create repeated adjacency entries, but those entries are still part of m and do not change the asymptotic bound. The auxiliary space is O(n + m) for the adjacency list, the visited array, and the iterative DFS stack in the worst case.

Where it is used

Connected-component counting is useful when linked records must be separated into independent groups. In this problem, near-duplicate document links form groups that can be processed as separate deduplication batches. The same pattern is useful for network groups, linked accounts, clusters created from pairwise relationships, and other systems where we need to find disconnected groups.

Why Interviewers Ask This

This problem tests whether you recognize the connected-components graph pattern and can implement it carefully. The interviewer is checking whether you build an undirected adjacency representation, mark visited nodes at the correct time, count isolated vertices, validate node IDs, and handle duplicate and self edges safely. It also checks whether you can avoid recursion-depth issues with iterative DFS, test sparse and dense graphs, and explain O(n + m) time and O(n + m) auxiliary space correctly.

Common interview mistakes

A common mistake is counting only nodes that appear in edges. That misses isolated documents, so the outer loop must check all n nodes. Another mistake is treating an undirected edge as one-way and adding only u to v. Candidates may also forget to validate node bounds. Marking visited too late can place the same node on the stack more than needed. Self edges must not create extra components, and duplicate edges must not change the count. Another mistake is claiming smaller space than the code uses because the adjacency list and DFS stack both require extra memory.

Interview tip

Build the explanation around one invariant: whenever the outer loop finds an unvisited node, that node starts exactly one new component. Then explain that DFS marks the entire reachable component before the outer loop continues. This connects the component count directly to the code and makes the correctness argument easy to follow.

Interviewer may ask next
How would this solution handle a very large graph?

The same iterative DFS still takes O(n + m) time and O(n + m) auxiliary space. Using a stack avoids Python recursion-depth limits, which helps when one component is very deep or large. The main memory cost is the adjacency list. If the full edge set cannot fit in memory, we would need a different storage or streaming design. That changes how the graph is supplied, but the connected-component idea remains the same.

Can we reduce the extra memory used by this implementation?

The current implementation builds an adjacency list, so its auxiliary space is O(n + m). The visited array and DFS stack can each use O(n). If the input already provides efficient neighbor access, we can reuse that graph representation instead of building another adjacency list. Then the additional traversal memory can be O(n). The time remains O(n + m). The tradeoff is that this depends on the existing input representation supporting efficient neighbor iteration.

12. Can you tell me about a time you failed?BehavioralEasyAmazon

Question Details

Use an AI or engineering example that identifies the candidate's own decision, the measurable consequence, how responsibility was communicated, what changed afterward, and evidence that the lesson altered later work.

Interview tip:

Use STAR to structure your answer: briefly explain the Situation and Task, make Action the most detailed part, and finish with the Result. For example, describe an AI project where your own decision caused a poor result, explain the consequence, show how you took responsibility and communicated it, and explain what you changed so the same lesson improved your later work.

Situation

In my last role, I worked on an AI assistant that retrieved information from internal documents before generating an answer. During one release, I relied too heavily on our normal evaluation set. I did not test enough difficult cases involving long documents and similar passages. The release passed the checks I had selected, but the pilot later showed that some answers were using the wrong supporting passage.

Task

I was responsible for the evaluation work that helped determine whether the new version was ready. My failure was not simply that the model made mistakes. I had made the decision to use an evaluation set that was too narrow. I needed to understand the impact, communicate my responsibility clearly, fix the immediate problem, and improve the release process.

Action

I first reproduced the bad answers and traced them through the retrieval and generation flow. This showed that the main problem appeared when several passages looked similar and the correct information was deeper in a long document. I told my manager and the team that my evaluation decision had missed this case. I did not blame the model or another part of the system. I recommended stopping the rollout until we understood the problem. I then expanded the evaluation set with difficult examples that represented the failure we had seen. I separated results by case type instead of looking only at one overall result. This mattered because a good overall result could hide a serious problem in one important group of examples. I also added a release check that compared the new version with the current production version on these difficult cases. After the immediate issue was fixed, I documented the failure and added the new checks to our normal evaluation process. On later projects, I used the same approach before recommending a release. I asked what important cases might be hidden by an average result and made sure those cases were tested separately.

Result

We stopped the rollout, corrected the evaluation gap, and released only after the difficult cases were tested successfully. The pilot had shown a repeatable pattern of answers using the wrong supporting passage, and the expanded evaluation made that failure visible before the release continued. The failure changed how I think about AI evaluation. I learned that passing a familiar test set does not prove that a model is ready for real use. More importantly, the lesson changed my later work. I now treat evaluation coverage as part of the product design, not as a final check, and I make important failure cases visible before a release decision is made.

Why Interviewers Ask This

Interviewers ask this question to see whether a candidate can admit a real mistake, take responsibility for a decision, respond constructively, and learn from the outcome. A strong answer shows ownership, clear communication, practical judgment, and evidence that the lesson changed later behavior.

Interviewer may ask next
What would you do differently if you faced the same situation today?

I would define the important failure cases before building the final evaluation set. I would include difficult examples from long documents and similar passages, review results by case type, and compare the new version with the current version before recommending a rollout. That would make the risk visible much earlier.

How did you know you had actually learned from the failure?

The main evidence was that I changed my process on later projects. I stopped relying only on one overall evaluation result. I began testing important failure cases separately and checking evaluation coverage before release decisions. The lesson became part of how I worked, not just something I wrote down after the incident.

13. Describe a situation where you had to earn trust with skeptical cross-functional stakeholders.BehavioralMediumAmazon

Question Details

The example should identify the source of skepticism, conflicting incentives, evidence and communication used, commitments the candidate made and kept, how disagreement was handled, and the observable change in collaboration or decision quality.

Interview tip:

Use STAR to structure your answer: briefly explain the Situation and Task, make Action the most detailed part, and finish with the Result. For example, describe a previous AI project where stakeholders were skeptical because they had different priorities, explain the evidence you shared, how you handled disagreement, the commitments you made and kept, and how stronger trust improved collaboration and decisions.

Situation

In my last role, I worked on an AI feature that would help an operations team review incoming cases. The operations stakeholders were skeptical because an earlier version had produced inconsistent suggestions. They were worried about reliability and extra review work. The engineering team wanted to move quickly, while operations wanted stronger evidence before using the feature more widely.

Task

I was responsible for improving the model evaluation process and helping both groups decide whether the feature was ready. I also needed to earn trust by making the risks visible, listening to the concerns from operations, and making commitments that I could realistically keep.

Action

I first met with the operations stakeholders and asked them to show me examples that had reduced their confidence. I did not defend the model. I wrote down the failure patterns they cared about and asked which mistakes created the most work or risk for them. This mattered because our existing evaluation focused mainly on overall model quality, while the stakeholders cared about specific types of errors. I then reviewed those cases with the engineering team and created a clearer evaluation set around the important failure patterns. I shared the results in simple language and included examples of both good and bad model behavior. I also explained where the model was still uncertain instead of presenting only positive results. When we disagreed about whether the system was ready, I suggested a limited rollout with human review instead of asking operations to accept a larger launch. I committed to reviewing reported failures, sharing evaluation updates regularly, and not expanding usage until we had discussed the evidence together. I kept those commitments. When operations raised new concerns, I investigated them and came back with the result, even when the result showed that more work was needed. Over time, the conversations changed. The stakeholders started bringing examples earlier and asking how we could test them together, instead of assuming engineering would dismiss their concerns.

Result

We reached a shared decision to continue with a controlled use of the feature while improving the remaining weak areas. The biggest result was better collaboration. Operations became more willing to participate in evaluation and engineering received better feedback earlier. I learned that earning trust with skeptical stakeholders is not about persuading them with more technical detail. It comes from understanding their incentives, showing evidence clearly, being open about limitations, and consistently doing what I said I would do.

Why Interviewers Ask This

Interviewers ask this question to see whether a candidate can build credibility when teams have different goals and reasons to be cautious. A strong answer shows that the candidate listens carefully, uses evidence instead of authority, handles disagreement professionally, makes realistic commitments, follows through, and improves the quality of shared decisions.

Interviewer may ask next
How did you handle the stakeholders who still disagreed with your recommendation?

I treated the disagreement as useful information rather than resistance to overcome. I asked which specific risk they believed was still unresolved and used real examples to understand it. When the evidence was not strong enough, I agreed that we should not expand usage yet. That helped because the stakeholders could see that I was trying to make a sound decision with them, not simply push the model into production.

What would you do differently if you faced a similar situation again?

I would involve the skeptical stakeholders earlier, before the evaluation plan was finalized. In this case, some of the skepticism came from the fact that our first evaluation did not reflect the mistakes that mattered most to their work. If I involved them earlier, I could define important failure cases together and build trust before we reached the launch decision.

14. Describe a time when you made a critical architectural trade-off under severe time constraints and ambiguity. How did Amazon Leadership Principles guide your decision?BehavioralHardAmazon

Question Details

The account must distinguish reversible and irreversible consequences, customer impact, missing evidence, alternatives rejected, the candidate's decision authority, risk mitigation, communication, outcome, and later reassessment of the trade-off.

Interview tip:

Use STAR to structure your answer: briefly explain the Situation and Task, make Action the most detailed part, and finish with the Result. For example, describe a time when you had to choose an AI system architecture with limited evidence and little time, separate reversible choices from hard to reverse choices, protect the most important customer need, reject weaker alternatives, explain your decision authority and risks, communicate the tradeoff clearly, reduce risk, and later reassess the decision when better evidence became available.

Situation

In my last role, I was helping launch an AI feature that used a language model to produce responses from internal reference content. We were close to a committed release when testing showed that response quality was less predictable than expected for some inputs. We did not have enough evidence to know whether the main cause was retrieval quality, prompt behavior, or the model itself. At the same time, changing the full architecture would have delayed the release and introduced new risks that we would not have enough time to test.

Task

I was responsible for the technical decision about the inference path and the safeguards around it. My goal was to protect customers from unreliable answers while still giving the team a realistic path to release. I also needed to separate decisions we could safely change later from decisions that would be expensive or risky to reverse after launch.

Action

I used the Amazon Leadership Principles as a practical decision framework. Customer Obsession came first. I defined the main customer risk as receiving an answer that sounded confident but was not supported by the available reference content. That meant I would not accept an architecture that increased coverage by guessing when evidence was weak. I then applied Dive Deep. I reviewed the failure examples with the team and separated what we knew from what we were assuming. We knew that some weak answers appeared when retrieval returned poor context. We did not yet know whether a larger model or a major retrieval redesign would solve the problem consistently. I treated that missing evidence as an important constraint instead of pretending we had certainty. Next, I used Bias for Action together with judgment about reversible and irreversible choices. Prompt rules, retrieval thresholds, and routing logic were reversible because we could change them after launch with controlled testing. A rushed replacement of the retrieval architecture was much harder to reverse because it would affect indexing, evaluation, deployment, and several dependent services. I decided not to make that large change under severe time pressure. I also rejected another option of sending every request directly to the model with the available context. It was faster to implement, but it did not give enough protection when the evidence was weak. Instead, I chose a smaller architecture change. We kept the existing retrieval path, added a check for whether enough relevant evidence was available, and returned a safe response when that condition was not met. I had authority over this technical decision, but I did not make it silently. I explained the customer risk, the missing evidence, the alternatives I rejected, and which parts of the decision were temporary. I shared the plan with engineering and product partners and made clear that the release would favor reliable answers over maximum coverage. To reduce risk, I kept the new logic simple, added targeted tests for the failure cases we had observed, and made the thresholds configurable so we could adjust them without redesigning the system. Ownership also mattered. I documented the assumptions and created a clear follow up plan to review the architecture after we had stronger production evidence.

Result

We released a more conservative version of the feature without making a rushed architectural change that would have been difficult to undo. The system avoided answering when the available evidence was too weak, which protected the customer experience while giving us a safe path to learn. After the release, I reviewed new evaluation results and failure examples with the team. That reassessment showed us where the temporary safeguards were useful and where deeper retrieval improvements were still needed. The main lesson for me was that Bias for Action does not mean making the biggest change quickly. It means moving quickly on reversible decisions while protecting customers and being much more careful with decisions that are hard to reverse.

Why Interviewers Ask This

Interviewers ask this question to see how a candidate makes important technical decisions when time and evidence are limited. A strong answer shows customer focus, sound judgment about reversible and irreversible choices, clear ownership, careful risk management, effective communication, and the willingness to revisit a decision when better evidence becomes available.

Interviewer may ask next
Why did you choose the conservative architecture instead of redesigning the retrieval system before launch?

I did not have enough evidence that a retrieval redesign would solve the observed failures, and that change would have affected several parts of the system at once. The smaller change protected customers immediately and was easier to adjust later. I wanted to use Bias for Action on the reversible parts while avoiding a rushed decision that would be difficult to undo.

What would you do differently if you faced the same situation again?

I would establish the evaluation cases and decision thresholds earlier in the project. That would give the team clearer evidence before the release deadline became urgent. I would still separate reversible choices from hard to reverse choices, but earlier evidence would let us make the architectural decision with less ambiguity and give partners more time to understand the tradeoff.

Disclaimer: This interview guide is for educational and informational purposes only. It is designed to help readers prepare, but it does not guarantee any interview result, hiring decision, offer, or outcome. Interview questions, hiring criteria, and preferred answers can vary by employer, interviewer, industry, location, and time. The examples and explanations reflect the authors' research and judgment, are provided without warranties of any kind, and should not be treated as the only correct approach. Diagrams are simplified illustrations intended to highlight the main components and their interactions; actual systems and implementations may be more complex. Alternative approaches may be equally valid or better suited to a particular question, context, or interviewer. To the fullest extent permitted by applicable law, the author, contributors, and publisher are not liable for decisions made, actions taken, or losses incurred based on this guide.

Company Notice: This guide is an independent educational resource and is not affiliated with, endorsed by, sponsored by, or approved by the company named in this guide. Company names are used only to identify interview experiences commonly reported by candidates. Interview practices can change without notice, and inclusion of company-specific content does not mean these questions are official, complete, or guaranteed to be asked. To the fullest extent permitted by law, the author, contributors, and publisher are not responsible for outcomes related to use of this material.