题目链接
给定两个字符串 s
和 t
,编写一个函数来判断 t
是否是 s
的字母异位词。
**注意:**若 s
和 t
中每个字符出现的次数都相同,则称 s
和 t
互为字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram"
输出: true
示例 2:
输入: s = "rat", t = "car"
输出: false
提示:
1 <= s.length, t.length <= 5 * 104
s
和 t
仅包含小写字母Python:
# 数组
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
if len(s) != len(t):
return False
c1 = [0] * 26
c2 = [0] * 26
for ch in s:
c1[ord(ch) - ord("a")] += 1
for ch in t:
c2[ord(ch) - ord("a")] += 1
return c1 == c2
# t 是 s的异位词等价于「两个字符串排序后相等」。因此我们可以对字符串 s 和 t 分别排序,看排序后的字符串是否相等即可判断。此外,如果 s 和 t 的长度不同,t 必然不是 s 的异位词。
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
if len(s) != len(t):
return False
return sorted(s) == sorted(t)
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
ls, lt = len(s), len(t)
if ls != lt:
return False
h = {}
for i in range(ls):
if s[i] in h:
h[s[i]] += 1
else:
h[s[i]] = 1
for i in range(lt):
if t[i] in h:
h[t[i]] -= 1
if h[t[i]] < 0:
return False
else:
return False
return True
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
ls, lt = len(s), len(t)
if ls != lt:
return False
h = defaultdict(int)
for i in range(ls):
h[s[i]] += 1
for i in range(lt):
h[t[i]] -= 1
if h[t[i]] < 0:
return False
for i in h.values():
if i != 0:
return False
return True
Go:
//使用数组
func isAnagram(s, t string) bool {
if len(s) != len(t) {
return false
}
var c1, c2 [26]int
for _, ch := range s {
c1[ch-'a']++
}
for _, ch := range t {
c2[ch-'a']++
}
return c1 == c2
}
//t 是 s的异位词等价于「两个字符串排序后相等」。因此我们可以对字符串 s 和 t 分别排序,看排序后的字符串是否相等即可判断。此外,如果 s 和 t 的长度不同,t 必然不是 s 的异位词。
func isAnagram(s, t string) bool {
if len(s) != len(t) {
return false
}
s1, s2 := []byte(s), []byte(t)
sort.Slice(s1, func(i, j int) bool { return s1[i] < s1[j] })
sort.Slice(s2, func(i, j int) bool { return s2[i] < s2[j] })
return string(s1) == string(s2)
}
func isAnagram(s string, t string) bool {
if len(s) != len(t) {
return false
}
h := make(map[rune]int)
for _, char := range s {
h[char]++
}
for _, char := range t {
h[char]--
if h[char] < 0 {
return false
}
}
return true
}
题目链接
给定两个数组 nums1
和 nums2
,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的
提示:
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000
Python:
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
return list(set(nums1) & set(nums2))
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
return list(set([x for x in nums1 if x in nums2]))
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
nums1 = set(nums1)
nums2 = set(nums2)
return [x for x in nums1 if x in nums2]
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
nums1=set(nums1)
return [x for x in nums1 if x in nums2]
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
vis = {}
out = []
for i in nums1:
vis[i] = False
for i in nums2:
if i in vis:
vis[i] = True
for k, v in vis.items():
if v:
out.append(k)
return out
Go:
func intersection(nums1 []int, nums2 []int) []int {
vis := make(map[int]bool)
out := make([]int, 0)
for _, i := range nums1 {
vis[i] = false
}
for _, i := range nums2 {
if _, ok := vis[i]; ok {
vis[i] = true
}
}
for k, v := range vis {
if v == true {
out = append(out, k)
}
}
return out
}
题目链接
编写一个算法来判断一个数 n
是不是快乐数。
「快乐数」 定义为:
如果 n
是 快乐数 就返回 true
;不是,则返回 false
。
示例 1:
输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
示例 2:
输入:n = 2
输出:false
提示:
1 <= n <= 23^1 - 1
Python:
# 哈希表
class Solution:
def isHappy(self, n: int) -> bool:
seen = set()
while n != 1 and n not in seen:
seen.add(n)
n = self.get_sum(n)
return n == 1
def get_sum(self, n: int):
_sum = 0
while n > 0:
n, digit = divmod(n, 10)
_sum += digit**2
return _sum
# 双指针法
class Solution:
def isHappy(self, n: int) -> bool:
def step(num):
_sum = 0
while num > 0:
num, digit = divmod(num, 10)
_sum += digit**2
return _sum
slow, fast = n, step(n)
while fast != 1 and slow != fast:
slow = step(slow)
fast = step(step(fast))
return fast == 1
Go:
//哈希表
func isHappy(n int) bool {
seen := make(map[int]bool)
for ; n != 1 && !seen[n]; n, seen[n] = getSum(n), true {
}
return n == 1
}
func getSum(n int) (sum int) {
for n > 0 {
sum += (n % 10) * (n % 10)
n /= 10
}
return sum
}
//双指针法
func isHappy(n int) bool {
slow, fast := n, step(n)
for fast != 1 && slow != fast {
slow = step(slow)
fast = step(step(fast))
}
return fast == 1
}
func step(n int) int {
sum := 0
for n > 0 {
sum += (n%10) * (n%10)
n = n/10
}
return sum
}
题目链接
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
Python:
#暴力解法
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
n = len(nums)
for i in range(n):
for j in range(i + 1, n):
if nums[i] + nums[j] == target:
return [i, j]
return []
#哈希表
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hashtable = dict()
for i, num in enumerate(nums):
if target - num in hashtable:
return [hashtable[target - num], i]
hashtable[nums[i]] = i
return []
Go:
//暴力解法
func twoSum(nums []int, target int) []int {
for i, x := range nums {
for j := i + 1; j < len(nums); j++ {
if x+nums[j] == target {
return []int{i, j}
}
}
}
return nil
}
//哈希表
func twoSum(nums []int, target int) []int {
hashTable := map[int]int{}
for i, x := range nums {
if p, ok := hashTable[target-x]; ok {
return []int{p, i}
}
hashTable[x] = i
}
return nil
}
题目链接
给你四个整数数组 nums1
、nums2
、nums3
和 nums4
,数组长度都是 n
,请你计算有多少个元组 (i, j, k, l)
能满足:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
示例 1:
输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]
输出:2
解释:
两个元组如下:
1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0
2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0
示例 2:
输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0]
输出:1
提示:
n == nums1.length
n == nums2.length
n == nums3.length
n == nums4.length
1 <= n <= 200
-2^28 <= nums1[i], nums2[i], nums3[i], nums4[i] <= 2^28
Python:
class Solution:
def fourSumCount(
self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]
) -> int:
count = 0
sum_count = defaultdict(int)
for i in nums1:
for j in nums2:
sum_count[i + j] += 1
for i in nums3:
for j in nums4:
count += sum_count[-(i + j)]
return count
#四数求和问题一个最常用的优化方法是通过降低复杂度,但这也取决于具体问题的需求。最直接的方法,即四个数组的四次循环,其时间复杂度为O(n^4)。以上述方法通过两次双重循环和哈希表降低了时间复杂度到O(n^2)。
class Solution:
def fourSumCount(self, A: List[int], B: List[int], C: List[int], D: List[int]) -> int:
countAB = collections.Counter(u + v for u in A for v in B)
ans = 0
for u in C:
for v in D:
if -u - v in countAB:
ans += countAB[-u - v]
return ans
Go:
func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int {
sumCount := make(map[int]int)
count := 0
for _, num1 := range nums1 {
for _, num2 := range nums2 {
sumCount[num1+num2]++
}
}
for _, num3 := range nums3 {
for _, num4 := range nums4 {
count += sumCount[-(num3 + num4)]
}
}
return count
}
//四数求和问题一个最常用的优化方法是通过降低复杂度,但这也取决于具体问题的需求。最直接的方法,即四个数组的四次循环,其时间复杂度为O(n^4)。以上述方法通过两次双重循环和哈希表降低了时间复杂度到O(n^2)。
题目链接
给你两个字符串:ransomNote
和 magazine
,判断 ransomNote
能不能由 magazine
里面的字符构成。
如果可以,返回 true
;否则返回 false
。
magazine
中的每个字符只能在 ransomNote
中使用一次。
示例 1:
输入:ransomNote = "a", magazine = "b"
输出:false
示例 2:
输入:ransomNote = "aa", magazine = "ab"
输出:false
示例 3:
输入:ransomNote = "aa", magazine = "aab"
输出:true
提示:
1 <= ransomNote.length, magazine.length <= 10^5
ransomNote
和 magazine
由小写英文字母组成Python:
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
if len(ransomNote) > len(magazine):
return False
return not collections.Counter(ransomNote) - collections.Counter(magazine)
#数组,速度最快
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
if len(ransomNote) > len(magazine):
return False
cnt = [0] * 26
for i in magazine:
cnt[ord(i) - ord("a")] += 1
for i in ransomNote:
t = ord(i) - ord("a")
cnt[t] -= 1
if cnt[t] < 0:
return False
return True
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
m = defaultdict(int)
for i in magazine:
m[i] += 1
for i in ransomNote:
if i in m and m[i]:
m[i] -= 1
else:
return False
return True
Go:
//哈希表
func canConstruct(ransomNote string, magazine string) bool {
m := make(map[rune]int)
for _, v := range magazine {
m[v]++
}
for _, v := range ransomNote {
if value, ok := m[v]; ok && value > 0 {
m[v]--
} else {
return false
}
}
return true
}
//数组
func canConstruct(ransomNote, magazine string) bool {
if len(ransomNote) > len(magazine) {
return false
}
cnt := [26]int{}
for _, ch := range magazine {
cnt[ch-'a']++
}
for _, ch := range ransomNote {
cnt[ch-'a']--
if cnt[ch-'a'] < 0 {
return false
}
}
return true
}
题目链接
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请
你返回所有和为 0
且不重复的三元组。
**注意:**答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
示例 3:
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。
提示:
3 <= nums.length <= 3000
-10^5 <= nums[i] <= 10^5
Python:
#集合法
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
result = [] # 初始化结果列表
nums.sort() # 对输入的列表进行排序
for i in range(len(nums) - 2): # 遍历每个元素
if nums[i] > 0: # 当前数大于0,由于是排序过的列表,后面的数肯定都大于0,不可能再找到和为0的三个数,因此直接退出循环
break
if i > 0 and nums[i] == nums[i - 1]: # 当前数和上一个数相同,跳过以避免出现重复的结果
continue
seen = set() # 初始化一个集合,用来保存已经遍历过的数
j = i + 1
while j < len(nums): # 从当前数的下一个元素开始扫描
complement = -(nums[i] + nums[j]) # 计算需要查找的补数值,这个补数值和当前的数与下一个数相加的和应该等于0
if complement in seen: # 如果这个补数值已经在seen集合中,说明找到了一个有效的组合,将其放入结果列表
result.append([nums[i], nums[j], complement])
# 向后移动指针以避免重复的解决方案
while j + 1 < len(nums) and nums[j] == nums[j + 1]:
j += 1
else:
seen.add(nums[j]) # 如果补数值不在seen集合中,将当前的数加入seen集合
j += 1
return result # 返回结果列表
#双指针法
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort() # 先将数组排序
result = [] # 结果集
l = len(nums)
for i in range(l - 2): # 遍历数组,为什么是到 l - 2,因为我们需要找的是三个数的组合
if nums[i] > 0: # 如果第一个元素已经大于0,不需要进一步检查
break
if i > 0 and nums[i] == nums[i - 1]: # 如果当前数字和前一个相同,跳过这个数字,防止结果中出现重复的组合
continue
left, right = i + 1, l - 1 # 定义双指针
while left < right: # 当左指针小于右指针的时候,执行以下操作
total = nums[i] + nums[left] + nums[right] # 计算三个数的和
if total < 0: # 和小于0,需要增大,所以左指针右移
left += 1
elif total > 0: # 和大于0,需要减小,所以右指针左移
right -= 1
else: # 和为0,记录这个组合
result.append([nums[i], nums[left], nums[right]])
left += 1 # 为了寻找下一个可能的组合,左指针右移
right -= 1 # 右指针左移
while left < right and nums[left] == nums[left - 1]: # 跳过重复的组合
left += 1
while left < right and nums[right] == nums[right + 1]: # 跳过重复的组合
right -= 1
return result # 返回结果集
Go:
//哈希表
func threeSum(nums []int) [][]int {
var result [][]int
sort.Ints(nums)
for i := 0; i < len(nums)-2; i++ {
if nums[i] > 0 {
break
}
if i > 0 && nums[i] == nums[i-1] {
continue
}
seen := make(map[int]bool)
for j := i + 1; j < len(nums); j++ {
complement := -(nums[i] + nums[j])
if seen[complement] {
result = append(result, []int{nums[i], complement, nums[j]})
for j+1 < len(nums) && nums[j] == nums[j+1] {
j++
}
}
seen[nums[j]] = true
}
}
return result
}
//双指针
func threeSum(nums []int) [][]int {
var result [][]int
sort.Ints(nums)
l := len(nums)
for i := 0; i < l-2; i++ {
if nums[i] > 0 {
break
}
if i > 0 && nums[i] == nums[i-1] {
continue
}
left, right := i+1, l-1
for left < right {
sum := nums[i] + nums[left] + nums[right]
if sum < 0 {
left++
} else if sum > 0 {
right--
} else {
result = append(result, []int{nums[i], nums[left], nums[right]})
left++
right--
for left < right && nums[left] == nums[left-1] {
left++
}
for left < right && nums[right] == nums[right+1] {
right--
}
}
}
}
return result
}
题目链接
给你一个由 n
个整数组成的数组 nums
,和一个目标值 target
。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]]
(若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a
、b
、c
和 d
互不相同nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:
输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]
提示:
1 <= nums.length <= 200
-10^9 <= nums[i] <= 10^9
-10^9 <= target <= 10^9
Python:
#双指针法
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
result = []
nums.sort()
l = len(nums)
for i in range(l - 3):
if i > 0 and nums[i] == nums[i - 1]:
continue
for j in range(l - 1, 2, -1):
if j < l - 1 and nums[j] == nums[j + 1]:
continue
left, right = i + 1, j - 1
while left < right:
total = nums[i] + nums[j] + nums[left] + nums[right]
if total < target:
left += 1
elif total > target:
right -= 1
else:
result.append([nums[i], nums[j], nums[left], nums[right]])
left += 1
right -= 1
while left < right and nums[left] == nums[left - 1]:
left += 1
while left < right and nums[right] == nums[right + 1]:
right -= 1
return result
#集合法
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
# 创建频率字典,用于存放每一个数出现的次数
freq = {}
for num in nums:
freq[num] = freq.get(num, 0) + 1
# 创建存放结果的集合,用于去重
ans = set()
# 遍历数组的每一个数
for i in range(len(nums)):
# 双层遍历,找到三元组
for j in range(i + 1, len(nums)):
for k in range(j + 1, len(nums)):
# 计算需要寻找的值
val = target - (nums[i] + nums[j] + nums[k])
# 判断需要寻找的值是否在字典中
if val in freq:
# 计算当前三元组中是否有重复值
count = (nums[i] == val) + (nums[j] == val) + (nums[k] == val)
# 检查字典中该值的个数是否大于三元组中的个数
if freq[val] > count:
# 添加到结果集中
ans.add(tuple(sorted([nums[i], nums[j], nums[k], val])))
# 返回格式化后的结果
return [list(x) for x in ans]
Go:
//双指针法,可类比三数之和这道题
func fourSum(nums []int, target int) [][]int {
var result [][]int
sort.Ints(nums)
l := len(nums)
for i := 0; i < l-3; i++ {
if i > 0 && nums[i] == nums[i-1] {
continue
}
for j := l - 1; j > 2; j-- {
if j < l-1 && nums[j] == nums[j+1] {
continue
}
for left, right := i+1, j-1; left < right; {
sum := nums[i] + nums[j] + nums[left] + nums[right]
if sum < target {
left++
} else if sum > target {
right--
} else {
result = append(result, []int{nums[i], nums[j], nums[left], nums[right]})
left++
right--
for left < right && nums[left] == nums[left-1] {
left++
}
for left < right && nums[right] == nums[right+1] {
right--
}
}
}
}
}
return result
}
//硬用哈希表,不建议
func fourSum(nums []int, target int) [][]int {
freq := make(map[int]int)
for _, num := range nums {
freq[num] = freq[num] + 1
}
var ans [][]int
for i := 0; i < len(nums); i++ {
for j := i + 1; j < len(nums); j++ {
for k := j + 1; k < len(nums); k++ {
val := target - (nums[i] + nums[j] + nums[k])
if _, ok := freq[val]; ok {
count := 0
if nums[i] == val {
count++
}
if nums[j] == val {
count++
}
if nums[k] == val {
count++
}
if freq[val] > count {
quadruplet := []int{nums[i], nums[j], nums[k], val}
sort.Ints(quadruplet)
if !contains(ans, quadruplet) {
ans = append(ans, quadruplet)
}
}
}
}
}
}
return ans
}
func contains(quadruplets [][]int, quadruplet []int) bool {
for _, q := range quadruplets {
if equal(q, quadruplet) {
return true
}
}
return false
}
func equal(a, b []int) bool {
if len(a) != len(b) {
return false
}
for i, v := range a {
if v != b[i] {
return false
}
}
return true
}