前言
- 今天是社畜开工第一天,刷题刷题刷题💪
53. 最大子数组和 - 力扣(LeetCode)
-
贪心法
- 连续子数组累加和小于零就重新累加,【代码随想录】刷题笔记Day34-CSDN博客
-
class Solution: def maxSubArray(self, nums: List[int]) -> int: count = 0 res = float('-inf') # 整数最小值 for num in nums: count += num res = max(res, count) if count < 0: # 小于0就重新累加 count = 0 return res
-
动态规划法
- dp[i]表示以i结尾的最大连续子数组和,【代码随想录】刷题笔记Day52-CSDN博客
-
class Solution: def maxSubArray(self, nums: List[int]) -> int: dp = [0] * len(nums) dp[0], res = nums[0], nums[0] for i in range(1, len(nums)): dp[i] = max(dp[i-1]+nums[i], nums[i]) res = max(res, dp[i]) return res
56. 合并区间 - 力扣(LeetCode)
-
排序 + 一次遍历
- 思路见【代码随想录】刷题笔记Day38-CSDN博客
- 直接sort按照第一个元素大小,放进第一个区间,判断res[-1]右和新加入的左更新
-
class Solution: def merge(self, intervals: List[List[int]]) -> List[List[int]]: intervals.sort() # 默认第一个元素,从小到大 # intervals.sort(key=lambda x: x[1], reverse=True) # 第二元素,从大到小 res = [intervals[0]] # 先放进第一个区间 # 遍历剩余区间,不重叠就加入结果,重叠则更新右区间 for left, right in intervals[1:]: if res[-1][1] < left: res.append([left, right]) else: res[-1][1] = max(res[-1][1], right) return res
189. 轮转数组 - 力扣(LeetCode)
-
额外数组
-
class Solution: def rotate(self, nums: List[int], k: int) -> None: # 方法 1 # k = k % len(nums) # nums[:] = nums[-k:] + nums[:-k] # 方法 2 n = len(nums) newArr = [0] * n for i in range(n): newArr[(i + k) % n] = nums[i] nums[:] = newArr[:]
-
-
利用队列
-
class Solution: def rotate(self, nums: List[int], k: int) -> None: for i in range(k): nums.insert(0, nums.pop())
-
-
三次翻转
-
思路类似【代码随想录】刷题笔记Day13-CSDN博客里的左旋转字符串
-
class Solution: def rotate(self, nums: List[int], k: int) -> None: # 方法1:利用Python数组复制翻转,O(n) n = len(nums) k %= n # 取余使得k小于n nums[:] = nums[::-1] nums[:k] = nums[:k][::-1] nums[k:] = nums[k:][::-1] # 方法2:定义一个函数用于[i,j]范围内的翻转,O(1) def reverse(i, j): while i < j: nums[i], nums[j] = nums[j], nums[i] i += 1 j -= 1 n = len(nums) k %= n # 取余使得k小于n reverse(0, n - 1) # 全部翻转 reverse(0, k - 1) # 前翻转 reverse(k, n - 1) # 后翻转
-
-
环状替换
- 先求k和n的最大公约数g,遍历前g个数,环状向后跳k格进行交换直到回到最初位置,详细数学证明见官方题解
-
class Solution: def rotate(self, nums: List[int], k: int) -> None: # gcd求最大公约数 def gcd(x, y) -> int: return x if y == 0 else gcd(y, x % y) n = len(nums) k %= n # 优化,取余使得k小于n g = gcd(n, k) # 一共有公约数g个环,前g个元素循环后跳直到回到开始位置 for start in range(g): current = start # 记录开始下标 prev = nums[start] # 记录上一个数 while True: next_idx = (current + k) % n # 计算跳到哪里 nums[next_idx], prev = prev, nums[next_idx] # 交换 current = next_idx # 更新当前坐标 if current == start: # 回到原点就退出 break
238. 除自身以外数组的乘积 - 力扣(LeetCode)
-
前缀积 × 后缀积
- 遍历两次,第一次用res记录前缀积,第二次用tmp记录后缀积,更新res
-
class Solution: def productExceptSelf(self, nums: List[int]) -> List[int]: """ 原数组: [1 2 3 4] 左部分的乘积: 1 1 1*2 1*2*3 右部分的乘积: 2*3*4 3*4 4 1 结果: 1*2*3*4 1*3*4 1*2*4 1*2*3*1 """ res, temp = [1] * len(nums), 1 for i in range(1, len(nums)): # 1 → n-1 res[i] = res[i-1] * nums[i-1] # 前缀积 for i in range(len(nums)-2, -1, -1): # n-2 → 0 temp *= nums[i+1] # 后缀积 res[i] *= temp # 乘得结果 return res
41. 缺失的第一个正数 - 力扣(LeetCode)
-
建立新哈希表(空间复杂度O(n))
- 把数组放入哈希表set中,从1开始查有没有在数组里,没有就返回i
-
class Solution: def firstMissingPositive(self, nums: List[int]) -> int: num_set = set(nums) for i in range(1, len(nums) + 1): if i not in num_set: return i return len(nums) + 1
-
排序查找(时间复杂度O(nlgn))
- 先排序,依次递增查找(跳过非正整数和重复值),相等递增不相等break返回值
-
class Solution: def firstMissingPositive(self, nums: List[int]) -> int: nums.sort() # 排序就是O(nlogn) n = len(nums) res = 1 for i in range(n): if nums[i] <= 0 or nums[i] == res - 1: continue # 跳过非正整数和重复值 else: if nums[i] == res: res += 1 # 相等就继续递增 else: return res # 不相等就返回缺失正数 return res
-
原地标记
-
第一遍把小于等于0的数变成n+1,第二遍将绝对值<=n的数对应的n-1位置变成负数(打上标记),第三遍找正数(说明没在对应位置上)
-
-
class Solution: def firstMissingPositive(self, nums: List[int]) -> int: n = len(nums) # 把小于等于0的数变成n+1 for i in range(n): if nums[i] <= 0: nums[i] = n + 1 # 将绝对值<=n的数对应的n-1位置变成负数(打上标记) for i in range(n): num = abs(nums[i]) if num <= n: nums[num - 1] = -abs(nums[num - 1]) # 遍历找正数(说明没在对应位置上) for i in range(n): if nums[i] > 0: return i + 1 # 都是负数说明缺失n+1 return n + 1
-
-
原地哈希
- 参考这个题解,从头遍历到尾不停交换,判断在下标范围内并且和数-1的位置不同,就交换使得将nums[i]放在下标为nums[i]-1的位置上,最后再扫一遍找出异常值即可
-
class Solution: def firstMissingPositive(self, nums: List[int]) -> int: size = len(nums) for i in range(size): # 先判断这个数字是不是索引,然后判断这个数字是不是放在了正确的地方 while 1 <= nums[i] <= size and nums[i] != nums[nums[i] - 1]: temp = nums[i] - 1 # 防止交换出错 nums[i], nums[temp] = nums[temp], nums[i] for i in range(size): if i + 1 != nums[i]: return i + 1 return size + 1
后言
-
刷了一整天的题了,脑子要炸了,但是也很充实,休息休息,晚上接npy咯