Buddy Strings

Updated on 15 May, 2025
Buddy Strings header image

Problem Statement

In this problem, we are provided with two strings s and goal. The task is to determine whether we can make the string s equal to goal by performing a single swap of two letters within s. A swap involves choosing two different indices i and j in string s, and exchanging the characters at these positions. The function should return true if such a swap can transform s into goal, and false otherwise. For example, in the string "abcd", swapping the characters at indices 0 and 2 results in the string "cbad". This problem tests our ability to manipulate strings and understand conditions under which character positions in strings can be swapped to match a target string configuration.

Examples

Example 1

Input:

s = "ab", goal = "ba"

Output:

true

Explanation:

You can swap s[0] = 'a' and s[1] = 'b' to get "ba", which is equal to goal.

Example 2

Input:

s = "ab", goal = "ab"

Output:

false

Explanation:

The only letters you can swap are s[0] = 'a' and s[1] = 'b', which results in "ba" != goal.

Example 3

Input:

s = "aa", goal = "aa"

Output:

true

Explanation:

You can swap s[0] = 'a' and s[1] = 'a' to get "aa", which is equal to goal.

Constraints

  • 1 <= s.length, goal.length <= 2 * 104
  • s and goal consist of lowercase letters.

Approach and Intuition

Based on the provided examples and constraints, the problem can be approached systematically:

  1. Initial Check of String Lengths:
    If the lengths of s and goal differ, a swap within s cannot equate it to goal. Hence, return false immediately.

  2. Checking if s and goal are Already Equal:

    • If s is equal to goal, then we specifically check for the presence of any duplicate characters in s. This is because we can swap these duplicates to give the same string.
    • If there are no duplicate characters, and s is equal to goal, return false, as swapping non-duplicate characters would just mess up the alignment without changing the string.
  3. Identifying Characters to Swap:

    • Traverse through the strings s and goal. Maintain a count of the positions where the characters in s do not match those in goal.
    • If at the end of the traversal, exactly two positions are mismatched, proceed to the next check. Otherwise, return false.
  4. Validating the Possible Swap:

    • Given the two mismatched positions, check if swapping these characters in s leads to a string that matches goal. Specifically, if s[i] matches goal[j] and s[j] matches goal[i] where i and j are the mismatched positions, the swap is valid and return true.
    • If not, return false.

This approach efficiently checks whether two mismatched indices can be swapped to transform s into goal, focusing on alignment and character equality post-swap. The condition checks and string traversals ensure we do not perform any unnecessary operations, adhering closely to the problem's constraints.

Solutions

  • C++
  • Java
  • JavaScript
  • Python
cpp
class Solution {
public:
    bool buddyStrings(string str1, string str2) {
        if (str1.size() != str2.size()) {
            return false;
        }

        if (str1 == str2) {
            vector<int> freq(26, 0);
            for (char c : str1) {
                freq[c - 'a']++;
                if (freq[c - 'a'] > 1) {
                    return true;
                }
            }
            return false;
        }
        
        int first_diff = -1;
        int second_diff = -1;

        for (int idx = 0; idx < str1.size(); ++idx) {
            if (str1[idx] != str2[idx]) {
                if (first_diff == -1) {
                    first_diff = idx;
                } else if (second_diff == -1) {
                    second_diff = idx;
                } else {
                    return false;
                }
            }
        }

        if (second_diff == -1) {
            return false;
        }
        
        return str1[first_diff] == str2[second_diff] && 
               str1[second_diff] == str2[first_diff];
    }
};

This C++ solution checks whether two strings, str1 and str2, can be transformed into one another by swapping just two characters from str1 (referred to as "buddy strings"). The function buddyStrings executes the following steps to determine this:

  • First, it checks if the two strings are of the same length. If not, it returns false immediately.
  • Then it checks if both strings are identical:
    • If they are, the function counts the frequency of each character. If any character appears more than once, it returns true, indicating that a swap within the string can occur without changing its appearance (since there are duplicate characters).
  • If the strings are not identical, the function then looks for positions where the characters differ.
    • It uses two markers, first_diff and second_diff to store the indices of the first two discrepancies between the two strings.
    • If more than two discrepancies are found, it returns false, as more than one swap would be needed.
    • If exactly two discrepancies are found, it checks if swapping the characters at these positions in str1 would make the strings identical. It performs this check by ensuring that the character at first_diff of str1 matches the character at second_diff of str2 and vice versa.

The final output is true if the strings can be made identical by a single swap of two characters; otherwise, it returns false.

java
class BuddyChecker {
    public boolean areBuddies(String a, String b) {
        if (a.length() != b.length()) {
            return false;
        }

        if (a.equals(b)) {
            int[] freq = new int[26];
            for (char c : a.toCharArray()) {
                freq[c - 'a']++;
                if (freq[c - 'a'] == 2) {
                    return true;
                }
            }
            return false;
        }

        int firstMismatch = -1;
        int secondMismatch = -1;

        for (int i = 0; i < a.length(); i++) {
            if (a.charAt(i) != b.charAt(i)) {
                if (firstMismatch == -1) {
                    firstMismatch = i;
                } else if (secondMismatch == -1) {
                    secondMismatch = i;
                } else {
                    return false;
                }
            }
        }

        if (secondMismatch == -1) {
            return false;
        }

        return a.charAt(firstMismatch) == b.charAt(secondMismatch) && 
               a.charAt(secondMismatch) == b.charAt(firstMismatch);
    }
}

