Search
30 results for “bfs”
Search results
Graph Traversal: BFS & DFS
Why breadth-first search's queue explores every neighbor before any of their children, guaranteeing the shortest path in an unweighted graph, while depth-first search's stack (or recursion) does the opposite and can't make that guarantee at all.
What is the defining structural difference between BFS and DFS, and what data structure does each rely on?
Breadth-first search considers every neighbor of a vertex before considering any of those neighbors' own outgoing edges, per NIST's definition, extremes are searched last, which is implemented with a queue: vertices are processed in the order they were discovered, level by level outward from the start. Depth-first search does the opposite, it considers a vertex's outgoing edges (children) before any of the vertex's siblings, plunging as deep as possible along one path before backtracking, and NIST notes it's "easily implemented with recursion," which uses the call stack implicitly as its ordering structure (or an explicit stack in an iterative version).
Why does BFS guarantee the shortest path in an unweighted graph, while DFS gives no such guarantee at all?
Because BFS processes vertices in strict order of distance from the start (via its queue, level by level), the first time it reaches any given vertex is necessarily via a shortest path to it, there's no way to discover a vertex at distance k before every vertex at distance k-1 has already been discovered. DFS has no such ordering property, it commits to going as deep as possible down one path before backtracking, so it can easily reach a target vertex via a long, winding path long before it would have found a much shorter one, there's nothing in DFS's structure that favors shorter paths over longer ones at all.
For the same graph, why might you choose DFS over BFS even though BFS finds shortest paths and DFS doesn't?
Shortest-path guarantees aren't always the goal, DFS is a natural fit for exhaustively exploring all possibilities along one path before trying another (backtracking problems, detecting cycles, topological sorting, finding connected components), where the actual requirement is "visit everything reachable" or "explore this branch fully before trying the next," not "find the closest thing first." DFS via recursion is also often simpler to implement for these problems, at the cost of consuming call-stack depth proportional to how deep the graph goes, which matters for very deep or very large graphs where an iterative approach (or BFS) avoids the recursion-depth risk entirely.
What is the difference between Blob Storage, File Storage, and Disk Storage in Azure?
Blob Storage is object storage for unstructured data (images, backups, logs), accessed via HTTP/HTTPS APIs, not mounted as a filesystem. File Storage provides fully managed file shares accessible via the SMB or NFS protocol, usable as a network drive that multiple VMs can mount simultaneously. Disk Storage provides block-level storage attached to a single VM, functioning as its virtual hard disk. The choice depends on access pattern: Blob for API-driven unstructured data at scale, File for shared network-drive-style access across machines, Disk for a VM's own persistent local-feeling storage.
What is the practical difference between SELECT ... FOR UPDATE and SELECT ... FOR SHARE?
FOR UPDATE takes an exclusive row lock, it blocks other transactions from updating, deleting, or taking any competing lock (including another FOR UPDATE or FOR SHARE) on the same rows, appropriate when you're about to modify the row and need to ensure nothing else changes or locks it first. FOR SHARE takes a shared lock, it still blocks updates and deletes, but permits other transactions to also take FOR SHARE or FOR KEY SHARE locks on the same rows concurrently, appropriate when you only need to ensure a row doesn't change or get deleted while you read it, without needing exclusive access.
What is the difference between ss and the older netstat command, and why would you reach for ss first?
Both report socket/connection information, but ss reads directly from kernel data structures and can display considerably more TCP and socket state detail than netstat, including fine-grained state groupings like every "connected" state (everything except listening and closed) or every "synchronized" state, which makes targeted filtering much easier. netstat has been effectively superseded across current Linux distributions, and ss is the tool actively maintained as part of the iproute2 suite alongside ip, which is why it is the modern default for socket inspection rather than a mere alternative.
Why does wrapping several statements in `BEGIN`/`COMMIT` matter, even for a multi-step operation that's logically one action?
Without an explicit transaction, PostgreSQL commits each statement independently the moment it succeeds; if a multi-step operation (debit one account, credit another) fails halfway through, the database is left in an inconsistent, partially-applied state with no way to undo the completed step. Wrapping the statements in `BEGIN`/`COMMIT` groups them so they can be committed or rolled back together, but that alone isn't automatic protection against every failure mode: PostgreSQL only aborts a transaction on its own when a statement raises an actual SQL error, an `UPDATE` that runs successfully but matches zero rows (a mistyped account id, for instance) is not an error at all, and would otherwise be committed as if the transfer had actually happened. Making the transaction genuinely safe means checking that each `UPDATE` affected exactly the one row expected and issuing an explicit `ROLLBACK` if either check fails, only issuing `COMMIT` once both checks pass.
Why does a chunk like "The company's revenue grew by 3% over the previous quarter" cause a retrieval failure even if it's embedded correctly?
That sentence is only meaningful with context the isolated chunk doesn't carry, which company, which quarter, information that likely lived in a heading or preceding paragraph that didn't survive the chunking boundary. Embedded on its own, the chunk's vector represents a generic, context-free statement about revenue growth, which means it won't be retrieved reliably for a query about "ACME Corp Q2 2023 earnings" even though it's exactly the right chunk, because nothing in its embedding actually encodes that it's about ACME Corp or Q2 2023 at all.
What does it mean for a sorting algorithm to be "stable," and why does that matter for sorting by multiple keys in separate passes?
A stable sort guarantees that when two elements compare as equal under the current sort key, their original relative order is preserved rather than left unspecified. This matters directly for multi-key sorting done as a series of single-key sorts: sort by a secondary key first, then stably sort by the primary key, and elements sharing the same primary key retain their secondary-key order from the first pass, correctly producing a combined sort by (primary, secondary) without needing a single comparator that handles both keys at once. An unstable sort would silently scramble that secondary ordering among equal-primary-key elements.
A custom dropdown built entirely from styled divs passes a visual design review. What is likely still broken for a keyboard-only or screen-reader user, and why doesn't looking right catch it?
Without the correct ARIA roles/states (or, better, a native `<select>`), a div-based dropdown typically has no way to be reached or operated via keyboard alone (no built-in Tab/Enter/Arrow-key handling), and a screen reader has no semantic information telling it "this is a dropdown, it is currently closed, here are its options," so it may announce nothing meaningful at all. A purely visual review can't catch this because the div looks and behaves correctly with a mouse, the missing behavior only surfaces via keyboard navigation or assistive technology, which is exactly why accessibility has to be tested directly with a keyboard and a screen reader, not inferred from how a component looks.
A page has a fast average LCP but users still frequently report the page feeling slow. What could the percentile-based measurement reveal that an average wouldn't?
If a substantial slice of real page loads, say the slowest 25%, badly miss the 2.5 second LCP threshold (a slow connection, a busy device, a cold cache), the average can still look fine because it's dominated by the faster majority, while a real, sizable group of users are having a genuinely bad experience the average is actively hiding. Checking the 75th-percentile value directly (rather than the mean) surfaces that gap: if the 75th percentile is well above 2.5 seconds even though the average looks fine, that's a concrete signal that meaningful numbers of real users are missing the threshold, not a false alarm.
Bash Fundamentals
The scripting layer built on top of the shell - variables, conditionals, loops, and functions - and the quoting and exit-status habits that separate a script that looks right from one that fails safely.
Why does an O(n log n) sort beat an O(n^2) sort for large inputs, even if the O(n^2) one is faster on small inputs?
Constant factors can make an O(n^2) algorithm faster for small n, Big O only describes the asymptotic trend, not the exact runtime. But growth rates diverge fast: at n = 1,000,000, n log n is about 20 million operations while n^2 is a trillion. Past a crossover point the asymptotically better algorithm always wins, which is why production sort implementations (like Timsort) still often special-case small arrays with a simpler O(n^2) sort under the hood.
Why is binary search O(log n) instead of O(n), and what specifically has to be true about the data structure for that to hold?
Each comparison eliminates half of the remaining search space, so after k comparisons only n/2^k elements remain to check, meaning the search terminates once 2^k ≥ n, k ≈ log2(n) comparisons, exponentially fewer than checking every element one at a time. That guarantee depends entirely on being able to jump directly to a midpoint in constant time, which is true for an array or list with O(1) random access, but not for a data structure like a linked list where reaching the "middle" element itself takes O(n) time, on a linked list, binary search's comparison-count advantage is real but gets erased by the cost of just navigating there.
What is the cloud shared responsibility model, and why does it matter for security?
It's the explicit division of security obligations between the cloud provider and the customer, and where that line falls depends on the service model. The provider is always responsible for "security of the cloud", physical data centers, host infrastructure, and (for managed services) the underlying platform. The customer is always responsible for "security in the cloud", for IaaS, that includes OS patching, network configuration, and IAM; for PaaS, it narrows to application code, data, and access control; for SaaS, it's mostly just access control and data. Misunderstanding this line is one of the most common causes of real cloud security incidents, assuming the provider handles something they explicitly don't.
Why does a naive `hash(key) % N` scheme for distributing keys across N servers fall apart the moment a server is added or removed?
With plain modulo hashing, the server a key maps to depends directly on the current value of N, since almost every key's `hash(key) % N` result changes the instant N changes to N-1 or N+1, even though the underlying hash values themselves didn't change at all. That means adding or removing a single server can remap the overwhelming majority of keys to different servers simultaneously, which for a cache means a massive wave of cache misses, and for a sharded store means a massive, unnecessary data-migration event, triggered by a change to just one server out of many.
Two transactions each update two of the same two accounts, but in opposite order, and deadlock. What's the actual fix, not just for this pair of transactions, but for the application generally?
The deadlock happens because Transaction 1 locks account A then waits for account B, while Transaction 2 locks account B then waits for account A, a circular wait. The general fix isn't retry logic alone, retries only paper over deadlocks that keep recurring, it's acquiring locks on multiple objects in the same, consistent order everywhere in the application (for example, always locking accounts in ascending id order), which makes the circular-wait pattern structurally impossible rather than merely less frequent. Retry logic is still worth having as a safety net, but consistent lock ordering is what actually eliminates this class of deadlock.
What is the required contract between equality and hashing for an object used as a dictionary key, and why does the hash table need it specifically?
The contract is one-directional but strict: if two objects compare equal, they must produce the same hash value. A hash table uses an object's hash to pick which bucket to look in, then uses equality only to confirm the exact match within that bucket, so if two equal objects hashed differently, a lookup for one would search the wrong bucket entirely and never even reach the equality check that would have confirmed the match. The hash doesn't have to be unique across unequal objects (collisions are expected and handled), it just has to agree for anything that compares equal, that's the one property the whole lookup mechanism depends on.
A custom class defines __eq__ based on a value field but leaves __hash__ using default identity-based hashing. What actually goes wrong when you use an instance as a dict key?
In Python 3, simply defining `__eq__` without touching `__hash__` doesn't leave the old identity-based hash in place, Python automatically sets `__hash__` to `None` on that class, making instances unhashable, so using one as a dict key raises `TypeError` immediately rather than corrupting anything. This happens even if a parent class defines `__hash__`: overriding `__eq__` in a subclass sets that subclass's `__hash__` to `None` regardless of what the parent provides, ordinary inheritance does not carry the parent's hash forward. The silent, no-exception version of this bug only happens if the class explicitly keeps or re-supplies an identity-based `__hash__` alongside the value-based `__eq__` (e.g. `__hash__ = object.__hash__`, or, to retain a parent's hash on purpose, `__hash__ = Parent.__hash__`). In that case, two instances with the same value compare equal (`a == b` is `True`) but hash differently, and inserting under key `a` then looking up with an equal-but-distinct key `b` lands in the wrong hash bucket and returns nothing, because the hash mismatch never gave the lookup a chance to even check equality against the right entry.
A process creates a file requesting mode 0666, but the file ends up with permissions 0644. What decided that, and would the outcome change if the parent directory had a default ACL?
The process's umask is what changed the requested mode: umask 022 turns off the write bit for group and others from any requested mode, so 0666 (rw-rw-rw-) becomes 0666 & ~022 = 0644 (rw-r--r--). The umask is applied by the kernel at file/directory creation time, not by the application deciding to be conservative. If the parent directory has a default ACL set, that changes the outcome: default ACL inheritance takes precedence over the umask entirely, so the new file's permissions would instead be derived from the ACL, not from applying umask to the requested mode.
In a systemd unit, what is the practical difference between Type=simple and Type=forking, and why does that distinction matter for dependency ordering?
With Type=simple, systemd considers the unit started the moment the main process is forked off, it does not wait for the application to finish its own initialization, so anything depending on that unit might start before the service is actually ready to handle requests. Type=forking expects the traditional daemon pattern, the initial process forks and exits once it judges its own startup complete, so systemd marks the unit started as soon as that original process exits successfully, while the actual daemon keeps running as a separate, now-orphaned process. That only tracks the daemonization handoff, not genuine application readiness, a process can exit believing setup is done while it is still finishing initialization in the background, so Type=forking is a better signal than Type=simple but still not a readiness guarantee. Type=notify is the one that actually is readiness-safe: the service explicitly calls sd_notify to tell systemd exactly when it's ready, rather than systemd inferring readiness from process exit behavior at all.
What is the difference between running "mount" once from the command line and adding an entry to /etc/fstab?
A manual `mount` command attaches a filesystem to the directory tree for the current running session only, it does not survive a reboot, the system has no record of it having ever happened. An `/etc/fstab` entry is the persistent, declarative definition of what should be mounted where and with what options, and it's what the boot process (and `mount -a`) reads to reconstruct every expected mount automatically. A filesystem mounted manually but never added to fstab is the classic cause of "it worked, then disappeared after a reboot," and works precisely because it was set up as a one-time action, not a declared, persistent one.
Why is an evaluation suite necessary before shipping a prompt change, instead of just testing it manually on a few examples?
A prompt change can improve one success dimension while quietly breaking another, better accuracy but worse consistency, or improved tone at the cost of latency, and manually eyeballing a handful of examples won't reliably catch a regression on a dimension you weren't specifically looking at. An evaluation suite tests against a defined, ideally large set of cases, including deliberately hard edge cases like sarcasm or mixed sentiment, and scores every dimension that actually matters, which turns "it feels better" into a measurable, defensible, trackable claim, and catches regressions before they reach production rather than after.
Why does explicitly telling a model it's allowed to say "I don't know" measurably reduce hallucination, and what's a second, complementary technique for the same problem?
Without that explicit permission, a model under an implicit expectation to always produce a confident, complete answer will sometimes fill a real information gap with a plausible-sounding but fabricated one; stating outright that uncertainty is an acceptable answer removes that pressure and lets the model surface "I don't have enough information" instead of guessing. A complementary technique for long documents is asking the model to first extract direct, word-for-word quotes relevant to the task before generating any analysis, grounding its response in verifiable text it actually has in front of it, and then citing which quote supports each claim, rather than generating an answer freely and hoping it stayed faithful to the source.
A request's input already exceeds the model's context window before generation even starts. What happens, versus a request that only exceeds the limit once output is generated?
If the input alone already exceeds the context window, the API rejects the request upfront with a 400 error, generation never starts at all. If the input fits but input tokens plus the requested max output tokens could exceed the window, current models accept the request and generate as far as they can; if generation actually reaches the window limit before finishing, it stops early with a specific stop reason indicating the context window was exhausted, rather than silently truncating or erroring out mid-response. The distinction matters operationally: the first case is a fixable request-construction bug, the second is a signal to reduce the requested output length or the accumulated conversation history.
Why does calling a blocking function inside an async function defeat the purpose of using asyncio?
A blocking call (synchronous file I/O, a synchronous HTTP request, `time.sleep`) occupies the single thread the event loop runs on, and unlike `await`, it does not yield control back, the entire event loop is frozen for the duration of that blocking call, so every other coroutine that could otherwise be making progress is stalled too. This is why async code requires async-compatible libraries throughout the I/O path; a single accidental blocking call anywhere in a hot path can silently serialize what was supposed to be concurrent work, and the bug often doesn't show up until real concurrent load exposes it.
What is the core philosophical difference between Flask and Django?
Flask is a microframework; it provides routing and request/response handling and deliberately leaves everything else (ORM, admin panel, authentication, forms) to be chosen and added by the developer. Django is batteries-included; it ships with an ORM, an admin interface, an authentication system, and a forms library as an integrated whole, with strong conventions about how a project should be structured. Flask trades built-in structure for flexibility; Django trades flexibility for a consistent, fully-equipped starting point. Neither is strictly better, the right choice depends on whether a project benefits more from Django's conventions or needs the freedom to pick its own pieces.
An O(n^2) sort can be faster than an O(n log n) sort for small inputs. Why, and why doesn't that matter for a general-purpose sort function?
Big O describes asymptotic growth, not actual runtime, and O(n^2) algorithms often have smaller constant factors and simpler inner loops (no recursion or merge-buffer overhead) that make them genuinely faster in wall-clock time for small n, even though the more sophisticated O(n log n) algorithm would eventually win as n grows. This is exactly why production sort implementations, including Timsort, special-case small subarrays with a simple insertion sort internally rather than using the full merge-sort machinery on tiny inputs, getting the best of both regimes instead of picking one algorithm for every input size.
Why would a hash join beat a nested loop join for two large, unindexed tables, but lose to a nested loop join when one table is tiny?
A nested loop join's cost scales with (outer rows) × (cost of an inner-side lookup per row), so with two large unindexed tables, the inner-side scan is expensive and gets repeated for every single outer row, making the total cost grow multiplicatively. A hash join instead pays a roughly one-time cost to build a hash table from one side, then does a cheap lookup per row from the other side, additive rather than multiplicative, which wins decisively at scale. But when one table is tiny, the nested loop's "repeat the inner scan per outer row" cost is trivial regardless, and it avoids the hash table's build overhead entirely, so the simpler algorithm wins for small inputs specifically.