leetcode刷题 task3(9-代码敲不队-QQ) 8.24

  1. 搜索插入位置
    给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。你可以假设数组中无重复元素。
    二分查找法:
class Solution:
    def search(self,x,nums:list):
     low,high=0,len(nums)-1
     while low<=high:
        mid = (low+high)//2
        if x > nums[mid]:
            low=mid+1
        elif x < nums[mid]:
            high=mid-1
        else:
            return mid
     return low
a=Solution()
print(a.search(8,[2,3,5,6]))
  1. 快乐数
    编写一个算法来判断一个数 n 是不是快乐数。

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

如果 n 是快乐数就返回 True ;不是,则返回 False 。
集合判定法:

class Solution(object):
    def isHappy(self, n):
      b=set() #集合用于记录每次的n,看n是否重复出现
      while n!=1:
          if n in b: #如果n出现多次则会无限循环,不是快乐数
              return 'false'
          b.add(n)
          s=0
          while n//10!=0:
              s += (n%10)**2
              n = n//10
          s+=n**2
          n=s
      else:
          return 'true'
a=Solution()
print(a.isHappy(39))
#19时为true

注,官方解释的寻找每位平方之和更清晰明了,将这部分作为一个函数,两部分分离:

sum=0
while x>0:
  cur=x%10
  sum+=cur*cur
  x=x//10
return sum

快慢指针法:
通过反复调用 getNext(n) 得到的链是一个隐式的链表。隐式意味着我们没有实际的链表节点和指针,但数据仍然形成链表结构。起始数字是链表的头 “节点”,链中的所有其他数字都是节点。next 指针是通过调用 getNext(n) 函数获得。
意识到我们实际有个链表,那么这个问题就可以转换为检测一个链表是否有环。因此我们在这里可以使用弗洛伊德循环查找算法。这个算法是两个奔跑选手,一个跑的快,一个跑得慢。在龟兔赛跑的寓言中,跑的快的称为 “乌龟”,跑得快的称为 “兔子”。
不管乌龟和兔子在循环中从哪里开始,它们最终都会相遇。这是因为兔子每走一步就向乌龟靠近一个节点(在它们的移动方向上)。
我们不是只跟踪链表中的一个值,而是跟踪两个值,称为快跑者和慢跑者。在算法的每一步中,慢速在链表中前进 1 个节点,快跑者前进 2 个节点(对 getNext(n) 函数的嵌套调用)。
如果 n 是一个快乐数,即没有循环,那么快跑者最终会比慢跑者先到达数字 1。
如果 n 不是一个快乐的数字,那么最终快跑者和慢跑者将在同一个数字上相遇。

class Solution:
    def isHappy(self, n: int) -> bool:
        def get_next(number):
            total_sum = 0
            while number > 0:
                number, digit = divmod(number, 10)
                total_sum += digit ** 2
            return total_sum

        slow_runner = n
        fast_runner = get_next(n)
        while fast_runner != 1 and slow_runner != fast_runner:
            slow_runner = get_next(slow_runner)
            fast_runner = get_next(get_next(fast_runner))
        return fast_runner == 1
a=Solution()
print(a.isHappy(19))
  1. 同构字符串
    给定两个字符串 s 和 t,判断它们是否是同构的。
    如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。
    所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。
    解法一:
    最开始我的想法是将两个字符串分别映射成两个列表,以不同数字代表不同的字母,解法如下:
class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
       dica = {
    
    }
       lisa = []
       seq=0
       for i in range(len(s)):
           if s[i] in dica:
               lisa.append(dica[s[i]])
           else:
               dica[s[i]]=seq
               lisa.append(seq)
               seq += 1
       dicb = {
    
    }
       lisb = []
       
       seq = 0
       for i in range(len(t)):
           if t[i] in dicb:
               lisb.append(dicb[t[i]])
           else:
               dicb[t[i]] = seq
               lisb.append(seq)
               seq += 1
       if lisa == lisb :
           return True
       else:
           return False
a=Solution()
print(a.isIsomorphic('abegg','ddadd'))


#[0, 1, 2, 3, 3]
#[0, 0, 1, 0, 0]
#False

此方法代码行数较多,可通过拆解成两个方法,两个字符串分别调用一次映射函数,比较结果,但不明显。
通过让一个字符串直接映射另一个字符串可简化成只循环一次:
解法二:

class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
       dic = {
    
    }
       lis = []
       for i in range(len(s)):
           if s[i] not in dic:
               if t[i] in dic.values(): #防止s中两个不同的字母映射到t中的同一个字母
                   return False
               dic[s[i]] = t[i]
           else:
               if dic[s[i]]!=t[i]:
                   return False
       return True
a=Solution()
print(a.isIsomorphic('add','egg'))

还有一种更简单的解法:
解法三:
Python index() 方法检测字符串中是否包含子字符串 str ,如果指定 beg(开始) 和 end(结束) 范围,则检查是否包含在指定范围内,该方法与 python find()方法一样,只不过如果str不在 string中会报一个异常。
返回值:如果包含子字符串返回开始的索引值,否则抛出异常。
根据这个特性,两个字符串若是同构,得到的索引就相等,得解法:

