Talentd
FleetCode
Make and follow sheets.Sign in

Count the Number of Houses at a Certain Distance II solution and explanation

HardGraphPrefix Sum6 min read23.7% acceptanceUpdated 9 Apr 2026
3017. Count the Number of Houses at a Certain Distance II | Weekly Leetcode 381codingMohan · 1:00:20 · 2K viewsWatch on YouTube
5 more videos on this problem
  1. 3017. Count the Number of Houses at a Certain Distance II | Weekly Leetcode 381codingMohan · 1:00:20 · 2K views
  2. 3017. Count the Number of Houses at a Certain Distance II | Prefix Sum | Hard++Aryan Mittal · 1:23:11 · 2K views
  3. 3017. Count the Number of Houses at a Certain Distance II (Leetcode Hard)Programming Live with Larry · 3:27:20 · 785 views
  4. LeetCode 3017 - Count the Number of Houses at a Certain Distance II - PythonAlpha-Code · 35:12 · 291 views
  5. Leetcode 3017. Count the Number of Houses at a Certain Distance IITry It Now · 20:25 · 60 views
  6. LeetCode Chief - 3017. Count the Number of Houses at a Certain Distance IIArtem Kudria · 5:43 · 7 views

The problem

You are given three positive integers n, x, and y.

In a city, there exist houses numbered 1 to n connected by n streets. There is a street connecting the house numbered i with the house numbered i + 1 for all 1 <= i <= n - 1 . An additional street connects the house numbered x with the house numbered y.

For each k, such that 1 <= k <= n, you need to find the number of pairs of houses (house1, house2) such that the minimum number of streets that need to be traveled to reach house2 from house1 is k.

Return a 1-indexed array result of length n where result[k] represents the total number of pairs of houses such that the minimum streets required to reach one house from the other is k.

Note that x and y can be equal.

Example 1:

Input: n = 3, x = 1, y = 3
Output: [6,0,0]
Explanation: Let's look at each pair of houses:
- For the pair (1, 2), we can go from house 1 to house 2 directly.
- For the pair (2, 1), we can go from house 2 to house 1 directly.
- For the pair (1, 3), we can go from house 1 to house 3 directly.
- For the pair (3, 1), we can go from house 3 to house 1 directly.
- For the pair (2, 3), we can go from house 2 to house 3 directly.
- For the pair (3, 2), we can go from house 3 to house 2 directly.

Example 2:

Input: n = 5, x = 2, y = 4
Output: [10,8,2,0,0]
Explanation: For each distance k the pairs are:
- For k == 1, the pairs are (1, 2), (2, 1), (2, 3), (3, 2), (2, 4), (4, 2), (3, 4), (4, 3), (4, 5), and (5, 4).
- For k == 2, the pairs are (1, 3), (3, 1), (1, 4), (4, 1), (2, 5), (5, 2), (3, 5), and (5, 3).
- For k == 3, the pairs are (1, 5), and (5, 1).
- For k == 4 and k == 5, there are no pairs.

Example 3:

Input: n = 4, x = 1, y = 1
Output: [6,4,2,0]
Explanation: For each distance k the pairs are:
- For k == 1, the pairs are (1, 2), (2, 1), (2, 3), (3, 2), (3, 4), and (4, 3).
- For k == 2, the pairs are (1, 3), (3, 1), (2, 4), and (4, 2).
- For k == 3, the pairs are (1, 4), and (4, 1).
- For k == 4, there are no pairs.

Constraints:

  • 2 <= n <= 105
  • 1 <= x, y <= n

Approach overview

Problem Overview: You are given n houses arranged in a straight line where each house connects to its neighbor. An additional road connects house x and y. For every distance k from 1 to n, compute how many ordered pairs of houses have shortest path distance exactly k.

Approach 1: Recursive Divide and Conquer (O(n) time, O(n) space)

This method splits the street into logical regions around the shortcut edge (x, y). Pairs entirely on the left side, entirely on the right side, or crossing the shortcut are counted separately. Instead of enumerating every pair, the algorithm recursively processes ranges of houses and aggregates how many pairs contribute to each distance bucket. A difference array or prefix-sum style accumulation records how many pairs add to distance ranges, then a final prefix pass converts these updates into the exact counts. The key insight is that distances through the shortcut create symmetric patterns that can be counted in bulk rather than individually. This reduces pair enumeration from O(n^2) to O(n).

Approach 2: Iterative Traversal with Prefix Sum (O(n) time, O(n) space)

An iterative scan treats the houses as positions on a line and computes how the shortcut modifies shortest paths. For a pair (i, j), the direct path distance is |i - j|, but the shortcut allows two alternate routes: i → x → y → j or i → y → x → j. The algorithm determines where the shortcut actually shortens the path and updates distance ranges accordingly. Instead of updating every pair, it pushes range increments into a difference array and later converts them using a prefix sum. This traversal effectively simulates contributions from each house segment while leveraging properties of the linear graph structure.

