• 献芹奏曝Python面试题算法数组篇


         上一篇:献芹奏曝-Python面试题 

          开篇的话:本文目的是收集和归纳力扣上的算法题,希望用python语言,竭我所能做到思路最清奇、代码最简洁、方法最广泛、性能最高效,了解常见题目,找到最利于记忆的答案,更加从容的应对面试。希望广思集益,共同进步。

    数组篇

    1. 26. 删除有序数组中的重复项(难度系数✯)

      class Solution:
          def removeDuplicates(self, nums: List[int]) -> int:
              current_item = None
              for index,item in enumerate(nums[:]):
                  if current_item == item:
                      nums.remove(item)
                  current_item = item
              return len(nums)
      方法一

      运行结果:1:耗时超过13%。2:内存超过62% 

      知识点/技巧: 数组有序,当前元素和下一个比较,相同就 remove

      class Solution:
          def removeDuplicates(self, nums: List[int]) -> int:
              for i in range(len(nums) - 1, 0, -1):
                  if nums[i] == nums[i - 1]:
                      del nums[i]
              return len(nums)
      方法二、降序删除

      运行结果:1:耗时超过47%。2:内存超过17% 

      知识点/技巧: 数组有序,倒叙循环,当前元素和前一个比较,相同就 del

    2. 122. 买卖股票的最佳时机 II(难度系数✯)

      class Solution:
          def maxProfit(self, prices: List[int]) -> int:
              # 一言以蔽之,如果明天比今天股价高,就买
              is_have = False # 当前是否拥有股票
              profit = 0 # 当前利润
              if len(prices)<2:
                  return profit
              for i in range(0,len(prices)):
                  if is_have:
                          # 如果手上还有股票,就抛
                          profit += prices[i] - prices[i-1]
                          is_have = False
                  if i+1<len(prices):
                      if prices[i+1]>prices[i]:
                          # 如果明天比今天股价高,就买。
                          is_have = True
      
              return profit
      方法一

      运行结果:1:耗时超过80%。2:内存超过33% 。3:思路奇特

      知识点/技巧: 一言以蔽之,手上有股票就卖;明天比今天股价高,就买。

    3. 189. 轮转数组(难度系数✯)

      class Solution:
          def rotate(self, nums: List[int], k: int) -> None:
              """
              Do not return anything, modify nums in-place instead.
              """
              if nums:
                  if nums:
                      k = k%len(nums)
                  right = nums[:-k:]
                  left = nums[-k::]
                  nums.clear()
                  nums.extend(left)
                  nums.extend(right)
      方法一

      运行结果:1:耗时超过92%。2:内存超过18%

      知识点/技巧: 先切片,再拼接 

      import copy
      from typing import List
      
      
      class Solution:
          def rotate(self, nums: List[int], k: int) -> None:
              """
              Do not return anything, modify nums in-place instead.
              """
              if nums:
                  re_time = k % len(nums)
                  len_nums = len(nums)
                  if re_time > len_nums / 2:
                      re_time = len_nums - re_time
                      # 删除前面的元素往后面添加
                      for i in range(re_time):
                          nums.append(nums.pop(0))
                  else:
                      # 删除后面的元素往前面添加
                      for i in range(re_time):
                          nums.insert(0, nums.pop(-1))
      一次失败的尝试

      运行结果:直接超时

      经验教训: 列表增删操作非常耗时

    4. 217. 存在重复元素(难度系数✯)

      class Solution:
          def containsDuplicate(self, nums: List[int]) -> bool:
              return len(set(nums))!=len(nums)
      方法一

      运行结果:1:耗时超过40%。2:内存超过33%。3:代码简洁

      知识点/技巧: 利用set去重,比较长度

      class Solution:
          def containsDuplicate(self, nums: List[int]) -> bool:
              dict_resut = {}
              for item in nums:
                  if dict_resut.get(item):
                      return True
                  else:
                      dict_resut[item]=1
              return False
      方法二

      运行结果:1:耗时超过76%。2:内存超过30%。

      知识点/技巧: 利用字典记录字母出现次数

    5. 1. 两数之和(难度系数✯)

      class Solution:
          def twoSum(self, nums: List[int], target: int) -> List[int]:
              for index,item in enumerate(nums):
                  for i in range(index+1,len(nums)):
                      if item + nums[i] == target:
                          return [index,i]
      方法一

      运行结果:1:耗时超过36%。2:内存超过68%。3:虽慢但对

      知识点/技巧: 遍历方法

      class Solution:
          def twoSum(self, nums: List[int], target: int) -> List[int]:
              for index,item in enumerate(nums):
                  result = target - item
                  for i in range(index+1,len(nums)):
                      if nums[i] == result:
                          return [index,i]
      方法二

      运行结果:1:耗时超过36%。2:内存超过65%。3:虽然没有减少时间复杂度,但是减少了求和次数

      知识点/技巧:在方法一的基础上减少了求和运算,但是时间复杂度仍是O(n*n)

      class Solution:
          def twoSum(self, nums: List[int], target: int) -> List[int]:
              dict_res = {}
              for index,item in enumerate(nums):
                  result=target-item
                  if dict_res.get(result) != None:
                      return [dict_res.get(result),index]
                  dict_res[item]=index
      方法三

      运行结果:1:耗时超过58%。2:内存超过41%。3:利用哈希表

      知识点/技巧: 哈希表作为读取和写入都很快的数据结构,常常用来实现空间换时间的效果。

    6. 167. 两数之和 II - 输入有序数组(难度系数✯)

      class Solution:
          import bisect
          def twoSum(self, numbers: List[int], target: int) -> List[int]:
              for index,item in enumerate(numbers):
                  remain = target-item
                  j = bisect.bisect_left(numbers,remain,index+1)
                  if j != len(numbers) and numbers[j] == remain:
                      return [index+1,j+1]
      方法一

      运行结果:1:耗时超过67%。2:内存超过45%。3:利用二分查找法

      知识点/技巧: 利用升序数据的特性,通过二分查找方法来快速找到我们需要的值。

      class Solution:
          import bisect
          def twoSum(self, numbers: List[int], target: int) -> List[int]:
              i,j = 0, len(numbers)-1
              while i<j:
                  current = numbers[i] + numbers[j]
                  if current == target:
                      return [i+1,j+1]
                  elif current<target:
                      i += 1
                  else:
                      j -= 1
      方法二

      运行结果:1:耗时超过53%。2:内存超过40%。3:指针移动

      知识点/技巧: 使用指针移动技巧在时间复杂度和空间复杂度都更加优化的解法。

    7. 15. 三数之和(难度系数✯✯)

      class Solution:
          def threeSum(self, nums: List[int]) -> List[List[int]]:
              nums.sort()
              result_list = []
              for index, item in enumerate(nums):
                  if index and item == nums[index-1]:
                      # 当前元素和上一元素相同
                      continue
                  elif item>0:
                      # 点睛之笔
                      break
                  target = -item
                  i, j = index + 1, len(nums) - 1
                  is_move_i = None
                  while i < j:
                      current = nums[i] + nums[j]
                      if is_move_i == True:
                          if nums[i-1] == nums[i]:
                              i += 1
                              continue
                      elif is_move_i == False:
                          if nums[j+1] == nums[j]:
                              j -= 1
                              continue
                      if current == target:
                          result_list.append([item, nums[i], nums[j]])
                          i += 1
                          j -= 1
                          is_move_i = True
                      elif current < target: 
                          i += 1
                          is_move_i = True
                      else:
                          is_move_i = False
                          j -= 1
              return result_list
      方法一

      运行结果:1:耗时超过58%。2:内存超过50%。3:三数之和转换成两数和问题。

      知识点/技巧: 首先对数据进行排序,遍历的时候如果当前节点大于0,就无需继续遍历。

    8. 18. 四数之和(难度系数✯✯)

      class Solution:
          def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
              nums.sort()
              print(nums)
              result_list = []
              for i in range(0, len(nums) - 3):
                  if i > 0 and nums[i - 1] == nums[i]:
                      continue
                  if nums[i] + nums[len(nums) - 3] + nums[len(nums) - 2] + nums[len(nums) - 1] < target:
                      # 当前数+后面最大的三个值仍小于目标值,遍历下一位
                      continue
                  if nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target:
                      # 当前数+后面最小的三个值仍大于目标值,退出
                      break
                  for j in range(i + 1, len(nums) - 2):
                      m, n = j + 1, len(nums) - 1
                      if nums[i] + nums[j] + nums[len(nums) - 2] + nums[len(nums) - 1] < target:
                          continue
                      if j > i + 1 and nums[j - 1] == nums[j]:
                          continue
                      if nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target:
                          break
                      is_move_m = None
      
                      while m < n:
                          current = nums[i] + nums[j] + nums[m] + nums[n]
                          if is_move_m == True:
                              if nums[m - 1] == nums[m]:
                                  m += 1
                                  continue
                          elif is_move_m == False:
                              if nums[n + 1] == nums[n]:
                                  n -= 1
                                  continue
                          if current == target:
                              result_list.append([nums[i], nums[j], nums[m], nums[n]])
                              m += 1
                              n -= 1
                              is_move_m = True
                          elif current < target:
                              m += 1
                              is_move_m = True
                          else:
                              is_move_m = False
                              n -= 1
              return result_list
      方法一

      主要考点:1:耗时超过82%。2:内存超过9%。

      知识点/技巧: 在处理三数之和的基础,暴力循环,循环时进行优化

    9. 36. 有效的数独(难度系数✯✯)

      class Solution:
          def get_dic(self):
              dic_result = {}
              for i in range(1, 10):
                  key_1 = "0_%s" % i
                  key_2 = "%s_0" % i
                  dic_result.setdefault(key_1, [])
                  dic_result.setdefault(key_2, [])
                  if not i % 3:
                      key_3 = "3_%s" % i
                      key_6 = "6_%s" % i
                      key_9 = "9_%s" % i
                      dic_result.setdefault(key_3, [])
                      dic_result.setdefault(key_6, [])
                      dic_result.setdefault(key_9, [])
              return dic_result
      
          def isValidSudoku(self, board: List[List[str]]) -> bool:
              dic_result = self.get_dic()
              for raw_index, raw_item in enumerate(board):
                  for col_index, col_item in enumerate(raw_item):
                      if col_item != ".":
                          dic_result[str(raw_index + 1) + "_0"].append(col_item)
                          dic_result["0_" + str(col_index + 1)].append(col_item)
                          key_sq_r = (raw_index // 3 + 1) * 3
                          key_sq_c = (col_index // 3 + 1) * 3
                          dic_result["%s_%s" % (key_sq_r, key_sq_c)].append(col_item)
              for value in dic_result.values():
                  if len(set(value)) != len(value):
                      return False
              else:
                  return True
      方法一

      主要考点:1:耗时超过88%。2:内存超过68%。

      知识点/技巧: 只要我的方法够暴力,问题就难不倒我

    10. 48. 旋转图像(难度系数✯✯✯)

      class Solution:
          def rotate(self, matrix: List[List[int]]) -> None:
              """
              Do not return anything, modify matrix in-place instead.
              """
              mid_line = len(matrix) // 2 if len(matrix) % 2 else len(matrix) // 2
              for i in range(mid_line):
                  for j in range(len(matrix)):
                      matrix[i][j], matrix[len(matrix) - 1 - i][j] = matrix[len(matrix) - i - 1][j], matrix[i][j]
              for i in range(len(matrix)):
                  for j in range(i, len(matrix)):
                      matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
             
      方法一

      主要考点:1:耗时超过29%。2:内存超过74%。

      知识点/技巧: 先水平翻转,再进行主对角线翻转

    11.  

  • 相关阅读:
    Redis-数据类型
    文件转二进制流拆分与组装
    word 文件转PDF 预览
    查询数据库还原时间
    Window10主机连接到Docker 中的mysql 数据库
    sqlServer 执行存储过程结果存表中
    启动mysql 镜像
    Java类型转换细节
    IDEA常用插件
    IDEA控制台中文乱码
  • 原文地址:https://www.cnblogs.com/YK2012/p/15972760.html
Copyright © 2020-2023  润新知