记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
-
-
- [5/18 1345. 跳跃游戏 IV](#5/18 1345. 跳跃游戏 IV)
- [5/19 2540. 最小公共值](#5/19 2540. 最小公共值)
- [5/20 2657. 找到两个数组的前缀公共数组](#5/20 2657. 找到两个数组的前缀公共数组)
- [5/21 3043. 最长公共前缀的长度](#5/21 3043. 最长公共前缀的长度)
- [5/22 33. 搜索旋转排序数组](#5/22 33. 搜索旋转排序数组)
- [5/231752. 检查数组是否经排序和轮转得到](#5/231752. 检查数组是否经排序和轮转得到)
- [5/24 1340. 跳跃游戏 V](#5/24 1340. 跳跃游戏 V)
-
5/18 1345. 跳跃游戏 IV
BFS
valueToloc记录每个值的位置所在
对于arr[loc]=v
他可以到达 loc+1,loc-1或者valueToloc[v]中的所有位置
第一次搜索到必定是最少次数 visited记录被搜索到的位置
同个值的位置搜索过后之后不需要搜索这个地方 删除valueToloc[v]
python
def minJumps(arr):
"""
:type arr: List[int]
:rtype: int
"""
from collections import defaultdict,deque
valueToloc = defaultdict(list)
for loc,v in enumerate(arr):
valueToloc[v].append(loc)
n = len(arr)
l = deque()
l.append((0,0))
visited= set()
visited.add(0)
while l:
loc,step = l[0]
if loc==n-1:
return step
value = arr[loc]
l.popleft()
for tmp in valueToloc[value][::-1]:
if tmp not in visited:
visited.add(tmp)
l.append((tmp,step+1))
valueToloc[value]=[]
if loc+1<n and loc+1 not in visited:
visited.add(loc+1)
l.append((loc+1,step+1))
if loc-1>0 and loc-1 not in visited:
visited.add(loc-1)
l.append((loc-1,step+1))
arr = [100,-23,-23,404,100,23,23,23,3,404]
print(minJumps(arr))
5/19 2540. 最小公共值
双指针 分别指向两个数组
如果两个指针指向的值相等 则返回该值
如果两个指针指向的值不相等 则移动较小的指针
python
def getCommon(nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: int
"""
i,j=0,0
while i<len(nums1) and j<len(nums2):
if nums1[i]==nums2[j]:
return nums1[i]
elif nums1[i]<nums2[j]:
i+=1
else:
j+=1
return -1
5/20 2657. 找到两个数组的前缀公共数组
一共50位 用一个50位的二进制数表示
将一个二进制数的第i位设置为1 表示值为i的元素在数组中
将两个二进制数相与 得到的结果就是两个数组的前缀公共数组
python
def findThePrefixCommonArray(A, B):
"""
:type A: List[int]
:type B: List[int]
:rtype: List[int]
"""
n=len(A)
ba,bb=0,0
def getOne(x):
ans = 0
while x:
ans += x&1
x >>= 1
return ans
ret=[]
for i in range(n):
ba |= 1<<A[i]
bb |= 1<<B[i]
num = getOne(ba&bb)
ret.append(num)
return ret
5/21 3043. 最长公共前缀的长度
将arr1中的所有数字的十进制前缀放入一个集合中
遍历arr2中的每个数字 不断去掉末位 直到该数字出现在集合中
记录该数字的位数 取最大值即为答案
python
def longestCommonPrefix(arr1, arr2):
"""
:type arr1: List[int]
:type arr2: List[int]
:rtype: int
"""
prefix_set = set()
for num in arr1:
x = num
if x == 0:
prefix_set.add(0)
while x > 0:
prefix_set.add(x)
x //= 10
ans = 0
for num in arr2:
x = num
if x == 0 and 0 in prefix_set:
ans = max(ans, 1)
continue
while x > 0:
if x in prefix_set:
ans = max(ans, len(str(x)))
break
x //= 10
return ans
5/22 33. 搜索旋转排序数组
根据题目 假设升序list[a0...an,b0...bm] a0<an<b0<bm
在an进行了旋转 变成了[b0...bm,a0...an] b0<bm a0<an
选取list中间点mid 会出现两种情况
1.[b0...mid...bm,a0...an] 此时 mid>b0>an 可知 mid左侧为升序list
2.[b0...bm,a0...mid...an] 此时 mid <an 可知mid右侧为升序list
所以我们可以取中间的一个点 与当前List最右边的点比较 可以得到左边或者右边是升序队列
比较查看target是否在升序队列中
如果不在 将另外一边队列 重新选点 重复上述操作
如果在 则在升序队列中二分
python
def search(nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
left = 0
right = len(nums)-1
while left<=right:
mid = int((left+right)/2)
if nums[mid]==target:
return mid
if nums[mid]<nums[right]: ##右边有序
if nums[mid] < target and target<=nums[right]:
left = mid+1
else:
right = mid-1
elif nums[left]<=target and target <nums[mid]:
right = mid-1
else:
left = mid+1
return -1
5/231752. 检查数组是否经排序和轮转得到
原数组所有元素非递减排列
假设轮转x个位置
source[x,...,n-1]+source[0,...,x-1] = nums
找到nums[i-1]<nums[i]
检查0~i-1 i~n-1是否都非递减
python
def check(nums):
"""
:type nums: List[int]
:rtype: bool
"""
n= len(nums)
x = 0
for i in range(1,n):
if nums[i]<nums[i-1]:
x=i
break
if x==0:
return True
for i in range(x+1,n):
if nums[i]<nums[i-1]:
return False
return nums[0]>=nums[-1]
5/24 1340. 跳跃游戏 V
设 dfs(i) 表示「从下标 i 出发,最多能访问多少个位置(包含 i 自己)」。
从 i 可以向左/右最多跳 d 步,但有两个限制:
只能跳到更小值:arr[j] < arr[i]
一旦某个方向遇到 arr[k] >= arr[i],该方向后续位置都不可达(被挡住),立即停止该方向搜索。
状态转移:
dfs(i) = 1 + max(dfs(j)),其中 j 是 i 在左右两侧可直接跳到的位置;
若没有可跳位置,则 dfs(i) = 1。
用缓存保存 dfs(i) 的结果,避免重复计算。最终答案是 max(dfs(i))。
python
def maxJumps(arr, d):
"""
:type arr: List[int]
:type d: int
:rtype: int
"""
from functools import lru_cache
n = len(arr)
@lru_cache(maxsize=None)
def dfs(i):
best = 1
# 向左跳
for step in range(1, d + 1):
j = i - step
if j < 0:
break
if arr[j] >= arr[i]:
break
best = max(best, 1 + dfs(j))
# 向右跳
for step in range(1, d + 1):
j = i + step
if j >= n:
break
if arr[j] >= arr[i]:
break
best = max(best, 1 + dfs(j))
return best
return max(dfs(i) for i in range(n))