# Leetcode - 查找1

mhxin

## 查找

### 35. 搜索插入位置

``````def search(nums -> list[int], target -> int) -> int:
"""
Params:
nums(list): sorted array

target(int): int
"""
# 如果数组为空
if not nums:
return -1

def helper(left -> int, right -> int):
# 循环结束条件: left = right + 1
while left <= right:

# 避免数值过大导致溢出
mid = left + (right - left) // 2

# 向左收缩
if nums[mid] < target:
right = mid -1

# 向右收缩
elif nums[mid] > target:
left = mid + 1

# 找到了, 直接返回
elif nums[mid] == target:
return mid

n = len(nums)
idx = helper(0, n-1)
return idx if idx else -1``````
``````def searchInsert(nums -> list[int], target -> int) -> int:
if not nums:
return 0

def helper(left, right):
while left <= right:
mid = (left + right) // 2

if nums[mid] < target:
left = mid + 1

elif nums[mid] > target:
right = mid - 1

elif nums[mid] == target:
right = right - 1

return left

return helper(0, len(nums)-1)``````

### 202. 快乐数

「快乐数」定义为：对于一个正整数，每一次将该数替换为它每个位置上的数字的平方和，然后重复这个过程直到这个数变为 1，也可能是 无限循环 但始终变不到 1。如果 可以变为 1，那么这个数就是快乐数。

12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

``````def isHappy(n):
if n == 1:
return True

dicts = {}
while n != 1:

# 如果字典中已存在变换的结果, 则直接返回False
if n in dicts:
return False

ans = 0
while n > 0:
ans += (n % 10) * (n % 10)
n //= 10

n = ans

# 如果可以跳出循环
return True``````

``````def isHappy(n):
if n == 1:
return True

def helper(num):
ans = 0
while n > 0:
ans += (n % 10) * (n % 10)
n //= 10
return ans

# 慢指针
slow = n
# 快指针
fast = helper(n)

# 如果快慢指针不相等, 直至它们相等
while slow != fast:
slow = helper(slow)
fast = helper(helper(fast))

return slow == 1``````

### 205. 同构字符串

``````def isIsomorphic(s -> str, t -> str):
if not s and not s:
return False

if not s or not t or len(s) != len(t):
return True

dicts = {}

for i, c in enumerate(s):
if c in dicts:
if dicts[c] != t[i]:
return False

dicts[c] = t[i]

return len(dicts) == len(set(dicts.values()))
``````

### 242. 有效的字母异位词

``````输入: s = "anagram", t = "nagaram"

``````输入: s = "rat", t = "car"

``````def isAnagram(s: str, t: str) -> bool:
if not s and not t:
return True

if not s or not t or len(s) != len(t):
return False

# 排序
s = sorted(s)

t = sorted(t)

# 如果两个字符串是字母异位词
return s == t``````

``````def isAnagram(s: str, t: str) -> bool:
if not s and not t:
return True

if not s or not t or len(s) != len(t):
return False

# 记录每个字母出现次数
arr = [0] * 26

for i, c in enumerate(s):
arr[ord(c) - ord('a')] += 1
arr[ord(t[i]) - ord('a')] -= 1

# 如果某个位置的元素小于0, 则可以直接返回False
for i in range(26):
if arr[i] < 0:
return False

#
return sum(arr) == 0``````

### 290. 单词规律

``````def wordPattern(pattern: str, str: str) -> bool:
if not pattern or not str:
return False

split_str = str.split()

if len(pattern) != len(split_str):
return False

dicts = {}
for i, c in enumerate(pattern):
if c in dicts:
if dicts[c] != split_str[i]:
return False

dicts[c] = split_str[i]

return len(dicts) == len(set(dicts.values()))``````

### 349. 两个数组的交集

``````def intersection(nums1: List[int], nums2: List[int]) -> List[int]:
if not nums1 or not nums2:
return []

# 去重
nums1 = set(nums1)
nums2 = set(nums2)

m = len(nums1)

# 查找
res = [i for i in nums1 if i in nums2]

return res``````

### 350. 两个数组的交集 II

``````def intersect(nums1: List[int], nums2: List[int]) -> List[int]:
if not nums1 or not nums2:
return []

m, n = len(nums1), len(nums2)
res = []

dicts = {}
# 使用字典记录每个数出现的次数
for i in nums1:
dicts[i] = dicts.get(i, 0) + 1

for i in nums2:
# 如果 i 在字典中并且它的值大于0
if i in dicts and dicts[i] > 0:
res.append(i)
dicts[i] -= 1

return res``````

### 410. 分割数组的最大值

1 ≤ n ≤ 1000
1 ≤ m ≤ min(50, n)

nums = [7,2,5,10,8]
m = 2

18

「使……最大值尽可能小」是二分搜索题目常见的问法。

``````def splitArray(nums: List[int], m: int) -> int:
def check(x: int) -> bool:
total, cnt = 0, 1
for num in nums:
if total + num > x:
cnt += 1
total = num
else:
total += num
return cnt <= m

left = max(nums)
right = sum(nums)
while left < right:
mid = (left + right) // 2
if check(mid):
right = mid
else:
left = mid + 1

return left
``````

### 451. 根据字符出现频率排序

"tree"

"eert"

'e'出现两次，'r'和't'都只出现一次。

"cccaaa"

"cccaaa"

'c'和'a'都出现三次。此外，"aaaccc"也是有效的答案。

"Aabb"

"bbAa"

``````def frequencySort(s: str) -> str:
if not s or len(s) < 2:
return s

dicts = {}
res = ''

# 统计每个字符出现的次数
for c in s:
dicts[c] = dicts.get(c, 0) + 1

# 按照出现次数对字符进行排序
dicts = sorted(dicts.items(), lambda x: x[1], reverse=True)

for k, v in dicts.items():
res += k * v
return res``````

``````def frequencySort(s: str) -> str:
if not s or len(s) < 2:
return s

from collections import Counter

# Counter(s) : 返回一个元素统计字典
# most_common() : 按照元素出现次数进行降序排序
return ''.join(k * v for k, v in Counter(s).most_common())``````

### 540. 有序数组中的单一元素

``````def singleNonDuplicate(nums: List[int]) -> int:
n = len(nums)
i = 0
while i < n - 1:
if nums[i] != nums[i+1]:
return nums[i]

return nums[n-1]
``````

``````def singleNonDuplicate(nums: List[int]) -> int:

res = nums[0]

for i in nums[1:]:
res = res & i

return res
``````

``````def singleNonDuplicate(nums: List[int]) -> int:
n = len(nums)

left, right = 0, n - 1

while left <= right:

mid = (left + right) // 2

if mid + 1 < n and mid % 2 == 0:
# mid为奇数, 说明mid之前的部分和之后的部分均为偶数
# 说明这个数在mid右侧
if nums[mid] == nums[mid + 1]:
left = mid + 2
#
else:
right = mid - 1

elif mid + 1 < n and mid % 2:
# mid为奇数, 说明mid之前的部分和之后的部分均为奇数
if nums[mid] == nums[mid + 1]:
right = mid - 1
#
else:
left = mid + 1

else:
return nums[mid]

return nums[left]``````

82 声望
12 粉丝
0 条评论