Leetcode学习--查找(1)(8.23-8.24)

查找表

一、考虑的基本数据结构

1、第一类: 查找有无–set

元素’a’是否存在,通常用set:集合

set只存储键,而不需要对应其相应的值。

set中的键不允许重复

2、第二类: 查找对应关系(键值对应)–dict

元素’a’出现了几次:dict–>字典

dict中的键不允许重复

3、第三类: 改变映射关系–map

通过将原有序列的关系映射统一表示为其他

二、Leetcode刷题练习

1、搜索插入位置

1)、描述

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

2)、示例
示例 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
3)、思想

本题可以采用二分法的思想,设置三个指针分别为左边界left,右边界right,中间mid。查找时,先比较mid,若大于mid则查找做右边,小于mid则查找左边。

4)、代码
class Solution:
    def searchInsert(self, nums: list[int], target: int) -> int:
        #左边界下标为0
        left = 0
        #有边界下标为数组长度
        right = len(nums)
        while left < right:
            mid = (left + right) // 2
            #查找右边
            if nums[mid] < target:
                left = mid + 1
            #查找左边
            elif nums[mid] > target:
                right = mid
            #与mid相等
            elif nums[mid] == target:
                right = mid
        return left

5)、来源

Leetcode(力扣):https://leetcode-cn.com/problems/search-insert-position/

2、快乐数

1)、描述

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

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

2)、示例
示例:

输入:19
输出:true
解释:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1
3)、思想

算法分为两部分:

给一个数字 nn,它的下一个数字是什么?
按照一系列的数字来判断我们是否进入了一个循环。
1.第 1 部分我们按照题目的要求做数位分离,求平方和。
2.第 2 部分可以使用 HashSet 完成。每次生成链中的下一个数字时,我们都会检查它是否已经在 HashSet 中。

如果它不在 HashSet 中,我们应该添加它。
如果它在 HashSet 中,这意味着我们处于一个循环中,因此应该返回 false。
我们使用 HashSet 而不是向量、列表或数组的原因是因为我们反复检查其中是否存在某数字。检查数字是否在哈希集中需要 O(1)O(1) 的时间,而对于其他数据结构,则需要 O(n)O(n) 的时间。选择正确的数据结构是解决这些问题的关键部分。

4)、代码
class Solution:
    def isHappy(self, n: int) -> bool:
        def get_next(n):
            total_sum = 0
            while n > 0:
                n, digit = divmod(n, 10)
                total_sum += digit ** 2
            return total_sum
        seen = set()
        while n != 1 and n not in seen:
            seen.add(n)
            n = get_next(n)
        return n == 1
5)、来源

Leetcode(力扣):https://leetcode-cn.com/problems/happy-number/

3、同构字符串

1)、描述

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

2)、示例
示例 1:
输入: s = "egg", t = "add"
输出: true

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

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

说明:
你可以假设 s 和 t 具有相同的长度。
3)、思想

分别遍历s和t,用字典和列表保存每个字符的编号。(编号从1开始,同字符的编号相同)返回s和t的编号列表是否相同。

4)、代码
class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        dct = {}
        for i in range(len(s)):
            if s[i] not in dct:
                if t[i] in dct.values():
                    return False
                dct[s[i]] = t[i]
            else:
                if dct[s[i]] != t[i]:
                    return False
        return True
5)、来源

Leetcode(力扣):https://leetcode-cn.com/problems/isomorphic-strings/

4、有效的字母异位词

1)、描述

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

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

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

说明:
你可以假设字符串只包含小写字母。
3)、思想

把其中一项用集合set(无重复性质)遍历每个字母的个数,如果每个都相等则为True,只要出现一次不等直接False结束。

4)、代码
class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        if len(s) != len(t):
            return False
        set1 = set(s)
        for i in set1:
            if s.count(i) != t.count(i):
                return False
        return True
5)、来源

Leetcode(力扣):https://leetcode-cn.com/problems/valid-anagram/

5、单词规律

1)、描述

给定一种规律 pattern 和一个字符串 str ,判断 str 是否遵循相同的规律。
这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非空单词之间存在着双向连接的对应规律。

2)、示例
示例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

说明:
你可以假设 pattern 只包含小写字母, str 包含了由单个空格分隔的小写字母。   
3)、思想

