查找算法

简单查找


查找表

考虑基本数据的结构:

  • 查找有无 – set
    • 查找元素’a’是否存在,通常用 set:集合
    • set 只存储键,而不需要对应其相应的值
    • set 中的键不允许重复
  • 查找对应关系(键值对应) – dict
    • 元素’a’出现了几次:dict:字典
    • dict中的键不允许重复,值可以重复
  • 改变映射关系 – map
    • 通过将原有序列的关系映射统一表示为其他

两个数组的交集

题目描述:

给定两个数组 nums,求两个数组的公共元素。

如nums1 = [1,2,2,1],nums2 = [2,2]
结果为[2]
结果中每个元素只能出现一次
出现的顺序可以是任意的

解题思路:

由于每个元素只出现一次,因此不需要关注每个元素出现的次数,故可以用 set 的数据结构。
把 nums1 和 nums2 的公共部分转换为 set 结构即可。

代码:

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        return set([i for i in nums1 if i in nums2])

也可以把 nums1 和 nums2 都转换为 set 然后对两个 set 求交集。

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        return set(nums1) & set(nums2)

两个数组的交集 II

题目描述:

给定两个数组nums,求两个数组的交集。

如nums1=[1,2,2,1],nums=[2,2]
结果为[2,2]
出现的顺序可以是任意的

解题思路:

因为元素出现的次数有用,因此应该选择 dict 结构,记录每个元素的同时要记录这个元素的频次。记录 num1 的字典,遍历 nums2,比较 nums1 的字典的 nums 的 key 是否大于零,从而进行判断。

代码:

class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        from collections import Counter
        nums1_dict = Counter(nums1)
        res = []
        for i in nums2:
            if nums1_dict[i] > 0:
                res.append(i)
                nums1_dict[i] -= 1
        return res

有效的字母异位词

题目描述:

给定两个字符串 s 和 t,编写一个函数来判断 t 是否是 s 的字母异位词。

示例1:
输入: s = "anagram", t = "nagaram"
输出: true

示例 2:
输入: s = "rat", t = "car"
输出: false

解题思路:

判断异位词即判断变换位置后的字符串和原来是否相同,因此不仅需要存储元素,还需要记录元素的个数。可以选择 dict 数据结构,将字符串 s 和 t 都用 dict 存储,而后直接比较两个 dict 是否相同。

代码:

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        from collections import Counter
        dict_s = Counter(s)
        dict_t = Counter(t)
        if dict_s == dict_t:
            return True
        else:
            return False

快乐数

题目描述:

编写一个算法来判断一个数是不是“快乐数”。

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

示例: 
输入: 19
输出: true
解释: 
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1

解题思路:

当 n 不等于 1 时进行循环,每次循环时,将其最后一位到第一位的数依次平方求和,比较求和是否为 1。

用 set 的数据结构,把每次求和的数追加进 set,当新一次求和的值存在于 set 中时,就停止循环并 return false.

代码:

class Solution:
    def isHappy(self, n: int) -> bool:
        already = set([n])
        while n!= 1:
            s = 0
            for i in str(n):
                s += int(i)**2
            n = s
            if n in already:
                return False
            else:
                already.add(n) 
        return True 

单词规律

问题描述:

给出一个模式 (pattern) 以及一个字符串,判断这个字符串是否符合模式。

示例1:
输入: pattern = "abba", 
str = "dog cat cat dog"
输出: true

示例 2:
输入:pattern = "abba", 
str = "dog cat cat fish"
输出: false

示例 3:
输入: pattern = "aaaa", str = "dog cat cat dog"
输出: false

示例 4:
输入: pattern = "abba", str = "dog dog dog dog"
输出: false

解题思路:

匹配模式既需要考虑键值对应的关系,也需要考虑单词出现的顺序,因此可以用 dict 结构。

代码:

class Solution:
    def wordPattern(self, pattern: str, str: str) -> bool:
        l = str.split()
        # 排除不一一对应以及长度不相等的情况
        if len(set(l)) != len(set(list(pattern))) or len(l) != len(list(pattern)):
            return False
        dic = {}
        count = 0
        for i in pattern:
            if i not in dic:
                dic[i] = l[count]
            else:
                if dic[i] != l[count]:
                    return False
            count += 1
        return True

还可以将原来的 dict 通过 map 映射为相同的 key,再比较相同 key 的 dict 是否相同。

class Solution:
    def wordPattern(self, pattern: str, str: str) -> bool:
        l = str.split()
        return list(map(pattern.index,pattern)) == list(map(l.index,l))
        

同构字符串

题目描述:

  • 给定两个字符串 s 和 t,判断它们是否是同构的。
  • 如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。
  • 所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。
示例 1:
输入: s = "egg", t = "add"
输出: true

示例 2:
输入: s = "foo", t = "bar"
输出: false

示例 3:
输入: s = "paper", t = "title"
输出: true

解题思路:

与上题类似。

代码:

class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        return list(map(s.index,s)) == list(map(t.index,t))

根据字符出现频率排序

题目描述:

给定一个字符串,请将字符串里的字符按照出现的频率降序排列。

示例 1:
输入:
"tree"
输出:
"eert"

示例 2:
输入:
"cccaaa"
输出:
"cccaaa"

示例 3:
输入:
"Aabb"
输出:
"bbAa"

解题思路:

使用字典统计频率,对字典的 value 进行排序,最终根据 key 的字符串乘上 value 次数,组合在一起输出。

代码:

class Solution:
    def frequencySort(self, s: str) -> str:
        from collections import Counter
        s_dict = Counter(s)
        s = sorted(s_dict.items(), key = lambda x:x[1], reverse = True)
        out = ''
        for k,v in s:
            out += k*v
        return out

有序数组中的单一元素

题目描述:

给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数。

示例 1:

输入: [1,1,2,3,3,4,4,8,8]
输出: 2
示例 2:

输入: [3,3,7,7,10,11,11]
输出: 10

解题思路:

因为只有一个元素出现了一次,其他元素都出现了两次,因此可以遍历列表中的所有元素,进行按位异或(每一位相同得 0,不同得 1)操作,最终的结果即为只出现了一次的元素。

代码:

class Solution:
    def singleNonDuplicate(self, nums: List[int]) -> int:
        res = 0
        for i in nums:
            res = res^i 
        return res 

搜索插入位置

题目描述:

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

你可以假设数组中无重复元素。

示例 1:
输入: [1,3,5,6], 5
输出: 2

示例 2:
输入: [1,3,5,6], 2
输出: 1

示例 3:
输入: [1,3,5,6], 7
输出: 4

示例 4:
输入: [1,3,5,6], 0
输出: 0

解题思路:

遍历 nums,如果 target 小于或等于数组中的某个元素,则把 target 插入到该元素所在的位置。

代码:

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        for i in range(0,len(nums)):
            if target <= nums[i]:
                return i
        return len(nums) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值