LeetCode100 -- Day4
1. 双指针:283、11、15
(1)283 移动0
要求保持相对顺序不变 → 不能使用左右指针,使用快慢指针
class Solution(object):def moveZeroes(self, nums):if len(nums)==1: return p,q=0,0for q in range(len(nums)):if nums[q]!=0:temp=nums[q]nums[q]=nums[p]nums[p]=tempp+=1return nums
(2)11 盛水最多的容器
class Solution(object):def maxArea(self, height):left,right = 0, len(height)-1v_max = 0while left<right:if height[right]>=height[left]:v_cur = height[left] * (right-left)left += 1else:v_cur = height[right] * (right-left)right -= 1v_max = max(v_max,v_cur)return v_max
(3)15 三数之和
class Solution(object):def threeSum(self, nums):n=len(nums)results=[]nums=sorted(nums)for i in range(n-2):if i>0 and nums[i]==nums[i-1]:continue ## 跳过重复的ij=i+1k=n-1while j<k:total = nums[i]+nums[j]+nums[k]if total==0:results.append([nums[i],nums[j],nums[k]])## 跳过重复的j、kwhile j<k and nums[j]==nums[j+1]:j+=1while j<k and nums[k]==nums[k-1]:k-=1## 移动j、k继续搜索j+=1k-=1elif total>0:k-=1else:j+=1return results
2. 链表:141、142
(1)141 环形链表
核心思想:如果有环,快指针早晚会追上慢指针
class Solution(object):def hasCycle(self, head):if not head: return slow=fast=headwhile fast and fast.next:slow = slow.nextfast = fast.next.nextif slow == fast:return Truereturn False
(2)142 环形链表②
注意:快慢指针相遇点不一定是环的入口点!
class Solution(object):def detectCycle(self, head):slow=fast=headwhile fast and fast.next:slow=slow.nextfast=fast.next.nextif slow==fast:while head!=slow:head=head.nextslow=slow.nextreturn head return
3. 矩阵:73、54
(1)73 矩阵置零
class Solution(object):def setZeroes(self, matrix):m=len(matrix)n=len(matrix[0])pos=[]for i in range(m):for j in range(n):if matrix[i][j]==0:pos.append((i,j))for row,col in pos:for i in range(n):matrix[row][i]=0for i in range(m):matrix[i][col]=0return matrix
不完全属于原地算法,使用了额外的空间来存储零元素的位置,最坏情况空间复杂度O(m+n)。
优化方案:使用第一行和第一列作为标记
class Solution(object):def setZeroes(self, matrix):m,n = len(matrix),len(matrix[0])"""标记第一行和第一列是否需要置零"""first_row_zero = any(matrix[0][j]==0 for j in range(n))first_col_zero = any(matrix[i][0]==0 for i in range(m))"""使用第一行和第一列作为标记"""for i in range(1,m):for j in range(1,n):if matrix[i][j]==0:matrix[i][0]=0matrix[0][j]=0"""根据标记置零"""for i in range(1,m):for j in range(1,n):if matrix[i][0]==0 or matrix[0][j]==0:matrix[i][j]=0if first_row_zero:for j in range(n):matrix[0][j]=0if first_col_zero:for i in range(m):matrix[i][0]=0
(2)54 螺旋矩阵
核心思想:边界收缩法 → 每完成一层螺旋,收缩边界,直到边界重叠或交叉
class Solution(object):def spiralOrder(self, matrix):if not matrix or not matrix[0]: return m,n = len(matrix),len(matrix[0])top,bottom = 0,m-1left,right = 0,n-1results=[]while top<=bottom and left<=right:"""1.从左到右遍历到右边界"""for col in range(left,right+1):results.append(matrix[top][col])top += 1 ## 上边界下移一行"""2.从上到下遍历到下边界"""for row in range(top,bottom+1):results.append(matrix[row][right])right -= 1 ## 右边界左移一列"""3.当还有行要遍历:从右到左遍历到左边界"""if top <= bottom:for col in range(right,left-1,-1):results.append(matrix[bottom][col])bottom -= 1 ## 下边界上移一行"""4.当还有列要遍历:从下到上遍历到上边界"""if left <= right:for row in range(bottom,top-1,-1):results.append(matrix[row][left])left += 1 ## 左边界右移一列return results
4. 栈:20、155、394、739
(1)20 有效括号
class Solution(object):def isValid(self, s):if len(s)%2 != 0: return Falsestack=[]mapping = {')': '(', ']': '[', '}': '{'}for char in s:"""右括号:和出栈元素匹配"""if char in mapping:"""1.左右不匹配 2.栈为空(只有右括号没有左括号和他匹配)"""if not stack or stack.pop() != mapping[char]:return False"""左括号:入栈"""else:stack.append(char)return False if stack else True
(2)155 最小栈
核心思想:双栈结构
1.主栈 (stack):
存储所有压入的元素
正常执行压栈和出栈操作
2.最小栈 (min_stack):
栈顶始终存储当前栈中的最小值
压栈时:如果新值 ≤ 当前最小值,则压入
出栈时:如果弹出的值等于当前最小值,则弹出
class MinStack(object):def __init__(self):self.stack = [] # 主栈:存储所有元素self.min_stack = [] # 辅助栈:存储当前最小值def push(self, val):""":type val: int:rtype: None"""self.stack.append(val)""" 同时更新最小值栈 """if not self.min_stack or self.min_stack[-1]>=val:self.min_stack.append(val)def pop(self):""":rtype: None"""if self.stack:val = self.stack.pop()""" 如果弹出的是当前最小值,更新最小值栈 """if self.min_stack[-1]==val:self.min_stack.pop()def top(self):""":rtype: int"""return self.stack[-1] if self.stack else Nonedef getMin(self):""":rtype: int"""return self.min_stack[-1] if self.min_stack else None
(3)394 字符串解码
class Solution(object):def decodeString(self, s):stack=[]cur_k=0cur_string=""for char in s:"""数字:转换为数值"""if char.isdigit():cur_k = cur_k*10 + int(char)"""左括号:有新的字符串要产生 将已有字符串(cur_string)入栈,准备开始处理新字符串"""elif char=='[':stack.append(cur_k)stack.append(cur_string)cur_k=0cur_string="""""右括号:当前字符串该输出了 获取栈中存储的历史字符串(pop_string)和其倍数(pop_k)完整字符串 = 历史字符串 + 新字符串(cur_string)*倍数(pop_k)"""elif char==']':pop_string = stack.pop()pop_k = stack.pop()cur_string = pop_string + cur_string*pop_k"""字母:将连续的字母拼成cur_string"""else: cur_string += charreturn cur_string
(4)739 每日温度
class Solution(object):def dailyTemperatures(self, temperatures):stack=[]result = [0]*len(temperatures)for i,t in enumerate(temperatures):while stack and t > temperatures[stack[-1]]:day = stack.pop()result[day] = i-daystack.append(i)return result
5. 堆:215、347
(1)215 数组中第k大元素
import heapq
class Solution(object):def findKthLargest(self, nums, k):min_heap=[]for num in nums:if len(min_heap)<k:heapq.heappush(min_heap,num)elif min_heap[0]<num:heapq.heapreplace(min_heap,num)return min_heap[0]
(2)347 前k个高频元素
heapq维护堆时,对于元组(a,b,c,……),它首要且主要依据的是第一个元素 a 的大小
import heapq
from collections import defaultdict
class Solution(object):def topKFrequent(self, nums, k):mapping = defaultdict(int)for num in nums:mapping[num] += 1min_heap=[]for num,count in mapping.items():if len(min_heap)<k:heapq.heappush(min_heap,(count,num))elif count > min_heap[0][0]:heapq.heapreplace(min_heap,(count,num))return [num for _,num in min_heap]