没事玩玩leetcode周赛 #30~#34 #40 #42~#48 #50~#54 #56 #58 #59 60 #61

来源:互联网 发布:unity3d water 编辑:程序博客网 时间:2024/06/08 14:45

怒跪。

#1. 矩阵reshape操作,手速题。

#2 求 给定整数【-1000,1000】数组(20000长度)  ,求区间和为k(1e-7,1e7)的区间数量。

算法:朴实平方算法肯定超时。 预处理前缀和,然后 问题转化为数组中内俩个数差为k的对数。  ,从前往后扫,每次 ans+=map[sum[i]-k]有几个,然后map[sum[i]]++。 这样子在统计答案之后再做后面的加入, 防止后面的和还没有求就加入。


#3 求 字符串 s1 的是否存在一个排列 是s2的子串。 

算法: 每次在s2中枚举s1长度的区间 (O(s2.size)), 看枚举的区间和s1各个字母数量是否完全一样(o(26))。一样就找到了。总复杂度O(s2.size*26)


反思:,每次看自己状态?状态是理由?


------------------------------------------------------------------------------------------------------------------------------------------------------
5.7

今天也是极差。。

@1 手速题,ps网站很卡。
@2 判断给定二叉树s , t是不是s子树。 拿到题一下,如果中序遍历和先序遍历 的序列都是s的子串。那么OK了。 结果错误,因为 不是子图, 是子树,即s的某子树是不是和t完全一样。。。。正确解法时间暴力,o(s)*(T)  ,对s的每个节点的形成的子树判断一次是否完全一样。

@3 求 s  到  t最短路, 经过 n个宝藏的必经点, 。。。题意理解错误。。。还想上蚁群了。  题意是每取得一个宝藏就要先放到t, 那么就是 s 到其中一个宝藏,然后就是宝藏和t点来回跑, 0(N)枚举先去哪个宝藏就可以了。。。。

为什么每次,,,,。。
希望下次好一点。。


------------------------------------------------------------------------------------------------------------------------------------------------

5.14

网速好差,每次都要延迟5分钟才能看到题。。

@1手速题,排序一下比对,注意一下坑点就是原数组有序。
@2求 给定俩个数组,第二个数组是第1个对应位置的父亲节点,求去掉某节点后,该点以及它的子树。 暴力每个点一直找父亲,如果是路径中存在指定点,则该点就是。优化方法是每次枚举,如果是的话,标记一下。

@ 3简单二维DP题。求给定俩个字符串,最少去掉多少字符后俩个字符串相同。模型:求最长公共子字符串(不需要连续)。也相当于给一个二分图匹配,求最大匹配(该匹配不能有连线相交)。一直以为是个最长上升子序列。。以为有的点可以对应多个,不符。 平方算法:dp[i][j],第一个串到i,第二个串到j时,最优情况。如果相等,dp【i+1】【j+1】=dp【i】【j】+1,否者(自己想)。。。

@ 4求凸包。 顺便学习了凸包问题的4种死法:
1 ,O(N^3)暴力判断俩个点连线,如果所有其他点都在一侧,则该直线一定是边界。
2  0(N*H)H是凸包上的点。纵坐标最小的点一定是凸包上的点。然后以该经过点平行X正方向的向量,逆时针转,第一个遇到的点就是下一个凸包上的点(遍历所有点,求角度最小的),然后以该点起点继续旋转向量,反复执行,每次获得一个凸包上的点,直到最后再次经过第一个点。
3. O(NLogN)先将所有坐标平移,使得Y值最小的点(这个必是凸包上的点)为原点,。然后将所有点按极角排序(相同的,远的排在后面),形成一个数组A。用栈来做:初初始化栈为A的前两个元素。然后每次用栈顶的俩个元素的连线,如果A中的当前点在直线右边,则弹栈,继续这样子判断。否则(左边或者直线上),入栈,继续取A中元素。
A中遍历结束算法结束。在栈中的点为图标上的点(按极角逆时针有序)。
4  divide and conquer(不说了)
这里说的不错,但是里面的算法4描述是错误的,按我的3来。:http://blog.csdn.net/bone_ace/article/details/46239187


------------------------------------------------------------------------------------------------------------------------------------------------

5.21

