LeetCode33搜索旋转排序数组
算法思路:这是一道好题。题目要求算法时间复杂度是O(logn)级别,那显然只能用二分查找了,关键在于二分查找算法只能用于有序的排列,而这道题给出的数组并不是有序的序列,在某个点上进行了旋转。那么我们应该怎么找到有序的子序列呢?
我们只需要判断序列的第一个值和序列中间值的大小就可以判断。因为这是一个有序的序列的必要条件。
具体的,先进行判断子序列是否是 有序子序列,然后检查target的值是否在有序子序列的范围之内。不过没有我们就继续找下一个有序的子序列,如果target的值在该有序子序列的范围,就继续在这个有序子序列中使用二分查找。
class Solution:
def search(self, nums: List[int], target: int) -> int:
low = 0
high = len(nums) -1
while(low <=high):
middle = low + ((high-low)>>1)
if nums[middle] == target:
return middle
else:
if nums[low] <= nums[middle]:
if target < nums[middle] and target >= nums[low]:
high = middle - 1
else:
low = middle + 1
else:
if target <= nums[high] and target > nums[middle]:
low = middle + 1
else:
high = middle-1
return -1
LeetCode34 在排序数组中查找元素的第一个和最后一个位置
算法思路,这道题还是考察二分查找算法,具体可以看这个链接上的二分查找总结。实际上我们只要找到这个元素的第一个位置就行。然后再进行遍历找到最后一个位置。
tips:具体的要注意一些特殊例子的判断
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
low = 0
high = len(nums)-1
if len(nums) < 0:
return [-1,-1]
if len(nums) == 1 and nums[0] ==target:
return [0,0]
elif len(nums) == 1 and nums[0] !=target:
return [-1,-1]
while(low <= high):
middle = low + ((high-low)>>1)
if nums[middle] >= target:
high = middle -1
else:
low = middle + 1
index = high + 1 if high != len(nums)-1 and nums[high+1] == target else -1
if index == -1:
return [-1,-1]
else:
j = index
while(j < len(nums) and nums[index] == nums[j]):
j += 1
return [index, j-1]
LeetCode39组合总和
算法思路,这道题主要考察最基本的深度优先搜索。题目中说要使数字之和等于target,那么我们使用深度优先搜索遍历所有的情况。
唯一需要注意的是题目中说candidates中的数字可以无限制的重复被选取,所以我们假设路径中加入了"2"这个结点,从这个结点出来以后我们还是继续可以进入"2"这个结点。
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
ength = len(candidates)
result = []
candidates.sort()
temp = []
sum = 0
self.DFS(0, candidates, target, sum, result, temp)
return result
def DFS(self,index,cadidate,target,sum,reauslt,temp):
length = len(cadidate)
if sum == target:
reauslt.append(temp.copy())
return
if index == length or sum > target:
return
temp.append(cadidate[index])
sum += cadidate[index]
self.DFS(index, cadidate, target, sum, reauslt, temp)
temp.pop()
sum -= cadidate[index]
self.DFS(index+1, cadidate, target, sum, reauslt, temp)
LeetCode40组合总和二
算法思路:这一题和上一题的算法思路几乎一样,目前我想到的是我们每次找到一个新的组合,就先判断已有的组合中是否有重复的,但是我觉得我的算法还可以再优化。
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
result = []
temp = []
sum = 0
candidates.sort()
self.DFS(0, target, sum, candidates, temp, result)
return result
def DFS(self,index, target, sum, candidate, temp, result):
if sum == target:
if temp not in result:
result.append(temp.copy())
return
else:
return
if sum > target or index == len(candidate):
return
temp.append(candidate[index])
sum += candidate[index]
self.DFS(index+1, target, sum, candidate, temp, result)
temp.pop()
sum -= candidate[index]
self.DFS(index+1, target, sum, candidate, temp, result)
LeetCode41缺失的一个正数
算法思路:这里有一个很妙的思路:我们先遍历一遍数组,将值在1和数组长度之间的元素放入下标为该元素值的位置,然后再遍历一遍数组,检查每个元素的值是否和下标对应,如果没有对应,那么该下标就是缺失的最小正数,如果遍历一遍都是对应好的,那么数组长度+1的元素就是缺失的最小正数。
class Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
for i in range(len(nums)):
while(nums[i] > 0 and nums[i] <= len(nums) and nums[nums[i]-1] != nums[i]):
temp = nums[nums[i]-1]
nums[nums[i]-1] = nums[i]
nums[i] = temp
flag = 0
for j in range(len(nums)):
if nums[j] != j+1:
flag = 1
return j+1
if flag == 0:
return len(nums)+1