859. Buddy Strings

859. Buddy Strings

原题:两个小写字母组成的字符串当且仅当串 A 交换两个字符与串 B 相等的时候返回 true 否则返回 false

第一次解法

根据题意直白来解,如果仅仅是交换字符能相等的话那么两个字符的哈希签名必须相等,还有一个 corner case 是两个串相等的时候 A 中必须要有重复的字母才能成立

时间复杂度:O(n) 空间复杂度:O(1)

bool buddyStrings(string a, string b) {
	// 长度必须相等且不为空
    if (a.size()!=b.size() || a.empty() || b.empty()) return false;

    bool repeat = false;
    int sign[26] = {0};
	// 构造 A 串的签名
    for(auto s : a)
        ++sign[s-'a'];
    for(auto s : b) {
		// 检查A串是否有重复
        if (sign[s-'a'] > 1) repeat = true;
        --sign[s-'a'];        
    }

	// 检查 A 与 B 的字符签名是否一致
    for(auto n : sign)
        if (n!=0) return false;

	// 签名一致则从头开始逐一比对
    int i,j;
    for(i=0;i<a.size() && a[i]==b[i];++i) {}
    if (i==a.size()) return repeat; // 串相等,取决于A是否有重复字符

	// 串不等,进行一次交换
    for(j=i+1;a[j]!=b[i];++j) {}
    swap(a[j], a[i]);

	// 交换后继续逐一比对得结果
    for(;i<a.size() && a[i]==b[i];++i) {}

    return i==a.size();
}

更简洁的方式判断重复与 diff

通过使用 stl 中的 unordered_set 容器来去重,根据容器的 size() 和B串的长度来判断是否重复

bool buddyStrings(string A, string B) {
    // Same length
    int len_A = A.size(), len_B = B.size();
    if (len_A != len_B) return false;
        
    // Repeat: same string, A needs repeated char, like "aab" "aab"
    int numChar_A = unordered_set<char>(A.begin(), A.end()).size();
	// 快速解决掉重复的情况
    if (A == B && numChar_A < len_B) return true;

    vector<int> index_diff;
                    
    for (int i = 0; i < len_A; i++) {
		// diff 仅记录不一样的下标,个数不能超过2个
      	if (A[i] != B[i]) index_diff.push_back(i);
      	if (index_diff.size() > 2) return false;
    }
    // 不一样的下标个数为2且对应字母交叉相等则符合要求
    return index_diff.size() == 2 &&
           A[index_diff[0]] == B[index_diff[1]] &&
           A[index_diff[1]] == B[index_diff[0]];
}

收获

  • unordered_set 快速去重
  • diff 遍历一遍记录不同的下标

#桶 #字符串 #HashSet