基础算法一--枚举

枚举算法(Enumeration Algorithm):也称为穷举算法,指的是按照问题本身的性质,一一列举出该问题所有可能的解,并在逐一列举的过程中,将它们逐一与目标状态进行比较以得出满足问题要求的解。在列举的过程中,既不能遗漏也不能重复。

注:在枚举算法中,当问题规模很大时,效率一般比较低

例1:两数之和https://leetcode.cn/problems/two-sum/

class Ques1:
    def twoSum(self,nums,target):
        answer=[]
        for i in range(len(nums)-1):
            for j in range(i+1,len(nums)):
                if nums[i]+nums[j] == target:
                    answer=[i,j]
                    return answer

时间复杂度为:O(n**2)

例二:计算质数https://leetcode.cn/problems/count-primes/

class Solution(object):
    def isprime(self,x):
        if x<=1:
            return False # x<=1的情况单独判断,质数的范围是大于1
        for i in range(2, int(math.sqrt(x))+1):
            if x % i == 0:
                return False
        return True
        
    def countPrimes(self,n):
        count = 0
        for i in range(1,n):
            if self.isprime(i):
                count+=1
        return count

结果是超时,我们选择更有效率的方法:

对于一个合数,它一定有除了1和本身的质因子,使得它本身一定是这个质因子的倍数;所以我们找到一个质数时,可以筛掉它的倍数。

朴素筛法:

import math
class Ques:
    def naive_sieve(self,n):
        if n<2:
            return []
        is_prime = [True]*(n)
        is_prime[0] = is_prime[1]=False
        primes = []
        for i in range(2,n):
            if is_prime[i]:
                primes.append(i)
                # 把所以i的倍数标记为合数
                for j in range(i**2,n,i):  #步长为i
                    is_prime[j] = False
        return primes

埃氏筛:

class Solution(object):
    def countPrimes(self,n):
        if n<2:
            return 0
        is_prime = [True]*(n)  # 判断小于n的所有素数,不包括n本身
        is_prime[1]=False
        for i in range(2,int(math.sqrt(n))+1):
            if is_prime[i]:
                for j in range(i**2,n,i):
                    is_prime[j] = False
        primes = [i for i in range(1,n) if is_prime[i]] //开辟列表需要更多的时间,可以直接if判断
        return len(primes)

例三:公因子数目https://leetcode.cn/problems/number-of-common-factors/

class Solution(object):
    def commonFactors(self,a,b):
        count = 0
        for i in range(1,min(a,b)+1): # 直接用min()找出最小值
            if a % i == 0 and b % i == 0:
                count+=1
        return count

例四:和为s的连续正数序列https://leetcode.cn/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/

解法1:数学计算

class Solution(object):
    def fileCombination(self, target):
        i,j,res = 1,2,[]
        while i<j:
            j = (-1 + (1 + 4 * (2 * target + i * i - i)) ** 0.5) / 2
            if i<j and j == int(j):
                res.append(list(range(i,int(j)+1)))
            i+=1
        return res

该解法:

解法2:滑动窗口

class Solution(object):
    def fileCombination(self, target):
        i,j,s,end = 1,2,3,[]
        while i<j:
            if s == target:
                end.append(list(range(i,j+1)))
            if s>= target:
                s -= i
                i+=1
            else:
                j+=1
                s+=j
        return end

上面两张图中,第一张图的结果正确!!!【先削减s的值,再递增i的值】

例五:统计圆内格点数目https://leetcode.cn/problems/count-lattice-points-inside-a-circle/

class Solution(object):
    def countLatticePoints(self, circles):
        min_x, min_y, max_x, max_y = 200, 200, 0, 0
        for circle in circles:
            if min_x > circle[0] - circle[2]:
                min_x = circle[0] - circle[2]
            if min_y > circle[1] - circle[2]:
                min_y = circle[1] - circle[2]
            if max_x < circle[0] + circle[2]:
                max_x = circle[0] + circle[2]
            if max_y < circle[1] + circle[2]:
                max_y = circle[1] + circle[2]
        count = 0
        for x in range(min_x,max_x+1):
            for y in range(min_y,max_y+1):
                for x1,y1,r1 in circles:
                    if (x-x1)**2+(y1-y)**2 <= r1**2:
                        count+=1
                        break
        return count

例六:网络信号最好的坐标https://leetcode.cn/problems/coordinate-with-maximum-network-quality/

class Solution(object):
    def bestCoordinate(self, towers, radius):
        max_tuples = [0,0]
        val_max = 0
        max_x=max(t[0] for t in towers ) # t[0]代表towers每个元素(是一个列表)的第一个值
        max_y = max(t[1] for t in towers) # t[1]则是代表每个元素第二个值,以此类推
        for x in range(max_x+1):
            for y in range(max_y+1):
                val0 = 0
                for a,b,r in towers:
                    d = (x-a)**2+(y-b)**2
                    if radius**2 >= d:
                        val0 += int(r/(1+d**0.5))
                if val0 > val_max:
                    val_max = val0
                    max_tuples = [x,y]
        return max_tuples

例七:和为k的子数组https://leetcode.cn/problems/subarray-sum-equals-k/

求一个数组的连续子数组:

n = len(nums)
subnums = []
for i in range(n):
	for j in range(n):
		subnums.append(nums[i,j+1])

那么求解该题:

class Solution(object):
    def subarraySum(self, nums, k):
        count = 0
        length = len(nums)
        for i in range(length):
            sums = 0
            for j in range(i,length):
                sums +=nums[j]  # 
                if sums == k:
                    count+=1
        return count

💡

注:相比于:

for i in range(n):
	for j in range(i,n):
		if nums[i:j+1] == k:
			count += 1

但是依旧会超时:前缀和

前缀和:前缀和指一个数组的某下标之前的所有数组元素的和(包括自身)

通常会在前缀和首位放一个0,如:数组[1,2,3],前缀和:[0,1,3,6]

前缀和的作用:

如:

class Solution(object):
    def subarraySum(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        count = 0
        n = len(nums)
        **preSum = [0]
        tmp = 0
        for i in range(n):
            tmp+=nums[i]
            preSum.append(tmp) # 求前缀和
        for i in range(1,n+1):
            for j in range(i,n+1):
                if preSum[j]-preSum[i-1]==k:
                    count+=1
        return count

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值