学号:16340008
Question:
Strings A
and B
are K
-similar (for some non-negative integer K
) if we can swap the positions of two letters in A
exactly K
times so that the resulting string equals B
.
Given two anagrams A
and B
, return the smallest K
for which A
and B
are K
-similar.
Example 1:
Input: A = "ab", B = "ba"
Output: 1
Example 2:
Input: A = "abc", B = "bca"
Output: 2
Example 3:
Input: A = "abac", B = "baca"
Output: 2
Example 4:
Input: A = "aabc", B = "abca"
Output: 2
Note:
1 <= A.length == B.length <= 20
A
andB
contain only lowercase letters from the set{'a', 'b', 'c', 'd', 'e', 'f'}
Answer:
题意是:给A,B两个字符串,在A中两个字母互相交换,求最少交换多少次后能得到B,即相似度K。首先我们可以知道A,B等长,且A必定能通过有限次字母交换后得到B。因此我们为得到最小交换次数,应保证每次交换能修正至少一个或两个(若能做到)字母。我们可以从A字符串左边开始,对字母(下标为i)作如下判断:
- 若A[i] == B[i],即A与B在该下标处相等,则对下一个字母进行判断。(保证A[0:i] 与 B[0:i]相等)
- 若A[i] != B[i],则在A[i+1:]中找到A[j]与B[i]相同与B[j]不同(否则修正效果为0),记录所有符合条件的下标j。若A[i]又恰好等于B[j],则可直接交换A[i]和A[j],因为这样修正效果为2,必是最优的交换之一。交换后,由于A[0:i+1]与B[0:i+1]这i个数相等,因此我们可调用函数进行递归,对A[i+1:]与B[i+1:]进行对比。调用的函数的返回值+1(此次交换)即为所求。
- 定义times为len(A)-1,该times必然大于等于所求次数(只要保证每次交换能修正一个,两完全不相似的字符串在times次交换后可相等)。遍历记录的每个j,对每个j作如下操作:交换A[i]与A[j],对A[i+1:]与B[i+1:]调用函数本身递归,对其返回值+1与times比较求更小值赋值给times。然后重新交换A[i]与A[j],开始下一个j的操作。结束对每个j的操作后返回times。
- 当字符串A长度为1时返回0
这里用到的搜索思路在于第三步的判断,对每个有修正意义交换的状态向下搜索,因此搜索的节点上必然字符串A与B越来越短,当字符串仅剩长度1时返回0(该字符串无需交换)。每个节点都对其子节点的返回次数中取最小值,再加一反馈给上层节点。顶层节点对所有返回值对比取最小即可。算法看似是BFS,然而实际上并不会在得到最小解时便停止搜索,仍然会搜索完可能节点后再比较取最小。
以下为代码(python3):
class Solution:
def kSimilarity(self, A, B):
"""
:type A: str
:type B: str
:rtype: int
"""
times = 0
for i in range(len(A)-1):
if A[i] == B[i]:
continue
container = []
for j in range(i+1, len(A)):
if A[j] == B[i] and A[j] != B[j]:
container.append(j)
if A[i] == B[j]:
A = A[:i] + A[j] + A[i+1: j] + A[i] + A[j+1:] # swap A[i] and A[j]
return 1 + self.kSimilarity(A[i+1:], B[i+1:])
times = len(A) - 1
for j in container:
A = A[:i] + A[j] + A[i+1: j] + A[i] + A[j+1:] # swap A[i] and A[j]
times = min(times, 1 + self.kSimilarity(A[i+1:], B[i+1:]))
A = A[:i] + A[j] + A[i+1: j] + A[i] + A[j+1:] # swap A[i] and A[j]
return times
return 0
以下代码可用于本地测试:
test = Solution()
A = 'aabc'
B = 'abca'
print(test.kSimilarity(A, B))
以下为LeetCode中测试结果: