
数据结构
小鱼喝可乐
南京大学、Alibaba淘系技术部
展开
-
笔试问你线段树你却不会?
本文首发自本人微信公众号:今天你A了吗。每日算法讲解,面试题,冲刺BAT大厂。微信扫码关注吧:线段树:例题1 前言在上一章:《线段树:讲解与模版》中,我们讨论了线段树的原理并且给予了一套模版。我们在文中也提到,每个节点包含数组下标在 [i, j]范围内的聚合信息(如最大值,最小值,总和等)。具体细节大家可以点击上一篇文章进行查看。这次,我们找到了一道题:杭电 1166:敌兵布阵(链接在本文末尾)。对线段树的应用进行讲解。本文中线段树维护范围中数组的和。2 题目概述给定一个一位数组代表各个军营将原创 2020-11-06 22:20:04 · 390 阅读 · 0 评论 -
线段树:讲解与模板
本章内容介绍另一种数据结构—线段树,线段树和前文所提到的前缀和所能解决的问题相似,但使用场景不同。并且在下一章《线段树:例题讲解》会针对相关例题做出讨论。1 前缀和的局限性在使用前缀和时,我们必须保证所生成前缀和的原始数组不能发生元素的更新操作。以一维数组为例,一旦前缀和数组已经生成完毕,此时若改变原始数组中的某个值,那么其后面的前缀和都要发生更改。可以看出,前缀和方法重新生成前缀和数组的时间复杂度为O(N)2 线段树与前缀和的比较树是一种比较灵活的数据结构,可以用来解决某个范围内的数据聚.原创 2020-11-06 18:39:29 · 442 阅读 · 0 评论 -
前缀和(一)
本文首发自本人微信公众号:今天你A了吗。每日算法讲解,面试题,冲刺BAT大厂。微信扫码关注吧:递归方法根据幂运算的性质,可以得出:计算a的n次方,如果n是偶数(不为0),那么就先计算a的n/2次方,然后平方;如果n是奇数,那么就先计算a的n-1次方,再乘上a;递归出口是a的0次方为1。根据以上原理可以得出递归的方法。递归方法时间复杂度为logn,递归不可避免的带来空间消耗int myPow(int a, int n){ if(n == 0){ return 1; }else if(n % 2 == 1){ return myPow(a, n-1) * a; }else{原创 2020-10-22 15:10:34 · 151 阅读 · 0 评论 -
环形链表与快慢指针
在leetcode中,环形链表1是判断链表是否存在环,环形链表2是判断环的连接点是哪一个。存在两种解法:使用set进行存储,如果在遍历过程中,遇到set中有重复的,其实这两个问题都解决了,一个是判断出是否存在环,另一方面第一个重复的肯定就是连接点。使用快慢指针。慢指针一次移动一个,快指针一次移动两个。如果在快指针不等于null前相遇说明存在环,否则说明出现null这个链表就不存在环。环状链表1:/** * Definition for singly-linked list. * class原创 2020-10-10 14:07:30 · 248 阅读 · 0 评论 -
根据前序遍历、中序遍历或者后序遍历,中序遍历重构二叉树
在leetcode上有两题,分别是根据前序/后序 和中序遍历重构二叉树。思路都是一样的,但是要记住,在从后序遍历重构二叉树的时候,要先从右子树进行建立,因为后序遍历先遍历的是右子树。前序遍历+中序遍历(1)首先进行边界判断,如果遍历数组为0或者1的情况下,说明这个树只有一个顶点或者没有顶点,直接进行构造。(2)根据前序遍历和中序遍历建立二叉树的思路是:前序遍历依次每一个节点对应一个子树,这个节点在中序遍历中找到它相应的位置,它的左边(当然是在子树数组范围内)就是左子树的顶点,右边就是右子树的顶点。原创 2020-10-08 15:14:34 · 225 阅读 · 0 评论 -
LeetCode 236. 二叉树的最近公共祖先
题目:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。思路:采用递归的方法,最小公共父节点,要么在二者之间,要么是二者之一。递归的边界是,遇到空或者p或者q就返回当前的节点。一个节点的子节点,如果左节点返回的是空,右节点返回的是空,说明目前还没遇到p或者q,直接返回空。如果一个子节点为空,另一个不是,说明在一个子树中找到了这个节点,返回这个子节点即可。如果两个子节点都不是空,那么说明他就是最小公共父节点。代码:/** * Definition for a binary tree n原创 2020-09-27 11:07:20 · 217 阅读 · 0 评论 -
LeetCode 235. 二叉搜索树的最近公共祖先
题意:思路:三种情况:最小公共祖先为p节点,q是p的子树中的节点最小公共祖先为q节点,p是q的子树中的节点p和q分布在最小公共子树的两边利用二叉搜索树的性质,如果root值要是大于两个节点的值,说明还可以往root的左子树去探索,因为搜索二叉树的性质是中序遍历的结果递增。如果root的值小于两个节点的值,可以向root的右子进行探索。如果出现root的值等于p或者q,或者root在p和q之间的情况,说明就找到了最小的祖先。代码:/** * Definition for a bina原创 2020-09-27 10:47:44 · 137 阅读 · 0 评论 -
LeetCode 106. 从中序与后序遍历序列构造二叉树
题意:根据一棵树的中序遍历与后序遍历构造二叉树。思路:后序遍历从后往前看,就是相当于一个前序遍历。从后往前一个个遍历,就相当于遍历了每个子树的根节点。根据这个根节点对中序遍历的数组进行划分即可。采用递归进行解题。在构造子树的时候,注意先构造右子树,再构造左子树。可以理解为在后序遍历的数组中整个数组是先存储左子树的节点,再存储右子树的节点,最后存储根节点,我们从后往前遍历post数组,相当于反过来,就是要先建立右子树。代码:class Solution { Map<Intege原创 2020-09-26 00:05:13 · 332 阅读 · 0 评论 -
LeetCode 501. 二叉搜索树中的众数
思路:二叉搜索树的中序遍历就是一个递增/递减的数组。可以把这一题当做一个数组处理,遍历一遍数组,如果当前元素的值跟之前的元素值一样,那么count++。如果不一样count就置1。同时设置base记录上一个元素的值,max记录出现的最大的次数。具体考虑以下两个点:是否跟之前的元素相同相同加count++不相同count = 1count是否大于max如果大于max,说明之前数组中存储的众数已经不是出现次数最多的元素,要将max结果置换,并且清空结果数组,放上当前元素。如果等于ma原创 2020-09-25 00:40:47 · 141 阅读 · 0 评论 -
一文轻松搞懂 链表反转
单链表反转(时间复杂度O(n), 空间复杂度O(1))的方法主要有以下三种:头插法:从第二个元素开始,依次把元素插到插入到头结点和第一个元素之间。指针逆转:把指向后面一个元素的指针指向前面一个元素递归法:本质上跟指针逆转相同前情提要:设置一个链表,带有头结点。元素为1->2->3->4倒转过来应该是:1.头插法:从第二个元素开始,每次选取一个元素插入到头结点和第一个节点之间。第一步:把 2 插到 head 和 1 之间第二步:把 3 插入 head 与 2 之原创 2020-08-23 01:44:52 · 539 阅读 · 0 评论 -
关于二分查找
在计算机科学中,二分搜索(英语:binary search),也称折半搜索(英语:half-interval search)[1]、对数搜索(英语:logarithmic search)[2],是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查...原创 2018-11-06 22:20:10 · 348 阅读 · 0 评论 -
浙江大学机试--畅通工程
题目: 牛客网链接概述: 给出m条道路,n个村庄,看这些道路能不能让所有村庄联通起来,如果能,输出联通的最小代价,如果不能,输出问号。思路: 最小生成树 Kruskal算法(并查集)。如果每个是相联通的,那么他们应该有一个共同的最终根节点。我们可以找出来一个与其他比较。用来判断是否这是个连通图#include <iostream>#include <algorithm&...原创 2019-01-31 18:32:04 · 360 阅读 · 0 评论 -
浙江大学机试--Grading
题目: 牛客网链接概述: 本题给出类似我们高考的评判条件,三个评卷老师,一个专家,看最终评判出多少分思路: 简单的逻辑问题#include <iostream>#include <cmath>#include <algorithm>using namespace std;int main(){ int p, t, g1, g2, g3, g...原创 2019-01-31 19:40:33 · 563 阅读 · 0 评论 -
牛客网浙江大学机试--Sharing
题目: 牛客网链接概述: 给出两个字符串,用链表来表示(不是严谨的链表,只是表示出每个节点的起始位置,和下一个节点位置)。让找两个字符串的公共节点。思路: 就是用一个足够大的数组表示可能出现的地址,读取下一个地址,并将对应数组的值+1,当为2的时候就是前缀对应的地址。当有出现两次的节点一定是公共节点。我们在采用scanf输入字符的时候要考虑后面的空格或者回车,而采用cin却不会出现这样情况...原创 2019-02-01 15:10:45 · 310 阅读 · 0 评论 -
牛客网浙江大学机试--找出直系亲属
题目: 牛客网链接概述: 用三个字母表示出三个人的关系,并回答提出的问题。思路: 这题采用两种方法:采用数组解决问题数组用来存储子女的下标(反正是独生子女),找关系的时候就不断地搜索子女。这里分为两种情况,一种是第一个字母是第二个字母的长辈,另一个是第一个字母是第二个字母的晚辈。只要把参数顺序倒过来即可。采用树的方法来解决问题。这里就没写粘贴的牛客网的代码。思路很清晰,很适合复习...原创 2019-02-02 00:45:43 · 420 阅读 · 0 评论 -
牛客网浙江大学牛客网机试--二叉搜索树
题目: 牛客网链接概述: 给定两个序列,比较形成的二叉搜索树是否长得一样思路: 只要给出的数一样,他们的中序遍历肯定是一样的。那么我们可以用前序遍历判断。而且前序(已确定)+ 中序就可以确定一个二叉树。另外,要关注一下里面getchar的用法:在输入完整数后,会形成一个回车,在输入字符串的前面要用getchar()接住。gets()可用来输入数组。尽管给出的是整数,但是用char类型保存...原创 2019-02-14 23:56:56 · 307 阅读 · 0 评论 -
牛客网浙江大学机试--寻找大富翁
题目: 牛客网链接思路: 给出一个数组,排序(所谓的财富榜)概述: 简单的sort函数的应用#include <iostream>#include <algorithm>using namespace std;bool cmp(int a, int b){ return a > b;}int main(){ int fortune[...原创 2019-02-04 15:23:16 · 340 阅读 · 0 评论 -
01背包问题,完全背包问题的二维数组,一维数组的解答
关于01背包问题,完全背包问题,这里就不过多阐述。这里只是总结一下这两个问题的二维数组,一维数组的两种表达方式。为什么要用一位数组,两个原因:1.节约空间(二维变一维)2.时间复杂度降为线性。直接上代码,如果对01背包问题,完全背包问题有问题的推荐看一下《背包九讲》和其他博客。背包九讲:https://github.com/tianyicui/pack01背包问题可视化的网站:http:...原创 2019-02-16 14:30:59 · 3176 阅读 · 2 评论 -
浙江大学机试--奥运会排序
题目: 牛客网链接概述: 给了每个国家的金牌数,奖牌数,人口数。然后给出四种排序条件,奖牌总数,金牌总数,金牌人口比例,奖牌人口比例。找出给定国家的最优排序方法。思路: 用了两种方法来解决这个问题。一个是用一个二维数组,还有一个是面向对象的方法。 这一题数据集比较坑,有时候人口总数竟然会为0。方法一:面向对象法vector存储对象时候很巧妙 ,多复习。#include <iostr...原创 2019-01-31 03:59:21 · 337 阅读 · 0 评论 -
浙江大学机试--继续畅通工程
题目:牛客网链接概述: 给定n个村庄,然后给出他们之间的路的长度和代价,和是否修好,问如何修路才能让代价最小,输出最小代价。**思路:**本题采用最小生成树 Kruskal算法(并查集)。相关的知识可以百度一下。注释中写思路。#include &lt;iostream&gt;#include &lt;algorithm&gt;using namespace std;//用于并查集中使...原创 2019-01-31 17:45:48 · 298 阅读 · 0 评论 -
浙江大学机试--欧拉回路
题目: 牛客网链接概述: 欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?思路: 确定无向图欧拉回路的充要条件:除孤立节点外,其它节点满足 1.连通 2.度为偶数。这里采用并查集进行操作,具体思路写在注释里。#include &amp;lt;iostream&amp;gt;using namespace std;int father[...原创 2018-11-29 10:49:09 · 448 阅读 · 2 评论 -
LeetCode 22-Generate Parentheses(DFS)
题目: https://leetcode.com/problems/generate-parentheses/概述: 给定一个n,排列n个“(”, n个“)”,是的左右能够闭合思路: 采用迭代算法,如果m > 0 说明已经有了左括号,才可以添加一个右括号。 如果n > 0 说明还有左括号没放完。class Solution {public: vector<stri...原创 2018-11-22 23:16:58 · 214 阅读 · 0 评论 -
背包问题(01背包 完全背包 多重背包)
今天刷牛客网题目,用到背包问题的求解。在这里总结一下背包问题。背包问题主要分为以下三种:01背包完全背包多重背包01背包问题有N件物品和一个容量为V的背包。第i件物品的价格(即体积,下同)是w[i],价值是c[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。这是我们最常遇见的背包问题,其实只要弄清楚状态转移方程即可。f[i][v] = max(...原创 2018-11-07 00:35:53 · 676 阅读 · 0 评论 -
LeetCode 72-Edit Distance(动态规划)
本题为经典的动态规划。解决本题的前提是把这题的动态方程先搞明白。题目:(动态规划)https://leetcode.com/problems/edit-distance/概述:给定两个单词,给了三种方法(替换,删除,插入),用这三种方法使得两个单词相同。思路:采用动态规划。要实现动态方程,我们需要考虑两种情况:①边缘情况 ②一般情况边缘情况:转化word1[0…i - 1] 到 “”...原创 2018-11-03 15:52:42 · 263 阅读 · 0 评论 -
牛客网研究生机试题刷题记录
1.成绩排序这题我一开始采用的是排序算法,排序最快的时间复杂度为O(nlogn)。所以这里换一种思路,既然有100分,不如建立一个二维vector,在每一份的vector上push上姓名,这样时间复杂度降到O(n)。顺便复习一下排序的时间代价和分类。时间代价表:2.算约数的个数思路很简答的算法题,但是容易用最简单的方法,导致超时。这里记录一下思路:用一个i来进行循环,i &amp;amp;lt; ...原创 2018-11-04 00:10:24 · 895 阅读 · 0 评论 -
扒开衣服看递归--递归的本质
编程语言中,函数Func(Type a,……)直接或间接调用函数本身,则该函数称为递归函数。 – 《百度百科》我们一般运用递归算法来解决以下的几种问题:数据的定义是按递归定义的。(Fibonacci函数,n的阶乘)问题解法按递归实现。(回溯)数据的结构形式是按递归定义的。(二叉树的遍历,图的搜索)可能到现在很多同学还没弄明...原创 2018-11-06 22:19:49 · 3159 阅读 · 0 评论 -
蓝桥杯复习笔记
BASIC 3 字母图形这一题可以简化思路,规律从两个循环中获得(i - j)BASIC 10 十进制转16进制十进制转x进制的题目惯用模板,注意如果要转的进制超过10,要考虑字母的情况。 if (a == 0) { cout &lt;&lt; "0"; } else { while (a != 0) ...原创 2018-11-12 21:43:38 · 627 阅读 · 0 评论 -
高精度乘法 JAVA 和 C++ 版本
本文采用c++手动计算大数乘法。这是是个常见、标准的乘法算法。简单易懂,可以多次看记下来。string multiply(string num1, string num2) { string sum(num1.size() + num2.size(), '0'); for (int i = num1.size() - 1; 0 &amp;lt;= i; --i) { ...原创 2018-11-12 21:48:01 · 616 阅读 · 0 评论 -
LeetCode 100-Same Tree(DFS)
题目:https://leetcode.com/problems/same-tree/(DFS)概述: 给定两棵树,看是不是两棵相同的树,权值,结构,都一样。思路: 这一题做的方法有很多,只要把这棵树遍历下来即可。这里采用了dfs(深搜),才回想起来,原来树上用的中序遍历就是DFS。如果有一个是空树,两个都是空树即可,如果两个都不是空树,两者进行DFS。/** * Definition...原创 2018-11-06 00:56:55 · 184 阅读 · 0 评论 -
LeetCode 21-Merge Two Sorted Lists(链表)
题目: https://leetcode.com/problems/merge-two-sorted-lists/概述: 给定两个链表,让合并成一个链表,而且大小顺序要一定思路: 遍历两个链表,谁值小,先插谁。/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNo...原创 2018-11-22 21:24:57 · 234 阅读 · 0 评论 -
LeetCode 20-Valid Parentheses(栈)
题目: https://leetcode.com/problems/valid-parentheses/概述: 符号匹配问题,问是否所有的开符号都对应一个闭符号。思路: 用个栈即可class Solution {public: bool isValid(string s) { stack<char> paren; int n = s.l...原创 2018-11-22 20:55:46 · 171 阅读 · 0 评论 -
LeetCode 19-Remove Nth Node From End of List(链表)
题目: https://leetcode.com/problems/remove-nth-node-from-end-of-list/概述: 给定一条链表和一个数字n,删除这条链表上倒数第n个元素。思路: 如果非空,那么先找一个快指针,向前走两步,然后快慢指针一起走,快指针走到尽头,说明慢指针走到了倒数第二个。/** * Definition for singly-linked list....原创 2018-11-22 20:30:51 · 176 阅读 · 0 评论 -
LeetCode 17-Letter Combinations of a Phone Number(DFS)
题目: https://leetcode.com/problems/letter-combinations-of-a-phone-number/概述: 给一个手机键盘,按两个按钮,看有多少种字母组合的可能。思路: 简单的DFS即可。class Solution {public: vector&amp;amp;amp;lt;string&amp;amp;amp;gt; res; void dfs(int...原创 2018-11-21 16:46:01 · 218 阅读 · 0 评论 -
LeetCode 15-3Sum(双指针)
题目: https://leetcode.com/problems/3sum/概述: 给定一个数组,找出其中的三个数和为0。思路: 先把整个数组进行排序,然后对数组进行遍历。 要让 -num[i] = num[front] + num[back];即可,如果小了就把front 向右调一调,大了就把back向左调一调。这时候要注意除去重复的值,一个是除去重复的front和back,还有一个是要...原创 2018-11-21 16:04:02 · 247 阅读 · 0 评论 -
LeetCode 11- Container With Most Water(逻辑)
题目: https://leetcode.com/problems/container-with-most-water/概述: 给定一些木板的高度,求哪两块木板底乘高为最大值。思路: i 和 j 从两边开始走,如果他们不能提高更高的高度,就进行忽略,记住是小于等于,否则就不往前走了。class Solution {public: int maxArea(vector&lt;int&...原创 2018-11-21 14:32:23 · 177 阅读 · 1 评论 -
LeetCode 5-Longest Palindromic Substring(回文)
题目: https://leetcode.com/problems/longest-palindromic-substring/概述: 求长回文串思路: 一个for循环,i为下标,我们以这个i为中心,向两边辐射,看最长的回文串能有多长。记住要考虑两种情况:①要求的最长回文串为偶数个 ②要求的回文串为奇数个。 这点会在传参中体现。class Solution {public: int...原创 2018-11-21 11:22:56 · 181 阅读 · 0 评论 -
LeetCode 3-Longest Substring Without Repeating Characters(Map的应用)
题目: https://leetcode.com/problems/longest-substring-without-repeating-characters/概述 :找给定字符串中不重复的最长子集。思路 : 用map来存储每个字母最后出现的位置。j来表示不出现重复字母的最后的位置。用当前的i - j + 1 就是求出不重复的子串的长度,如果能当前不重复的子串的长度大于以前求的最大值,就进...原创 2018-11-21 11:09:30 · 157 阅读 · 0 评论