leetcode刷题
Posted TFknight
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode刷题相关的知识,希望对你有一定的参考价值。
python刷题常用数据结构
引用自:https://blog.csdn.net/afterlake/article/details/100054150
我总结了一下自己在刷leetcode时关于python这个语言的经常被使用的数据结构和内置方法。
基础
离开数据结构,算法就是空中楼阁,所以了解python内置的数据类型用法和其效率是非常有必要的
list
list作为最常见的内置数据结构,其不仅可以当作C语言的数组来使用,一些python特有的特性往往可以事半功倍
append 在list的结尾追加一个元素
sort 对list进行排序,在list长度小的时候使用插入排序,在长度大的时候使用快排,所以其时间复杂度可以视为O(nlgn)
pop 将最后一个元素重list内部弹出并返回
切片 python强大的语法糖之一,不仅可以用非负数索引,负数索引的合理使用可以节省不少代码量
set
set本质是哈希表,会对其内部元素去重,检查一个元素是否在set内部的时间复杂度是O(1)
常用的方法为
add 添加一个元素,就算是用一个元素多次添加,其内部也仅保留一份
pop 随机弹出一个元素并返回
dict
同set一样,dict本质也是哈希表,但是set是单个元素,dict是key-value的组合
setdefault 接受两个入参key、default, 如果dict存在key则不做任何操作,如果不存在key,则创建一个 key其value为default
get 同setdefault一样接受两个参数key、default,如果存在key,则返回其value,否则返回default
pop 同setdefault一样接受两个参数key、default,如果存在key,则删除key返回其value,否则返回default
str
字符串也是一个经常在算法中常用的数据结构,在python中str是不可变对象,支持”+“操作当时效率不高需要慎用
split 用指定的分隔符将str分割为list
strip 返回str去掉首尾的空白符后新的str,原来的str不受影响
join 用str作为连接符连接参数里面的每一个元素,常常用来替代”+“
进阶
这里介绍几个常用的内置函数
int 将一个参数转为int类型,在遇到字母等字符时会抛出错误
sum 返回参数的求和
min 返回多个参数的最小值
max 返回多个参数的最大值
abs 返回一个数字的绝对值
高级
这里对于数据结构的知识点要求就比较高了,仅仅介绍常用方法,如果不了解其特性的还请自己查阅资料
queue 队列
put 入队操作
get 出队操作
list 栈
这里又有list,是因为python没有单独的栈,在需要栈的时候往往使用list
append 入栈
pop 出栈
heapq 堆
仅支持最小堆,有个小技巧:如果最大堆,取反之后再放入堆,取出的时候再取反
heapfiy 将一个list转为最小堆
heappush 往一个最小堆添加元素
heappop 弹出堆中的最小值并返回
题目:
给定 matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],
原地旋转输入矩阵,使其变为:
[
[7,4,1],
[8,5,2],
[9,6,3]
]
class Solution(object): def rotate(self, matrix): """ :type matrix: List[List[int]] :rtype: None Do not return anything, modify matrix in-place instead. """ length=len(matrix) ans=[] for i in range(length): row=[] for j in range(length): row.append(matrix[length-j-1][i]) ans.append(row) matrix[:]=ans return matrix
字符串轮转。
给定两个字符串s1和s2,请编写代码检查s2是否为s1旋转而成(比如,waterbottle是erbottlewat旋转后的字符串)。
示例1:
输入:s1 = "waterbottle", s2 = "erbottlewat"
输出:True
return len(s1) == len(s2) and s1 in s2*2
链表去重
编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。
示例1:
输入:[1, 2, 3, 3, 2, 1] 输出:[1, 2, 3]
# Definition for singly-linked list. # class ListNode(object): # def __init__(self, x): # self.val = x # self.next = None class Solution(object): def removeDuplicateNodes(self, head): """ :type head: ListNode :rtype: ListNode """ if not head: return head history = set() # history = [] temp = head while temp: if temp.val not in history: # history.append(temp.val) history.add(temp.val) pre = temp temp = temp.next else: pre.next = temp.next temp = temp.next return head
输出链表的倒数k个元素
暴力破解
class Solution(object): def kthToLast(self, head, k): """ :type head: ListNode :type k: int :rtype: int """ cur = head n = 0 while cur.next: n += 1 cur = cur.next c,cur2 = 0,head while c <= n-k: c += 1 cur2 = cur2.next return cur2.val
机器人过关问题
输入:
[
[0,0,0],
[0,1,0],
[0,0,0]
]
输出: [[0,0],[0,1],[0,2],[1,2],[2,2]]
解释:
输入中标粗的位置即为输出表示的路径,即
0行0列(左上角) -> 0行1列 -> 0行2列 -> 1行2列 -> 2行2列(右下角)
思路:递归,注意边界条件
# 递归算法 class Solution: def move(self, path, now, grid, r, c): # 传入递归变量path(保存正确路径),现在的位置,整个地图,以及地图大小(重复传入避免重复计算) print(now) if now==[r-1, c-1]: # 递归终止条件: 现在在终点 path.insert(0, now) # 把当前位置(终点)插入正确路径的首位(因为它是第一个完成的所以插在首位,后面的位置都插在他前面) return True, now else: # 递归: 若不在终点 if now[1]<=c-2 and grid[now[0]][now[1]+1]==0: # 若当前位置的右边可行进(注意与可完成的区别),则 next_op = [now[0], now[1]+1] # 下一步向右 now_way = self.move(path, next_op, grid, r, c) # 接受向右的结果 if now_way[0]: # 向右可到达(则当前位置可到达) path.insert(0, now) # 把当前位置插在历史记录的可到达路径的首位 return True, path elif now[0]<=r-2 and grid[now[0]+1][now[1]]==0: # 若右方不可行进 next_op = [now[0]+1, now[1]] # 则尝试下方 now_way = self.move(path, next_op, grid, r, c) # 接受向下的结果 if now_way[0]: # 向下可到达(则当前位置可到达) path.insert(0, now) # 把当前位置插在历史记录的可到达路径的首位 return True, path else: # 若右方与下方均不可到达 return False, # 则当前位置不可到达终点 else: return False, elif now[0]<=r-2 and grid[now[0]+1][now[1]]==0: # 若右方不可行进(如有障碍物或者到地图边缘) next_op = [now[0]+1, now[1]] # 下一步向下 now_way = self.move(path, next_op, grid, r, c) if now_way[0]: path.insert(0, now) return True, path else: return False, else: # 若右方与下方均不可行进 return False, # 则当前位置不可到达 def pathWithObstacles(self, obstacleGrid: List[List[int]]) -> List[List[int]]: r = len(obstacleGrid) c = len(obstacleGrid[0]) # 记录下地图的大小 if r==1 and c==1: # 如果是1x1直接返回结果 if obstacleGrid[0][0]==0: return [[0, 0]] else: return [] if obstacleGrid[0][0]==1 or obstacleGrid[r-1][c-1]==1: # 如果起点或者终点有障碍物则判否 return [] way = self.move([], [0, 0], obstacleGrid, r, c) # 递归运算,返回值是元组,way[0]表示是否存在路径,way[1]给出路径 print(way) if way[0]: return way[1] else: return []
思路: 递归,从根开始
# Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution(object): def pathSum(self, root, sum): """ :type root: TreeNode :type sum: int :rtype: int """ self.ans = 0 def f(node, vals): if node: vs = [i + node.val for i in vals] + [node.val] for i in range(len(vs)): if vs[i] == sum: self.ans += 1 f(node.left, vs) f(node.right, vs) f(root, []) return self.ans
照样普通二分可以做
两个等价
mid = (left + right) >> 1
mid = (left + right) /2
把循环的归类
编写一种方法,对字符串数组进行排序,将所有变位词组合在一起。变位词是指字母相同,但排列不同的字符串。
对于这种去重、分类问题,用sorted()排序之后就可以放入dict了
括号匹配问题:
括号。设计一种算法,打印n对括号的所有合法的(例如,开闭一一对应)组合。
说明:解集不能包含重复的子集。
例如,给出 n = 3,生成结果为:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
class Solution(object): def generateParenthesis(self, n): """ :type n: int :rtype: List[str] """ re = [] state = \'\' def dsp(state, p, q): #p,q分别表示(和)还剩的个数,有个隐含条件:就是(在组合时候比)用的多或相等 if p > q: #非法,剪枝 return if q == 0: #)用完之时 re.append(state) if p > 0: dsp(state+\'(\', p-1, q) if q > 0: dsp(state+\')\', p, q-1) dsp(state, n, n) return re
以上是关于leetcode刷题的主要内容,如果未能解决你的问题,请参考以下文章