这是悦乐书的第330次更新,第354篇原创

01 看题和准备

今天介绍的是LeetCode算法题中Easy级别的第200题(顺位题号是859)。给定两个字母A和B的小写字母,当且仅当我们可以在A中交换两个字母以使结果等于B时返回true。例如:

输入:A =“ab”,B =“ba”

输出:true



输入:A =“ab”,B =“ab”

输出:false



输入:A =“aa”,B =“aa”

输出:true



输入:A =“aaaaaaabc”,B =“aaaaaaacb”

输出:true



输入:A =“”,B =“aa”

输出:false

注意

  • 0 <= A.length <= 20000

  • 0 <= B.length <= 20000

  • A和B仅由小写字母组成。

本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试。

02 错误的尝试

一次错误的提交,原因是理解题目出现偏差,我以为是相邻的两个字符进行替换,但是不然,是任意两个字符进行替换能够和B相等,就可以返回true。例如:A="abab",B="abab",下面的方法计算的结果是false,但其实应该是true,因为只要将A中的第一个a换到第三个位置,将第三个位置的a换到第一个位置,就能保证A和B相等,交换b也是一样的。再例如A="aaabac",B="aaacab",也是一样的情况。

public boolean buddyStrings(String A, String B) {
if (A.length() != B.length()) {
return false;
}
boolean result = false;
char[] arr = A.toCharArray();
int n = arr.length;
for (int i=0; i<n-1; i++) {
char temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
if (B.equals(String.valueOf(arr))) {
return true;
} else {
char temp2 = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp2;
}
}
return result;
}

03 第一种解法

我们再来好好分析下题目,既然不是交换相邻的两个字母,那么就需要分三种情况来具体分析:

  1. A和B的长度不相等。两者的长度不相等,无论A怎么换字母,都不可能变成B,直接返回false。

  2. A和B的长度相等,并且A和B相等。要想满足A换两字母后能够等于B,A就必须至少要有一个字母出现两次以上,因为只有交换重复出现的字母,A才不会变,也就可以和B相等了。例如,A="aa",B="aa",或者A="afag",B="afag",这两组都是满足条件。再例如,A="abc",B="abc",虽然A等于B,但是A无论交换哪两个字母,交换后的新A都不会等于B。

  3. A和B的长度相等,但是A和B不相等。同样,要想A交换两个字母后等于B,前提条件就是在对应索引位置上A不等于B的字母的个数,只能是2个,多于2个或少于2个都不行。同时还要满足:A中第一个不等于B的字母要等于B中不等于A的第二个字母,A中第二个不等于B的字母要等于B中不等于A的第一个字母。换成伪代码就是A[i] == B[j] and A[j] == B[i],i和j是A和B两个不同字母的索引。

在处理第二种情况时,使用了HashSet,将A变成字符数组存入其中,只要HashSet的size小于A的长度,就说明A中包含重复出现的字母,符合条件。

在处理第三种情况时,使用了两个List,分别存储了A中、B中对应索引位置不相等的字母,最后判断存储A中字母List的长度、两个List中的元素是否交叉相等这两个条件。

此解法的时间复杂度是O(N),空间复杂度是O(N)。

public boolean buddyStrings2(String A, String B) {
if (A.length() != B.length()) {
return false;
}
if (A.equals(B)) {
Set<Character> set = new HashSet<Character>();
for (char ch : A.toCharArray()) {
set.add(ch);
}
return set.size() < A.length();
} else {
List<Character> list = new ArrayList<Character>();
List<Character> list2 = new ArrayList<Character>();
int n = A.length();
for (int i=0; i<n; i++) {
char c = A.charAt(i);
char c2 = B.charAt(i);
if (c != c2) {
list.add(c);
list2.add(c2);
}
}
return list.size() == 2 &&
list.get(0) == list2.get(1) &&
list.get(1) == list2.get(0);
}
}

04 第二种解法

对于上面的解法,还可以再优化下,在处理第三种情况的时候,只是用一个List,改为存储A和B对应位置不相等字母的索引,最后判断List的长度是否等于2,以及A和B在List中的索引位置上对应的字母是否交叉相等。

此解法的时间复杂度是O(N),空间复杂度是O(N)。

public boolean buddyStrings3(String A, String B) {
if (A.length() != B.length()) {
return false;
}
if (A.equals(B)) {
Set<Character> set = new HashSet<Character>();
for (char ch : A.toCharArray()) {
set.add(ch);
}
return set.size() < A.length();
} else {
List<Integer> diffIndex = new ArrayList<Integer>();
int n = A.length();
for (int i=0; i<n; i++) {
if (A.charAt(i) != B.charAt(i)) {
diffIndex.add(i);
}
}
return diffIndex.size() == 2 &&
A.charAt(diffIndex.get(0)) == B.charAt(diffIndex.get(1)) &&
A.charAt(diffIndex.get(1)) == B.charAt(diffIndex.get(0));
}
}

05 第三种解法

对于前一种解法,我们还可以再优化下。

在第二种情况中,使用一个长度为26的整数数组,来判断A中是否有重复出现的字母。

在第三种情况中,使用两个临时变量存储A和B中对应位置字母不相等的索引值,如果字母不相等的个数多于2个就直接返回false,最后判断两个索引位置上对应的字母是否交叉相等。

此解法的时间复杂度是O(N),空间复杂度是O(1)。