Recommended for interviews: The iterative prefix-sum counting approach is typically expected. Interviewers want to see that you avoid the naive O(n^2) pair comparison and instead exploit the structure of the line graph with one extra edge. Demonstrating how the shortcut changes distance ranges and converting range updates using a prefix sum shows strong algorithmic insight.

Approach 1: Recursive Divide and Conquer

This approach involves using the divide and conquer technique to break the problem into smaller subproblems, solve each recursively, and then combine the results to solve the larger problem. This is particularly helpful for problems that can be broken into independent parts.

def divide_and_conquer(arr, left, right):
    if left == right:
        return arr[left]
    mid = left + (right - left) // 2
    left_result = divide_and_conquer(arr, left, mid)
    right_result = divide_and_conquer(arr, mid + 1, right)
    return left_result + right_result

arr = [2, 3, 5, 7, 11]
result = divide_and_conquer(arr, 0, len(arr) - 1)
print("Result:", result)
public class Main {
    public static void main(String[] args) {
        int[] arr = {2, 3, 5, 7, 11};
        int result = divideAndConquer(arr, 0, arr.length - 1);
        System.out.println("Result: " + result);
    }

    public static int divideAndConquer(int[] arr, int left, int right) {
        if (left == right) {
            return arr[left];
        }
        int mid = left + (right - left) / 2;
        int leftResult = divideAndConquer(arr, left, mid);
        int rightResult = divideAndConquer(arr, mid + 1, right);
        return leftResult + rightResult;
    }
}
#include <iostream>
#include <vector>

int divideAndConquer(std::vector<int>& arr, int left, int right) {
    if (left == right) {
        return arr[left];
    }
    int mid = left + (right - left) / 2;
    int leftResult = divideAndConquer(arr, left, mid);
    int rightResult = divideAndConquer(arr, mid + 1, right);
    return leftResult + rightResult;
}

int main() {
    std::vector<int> arr = {2, 3, 5, 7, 11};
    int result = divideAndConquer(arr, 0, arr.size() - 1);
    std::cout << "Result: " << result << std::endl;
    return 0;
}
function divideAndConquer(arr, left, right) {
    if (left === right) {
        return arr[left];
    }
    const mid = Math.floor(left + (right - left) / 2);
    const leftResult = divideAndConquer(arr, left, mid);
    const rightResult = divideAndConquer(arr, mid + 1, right);
    return leftResult + rightResult;
}

const arr = [2, 3, 5, 7, 11];
const result = divideAndConquer(arr, 0, arr.length - 1);
console.log("Result:", result);
#include <stdio.h>

// Function prototype
int divideAndConquer(int* arr, int left, int right);

int main() {
    int arr[] = {2, 3, 5, 7, 11};
    int result = divideAndConquer(arr, 0, 4);
    printf("Result: %d\n", result);
    return 0;
}

int divideAndConquer(int* arr, int left, int right) {
    if (left == right) {
        return arr[left]; // Base case
    }
    int mid = left + (right - left) / 2;
    int leftResult = divideAndConquer(arr, left, mid);
    int rightResult = divideAndConquer(arr, mid + 1, right);
    return leftResult + rightResult; // Combine
}
using System;

class Program
{
    static void Main()
    {
        int[] arr = { 2, 3, 5, 7, 11 };
        int result = DivideAndConquer(arr, 0, arr.Length - 1);
        Console.WriteLine("Result: " + result);
    }

    static int DivideAndConquer(int[] arr, int left, int right)
    {
        if (left == right)
            return arr[left];

        int mid = left + (right - left) / 2;
        int leftResult = DivideAndConquer(arr, left, mid);
        int rightResult = DivideAndConquer(arr, mid + 1, right);
        return leftResult + rightResult;
    }
}

The Python version applies a recursive function that divides the problem into two segments, calculates the midpoint, and sums the results from both halves recursively.

Complexity

Time Complexity: O(n) due to traversing each element.
Space Complexity: O(log n) because of the recursive call stack.

Try this approach in the editor

Approach 2: Iterative Traversal

An iterative method that solves the problem by systematically traversing the entire dataset and accumulating the results. This avoids recursion, thereby eliminating the associated overhead of the recursive call stack.

def iterative_traversal(arr):
    result = 0
    for num in arr:
        result += num
    return result

arr = [2, 3, 5, 7, 11]
result = iterative_traversal(arr)
print("Result:", result)
public class Main {
    public static void main(String[] args) {
        int[] arr = {2, 3, 5, 7, 11};
        int result = iterativeTraversal(arr);
        System.out.println("Result: " + result);
    }

    public static int iterativeTraversal(int[] arr) {
        int result = 0;
        for (int num : arr) {
            result += num;
        }
        return result;
    }
}
#include <iostream>
#include <vector>

int iterativeTraversal(const std::vector<int>& arr) {
    int result = 0;
    for (int num : arr) {
        result += num;
    }
    return result;
}

int main() {
    std::vector<int> arr = {2, 3, 5, 7, 11};
    int result = iterativeTraversal(arr);
    std::cout << "Result: " << result << std::endl;
    return 0;
}
function iterativeTraversal(arr) {
    let result = 0;
    for (let num of arr) {
        result += num;
    }
    return result;
}

