LeetCode刷题之路(五)

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

你可能感兴趣的:(LeetCode)