Ⅰ array code exercise1

###  祝我顺利,申请季太难受了 ###

Leetcode 34

# 这道题,一开始使用二分没写出来,我又纯粹按照自己的思路解答看能否跑通所有的用例,最后得到了复杂度为N的解法, 不符合题目要求,但技术面手撕代码的时候,可以用。

解题思路一

读懂题目很重要:数组里没有目标,返回[-1,-1];数组里有一个符合的目标且是数组首元素,返回[0,0];数组里有一个符合的目标且不是数组首元素,返回[符合索引,符合索引];数组里有多个符合目标,返回[首符合索引,末符合索引]。看完下面的代码,再返回看这个分析,你会恍然大悟。

class Solution(object):
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        if len(nums) >= 2:  #nums长度大于等于2情况
            li = []  
            for i in range(0,len(nums)):     #python列表中如果有重复的元素,列表的index()函数只返回第一个元素的索引
                if nums[i] == target:        #故而使用range函数
                    li.append(i)  #记录所有符合的索引           
                else:
                    continue

            # li有元素
            if len(li) > 1:
                return [li[0],li[-1]]  #输出首末索引
            elif len(li) == 1:
                if li[0] == 0:     #nums只有一个符合target,且nums里首元素0
                    return [0,0]
                else:
                    return [nums.index(target),nums.index(target)]  #nums只有一个符合target,但非nums里首元素
            # li无元素
            else:
                return[-1,-1]

        elif len(nums) == 1:   #nums长度为1,要输出[左,右]格式,调整代码,通过所有用例; 
            if nums[0] == target:
                return[0,0]
            else:
                return [-1,-1]

        else:                   #nums长度为0情况
            return [-1,-1]

解题思路二——二分法

class Solution(object):
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        # 复杂度为logn,想到二分法。
        # 找到数组中首末索引并返回,不存在返回[-1,-1]

        def left_index(nums, target):
            left = 0
            right = len(nums) - 1
            while left <= right:
                mid = left + (right - left) // 2
                if nums[mid] == target:  #mid是目标元素
                    if mid == 0 or nums[mid - 1] < target: #mid是首元素位置或mid左边小于target,左下标确认
                        return mid
                    else:
                        right = mid - 1
                elif nums[mid] > target: #递增数组mid大于目标元素,改变right
                    right = mid - 1
                else:
                    left = mid + 1    #递增数组mid小于目标元素,改变left
            # 找不到目标元素
            return -1

        def right_index(nums, target):
            left = 0
            right = len(nums) - 1
            while left <= right:
                mid = left + (right - left) // 2
                if nums[mid] == target:  #mid是目标元素
                    if mid == len(nums)-1 or nums[mid + 1] > target: #末元素是mid或者mid右边大于target,右下标确认
                        return mid
                    else: #mid右边小于等于target
                        left = mid + 1
                elif nums[mid] > target: #递增数组mid大于目标元素,改变right
                    right = mid - 1
                else:
                    left = mid + 1    #递增数组mid小于目标元素,改变left
            # 找不到目标元素
            return -1


        #返回左右下标
        return [left_index(nums, target), right_index(nums, target)]

Leetcode 35

易错点:if判断,我第一次写的是<=,无法跑过所有用例,比如当数组是[1],target也是1,应该返回0

class Solution(object):
    def searchInsert(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        left, right = 0, len(nums)-1

        if nums[right] < target:  #nums无重复升序,先比较最后一个元素与target关系
            return len(nums)
        else:
            while left <= right:
                mid = left + (right-left)//2
                if nums[mid] > target:
                    right = mid - 1
                elif nums[mid] < target:
                    left = mid + 1
                else:
                    return mid
            return left

Leetcode 69

方法一:库函数

import math
class Solution(object):
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        return int(math.sqrt(x))

方法二:二分法

第一次写的时候,mid被赋值 left + (right - left) // 2 ,超时警告,碰到这种问题,可以写一个较小的数字判断几圈(会发现无法逼近正确答案)。修改为取平均数, 即(left + right)//2。

Note: 这几道题,你会发现,最后的return, 有left, 有right, 感觉return哪一个,最简单的方法,用一个小数尝试,看满足条件结束时,左指针还是右指针该被输出

class Solution(object):
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        left = 0
        right = x
        while left <= right:
            mid = (right + left)//2

            if mid * mid == x:
                return mid
            elif mid * mid < x:
                left = mid + 1
            else:
                right = mid - 1
                
        return right       
Leetcode 367

方法1:循环,不仔细考虑有超时的风险

超时代码

class Solution(object):
    def isPerfectSquare(self, num):
        """
        :type num: int
        :rtype: bool
        """
        for i in range(num+1):
            if i * i == num:
                return True
            else:
                continue
        return False

优化代码

简单分析,一个数的完全平方数肯定不会大过该数的一半的平方,画个函数图像辅助理解,一元线性函数的增幅会在临界点后远小于指数增长

class Solution(object):
    def isPerfectSquare(self, num):
        """
        :type num: int
        :rtype: bool
        """
        j = int(math.sqrt(num)) + 1
        for i in range(j):
            if i * i == num:
                return True
            else:
                continue
        return False

方法2:二分

class Solution(object):
    def isPerfectSquare(self, num):
        """
        :type num: int
        :rtype: bool
        """
        left = 0
        right = num
        while left <= right:
            mid = left + (right-left)//2
            if mid * mid == num:
                return True
            if mid * mid > num:
                right = mid - 1
            else:
                left = mid + 1
        return False

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值