文章目录
- 前言
- 一、枚举算法
- 两数之和
- 计数质数
- 统计平方和三元组的数目
- [2427. 公因子的数目](https://leetcode.cn/problems/number-of-common-factors/description/)
- [剑指 Offer 57 - II. 和为s的连续正数序列](https://leetcode.cn/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/description/)
- [2249. 统计圆内格点数目](https://leetcode.cn/problems/count-lattice-points-inside-a-circle/description/)
- 总结
前言
本文为Datawhale学习9月份Leetcode基础算法
学习日记
一、枚举算法
最简单的算法,又称穷举法,依次遍历所有可能出现的情况,效率应该是最低的,不过在数据较小的时候非常好用.
在写出枚举算法的基础之后可以进行代码的部分优化提升速度
两数之和
个人思路:
外层for循环依次遍历每一个元素,内层for循环依次遍历从外层+1开始到最后一个数,如果遇到和为目标则返回
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
total_len = len(nums)
for outer in range(total_len-1):
for inner in range(outer+1,total_len):
if nums[outer]+nums[inner] == target:
return [outer,inner]
计数质数
个人思路:
遍历从2开始到n的每个数,判断是不是质数,是的话就计数+1
class Solution:
def is_prime(self,x):
for i in range(2,x):
if x % i == 0:
return False
else:
return True
def countPrimes(self, n: int) -> int:
prime_count = 0
for i in range(2,n):
if self.is_prime(i):
prime_count += 1
return prime_count
不过leetcode告诉我超出时间限制,所以需要精简一下,众所周知,除了2以外所有的偶数都不可能是质数,所以先把偶数全部去掉,这样效率应该能提高一倍. 并且我们知道,一个数如果不是质数一定能分解成两个数的乘积,且总是成对出现,比如 16 一定可以分解成2 x 8 与 8 x 2,那么,我们只需要判断到根号下16 就可以知道是否是质数了.
第二版
class Solution:
def countPrimes(self, n: int) -> int:
def is_prime(x):
for i in range(2, int(x**0.5) + 1):
if x % i == 0:
return False
else:
return True
# 题目要求到n为止,不包括n
prime_count = 0
if n > 2:
prime_count += 1
for i in range(3, n, 2):
if is_prime(i):
prime_count += 1
return prime_count
还是超过用时了,现阶段就只能想到这里,后面也许还有更高效的算法.
统计平方和三元组的数目
个人思路:
人为规定a < b < c,然后只需要判断 a从下限到n-2为止所有的组合,最后由于ab可以交换位置所以结果乘以2
class Solution:
def countTriples(self, n: int) -> int:
count = 0
for i in range(1,n-1):
for j in range(i+1,n):
for k in range(j+1,n+1):
if i ** 2 + j ** 2 == k ** 2:
count += 1
return count * 2
三重循环太浪费时间了,根据题目给出的k**2 = i**2 + j**2
,把k用i和j来表示,去掉第三层循环
class Solution:
def countTriples(self, n: int) -> int:
count = 0
for i in range(1,n):
for j in range(i+1,n):
k_square = (i**2 + j **2) # 去掉第三重循环,大幅度提高效率
k = int(k_square ** 0.5)
if k <= n and k**2 == k_square:
count += 1
return count * 2
2427. 公因子的数目
个人思路:
分别求出两个数的因子然后取交集的数目就是公因子数
class Solution:
def commonFactors(self, a: int, b: int) -> int:
def find_factor(x):
factors = []
for i in range(1,x+1):
if x % i == 0:
factors.append(i)
return factors
a_factors = set(find_factor(a))
b_factors = set(find_factor(b))
return len(a_factors & b_factors)
又仔细一想,这样比较麻烦,不如直接遍历从1到 min(a,b)+1
,只要能同时被a,b整除,那就是公因子了
class Solution:
def commonFactors(self, a: int, b: int) -> int:
count = 0
for i in range(1,min(a,b)+1):
if a % i == 0 and b % i == 0:
count += 1
return count
剑指 Offer 57 - II. 和为s的连续正数序列
个人思路:
连续正整数就是等差数列,可以用等差数列求和公式s = (2*a1 + n-1)(n)/2
找到满足条件的a1 和k的组合,a1从1开始,n从2开始
class Solution:
def fileCombination(self, target: int) -> List[List[int]]:
# 连续正整数数列,就是等差数列,那么等差数列求和公式为(a1 + an)*n / 2
# an = a1 + (n-1) * k 这里连续正整数k = 1
# s = (a1 + a1 + n - 1)(n)/2
result = []
for a1 in range(1,target//2+1): # 至少两个数,所以只需要遍历到一半
for n in range(2,target):
if target == (a1 + a1 + n - 1)*(n)/2:
answer = [i for i in range(a1,a1+n)]
result.append(answer)
return result
结果就是超出时间限制了.QaQ
不如换一个思路,我们的目标是为了找和=target的,那大于target的时候就没戏了.所以进行如下改进
class Solution:
result = []
for a1 in range(1,target//2+1): # 至少两个数,所以只需要遍历到一半
start = a1
end = a1 + 1
total = sum(range(start,end+1))
while total <= target:
if total == target:
result.append([i for i in range(start,end+1)])
start += 1
elif total < target:
end += 1
total = sum(range(start,end+1))
return result
2249. 统计圆内格点数目
个人思路:
找到圆内左下到右上的点进行判断即可
class Solution:
def countLatticePoints(self, circles: List[List[int]]) -> int:
inner_set = set()
for circle in circles:
center_x, center_y, radius = circle
for x in range(center_x - radius, center_x + radius + 1):
for y in range(center_y - radius, center_y + radius + 1):
if (x - center_x) ** 2 + (y - center_y) ** 2 <= radius ** 2:
inner_set.add((x, y))
return len(inner_set)
总结
穷举法是最笨的办法,但是逻辑上是最简单的,也是最容易写出来的.