今天大521生日~
哎。。
@1  给定数组,求最长的子序列(可以不连续), 子序列中最大的数-最小的=1.   
       因为顺序无关,先排序,然后不同的数分段,如果下一段是前一段+1,就更新一次。   还有一种就是hash方法,扫一次,统计每个数多少。然后遍历1-最大的数,统计更新。

@2  二维空间,给四个整点,判断是不是正方形。
       先按横坐标排序,次纵坐标,然后判断,结果 WA了一次,因为还有斜着的情况QAQ。。。所以,求6条长度(4条边+2对角线),排序长度后判断。

@3 分数加减模拟
      QAQ,减法负负得正也是醉了。。傻到没朋友。。 。。直接模拟分数加法,然后求GCD,约分。


------------------------------------------------------------------------------------------------------------------------------------------------

5.28

@1  看thcik 手速题。

@2  直接暴力 平方算

@3  给定数组(0 -N-1), 求从某下标开始不断迭代,形成的最大集合。 
        每个迭代形成一个集合,标记一下,每次循环没有标记的,直接搞或者并查集都可以。

@4   求小于等于n 的 它的二进制表达不含连续1的 数的个数。
         数位dp, dp[i] : i 位数 满足条件的个数。  则dp[i]=dp[i-1]+dp[i-2]  
         则从高位到低位扫描数,每扫描到一个1 统计一次(相当于本次计算一个区间),到连续的1则停止。
       
      

---------------------------------------------------------------------------------------------
7.9 
不小心瞎忙了一个月。。也不知道忙什么。。。

#40
@1  二叉树遍历,求每层的平均值,直接搞了

@2 字符串模拟,求给定1元1次方程求解,或者输出无解或者无穷解。模拟等号俩边求出x项系数和常数项,对比一下即可。

@3 给一些商品,还有一些搭配的组合买法,求一种最佳的恰好满足需求的方案。居然是指暴力2^N的算法。暴力DFS。

@4 求字符数的解码。很容易想到的位数dp. 一遍扫过去,每次考虑与前一位结合或者不结合的情况。


---------------------------------------------------------------------------------------------

7.23
暑期一半又过去了,除了做项目,,,什么都没有干。。。打打比赛还是练练手。
#42
@1手速题(今天好像都是手速。。),统计一下数即可
@2求最长的序列。直接按结束的那个数字排序,贪心拼接即可。后面数字小的取来。
@3求回文子字符串数量。老掉牙的题。 2种情况枚举中心, 平方算法。或者dp
@4用给定词根字典,去替换给定的句子中的词(用最短的词根去替换含有该词根的所有词):
    我是直接暴力过的。赛后看别人的,有的用字典树,有的给词根编码(longlong,string,26进制或者257,爆了可能是负数,没事,冲突?概率极低吧。)



---------------------------------------------------------------------------------------------
7.30
#43
第一题没理解,没做。
@2  求完成给定长度的最小操作。 直接dp 处理出所有 情况, dp[i] 表示 长度为i 的最少次数。dp [i] =max(dp[i], dp[j]*i/j+1)  其中 j是 i的最大因子
@3  直接暴力模拟就可以,晚了一点点题交
@4  求给定操作次数的最大长度。 dp, 枚举比自己小的长度不断复制而得,平方算法。





---------------------------------------------------------------------------------------------
8.6
#44
@1 求二叉搜索树,存在俩个节点的和等于给定数字。dfs一遍,map保存判断一下。
@2 求给定数组,求对应数组最大二叉树,最大二叉树:root节点是最大值,左右子树都是最大二叉树,左/右子树对饮数组最大值左/右边的子数组序列。
        直接按定义模拟递归生成二叉树即可。
@3 求给定二叉树,按规则打印一个二维的字符串数组。
       先按层次算出数组的行,列数。然后再dfs二叉树,打印每个节点对应位置。
@4 求花费最小的跳步路径,如果一样,按字典序最小的路径输出。每次最多跳b步,-1的地方不能跳。
     dp直接,正向dp有结果,但是路径不对,不是字典序最小。赛后发现是反向dp,这样子每次选择,在相同解的情况下,保证字典序最小,肯定选最近的跳。

---------------------------------------------------------------------------------------------