public boolean buddyStrings4(String A, String B) {
if (A.length() != B.length()) {
return false;
}
if (A.equals(B)) {
int[] arr = new int[26];
for (char ch : A.toCharArray()) {
if (++arr[ch-'a'] >= 2) {
return true;
}
}
return false;
} else {
int index = -1;
int index2 = -1;
int n = A.length();
for (int i=0; i<n; i++) {
if (A.charAt(i) != B.charAt(i)) {
if (index == -1) {
index = i;
} else if (index2 == -1) {
index2 = i;
} else {
return false;
}
}
}
return A.charAt(index) == B.charAt(index2) &&
A.charAt(index2) == B.charAt(index);
}
}

06 小结

算法专题目前已连续日更超过五个月,算法题文章200+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。

以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!

LeetCode.859-伙伴字符串(Buddy Strings)的更多相关文章

  1. LeetCode 859. 亲密字符串(Buddy Strings) 23

    859. 亲密字符串 859. Buddy Strings 题目描述 给定两个由小写字母构成的字符串 A 和 B,只要我们可以通过交换 A 中的两个字母得到与 B 相等的结果,就返回 true:否则返 ...

  2. [Swift]LeetCode859. 亲密字符串 | Buddy Strings

    Given two strings A and B of lowercase letters, return true if and only if we can swap two letters i ...

  3. LeetCode 205. 同构字符串(Isomorphic Strings)

    205. 同构字符串 205. Isomorphic Strings

  4. 859. Buddy Strings - LeetCode

    Question 859. Buddy Strings Solution 题目大意: 两个字符串,其中一个字符串任意两个字符互换后与另一个字符串相等,只能互换一次 思路: diff 记录不同字符数 两 ...

  5. 【Leetcode_easy】859. Buddy Strings

    problem 859. Buddy Strings solution: class Solution { public: bool buddyStrings(string A, string B) ...

  6. C#LeetCode刷题-字符串

    字符串篇 # 题名 刷题 通过率 难度 3 无重复字符的最长子串   24.6% 中等 5 最长回文子串   22.4% 中等 6 Z字形变换   35.8% 中等 8 字符串转整数 (atoi)   ...

  7. C# 6.0 内插字符串 (Interpolated Strings )

    讲Interpolated Strings之前,让我们先看EF Core 2.0 的一个新的特性:String interpolation in FromSql and ExecuteSqlComma ...

  8. C#版(击败100.00%的提交) - Leetcode 151. 翻转字符串里的单词 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  9. C#版(击败97.76%的提交) - Leetcode 557. 反转字符串中的单词 III - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. Leetcod ...

  10. LeetCode:反转字符串中的元音字母【345】

    LeetCode:反转字符串中的元音字母[345] 题目描述 编写一个函数,以字符串作为输入,反转该字符串中的元音字母. 示例 1: 输入: "hello" 输出: "h ...

随机推荐

  1. 牛客练习赛47 A DongDong破密码 (异或性质,递推)

    链接:https://ac.nowcoder.com/acm/contest/904/A 来源:牛客网 DongDong破密码 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 1310 ...

  2. D Merge Equals Educational Codeforces Round 42 (Rated for Div. 2) (STL )

    D. Merge Equals time limit per test2 seconds memory limit per test256 megabytes inputstandard input ...

  3. 机器学习四 SVM

    目录 引言 SVM 线性可分SVM 线性不可分SVM Hinge Loss 非线性SVM 核函数 总结 参考文献 引言 在深度神经网终(Deep Neural Network, DNN) 大热之前, ...

  4. 批量修改zencart产品价格、原价、特价、产品属性价格

    批量修改zencart商品价格无非只有下面几种情况: 一 在原来基础上批量调高一定比例 二 将原来的价格批量换成一个新的价格 针对第一种情况的话,网上很多人已经给出了解决办法: 利用SQL语句批量修改 ...

  5. ng-model 和ng-bind的区别

    也就是说 ng-model是绑定html输入的值-->到控制器的变量,输入值变了,控制器对应的变量message的值页变了,这样,在其他地方就可以使用这个变化后的值 ng-bind 是绑定控制器 ...

  6. java 集合之ArrayList、Vector、LinkedList、CopyOnWriteArrayList

    ArrayList 线程不安全. 底层Object[]数组实现,用transient关键字修饰,防止序列化,然后重写了readObject和writeObject方法,为了提高传输效率. 插入时会判断 ...

  7. 【leetcode】1224. Maximum Equal Frequency

    题目如下: Given an array nums of positive integers, return the longest possible length of an array prefi ...

  8. Haproxy-4层和7层代理负载实战

    目录 HAProxy是什么 HAProxy的核心能力和关键特性 HAProxy的核心功能 HAProxy的关键特性 HAProxy的安装和运行 安装 运行 添加日志 使用HAProxy搭建L7负载均衡 ...

  9. shiro框架学习-9-shiroSession

    1.什么是会话session : 用户和程序直接的链接,程序可以根据session识别到哪个用户,和javaweb中的session类似 2. 什么是会话管理器SessionManager : 会话管 ...

  10. 多线程——Java中继承Thread类与实现Runnable接口的区别

    线程我只写过继承Thread类的,后来知道java多线程有三种方式,今天首先比较一下常用的继承Thread类和实现Runnable接口的区别. 按着Ctrl键进入Thread之后,发现Thread类也 ...