Save the next pointer before redirecting it, then advance the two working heads. No node is allocated and the name/number fields are untouched.
def reverseBook(): Unit = {
  var prev: Node = null
  var cur = list
  while (cur != null) {
    val following = cur.next
    cur.next = prev
    prev = cur
    cur = following
  }
  list = prev
}
Let be the original sequence of node identities, not just their possibly equal field values. Write for the sequence currently headed by prev and for that headed by cur. A suitable loop invariant for in-place linked-list reversal is
with both working lists finite, acyclic, disjoint, together containing exactly the original nodes, and with every name and number unchanged. Here ++ means concatenation. Initially and . One iteration takes from the front of and replaces by . Since , the equation is preserved. Saving following before changing cur.next retains access to .
The loop variant is the length of , decreasing by one. At exit , so ; assigning the head establishes reversal. The empty and singleton cases work without a special branch. The abstraction function of the phone book ignores order, so it still maps every original name to its original number. All original node identities are reused, with running time and auxiliary space.
Figure 1.
In-place reversal preserves node identities while moving nodes from an untouched suffix into a reversed prefix
. Details.
Update an existing node, otherwise append one fresh node while preserving the cycle:
def store(name: String, number: String): Unit = {
  val p = find(name)
  if (p != null) p.number = number
  else {
    val fresh = new Node(name, number, null)
    if (last == null) {
      fresh.next = fresh
      last = fresh
    } else {
      fresh.next = last.next
      last.next = fresh
      last = fresh
    }
  }
}
For an existing name, changing only its number realizes replacement in the abstract partial function. On an empty book, the new node points to itself, establishing a singleton cycle. On a nonempty book, its successor becomes the old first node and the old last points to it; advancing last leaves the first node unchanged and closes the enlarged cycle. Since a full search established absence, name uniqueness is preserved. Thus the postcondition is exactly the old book with this name mapped to the supplied number, and all other entries unchanged. A store takes running time for the name search and additional pointer work.
Return the key's active array index, or -1 if absent:
private def isInMap(x: Int): Int = {
  var i = 0
  while (i < used && elements(i) != x) i += 1
  if (i < used) i else -1
}
The loop invariant states that every index below i has a key different from x. The scan ignores all inactive cells, and short-circuit evaluation protects the array access at the end of the active prefix. Key uniqueness makes a successful index unambiguous. Its running time is .
Polynomial-time reduction Created 2026-10-03 Updated 2026-11-05
A polynomial-time reduction uses a solver for one computational problem to solve another with polynomial overhead, while preserving the required answer. Efficiently transforming data alone is insufficient: the transformation must come with a correctness argument connecting the two tasks.
For a polynomial-time many-one reduction between decision problems , one function satisfies
A polynomial-time Turing reduction instead permits adaptively chosen queries to a solver for . Writing the queries and processing their answers count toward the reduction's resource bound. These are different reduction conventions and should be named explicitly.
If has a polynomial-time algorithm, either such reduction supplies one for : query lengths and the total number of queries are polynomially bounded, so replacing each solver call preserves a polynomial total running time. Conversely, a reduction from a hard helps establish a lower bound on .
Probably approximately correct learning formalizes learning as a two-parameter guarantee. With probability at least over the training random sample and any learner randomness, the returned hypothesis must have true prediction error at most . In the realizable distribution-free setting, this must hold for every input probability distribution and every target in the specified concept class, using an appropriate polynomial number of examples; efficient PAC learning also requires polynomial running time.
“Probably” refers to the chance of obtaining a good hypothesis; “approximately” refers to that hypothesis's error on a fresh observation. For example, and require a 95% chance of returning a predictor whose error is at most 1%, rather than a claim that 95% of individual predictions are right. For finite realizable classes, the sample complexity bound follows by excluding every high-error rule that could have survived the observations.[ref]
Pseudo-polynomial time Created 2026-10-14 Updated 2026-11-05
An algorithm has pseudo-polynomial time when its running time is bounded by a polynomial in the numerical magnitudes of input quantities, rather than necessarily in their encoded lengths. The dynamic programming table for the 0-1 knapsack problem uses arithmetic operations for items and capacity .
A binary numeral system representation needs only bits for that capacity, so the table bound can be exponential in the number of capacity bits. For example, capacities below fit in bits, while a table with one entry for every capacity can have nearly columns. The numerical-value bound does not claim that every instance requires exponential work.
Recursion tree Created 2026-10-24 Updated 2026-10-31
A recursion tree records recursive calls as nodes and their direct recursive subcalls as children. Its node labels can record the work done outside those subcalls. Summing the work over levels or charging it to nodes proves a total running time bound. For , level has approximately instances of size , so its nonrecursive work is . Summing those quantities explains the cases of the master theorem.
Running time Created 2026-10-20 Updated 2026-11-05
An algorithm's running time is its computational work on an input, measured either as elapsed time on a specified system or as an operation count under a cost model. Time complexity expresses how that count grows with input size. For binary search in a random-access sorted array, halving the candidate interval needs comparisons. The same index-based code on a linked representation need not have that cost. Worst-case, average-case and amortized bounds quantify different questions; a measured duration alone does not prove any asymptotic guarantee.
Shortest cycle by repeated shortest-path trees Created 2026-10-25 Updated 2026-10-31
In a positive-weight directed graph, run the Dijkstra algorithm from each source and minimize over closing edges. In an undirected graph, minimize only over edges absent from the current shortest-path tree. A tree edge would otherwise give a spurious traversal out and back. A non-tree candidate contains a genuine cycle no longer than its score, even when the two tree routes share a prefix.
For the undirected optimum, choose a shortest cycle and a source on it. If an incident cycle edge is absent from the tree, its candidate is bounded by the cycle length. Otherwise its two neighbours lie in distinct tree branches, and some edge on the remaining cycle segment crosses branches. That edge is non-tree; shortest distances to its endpoints are bounded by the two complementary cycle segments, again giving a candidate no greater than the optimum. Thus the minimum candidate equals the shortest-cycle length. Repeated Dijkstra algorithm runs take running time with a binary heap.
Somenath Biswas 2026-11-05
Somenath Biswas coauthored the 2003 paper on primality testing and polynomial identity testing with Manindra Agrawal. Their randomized algorithm reduces a candidate integer's primality to a univariate polynomial identity over the integers modulo that candidate.[ref]
A polynomial can have very high polynomial degree while being represented by a small arithmetic circuit. Expanding every polynomial coefficient can then be impractical. The paper also gives randomized algorithms for multivariate polynomial identity testing with running time polynomial in the circuit representation size and an error parameter. The input representation and probability of error are consequently essential parts of the algorithmic statement.
Suzanne J. Matthews Created 2026-10-13 Updated 2026-11-05
Suzanne J. Matthews coauthored Dive into Systems by Suzanne J. Matthews and others, which connects computer programs to their machine-level implementation. Its progression through programming languages, instruction set architectures, computer memory and parallel computing explains how the representation and execution of a computer program affect its running time. The authors maintain an open online version with concrete examples.[ref]
Figure 1. . External portrait hosted by Suzanne J. Matthews’s official academic website. Source.
Tia Newhall Created 2026-10-13 Updated 2026-11-05
Tia Newhall coauthored Dive into Systems by Suzanne J. Matthews and others, which connects computer programs to their machine-level implementation. Its progression through programming languages, instruction set architectures, computer memory and parallel computing explains how the representation and execution of a computer program affect its running time. The authors maintain an open online version with concrete examples.[ref]
Figure 1.
Portrait of Tia Newhall
. External portrait hosted by Swarthmore College. Source.
Two-sum problem 2026-10-24
Find two distinct input positions whose values sum to a target, or establish that no such pair exists. Distinct values are not required: two equal values may form a pair when they occur at different positions. On a sorted array, distinct-index two-sum by suffix lower bounds gives running time, while a two-pointer technique can give linear time.
Ulrich Drepper Created 2026-10-13 Updated 2026-11-05
Ulrich Drepper wrote an extended account of computer memory and memory caches, including Memory part 2: CPU caches by Ulrich Drepper. It explains why a computer program's memory-access pattern affects running time, even when the number of arithmetic operations is unchanged. The treatment distinguishes cache organization, lookup and the possibility of overlapping latency with other work.[ref]
Vertex cover decision problem Created 2026-10-25 Updated 2026-10-31
The vertex cover decision problem asks whether a finite simple graph has a vertex cover containing at most vertices. For an uncovered edge , any valid vertex cover contains or . Branch on these two possibilities, delete the chosen vertex and its incident edges, and decrease by one. An edgeless graph accepts and a nonempty graph with rejects. The search tree has at most leaves, giving running time with straightforward copying. Thus this parameterization is fixed-parameter tractable.