8.13
#45
@1 手速题,2分钟。
@2 查找数组中最近的k个数,直接找到最近的数后俩边扫。
@3 将一个非递减序列,拆分成n个子序列,要求每个子序列连续(严格增),而且至少包括3个元素。 (不会做)
@4 将自然数序列,去掉所有包含9的数字。求该新序列第N个数。
解法:1到10^i内 含有9个数字个数递推公式为 f[i]=9*f[i-1]+10^(i-1),这个好推。有这个,就好算了,按区间从大到小去减不含9的数字个数。 这是通用解法。
牛逼解法: 这样子做,不就是等价于,给你十进制数N,转为9进制是几吗QAQ。 去掉9相当于逢9进1.



---------------------------------------------------------------------------------------------

8.20
#46
@1 扫描矩阵每个元素的8领域,草,我居然一个点一个点判断越界、、、一是复制到新的有边缘的矩阵(边缘赋值-1),然后判断,或者每次循环-1到1。
@2 求二叉树 最大宽度:某一层最左边的节点和最右边的节点的距离(中间空节点也算)。 解法: dfs向左走val*2-1,右走val*2,记录每层最左(小)值和最右(大)值,最后遍历每层的最大差即可。

@3 求二叉树,拿掉一条边之后,俩个子树是否相等:(所有节点之和是否相等)。先dfs算出总和。然后dfs 计算当前子树和,当前子树和如果是总和一半就肯定可以。


---------------------------------------------------------------------------------------------
#47
@1 给一个序列,在允许修改一个数字的情况下,保证序列是非递减序列。判断是否可能。
解法: 1:如果两次出现递减,则不可能。2 当第i处-第i+1处出现递减时候:要么修复第i处,要么修改第i+1处,如果这俩个地方修改都不可能做到(修改第i处不可能:如果i-1处大于i+1处,修改i+1处同理),则不可能。

@2 给一种新的二叉树定义。求所有根到叶子节点路径,求经过的节点之和。
ans: sum{经过节点次数*该节点值} ,关键是求节点次数,他的子树有几个叶子,就是次数,从底往上传递即可。
@3 求构造一个1-n的一个排列,该排列满足所有相邻的数之间的差的绝对值 构成的集合的大小为给定的K(K<N)。
解法:刚刚开始想,如果给定排列,那么这个集合大小就能算出,现在反过来求,那么我构造1~k+1,剩下的递增即可。很容易就想到交叉构造:1 k+1 2 k-1...这样子的满足条件。当然构造方法有很多,任意一种满足条件都可以

---------------------------------------------------------------------------------------------
#48
暑期是结束了,一事无成。。
@1 求二叉树中第二大的数。dfs找出来,排序取第二大的数。这树自己的特点,直接找也可以。
@2 给定搜索二叉树,要求删去在给定【L,R】范围以外的所有节点。
解法:先处理根节点,不满足的话(分小于L或者大于R)对应以左/右孩子对根,直到满足为止。然后dfs,如果左孩子不满足,将左孩子的右孩子挂过来,右孩子同理。
高手解法:函数返回的是已经满足条件的树。如果当前节点不满足,那当前节点小于L:当前右孩子为根递归,同理左孩子。当前节点满足:新建节点值为当前节点,然后左右孩子分别指向以该节点左右孩子为参数的递归函数。

@3 给数字,求交换俩个位后最大的数。直接暴力。转字符串再转数字。