本体可以按照205题同构字符串的方法去想,不再赘述

4)、代码
class Solution:
    def wordPattern(self, pattern: str, str: str) -> bool:
        t = str.split()
        if len(pattern) != len(t):
            return False
        dct = {}
        for i in range(len(pattern)):
            if pattern[i] not in dct:
                if t[i] in dct.values():
                    return False
                dct[pattern[i]] = t[i]
            else:
                if dct[pattern[i]] != t[i]:
                    return False
        return True

5)、来源

Leetcode(力扣):https://leetcode-cn.com/problems/word-pattern/

6、 两个数组的交集

1)、描述

给定两个数组,编写一个函数来计算它们的交集。

2)、示例
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]

说明:
输出结果中的每个元素一定是唯一的。
我们可以不考虑输出结果的顺序。
3)、思想

遍历其中一个数组,判断此数组中的元素:
1.是否在另一个数组里;
2.是否已经在交集中。
同时满足条件后,添加到交集中。

4)、代码
class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        array = []
        for m in nums1:
            if m in nums2 and m not in array:
                array.append(m)
        return array
5)、来源

Leetcode(力扣):https://leetcode-cn.com/problems/intersection-of-two-arrays/

7、两个数组的交集 II

1)、描述

给定两个数组,编写一个函数来计算它们的交集

2)、示例
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]

示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]

说明:
输出结果中每个元素出现的次数,应与元素在两个数组中出现次数的最小值一致。
我们可以不考虑输出结果的顺序。

3)、思想

如果两个数组是有序的,则可以便捷地计算两个数组的交集。首先对两个数组进行排序,然后使用两个指针遍历两个数组。
初始时,两个指针分别指向两个数组的头部。每次比较两个指针指向的两个数组中的数字,如果两个数字不相等,则将指向较小数字的指针右移一位,如果两个数字相等,将该数字添加到答案,并将两个指针都右移一位。当至少有一个指针超出数组范围时,遍历结束。

4)、代码
class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        nums1.sort()
        nums2.sort()

        length1, length2 = len(nums1), len(nums2)
        intersection = list()
        index1 = index2 = 0
        while index1 < length1 and index2 < length2:
            if nums1[index1] < nums2[index2]:
                index1 += 1
            elif nums1[index1] > nums2[index2]:
                index2 += 1
            else:
                intersection.append(nums1[index1])
                index1 += 1
                index2 += 1

        return intersection
5)、来源

Leetcode(力扣):https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/

8、分割数组的最大值

1)、描述

给定一个非负整数数组和一个整数 m,你需要将这个数组分成 m 个非空的连续子数组。设计一个算法使得这 m 个子数组各自和的最大值最小。

注意:
数组长度 n 满足以下条件:
1 ≤ n ≤ 1000
1 ≤ m ≤ min(50, n)

2)、示例
输入:
nums = [7,2,5,10,8]
m = 2
输出:
18

解释:
一共有四种方法将nums分割为2个子数组。
其中最好的方式是将其分为[7,2,5][10,8],
因为此时这两个子数组各自的和的最大值为18,在所有情况中最小。
3)、思想

本题可以使用贪心算法,贪心地模拟分割的过程,从前到后遍历数组,用 sum 表示当前分割子数组的和,cnt 表示已经分割出的子数组的数量(包括当前子数组),那么每当 sum 加上当前值超过了 x,我们就把当前取的值作为新的一段分割子数组的开头,并将 cnt 加 1。遍历结束后验证是否 cnt 不超过 m。

4)、代码
class Solution:
    def splitArray(self, nums: List[int], m: int) -> int:
        def check(x: int) -> bool:
            total, cnt = 0, 1
            for num in nums:
                if total + num > x:
                    cnt += 1
                    total = num
                else:
                    total += num
            return cnt <= m
        left = max(nums)
        right = sum(nums)
        while left < right:
            mid = (left + right) // 2
            if check(mid):
                right = mid
            else:
                left = mid + 1
        return left

5)、来源

Leetcode(力扣):https://leetcode-cn.com/problems/split-array-largest-sum/

9、根据字符出现频率排序

1)、描述

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

2)、示例
示例 1:
输入:
"tree"
输出:
"eert"
解释:
'e'出现两次,'r''t'都只出现一次。
因此'e'必须出现在'r''t'之前。此外,"eetr"也是一个有效的答案。

