Buddy Strings, by LeetCode

Problem is here: https://leetcode.com/problems/buddy-strings/description/

Given two strings A and B of lowercase letters, return true if and only if we can swap two letters in A so that the result equals B.

Example 1:
Input: A = "ab", B = "ba"
Output: true
Example 2:
Input: A = "ab", B = "ab"
Output: false
Example 3:
Input: A = "aa", B = "aa"
Output: true
Example 4:
Input: A = "aaaaaaabc", B = "aaaaaaacb"
Output: true
Example 5:
Input: A = "", B = "aa"
Output: false

Note:
  1. 0 <= A.length <= 20000
  2. 0 <= B.length <= 20000
  3. A and B consist only of lowercase letters.

Problem is deceivingly more obnoxious than it looks. Not hard in terms of "algorithms", but rather the different "special" cases need to be thought thru properly. Here they are:
  • Conditions where you know there won't be a solution:
    • String have different lengths, OR
    • At least one of them is null or empty, OR
    • They are equal with unique characters only, OR
    • They differ by more or less than 2 characters
  • If the above passes, the next step is to check:
    • If they are equal but at least one character is duplicated, then return true (the dupe chars can be swapped)
    • If they differ by two characters, make sure that swapping them makes the strings equal
The code is a little more concise than the explanation above (below).
The interesting thing to notice here is that sometimes in real life problems, they are actually more like this nature where you're dealing mostly with the "special cases", trying to cover all the logical bases, rather than dealing with complex algorithms. Hope you enjoy, cheers, Marcelo


public class Solution
{
 private bool OneDupe(string s)
 {
  Hashtable count = new Hashtable();
  for (int i = 0; i < s.Length; i++)
  {
   char c = s[i];
   if (!count.ContainsKey(c)) count.Add(c, 0);
   count[c] = (int)count[c] + 1;

   if ((int)count[c] > 1) return true;
  }
  return false;
 }
 public bool BuddyStrings(string A, string B)
 {
  if (String.IsNullOrEmpty(A) || String.IsNullOrEmpty(B)) return false;
  if (A.Length != B.Length) return false;

  if (A.Equals(B))
   return OneDupe(A);

  int indexDiff1 = -1;
  int indexDiff2 = -1;
  int countDiff = 0;
  for (int i = 0; i < A.Length; i++)
  {
   if (A[i] != B[i])
   {
    countDiff++;
    if (countDiff == 1)
     indexDiff1 = i;
    else if (countDiff == 2)
     indexDiff2 = i;
    else return false;
   }
  }

  return countDiff == 2 && A[indexDiff1] == B[indexDiff2] && A[indexDiff2] == B[indexDiff1];
 }
}

Comments

  1. Very nice, Marcelo! My solution is extremely similar with an exception that it does not have an extra scan for the equality (though it does not affect asymptotic complexity), uses a vector instead of 2 variables and since it's written in C++ it runs in 4ms :)

    class Solution {
    public:
    bool buddyStrings(const string& A, const string& B) {
    if (A.size() != B.size()) return false;
    vector mismatches;
    bool has_duplicates = false;
    int letters = 0;
    for (int i = 0; i < A.size(); ++i) {
    int idx = 1 << (A[i] - 'a');
    has_duplicates |= letters & idx;
    letters |= idx;
    if (A[i] != B[i]) {
    if (mismatches.size() >= 2) return false;
    mismatches.push_back(i);
    }
    }
    if (mismatches.empty() && has_duplicates) return true;
    if (mismatches.size() < 2 || mismatches.size() > 2) return false;
    return A[mismatches[0]] == B[mismatches[1]] && A[mismatches[1]] == B[mismatches[0]];
    }
    };

    https://gist.github.com/ttsugriy/ef261e21dc6ce2d5df6278aa1731af51

    ReplyDelete

Post a Comment

Popular posts from this blog

Advent of Code - Day 6, 2024: BFS and FSM

Advent of Code - Day 7, 2024: Backtracking and Eval

Golang vs. C#: performance characteristics (simple case study)