class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        for i in range(len(s))if s.index(s[i]) != t.index(t[i]):
                return False
        return True
a=Solution()
print(a.isIsomorphic('egg','add'))
  1. 有效的字母异位词
    给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
    你可以假设字符串只包含小写字母。
    解法一:
    为每个字符串建立一个字典,字典键值分别是字符串中的字符及其出现的次数,两个字典相同则代表两个字符串是字母异位词
class Solution:
    def judge(self,x):
        dic = {
    
    }
        for i in range(len(x)):
            if x[i] not in dic :
                dic[x[i]]=1
            else:
                dic[x[i]]+=1
        return dic
    def isIsomorphic(self, s: str, t: str):
        if self.judge(s)==self.judge(t):
            return 'true'
        else:
            return 'false'


a=Solution()
print(a.isIsomorphic('addcas','ascdda'))

方法二:
将字符排序后比较结果:

class Solution:
   def isIsomorphic(self, s: str, t: str):
        if sorted(s)==sorted(t):
            return 'true'
        else:
            return 'false'
a=Solution()
print(a.isIsomorphic('addcad','ascdda'))

方法三:使用集合,然后逐个字符计算出现次数进行比较

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
a=Solution()
print(a.isAnagram('addcas','ascdda'))

方法四:使用python内置模块collections:

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        return collections.Counter(s) == collections.Counter(t)
a=Solution()
print(a.isAnagram('addcad','ascdda'))
  1. 单词规律
    给定一种规律 pattern 和一个字符串 str ,判断 str 是否遵循相同的规律。
    这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非空单词之间存在着双向连接的对应规律。
    示例1:
    输入: pattern = “abba”, str = “dog cat cat dog”
    输出: true
    示例 2:
    输入:pattern = “abba”, str = “dog cat cat fish”
    输出: false

解法一:
此题类似前边的同构字符串,可以将str用split函数拆分为一个列表,建立pattern中字符与列表中字符串的映射即可:

class Solution:
    def wordPattern(self, pattern: str, str: str) -> bool:
        dic={
    
    }
        s=str.split(' ')
        if len(s)!=len(pattern):
            return False
        for i in range(len(pattern)):
            if pattern[i] not in dic:
                if s[i] in dic.values():
                    return False
                else:
                    dic[pattern[i]] = s[i]
            else:
                if dic[pattern[i]] != s[i]:
                    return False
        return True
a=Solution()
print(a.wordPattern('abba','dog cat cat dog'))

方法二:
也可使用index索引:

class Solution:
    def wordPattern(self, pattern: str, str: str) -> bool:
        res = str.split()
        return list(map(pattern.index, pattern)) == list(map(res.index, res))
a=Solution()
print(a.wordPattern('abba','dog cat cat dog'))
  1. 两个数组的交集
    给定两个数组,编写一个函数来计算它们的交集。
    示例 1:
    输入:nums1 = [1,2,2,1], nums2 = [2,2]
    输出:[2]
    示例 2:
    输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
    输出:[9,4]

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

方法一:
首先可以使用集合求交集的操作,set1&set2

class Solution(object):
    def intersection(self, nums1:list, nums2:list):
        a=set(nums1)
        b=set(nums2)
        return list(a&b)
a=Solution()
print(a.intersection([9,4,9,8],[4,8]))

解法二:
转成集合后遍历:

class Solution(object):
    def intersection(self, nums1:list, nums2:list):
        a=set(nums1)
        b=set(nums2)
        c=[]
        for i in a:
            if i in b:
                c.append(i)
        return c
a=Solution()
print(a.intersection([9,4,9,8],[4,8]))
  1. 两个数组的交集 II
    给定两个数组,编写一个函数来计算它们的交集。

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

说明:
输出结果中每个元素出现的次数,应与元素在两个数组中出现次数的最小值一致。
我们可以不考虑输出结果的顺序。
进阶:
如果给定的数组已经排好序呢?你将如何优化你的算法?
如果 nums1 的大小比 nums2 小很多,哪种方法更优?
如果 nums2 的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

解法一:
遍历查找相交的元素,在查找该元素在两个数组中出现的最小次数:

class Solution(object):
    def intersection(self, nums1:list, nums2:list):
        c = []  #c用于记录结果
        ever=[] #ever 用于防止值相同的数重复进行下一步循环
        for i in nums1:
            if i in nums2 and i not in ever:
                n=min(nums1.count(i),nums2.count(i)) #两个数组中都有的值,计算其在两个数组中出现的最小次数
                c.extend([i]*n)
                ever.append(i)
        return c
a=Solution()
print(a.intersection([3,3,8,8,8,8],[3,3,3,3,8,8]))

方法二:
选择较短的一个数组,为其建立一个字典(数字:数字出现的次数),
各个数字出现的次数统计完毕后,遍历另一个数组,若其中的数字在字典中且,出现的次数大于零(如【3,3,8,8,8,8】和【8,8,3,3,3,3】,防止结果变成【3,3,3,3,8,8,8,8】),则将该数字加入结果集中,最后返回结果集即可

