859. 亲密字符串
给定两个由小写字母构成的字符串 A
和 B
,只要我们可以通过交换 A
中的两个字母得到与 B
相等的结果,就返回 true
;否则返回 false
。
示例 1:
输入: A = "ab", B = "ba"
输出: true
示例 2:
输入: A = "ab", B = "ab"
输出: false
示例 3:
输入: A = "aa", B = "aa"
输出: true
示例 4:
输入: A = "aaaaaaabc", B = "aaaaaaacb"
输出: true
示例 5:
输入: A = "", B = "aa"
输出: false
提示:
0 <= A.length <= 20000
0 <= B.length <= 20000
A
和B
仅由小写字母构成。
代码:
class Solution:
def buddyStrings(self, A, B):
"""
:type A: str
:type B: str
:rtype: bool
"""
a = list(A)
b = list(B)
# 字符串均为空
if not A and not B:
return False
# 字符串长度不等
if len(A) != len(B):
return False
# 字符串长度相等,字符相同
if A == B:
if len(set(a)) < len(a):
return True
else:
return False
# 字符串长度相等,字符不同
count = 0
temp1 = []
temp2 = []
for i in range(len(A)):
if a[i] != b[i]:
count += 1
temp1.append(a[i])
temp2.append(b[i])
else:
continue
if count > 2 :
return False
elif count == 2 and temp1[0] == temp2[1] and temp1[1] == temp2[0]:
return True
else:
return False
if __name__ == '__main__':
A = "abab"
B = "abab"
out = Solution()
output = out.buddyStrings(A, B)
print(output)
解决方案
方法:情况列举
思路
如果 A[i] == B[i]
,我们就说 i
是匹配的,否则称 i
是不匹配的。亲密字符串几乎是完全匹配的,因为一次交换只会影响到两个索引。
如果交换 A[i]
和 A[j]
可以证明 A
和 B
是亲密字符串,那么就有 A[i] == B[j]
以及 A[j] == B[i]
。 这意味着在 A[i], A[j], B[i], B[j]
这四个自由变量中,只存在两种情况:A[i] == A[j]
或 A[i] != A[j]
算法
让我们来看看这些情况。
在 A[i] == A[j] == B[i] == B[j]
的情况下,字符串 A
与 B
相等。因此,如果 A == B
,我们应当检查每个索引 i
以寻找具有相同值的两个匹配。
在 A[i] == B[j], A[j] == B[i], (A[i] != A[j])
的情况下,其余索引是相匹配的。所以如果 A
和 B
只有两个不匹配的索引(记作 i
和 j
),我们应该检查并确保等式 A[i] == B[j]
和 A[j] == B[i]
成立。
代码:
class Solution(object):
def buddyStrings(self, A, B):
if len(A) != len(B): return False
if A == B:
seen = set()
for a in A:
if a in seen:
return True
seen.add(a)
return False
else:
pairs = []
for a, b in itertools.izip(A, B):
if a != b:
pairs.append((a, b))
if len(pairs) >= 3: return False
return len(pairs) == 2 and pairs[0] == pairs[1][::-1]
888. 公平的糖果交换
爱丽丝和鲍勃有不同大小的糖果棒:A[i]
是爱丽丝拥有的第 i
块糖的大小,B[j]
是鲍勃拥有的第 j
块糖的大小。
因为他们是朋友,所以他们想交换一个糖果棒,这样交换后,他们都有相同的糖果总量。(一个人拥有的糖果总量是他们拥有的糖果棒大小的总和。)
返回一个整数数组 ans
,其中 ans[0]
是爱丽丝必须交换的糖果棒的大小,ans[1]
是 Bob 必须交换的糖果棒的大小。
如果有多个答案,你可以返回其中任何一个。保证答案存在。
示例 1:
输入:A = [1,1], B = [2,2]
输出:[1,2]
示例 2:
输入:A = [1,2], B = [2,3]
输出:[1,2]
示例 3:
输入:A = [2], B = [1,3]
输出:[2,3]
示例 4:
输入:A = [1,2,5], B = [2,4]
输出:[5,4]
提示:
1 <= A.length <= 10000
1 <= B.length <= 10000
1 <= A[i] <= 100000
1 <= B[i] <= 100000
- 保证爱丽丝与鲍勃的糖果总量不同。
- 答案肯定存在。
代码:
class Solution:
def fairCandySwap(self, A, B):
"""
:type A: List[int]
:type B: List[int]
:rtype: List[int]
"""
C = [None, None]
suma = sum(A)
sumb = sum(B)
d = (suma - sumb)/2
ret = []
flag = 0
for i in range(len(A)):
for j in range(len(B)):
if A[i] - B[j] == d:
C[0] = A[i]
C[1] = B[j]
flag = 1
if flag > 0:
return C
return C
if __name__ == '__main__':
A = [2]
B = [1, 3]
out = Solution()
output = out.fairCandySwap2(A, B)
print(output)
解决方案
方法:方程求解
思路
如果爱丽丝交换糖果 x
,她将会期待交换一些特定量的糖果 y
回来。
算法
设爱丽丝和鲍勃分别总计有 S_A, S_BSA,SB 的糖果。
如果爱丽丝给了糖果 xx,并且收到了糖果 yy,那么鲍勃收到糖果 xx 并给出糖果 yy。那么,我们一定有
S_A - x + y = S_B - y + xSA−x+y=SB−y+x
对于公平的糖果交换。这意味着
y = x + \frac{S_B - S_A}{2}y=x+2SB−SA
我们的策略很简单。对于爱丽丝拥有的每个糖果 xx,如果鲍勃有糖果 y = x + \frac{S_B - S_A}{2}y=x+2SB−SA,我们就返回 [x,y][x,y]。我们在常量时间内使用集 Set
结构来检查Bob是否拥有所需的糖果 yy。
代码:
class Solution(object):
def fairCandySwap(self, A, B):
Sa, Sb = sum(A), sum(B)
setB = set(B)
for x in A:
if x + (Sb - Sa) / 2 in setB:
return [x, x + (Sb - Sa) / 2]
复杂度分析
-
时间复杂度:O(A\text{.length} + B\text{.length})O(A.length+B.length)。
-
空间复杂度:O(B\text{.length})O(B.length),
setB
用去的空间。(通过使用 if 语句,我们可以将其改进到 \min(A\text{.length}, B\text{.length})min(A.length,B.length)。)