@4 给N个灯初期全为1,4种操作(1.反转所有状态。2 反转奇数位状态,3反转偶数位状态 4 从第一个开始反转,然后每隔2个反转状态) 。求M次操作后,可能的状态数。、
解法: 主要要想到这一点;最后状态与操作顺序无关,而且对每种操作,只与偶数次和奇数次有关。那么最多一共(2*2*2*2=16)种最终结果(实际达不到,因为有操作叠加效果会重复)。 我是暴力枚举,判断m/n。 他们是枚举16种状态,每次判断n种灯状态,最后set统计状态数(注意,n很大无关,可以n>30,n=30,不影响结果




---------------------------------------------------------------------------------------------
#50
这次一看居然都有点小麻烦。。
@1 给一个字符串判断最多去掉一个的情况下,是否回文。
解法: 俩边一起走,到不同:这时候必须要去掉一个,分别测试。
@2 《字符串,Int>对,每次可以插入,或者求给定前缀下,所有拥有该前缀的key的值的和。 用map,然后暴力。
@3 给( * )三种组成的序列,求序列是否合法。其中*是万能符号,可以替代也可以为空。解法,用栈,(*入栈,遇到),回溯找到第一个对应的(,消掉,否则用*消掉。最后在栈中只有( *,每次遇到* mark++, 否则遇到(,判断mark==0则失败。反之成功。
@4速算24点,给4个实数。判断能否通过加减乘除括号(不能取负),最后算出24点。
解法:暴力!!!每次暴力枚举前2个数,加减乘除中间结果6个数字(减法和除法有顺序),再枚举第三个数字加减乘除产生6个,再与最后一个,加减乘除产生6个,最后判断结果中是否有24。 还有一种情况:俩俩枚举, 最后中间过程6*6种情况,运算。总复杂度(4*4*4)*(6*4*6*6+4*6*6*6)=64*216*2,很小的数。



---------------------------------------------------------------------------------------------
#52 /2017.10.1
@1 求字符串A至少重复几次后B是A的子串。 不断重复,到比它长,最多再重复一次。主要还是string中 s.find() ,失败返回string::nops(一般是-1)。

@2 求给定二叉树,求最长路径(要求路径中的所有节点的值相等情况下)。递归做,每次判断左右孩子是否和自己相等(不等则为0),返回max(左子树最长,右子树最长)+1。

@3给一个棋盘,马从(x,y)出发,每次等概率走八个方向,求最后K步之后留下来概率。
   其实就是求K步之后有多少状态可能留下来,每走一步乘以1/8.
   这种题型可用扫描法,dp[s][i][j] 当前走了s步,i,j位置的概率。dp[s][i][j]=dp[s-1][x][y](x,y为 八个方向过来的位置)。



---------------------------------------------------------------------------------------------
#53 /2017.10.8
@1 求给定数字,判断其二进制下是否是101/1010交替的。遍历一下,判断即可(为什么自己手速总是慢QAQ)
@2 给一个01矩阵,求最大的1的连通块大小。一直在想有没有简单的方法。最后还是用的遍历,每次检测到1再bfs/dfs.
@3 同上,但是求有几个形状不同的连通块。我的方法先是用bfs,记录四个方向的遍历顺序,但是WA,该用DFS也是WA,因为不同的形状可能有相同的遍历顺序,于是同时记录回溯的顺序,这样子来记录形状。最后AC。看高手解法是记录坐标,形状不同但是相对位置相同的,于是每个点都减去第一检测到的(最右上的)点的坐标。最后都用set判重。


#54 /2017.10.15
最近大比赛的人越来越多了。
@1 #697 给一个数组,出现次数最多的数个个数就是这个数组的度。求所有数组的连续子序列中度数和原数组一样的长度最短的。
O(N),求最短的,遍历一下,用三个map<int,int> 记录当前数的出现次数、最左边的元素、最右边的元素。然后遍历找到最大度数的数,更新最小长度。
@2 #696 给一个字符串,求满足要求的子串个数:1,要求子串01数量相等,2 要求子串0或者1连续出现(不能交替出现)
dp[i]记录到i为止子串个数,c[i]记录i为止,i包括满足要求的长度。好写递推。
暴力搞也行。
#3 判断数组划分成k个和相等的集合(可以不连续)。
这题数组长度只有16,K不超过16. 所以直接暴力dfs.

#56 /2017.10.29

@1 # 717 求给定数组,求反编码(解码)的方式。判断一下,想想就够了。
@2 # 443 求给定字符数组,求压缩后字符字符数组 。如“aabbccc”->"a2b2c3" 每次hi考虑单个字符。扫一遍即可。
@3 # 718 求最长公共自序列,要求连续。 哈哈哈 ,相等的话 dp[i][j]=dp[i-1][j-1]+1,否者dp[i][j]=0, 最后扫一遍得最大的即可。
@4 # 719 求给定正整数的数组,求绝对值差为第K小的差值。 这里第k小指所有对形成的差排序后,第k个。思路:先排序,二分枚举绝对值(答案),然后o(N)判断出是第几,(扫一遍,求出比当前差小的数对对数)。典型二分枚举答案,然后判断答案来指导二分!


# 58 2017.11.12

@1 给一数组,求最左边的下标,使得该下标左右俩边之和相等。 我开了一个前缀和数组,判断了下。看别人直接开前缀和和后缀和,更加方便一点。
@2 给一个链表,按序切分成k段。 每段长度最多差1。直接遍历下。
@4 !!!!!! 求字符串S 的最短连续子串,该子串包含着字符串t (字符串t可以不连续地镶嵌在最短子串中)。 (字符串只含小写字母)
估计是这种题型(包含有限字符的字符串包含问题m+n)通用解法: 用一个数组next[i][j]: 原字符串s下标i后面距离字母j最近的位置。 一般开 ; next[s.size()][26]. 有了这个数组就好做了,枚举s的开头字母,然后每给 t的一个字符t[j] 不断next[i][t[j]-'a'] , 如果next值为初始值-1,表示没有找到。总复杂度m*n.


#59 11.19

@1 手速题。
@2 给每次来一个区间,如果没有重叠,则加入,否者不要。 平方暴力。 还有一种就是用map标记法 :起点标记为1,终点为-1, 然后从小到大遍历(map默认有序)。 如果当期和大于等于2,则比如重叠,去掉。
@4 在上题基础上,改为3个区间有重才不要,否者就加入。则条件改为 大于等于3即可。注意此时map记录下当期点个数。


#60 11.26

@1,2简单题。bfs之类

@3 给一个一维空间,很多质点有质量,以相同速度,要么往左要么右。如果相碰,那么小的质量将被毁灭。问最后留下的球的集合。
骚味思考一下就有答案了: 消失只会发生在方向不一样的情况下,考虑往右的,倒过来扫,如果遇到往左的就入栈,遇到右的,每次和栈顶元素比,一样就俩个都消失(标记一下,并出战),右的大,就出战(消失标记),直到栈空,或者左大,那右的消失。。。也不知怎么解释怎么想到的。。。


2017.12 .3
#61 今天都是dp??
@1(739) 给一个温度序列 ,返回一个序列, 记录每个数字后面最近的一个比它大的数字和它间隔多少。打过来扫,用一个数组每次记录最近的比自己大的位子,如果当前不比自己大,那就用这个数组跳转到下个比它大的位子。没有就是-1.

@2 给一个数字,求不比大的的最近的 按位不减数字(如1123,而3211不是)。 直接暴力,扫到第一处递减时候,返回到第一处地方减一,然后后面都是9。比如(668846->667999)

@3 给一个数组,每次可以取一个数,取了这个数可以得这个数字分数,然后他+1或者他-1的数字将消失。求最大获利。(每次只能往下或者玩右,回来相反)
先排序,然后dp, dp[i][1]:目前为止取这个数最大获利,dp[i][0]不取这个数最大获利。递推过去就可以。
方法2: 统计所有数字频率,然后dp[x] 从1开始扫到x的最大获利。dp[x]=max(dp[x], dp[x-2]+cnt[x]*x)??
@4 经典题。一个矩阵,-1是墙,从0,0 到n-1,n-1,然后回来,到0,0. 求最大分数(每个点有分数,但是走过一次,分数降为0)。
相当于2个人同时走,从从0,0 到n-1,n-1,dp[k][x1][x2], 记录状态: 一共走了第k步,第一个人坐标(x1,k-x1),第二个(x2,k-x2)。 当x1=x2时候,总分只能加一次当前点。还有每次从各个状态更新过来,初始化dp -1,如果更新后还是-1 就continue,说明这个点走不过来!
 vector<vector<vector<int>>> dp(n*2+1,vector<vector<int>>(n+1,vector<int>(n+1,-1)));               dp[2][1][1]= a[0][0];        for(int k=3;k<=2*n;k++)   //这样子初始化,因为从1,1开始,k没走时候就是2.       {           for(int x1=1;x1<=n&&x1<k;x1++)               for(int x2=1;x2<=n&&x2<k;x2++)               {                   if(a[x1-1][k-x1-1]==-1||a[x2-1][k-x2-1]==-1) //有一个走不过去,当前状态作废                       continue ;                    dp[k][x1][x2]=max(dp[k-1][x1][x2],max(dp[k-1][x1-1][x2],max(dp[k-1][x1][x2-1],dp[k-1][x1-1][x2-1])));                                      if(dp[k][x1][x2]==-1)    continue;                                       if(x1==x2)                    dp[k][x1][x2]+=a[x1-1][k-x1-1];                //相等算一次                   else                    dp[k][x1][x2]+=a[x1-1][k-x1-1]+a[x2-1][k-x2-1];               }       }        return max(0,dp[2*n][n][n]);















---------------------------------------------------------------------------------------------

1 0
原创粉丝点击