![](https://img-blog.csdnimg.cn/20201014180756757.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
数据结构
Y·Not·Try
这个作者很懒,什么都没留下…
展开
-
图的宽度优先遍历与深度优先遍历
1.图的宽度优先搜索代码非常容易实现,如果你会二叉树的层序遍历,那么图的宽度优先搜索就是在层序遍历的基础之上,引入visited集合,每当入队时,首先考虑入队结点是否处于visited集合中,如果在,说明曾经入队,就跳过。我们先看一下二叉树的层序遍历class Solution: def levelOrder(self, root: TreeNode) -> List[List[int]]: if not root: return []原创 2020-10-06 19:52:09 · 1422 阅读 · 0 评论 -
前缀树(字典树)
前缀树可以用来解决诸如搜索提示,字符串查询等问题,实现一个前缀树首先需要定义一个前缀树结点,结点不代表字符串中的字符,每个结点的值通常有end(表示是否是某个字符串结尾),past(表示有多少单词经过此结点),next_node(是一个字典,其中key代表此结点相连的字符,value代表这条字符所代表的边连接的结点)。定义前缀树类时,首先要初始化一个前缀树结点,然后定义常用的方法,如插入,删除,搜索和startwith,其基本搜索过程类似,以插入举例,首先定义一个变量node指向root,然后循环遍历字原创 2020-10-06 18:34:17 · 186 阅读 · 0 评论 -
并查集
并查集可以用来解决集合从属关系,很容易的可以获取如连通分量的个数,其基本实现主要由三部分构成,即:①find函数,用于寻找某一个节点的集合代表节点。②union函数,用于将两个集合合并,简易并查集直接将二者合并,而优化后的并查集要求小集合并到大集合中。③connected函数,用于判断两个节点是否从属于一个集合,在union中也会调用此函数如例题:class UnionFind: father = {} size = {} cnt = 0 def原创 2020-10-06 12:15:03 · 99 阅读 · 0 评论 -
TopK问题
TopK问题有两种常见的解决方式,一种是利用堆,一种是利用快速排序的partition过程。一,堆import heapqclass Finder: def findKth(self, a, n, K): b = list(map(lambda x:-x, a)) heapq.heapify(b) for _ in range(K-1): heapq.heappop(b) return -heapq原创 2020-10-05 18:16:38 · 100 阅读 · 0 评论 -
断金条-贪心算法
一块金条切成两半,是需要花费和长度数值一样的铜板的。比如 长度为20的 金条,不管切成长度多大的两半,都要花费20个铜 板。一群人想整分整块金 条,怎么分最省铜板? 例如,给定数组{10,20,30},代表一共三个人,整块金条长度为 10+20+30=60. 金条要分成10,20,30三个部分。 如果, 先把长 度60的金条分成10和50,花费60 再把长度50的金条分成20和30, 花费50 一共花费110铜板。 但是如果, 先把长度60的金条分成30和30,花费60 再把长度30 金条分成10和20,花原创 2020-10-05 13:22:29 · 156 阅读 · 0 评论 -
随时确定中位数
思路:设置一个大根堆和一个小根堆,大根堆力求存储N/2部分的小值,小根堆力求存储N/2部分的大值,保持此状态后,哪个堆的值多则中位数就是哪个堆的堆顶元素。如何保持均衡分布?每次进入的值和大根堆的堆顶元素比较,当其值大于大根堆时,进入小根堆,当两者的值相差大于等于2时,多的一个堆出堆顶元素赋值给小的堆。、整个过程对于python可以使用heapq简易实现。...原创 2020-10-05 11:40:01 · 106 阅读 · 0 评论 -
相交链表
思路:对于确定无环的两个链表,有两种思路,一种是让ha和hb不断向下走当走到空时从头继续走直到两者相等返回ha另一种是分别遍历两条链表,让长的一条先走,然后同步走。class Solution: def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode: ha, hb = headA, headB while(ha != hb): ..原创 2020-10-04 20:33:35 · 170 阅读 · 1 评论 -
返回环形链表的入环结点
套路:快慢指针,当两指针相遇时,快指针回到头结点,两个指针继续同步移动一步,直到第二次相遇即为所求。class Solution: def detectCycle(self, head: ListNode) -> ListNode: if not head or not head.next: return fast = slow = head while fast and fast.next: ..原创 2020-10-04 20:02:29 · 155 阅读 · 0 评论 -
之字打印矩阵
基本思路,两个指针都从矩阵左上角出发,一个沿着右上半边移动,一个沿着左下半边移动(碰到边界转向),这样两个指针就压着一条对角线,从而我们只需要打印这个对角线元素,并在每次打印对角线后更新从上到下的标记。class Solution: def findDiagonalOrder(self, matrix: List[List[int]]) -> List[int]: if not matrix: return [] Row1, C..原创 2020-10-04 13:45:48 · 121 阅读 · 0 评论 -
螺旋打印矩阵
思路:使用Col1和Row1变量记录左上角坐标,使用Col2和Row2变量记录右下角坐标,两个角固定了这个矩阵,设置初始值CurR=0,CurC=0,从左上角开始,然后分四部分打印一圈:当CurC<Col2时,打印并CurC++当CurR<Row2时,打印并CurR++当CurC>Col1时,打印并CurC--当CurR>Row1时,打印并CurR--注意打印时考虑特例一行或一列的情况在大循环中,每次打完一圈以后,左上坐标向右下角移动一格,右下坐标..原创 2020-10-03 22:23:16 · 339 阅读 · 0 评论 -
栈与队列常见面试问题
问题一:使用数组实现栈和队列实现栈的方法:设置索引index用于表示插入时向哪个下标位置插入,初始时index指向0位置,入栈:当index = len(stack)时报栈满错误,否则stack[index++] = obj出栈:当index = 0时报栈空错误,否则index -= 1peek操作:当index = 0 时返回Null,否则返回stack[index - 1]实现队列的方法:设置索引start表示出队时从哪个下标出队,索引end表示从哪个下标入队,设原创 2020-10-03 22:13:31 · 664 阅读 · 0 评论 -
堆排序,归并排序和快速排序
一,堆排序,可以用来解决优先队列,topk等问题class Solution: def sortArray(self, nums: List[int]) -> List[int]: def heapsort(nums): len_nums = len(nums) # 建堆过程,也可以理解为向上调整的过程 for i in range(len_nums//2-1, -1, -1):原创 2020-10-03 12:59:04 · 334 阅读 · 0 评论 -
单调队列及典型例题
一,单调队列和单调栈类似,队列中的元素保持单调递增或递减,可以用以解决区间最小值的问题。二,例题class Solution: def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: queue = [] # 单调队列 res = [] # 结果 for i,num in enumerate(nums): if queue and原创 2020-10-02 22:44:54 · 380 阅读 · 1 评论 -
二叉树的最近公共祖先
此题可分为种情况:1.p,q同侧,则左或右必有一个返回非null节点,此时将其返回2.p,q异侧,此时左右均非null,此时返回根节点3.左右均为null,则无class Solution: def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode: if not(root) or p == root or q == root: ..原创 2020-09-21 12:25:29 · 63 阅读 · 0 评论 -
排序总结
选择排序,外循环每次确定一个最小的,内循环从下一个元素开始比较class Solution: def sortArray(self, nums: List[int]) -> List[int]: len_nums = len(nums) for i in range(len_nums): for j in range(i+1, len_nums): if nums[j] < nums[i]:原创 2020-09-17 14:41:17 · 80 阅读 · 0 评论 -
快速排序
class Solution: def sortArray(self, nums: List[int]) -> List[int]: if len(nums) <= 1: return nums left = [] right = [] for num in nums[1:]: if num <= nums[0]: left.append.原创 2020-09-17 13:10:57 · 64 阅读 · 0 评论 -
堆排序
堆排序的过程:1.创建初始堆。2.将堆的最后一个元素和堆顶元素交换,减少堆的范围, 调整堆。class Solution: def findKthLargest(self, nums: List[int], k: int) -> int: len_nums = len(nums) for i in range(len_nums//2-1, -1, -1): self.adjust_heap(nums, i, len_nums原创 2020-09-17 11:37:43 · 91 阅读 · 0 评论 -
回文串之中心扩展法
中心扩展法可以帮助减少在回文子串中暴力遍历的一次循环,在普通暴力遍历中,我们需要两次循环分别确定左指针和右指针(即回文子串的左右边界),然后还有一次循环向中间靠拢判断。中心扩展法将向中心靠拢的这一步改为了由中心向两边延申,由于回文子串有奇数和偶数之分,所以中心扩展法的起始点需要分两种情况讨论,即在遍历变量i在遍历的过程中,分别需要从i,i,和i,i+1开始。class Solution: def countSubstrings(self, s: str) -> int:原创 2020-09-17 10:44:33 · 589 阅读 · 0 评论 -
单调栈
1.什么是单调栈?单调栈是一种数据结构,其栈底到栈顶元素必然是有序的,如果是单调递增,则是单调递增栈,反之则是单调递减栈。2.单调栈的应用由于单调递增栈在每时每刻栈底到栈顶都是递增的,所以在维护这样的一个栈后,栈顶元素一定是新加入的元素左边第一个比他小的值。相反,单调递减栈可以帮助我们找到某一元素左边第一个比他大的元素。如果我们读入元素的顺序是相反的,则我们可以确定右边第一个比元素大的值和右边第一个比元素小的值。3.单调栈的代码target = [4, 7, 5, 2, 3]原创 2020-09-15 16:07:00 · 103 阅读 · 0 评论 -
回溯法之括号生成
class Solution: def generateParenthesis(self, n: int) -> List[str]: res = [] track = "(" def back_track(track, n): left_num , right_num = track.count('('), track.count(')') if left_num == n and righ...原创 2020-09-13 10:31:35 · 204 阅读 · 0 评论 -
回溯法之递增子序列
class Solution: def findSubsequences(self, nums: List[int]) -> List[List[int]]: res = [] track = [] used = [] # 使用used数组对同层重复元素剪枝, 使用start变量对下一层重复元素剪枝 len_nums = len(nums) def back_track(start, track, used)...原创 2020-09-13 10:23:57 · 132 阅读 · 0 评论 -
回溯模板之组合总和
class Solution: def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: res = [] track = [] def back_track(start, track, target, candidates): if sum(track) == target: re...原创 2020-09-12 21:03:25 · 88 阅读 · 0 评论 -
二分搜索及左边界右边界模板
int binary_search(int[] nums, int target) { int left = 0, right = nums.length - 1; while(left <= right) { int mid = left + (right - left) / 2; if (nums[mid] < target) { left = mid + 1; } else if (nums[mid.原创 2020-09-12 18:07:23 · 79 阅读 · 0 评论 -
位运算及典型例题
前置知识:任意一个数和0异或仍然为自己:a^0 = a任意一个数和自己异或是0:a^a=0异或操作满足交换律和结合律:a^b^a=(a^a)^b=0^b=b题目:解答:class Solution: def singleNumber(self, nums: List[int]) -> int: res = 0 for i in nums: res ^= i return res原创 2020-09-09 16:39:21 · 246 阅读 · 0 评论 -
前、中、后序遍历通用模板
class Solution: def inorderTraversal(self, root: TreeNode) -> List[int]: res = [] stack = [] cur = root # 中序,模板:先用指针找到每颗子树的最左下角,然后进行进出栈操作 while stack or cur: while cur: stack.appe...原创 2020-09-09 15:18:08 · 133 阅读 · 0 评论 -
二叉树和N叉树的后序遍历
二叉树:class Solution: def postorderTraversal(self, root: TreeNode) -> List[int]: if not(root): return [] stack = [root] res = [] while(stack): cur_node = stack.pop() res.append(cur原创 2020-09-09 15:17:11 · 83 阅读 · 0 评论 -
二叉树和N叉树的前序遍历
二叉树:class Solution: def preorderTraversal(self, root: TreeNode) -> List[int]: if not(root): return [] stack = [root] res = [] while(stack): cur_node = stack.pop() res.append(cur_原创 2020-09-09 15:03:15 · 124 阅读 · 0 评论 -
向二叉搜索树中插入节点
向二叉搜索树插入节点需要保持其本身的性质,即节点左子树的节点值皆小于其根节点的值,节点右子树的节点值皆大于其根节点的值。这里使用递归解决class Solution{ public TreeNode insert(TreeNode root, TreeNode node){ if(root == null){ return node; } // 此时遍历到空引用,返回节点node引用即可 if(node.val <原创 2020-06-22 20:17:48 · 351 阅读 · 0 评论 -
递归求二叉树的高度
此问题可拆解为求左右子树最高的高度加1,递归出口为访问到叶子节点本身时其高度为1,此时返回0即可。class Solution{ public int height(TreeNode root){ if(root == null){ return 0; } return Math.max(height(root.left),height(root.right)) + 1; }}由于使用了递归,内存开销巨大原创 2020-06-22 15:16:38 · 852 阅读 · 0 评论 -
递归求二叉树叶子节点和
使用递归解决此类问题,可以首先分析问题及其拆解,这里面可以将求叶子节点的和拆解为求左子树叶子节点和与求右子树的叶子节点和,然后分析递归出口,这里即访问到叶子节点退出,返回叶子节点本身的值。class Solution{ public int leafsum(TreeNode root){ if(root == null){ return 0; } if(root.left == null && root.r原创 2020-06-22 14:47:17 · 745 阅读 · 0 评论 -
单链表的创建及增删查验
1.单链表的初始化单链表是由节点构成的,所以,在创建单链表时,我们首先应该创建构成单链表的节点class ListNode{ public int val; public ListNode next; public ListNode(value){ this.val = value; }}这里我们设定了节点类,其中val用于存储节点值,next是指向下一个ListNode的引用(c里面称为指针),构造函数初始化对象的值。然后,我们构造单链表原创 2020-06-20 16:36:27 · 130 阅读 · 0 评论