↓Skip to main content
  1. LeetCode/

LeetCode 3805: Count Caesar Cipher Pairs

·2 mins· ·
LeetCode Medium Math Hash-Table String Counting
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: medium First Attempt: 2026-01-11

  • Submissions: Accepted (first try)

Approach
#

Two strings become equal by shifting ⇔ every position differs from the first letter by the same amount (mod 26).

So normalize each string: shift it so the first letter is a, i.e. record each letter as (c - word[0]) mod 26. Equivalent strings get the same form; count each form with a hash map, and pairs are c × (c - 1) / 2.

My Solution
#

class Solution:
    def countPairs(self, words: List[str]) -> int:
        cnt = Counter()
        pairs = 0
        for w in words:
            key = tuple((ord(c) - ord(w[0])) % 26 for c in w)   # shift so the first letter is a
            pairs += cnt[key]                      # pair with every earlier equivalent
            cnt[key] += 1
        return pairs

My original built the shifted string with chr and branches for wrapping around, then computed v * (v - 1) / 2 (float division converted back to int). A tuple of % 26 values as the key is cleaner and avoids floats.

Complexity
#

Time O(n · m), space O(n · m).

Mistakes to Avoid
#

  • Shifts wrap around: after z comes a, so use % 26.
  • Count pairs with integer arithmetic.

Interview Explanation
#

Two strings are Caesar-equivalent when every letter’s difference from the first letter, mod 26, matches. I normalize each string to that difference sequence as a key and, while scanning, add how many earlier strings had the same key. Time O(n · m).

Related

LeetCode 2131: Longest Palindrome by Concatenating Two Letter Words
·2 mins
LeetCode Medium Greedy Hash-Table String Counting
LeetCode 2131 note: pair each word with its reverse on both sides; self-palindromes also pair with each other, and only one leftover can sit in the middle
LeetCode 3518: Smallest Palindromic Rearrangement II
·3 mins
LeetCode Hard Math Combinatorics Counting Hash-Table String
LeetCode 3518 note: a palindrome is determined by its left half, so this is the k-th permutation of a multiset; try characters position by position and use permutation counts, updated in O(1), to find k’s branch
LeetCode 1814: Count Nice Pairs in an Array
·1 min
LeetCode Medium Array Hash-Table Math Counting
LeetCode 1814 note: rearrange the condition into nums[i] - rev(nums[i]) == nums[j] - rev(nums[j]), count pairs per value, and remember the modulus
LeetCode 2516: Take K of Each Character From Left and Right
·2 mins
LeetCode Medium Sliding-Window Hash-Table String
LeetCode 2516 note: taking from both ends leaves a middle block in which each letter may appear at most total − k times; find the longest such window
LeetCode 1461: Check If a String Contains All Binary Codes of Size K
·2 mins
LeetCode Medium Hash-Table String Bit-Manipulation Rolling-Hash
LeetCode 1461 note: put every length-k substring in a set and check that its size reaches 2^k; the last start is len(s) - k
LeetCode 1016: Binary String With Substrings Representing 1 To N
·3 mins
LeetCode Medium Sliding-Window String Bit-Manipulation Hash-Table
LeetCode 1016 note: s has at most 1000 characters, so there are few substrings of any fixed length and a large n must be False; checking from n downward fails fast, or extend up to 30 bits from each start to collect every value <= n