示例 2:
输入:
"cccaaa"
输出:
"cccaaa"
解释:
'c''a'都出现三次。此外,"aaaccc"也是有效的答案。
注意"cacaca"是不正确的,因为相同的字母必须放在一起。

示例 3:
输入:
"Aabb"
输出:
"bbAa"
解释:
此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。
注意'A''a'被认为是两种不同的字符。
3)、思想

本题可以使用python内置的counter解决

简单介绍一下 Counter。
1.它是一个用来统计出现次数的类,在 collections 包里。
2.Counter(s) 就可以返回一个类似字典的结构,键是s中的项,值是这个项出现的次数。
3.对于字符串,就是每个字符和它出现的次数。
4.Counter类有一个函数,叫most_common(int n),可以返回最常出现的几项,如果不加参数,就全部返回,相当于按照出现次数从大到小输出。
输出的格式形如 [('s',4),('a',3)]。
即字符s出现4次,a出现3次。
4)、代码
from collections import Counter

class Solution:
    def frequencySort(self, s: str) -> str:
        return ''.join(i * j for i,j in Counter(s).most_common())
5)、来源

Leetcode(力扣):https://leetcode-cn.com/problems/sort-characters-by-frequency/

10、有序数组中的单一元素

1)、描述

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

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

示例 2:
输入: [3,3,7,7,10,11,11]
输出: 10

注意: 您的方案应该在 O(log n)时间复杂度和 O(1)空间复杂度中运行。
3)、思想

只对偶数进行搜索:
1.奇数长度的数组首尾元素索引都为偶数,因此我们可以将 lo 和 hi 设置为数组首尾。
2.我们需要确保 mid 是偶数,如果为奇数,则将其减 1。
3.然后,我们检查 mid 的元素是否与其后面的索引相同。
4.如果相同,则我们知道 mid 不是单个元素。且单个元素在 mid 之后。则我们将 lo 设置为 mid + 2。
5.如果不是,则我们知道单个元素位于 mid,或者在 mid 之前。我们将 hi 设置为 mid。
6.一旦 lo == hi,则当前搜索空间为 1 个元素,那么该元素为单个元素,我们将返回它。

4)、代码
class Solution:
    def singleNonDuplicate(self, nums: List[int]) -> int:
        lo = 0
        hi = len(nums) - 1
        while lo < hi:
            mid = lo + (hi - lo) // 2
            if mid % 2 == 1:
                mid -= 1
            if nums[mid] == nums[mid + 1]:
                lo = mid + 2
            else:
                hi = mid
        return nums[lo]
5)、来源

Leetcode(力扣):https://leetcode-cn.com/problems/single-element-in-a-sorted-array/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeetCode-Editor是一种在线编码工具,它提供了一个用户友好的界面编写和运行代码。在使用LeetCode-Editor时,有时候会出现乱码的问题。 乱码的原因可能是由于编码格式不兼容或者编码错误导致的。在这种情况下,我们可以尝试以下几种解决方法: 1. 检查文件编码格式:首先,我们可以检查所编辑的文件的编码格式。通常来说,常用的编码格式有UTF-8和ASCII等。我们可以将编码格式更改为正确的格式。在LeetCode-Editor中,可以通过界面设置或编辑器设置来更改编码格式。 2. 使用正确的字符集:如果乱码是由于使用了不同的字符集导致的,我们可以尝试更改使用正确的字符集。常见的字符集如Unicode或者UTF-8等。在LeetCode-Editor中,可以在编辑器中选择正确的字符集。 3. 使用合适的编辑器:有时候,乱码问题可能与LeetCode-Editor自身相关。我们可以尝试使用其他编码工具,如Text Editor、Sublime Text或者IDE,看是否能够解决乱码问题。 4. 查找特殊字符:如果乱码问题只出现在某些特殊字符上,我们可以尝试找到并替换这些字符。通过仔细检查代码,我们可以找到导致乱码的特定字符,并进行修正或替换。 总之,解决LeetCode-Editor乱码问题的方法有很多。根据具体情况,我们可以尝试更改文件编码格式、使用正确的字符集、更换编辑器或者查找并替换特殊字符等方法来解决这个问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值