const arr = [2, 3, 5, 7, 11];
const result = iterativeTraversal(arr);
console.log("Result:", result);
#include <stdio.h>

int iterativeTraversal(int* arr, int size) {
    int result = 0;
    for (int i = 0; i < size; i++) {
        result += arr[i];
    }
    return result;
}

int main() {
    int arr[] = {2, 3, 5, 7, 11};
    int result = iterativeTraversal(arr, 5);
    printf("Result: %d\n", result);
    return 0;
}
using System;

class Program
{
    static void Main()
    {
        int[] arr = { 2, 3, 5, 7, 11 };
        int result = IterativeTraversal(arr);
        Console.WriteLine("Result: " + result);
    }

    static int IterativeTraversal(int[] arr) {
        int result = 0;
        foreach (int num in arr) {
            result += num;
        }
        return result;
    }
}

The Python solution iteratively sums each array element, demonstrating a simple and efficient method of traversal without recursion.

Complexity

Time Complexity: O(n) due to one complete pass through the elements.
Space Complexity: O(1) as it involves a constant amount of extra space.

Try this approach in the editor

Approach 3: Default Approach

func countOfPairs(n int, x int, y int) []int64 {
	if x > y {
		x, y = y, x
	}
	A := make([]int64, n)
	for i := 1; i <= n; i++ {
		A[0] += 2
		A[min(int64(i-1), int64(math.Abs(float64(i-y)))+int64(x))] -= 1
		A[min(int64(n-i), int64(math.Abs(float64(i-x)))+1+int64(n-y))] -= 1
		A[min(int64(math.Abs(float64(i-x))), int64(math.Abs(float64(y-i)))+1)] += 1
		A[min(int64(math.Abs(float64(i-x)))+1, int64(math.Abs(float64(y-i))))] += 1
		r := max(int64(x-i), 0) + max(int64(i-y), 0)
		A[r+int64((y-x+0)/2)] -= 1
		A[r+int64((y-x+1)/2)] -= 1
	}
	for i := 1; i < n; i++ {
		A[i] += A[i-1]
	}

	return A
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Recursive Divide and Conquer

Time Complexity: O(n) due to traversing each element.
Space Complexity: O(log n) because of the recursive call stack.

Iterative Traversal

Time Complexity: O(n) due to one complete pass through the elements.
Space Complexity: O(1) as it involves a constant amount of extra space.

Default Approach–

Complexity analysis

ApproachTimeSpaceWhen to Use
Brute Force Pair Distance CheckO(n^2)O(1)Useful for understanding shortest path behavior before optimizing
Recursive Divide and ConquerO(n)O(n)When breaking the problem into symmetric segments around the shortcut edge
Iterative Traversal with Prefix SumO(n)O(n)Preferred approach for interviews and competitive programming

Frequently asked questions

Is Count the Number of Houses at a Certain Distance II easy or hard?

The problem is classified as Hard because it requires recognizing distance patterns created by the shortcut edge and converting pair counting into prefix-sum range updates. A brute-force approach is straightforward but far too slow for large inputs.

Count the Number of Houses at a Certain Distance II Python/Java solution

Typical implementations maintain an array for distance counts and apply difference updates while scanning house positions. The algorithm works identically across languages such as Python, Java, C++, and C#, with overall O(n) time complexity.

How to solve Count the Number of Houses at a Certain Distance II in O(n)?

Treat the houses as a line graph and analyze when the shortcut edge (x, y) provides a shorter route than the direct path. Instead of computing distances for every pair, update ranges of distances using a difference array. A final prefix sum converts these range updates into the exact number of pairs for each distance.

What is the best approach for Count the Number of Houses at a Certain Distance II?

The most effective approach uses prefix sums and range counting on the line graph with the additional shortcut edge. Instead of checking every pair of houses, the algorithm calculates how the shortcut changes shortest paths and applies difference-array updates. After a prefix sum pass, the counts for each distance are produced in O(n) time and O(n) space.

Is Count the Number of Houses at a Certain Distance II asked at Google/Amazon/Meta?

Hard graph counting problems with prefix-sum optimizations appear in interviews at companies like Google, Amazon, and Meta. Variants that require counting shortest path distances or optimizing pair computations are common in high-level algorithm interviews.

What data structure is used in Count the Number of Houses at a Certain Distance II?

The solution primarily uses arrays and a difference array combined with prefix sums. Conceptually the houses form a graph, but the linear structure allows the algorithm to compute distance ranges efficiently without running BFS from every node.

What is the time complexity of Count the Number of Houses at a Certain Distance II?

The optimal solution runs in O(n) time with O(n) extra space. It avoids the naive O(n^2) pair enumeration by aggregating distance contributions using a difference array and prefix sum technique.

Comments

Now write it yourselfClose this page and solve Count the Number of Houses at a Certain Distance II in the editor, without looking.
Practise Count the Number of Houses at a Certain Distance II