The Java implementation provided defines a method to determine if two strings, denoted as a and b, can be considered "buddy strings". Buddy strings are defined as strings that can be made equal through a single swap of two characters in one of the strings. Here's how the solution is structured:

  • Initially, the method areBuddies checks if both strings are of the same length. If not, it returns false.

  • If a and b are identical, it then checks for any character that appears at least twice within the string a. This is because, with at least one duplicate character, a valid swap can occur within a itself to make it equal to b after some hypothetical change in b due to the identical nature of the two strings.

  • If a and b differ, the approach identifies the positions of the first two mismatched characters. If there are more than two mismatched characters, the function returns false, as more than one swap would be necessary.

  • If exactly two mismatches are detected, it then checks whether swapping the characters at these mismatched positions in a makes the two strings identical.

This procedure effectively assesses if the two input strings can be transformed into one another via a single swap of two characters, returning true if possible and false otherwise. The solution leverages direct comparison, character frequency counting, and index tracking to accomplish the task.

js
var swappedStrings = function(str1, str2) {
    if (str1.length !== str2.length) {
        return false;
    }

    if (str1 === str2) {
        const charCount = new Array(26).fill(0);
        for (const character of str1) {
            const index = character.charCodeAt() - 97;
            charCount[index]++;
            if (charCount[index] === 2) {
                return true;
            }
        }
        return false;
    }

    let idx1 = -1;
    let idx2 = -1;

    for (let idx = 0; idx < str1.length; ++idx) {
        if (str1[idx] !== str2[idx]) {
            if (idx1 === -1) {
                idx1 = idx;
            } else if (idx2 === -1) {
                idx2 = idx;
            } else {
                return false;
            }
        }
    }

    if (idx2 === -1) {
        return false;
    }

    return (str1[idx1] === str2[idx2] && 
            str1[idx2] === str2[idx1]);    
};

The function swappedStrings in JavaScript determines if two strings, str1 and str2, are "buddy strings." Buddy strings are strings that can be made identical by swapping exactly two characters in one of the strings. Here's a concise breakdown of how the function operates:

  • First, it checks if the two strings are of equal length. If not, it immediately returns false since swapping wouldn't make them identical due to the length difference.

  • If the strings are already identical, the function then checks if there are at least two identical characters in the string. This is because even without swapping, the strings can be considered buddy strings if they have at least one character that could hypothetically be "swapped" with itself. It returns true if there are, otherwise false.

  • If the strings are not identical, the function identifies the indices where the characters differ and stores these in idx1 and idx2.

  • The function allows at most two differing indices. If there are more than two, it returns false as more than one swap would be needed.

  • Finally, it checks whether swapping the characters at the stored indices (idx1 and idx2) in str1 would make the string equal to str2. If true, the function returns true, otherwise false.

This solution is efficient in identifying whether two strings can be classified as buddy strings under the specified conditions, using linear time complexity relative to the length of the strings due to the single pass required to identify differing indices and constant space for storing indices and character counts.

python
class Solution:
    def similarStrings(self, str1: str, str2: str) -> bool:
        if len(str1) != len(str2):
            return False

        if str1 == str2:
            count = [0] * 26
            for char in str1:
                count[ord(char) - ord('a')] += 1
                if count[ord(char) - ord('a')] == 2:
                    return True
            return False

        idx1 = -1
        idx2 = -1

        for i in range(len(str1)):
            if str1[i] != str2[i]:
                if idx1 == -1:
                    idx1 = i
                elif idx2 == -1:
                    idx2 = i
                else:
                    return False

        if idx2 == -1:
            return False

        return str1[idx1] == str2[idx2] and str1[idx2] == str2[idx1]

The submitted Python solution defines a method similarStrings that determines if two strings can be made equivalent by swapping two characters in one of the strings just once. Here is a breakdown of how this solution works:

  • First, the function checks if the input strings, str1 and str2, are of the same length. If they are not, the function immediately returns False because differing lengths mean they cannot be made equal with a single swap.

  • If the strings are of the same length and are identical (str1 == str2), the function next checks if there is any character that appears at least twice in str1. This would allow for a swap within str1 without altering its appearance, thus they might still be considered "buddy strings." If such a character exists, it returns True, otherwise False.

  • If str1 and str2 are different, the function identifies the indices of the first two differing characters. If there are more than two characters that differ, it returns False since more than one swap would be needed, which is not allowed.

  • If there are exactly two differing positions, the function then checks if swapping the characters at these two indices in str1 would make str1 equal to str2. If it does, the function returns True. Otherwise, it returns False.

This solution efficiently addresses the problem by quickly dismissing cases that cannot be solved by one swap and meticulously checking the conditions under which a single swap would suffice. It uses a linear scan to compare characters and an additional simple check for character counts, both operations being quite efficient for relatively small strings typical of such challenges.

Comments

No comments yet.