class Solution(object):
    def intersection(self, nums1:list, nums2:list):
       c={
    
    }
       result=[]
       if len(nums2)<len(nums1):
           return self.intersection(nums2,nums1)
       for i in nums1:
           if i in c:
               c[i]+=1
           else:
               c[i]=1
       for i in nums2:
           if i in c and c[i]>0:
               result.append(i)
               c[i]-=1
       return result

a=Solution()
print(a.intersection([3,3,8,8,8,8],[3,3,3,3,8,8]))

方法三:排序法
将两个数组排序后方便比较

class Solution(object):
    def intersection(self, nums1:list, nums2:list):
       nums1.sort()
       nums2.sort()
       i=j=0
       result=[]
       while i <len(nums1) and j <len(nums2):
           if nums1[i]==nums2[j]:
               result.append(nums1[i])
               i+=1
               j+=1
           elif nums1[i]>nums2[j]:
               j+=1
           else:
               i+=1
       return result
a=Solution()
print(a.intersection([3,4,8,8,8,8],[3,3,3,3,7,8]))
  1. 分割数组的最大值
    给定一个非负整数数组和一个整数 m,你需要将这个数组分成 m 个非空的连续子数组。设计一个算法使得这 m 个子数组各自和的最大值最小。
    注意:
    数组长度 n 满足以下条件:
    1 ≤ n ≤ 1000
    1 ≤ m ≤ min(50, n)
    示例:
    输入:
    nums = [7,2,5,10,8]
    m = 2
    输出:
    18
    解释:
    一共有四种方法将nums分割为2个子数组。
    其中最好的方式是将其分为[7,2,5] 和 [10,8],
    因为此时这两个子数组各自的和的最大值为18,在所有情况中最小。

方法一:

class Solution:
    def splitArray(self, nums: list, m: int) -> int:
        n = len(nums)
        f = [[10 ** 18] * (m + 1) for _ in range(n + 1)]
        sub = [0]
        for elem in nums:
            sub.append(sub[-1] + elem)
        f[0][0] = 0
        for i in range(1, n + 1):
            for j in range(1, min(i, m) + 1):
                for k in range(i):
                    f[i][j] = min(f[i][j], max(f[k][j - 1], sub[i] - sub[k]))
        return f[n][m]
a=Solution()
print(a.splitArray([7,2,5,10,8],3))
  1. 根据字符出现频率排序
    给定一个字符串,请将字符串里的字符按照出现的频率降序排列。
    示例 1:
    输入:
    “tree”
    输出:
    “eert”
    解释:
    'e’出现两次,'r’和’t’都只出现一次。
    因此’e’必须出现在’r’和’t’之前。此外,"eetr"也是一个有效的答案。
    示例 2:
    输入:
    “cccaaa”
    输出:
    “cccaaa”
    解释:
    'c’和’a’都出现三次。此外,"aaaccc"也是有效的答案。
    注意"cacaca"是不正确的,因为相同的字母必须放在一起。
    示例 3:
    输入:
    “Aabb”
    输出:
    “bbAa”
    解释:
    此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。
    注意’A’和’a’被认为是两种不同的字符。
    方法一:大根堆
import collections
import heapq
class Solution:
        def frequencySort(self, s: str) -> str:
            # 大顶堆
            countFrequency = collections.defaultdict(int)
            for i in s:
                countFrequency[i] += 1
            lst = []
            heapq.heapify(lst)
            for i in countFrequency:
                for j in range(countFrequency[i]):
                    heapq.heappush(lst, (-countFrequency[i], i))

            return ''.join([heapq.heappop(lst)[1] for _ in range(len(s))])

a=Solution()
print(a.frequencySort('tree'))
  1. 有序数组中的单一元素
    给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数。
    示例 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)空间复杂度中运行。

方法一:

class Solution:
    def singleNonDuplicate(self, nums: list) -> int:
        if len(nums) == 1:
            return nums[0]
        left = 0
        right = len(nums)-1
        while left <= right:
            mid = (left + right) // 2
            if mid % 2 == 0 and mid + 1 < len(nums):  # mid是偶数(nums[mid]前面有偶数个元素)
                if nums[mid] == nums[mid+1]:   # mid前面没有单一元素
                    left = mid + 1
                else:   # mid前面有单一元素
                    right = mid - 1
            elif mid % 2 != 0 and mid + 1 < len(nums):   # mid是奇数(nums[mid]前面有奇数个元素)
                if nums[mid] == nums[mid+1]:  # mid前面有单一元素
                    right = mid - 1
                else:   # mid前面没有单一元素
                    left = mid + 1
            else:
                return nums[mid]
        return nums[left]
a=Solution()
print(a.singleNonDuplicate( [1,1,2,3,3,4,4,8,8]))

猜你喜欢

转载自blog.csdn.net/m0_45672993/article/details/108173961