Datawhale Task3-查找1

1.二分查找

二分查找:根据中间元素与目标值的大小关系将数组不断进行切分成两半,因为一个长为n的数组最多可以二分logn次,所以二分查找的时间复杂度为o(logn)。

1.1例题-搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。你可以假设数组中无重复元素。

思路:

  1. 计算中间元素的值
  2. 比较中间元素和目标值的大小关系,若前者大,则搜索区间缩小到左半区间,若前者小,则缩小到右半区间。
  3. 重复1,2过程直到中间元素和目标值相等或者搜索区间只剩下一个元素,此时头指针等于尾指针。
  4. 讨论目标值不存在于数组中的情况,若最终指针指向的元素小于目标值,则返回指针索引+1;若最终指针指向的元素大于目标值,则返回指针索引。

代码如下:

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        left = 0  # 头指针
        right = len(nums) - 1  # 尾指针
        result = -1
        while left < right:
            # mid 指向中间位置的指针
            mid = left + (right - left) // 2  # 避免left+right溢出
            if nums[mid] > target:
                right = mid - 1
            elif nums[mid] < target:
                left = mid + 1
            else:
                result = mid
                break
        if result == -1:
            if nums[left] >= target:
                result = left
            else:
                result = left + 1
        return result

结果如下:
运行结果

2.考虑的基本数据结构

2.1第一类:查找有无–set

元素’a’是否存在,通常用set:集合,set只存储键,而不需要对应其相应的值。set中的键不允许重复
编写一个算法来判断一个数 n 是不是快乐数。

2.2例题- 快乐数

「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环
但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。

如果 n 是快乐数就返回 True ;不是,则返回 False 。

思路:通过set集合记录n的变化值,判断原始n是否出现第二次,第二次代表进入了无限循环,返回False;若n的变化过程出现1,返回True,是一个快乐数。

代码如下:

class Solution:
    def isHappy(self, n: int) -> bool:
        # 有无限循环,想到哈希set可以判断是否存在
        def get_next(n):# 求平方和获取下一个数
            total_sum = 0
            while n > 0:
                n, digit = divmod(n, 10)#获得商和余数
                total_sum += digit ** 2#平方和
            return total_sum
        seen = set()# 集合set
        while n != 1 and n not in seen:#n==1或者n进行无限循环  退出while循环
            seen.add(n)
            n = get_next(n)
        return n == 1# 判断已何种情况退出循环

结果如下:
快乐数

2.3例题- 同构字符串

给定两个字符串 s 和 t,判断它们是否是同构的。

如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。

所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。

思路:限制条件是两个字符不能映射到同一个字符上,若某对字符已经存在一个映射关系,则发现映射到相同字符的新映射关系直接返回False。因为每次只关注一个方向,保证双向映射都符合条件,调换字符串位置再执行一次遍历。

代码如下:

class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        def helper(s, t):
            seenDict = set()  # 记录映射的set
            seenKey = set()  # 记录映射对象的set
            for i in range(len(s)):
                # 两个字符不能映射到同一个字符
                if t[i] not in seenKey:  # 未出现映射到该字母的映射
                    # 添加新映射
                    seenDict.add((s[i], t[i]))
                    seenKey.add(t[i])
                    # 以往存在这个映射,跳出操作
                elif (s[i], t[i]) in seenDict:
                    continue
                else:  # 错误情况:两个字符映射到同一个字符
                    return False
            return True  # 安全遍历完,返回True
        return helper(s, t) and helper(t, s)  # 合并两次映射结果

结果如下:
同构字符串
类似的利用set进行查找的题还有349. 两个数组的交集
未完待续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值