L++

《Java练习题》Java进阶练习题(二)

醉酒当歌 提交于 2021-01-09 02:07:54
编程合集: https://www.cnblogs.com/jssj/p/12002760.html 前言:不仅仅要实现,更要提升性能,精益求精,用尽量少的时间复杂度和空间复杂度解决问题。 【程序58】 给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点?(i,?ai) 。在坐标内画 n 条垂直线,垂直线 i?的两个端点分别为?(i,?ai) 和 (i, 0)。找出其中的两条线,使得它们与?x?轴共同构成的容器可以容纳最多的水。 说明:你不能倾斜容器,且?n?的值至少为 2。 图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。 /** * 给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点?(i,?ai) 。在坐标内画 n 条垂直线,垂直线 i?的两个端点分别为?(i,?ai) 和 (i, 0)。找出其中的两条线,使得它们与?x?轴共同构成的容器可以容纳最多的水。 * 说明:你不能倾斜容器,且?n?的值至少为 2。 * 图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。 */ public class Subject58 { public static void main(String[]

哈夫曼树与哈夫曼编码的实现

三世轮回 提交于 2020-12-19 10:43:12
  哈夫曼树是一种特殊的树,结合前面做书上 动态规划题 的了解,哈夫曼树就是最优二叉树。   建立一颗哈夫曼树前需要明确条件,比如一颗词典树(节点值为单词),我们希望能通过我们的查找习惯建立一颗更快、更合适的二叉树,那么,这里的条件就是树中每个单词的搜索频率,显然,搜索频率越高的单词越靠近树根,查找效率会更好,通过搜索频率(权值)与节点离根节点的路径距离计算出WPL(带权路径长),当词典树的形态为某种情况的时候(哈夫曼树总是一颗满二叉树 — 除叶节点外,内部节点都是儿孙满堂的),WPL最小,那么这样的一颗二叉树就是最优二叉树,也就是我们想要的树的形态了。   可通过动态规划算法证明,上面描述的二叉树的各个节点是否与最优二叉树的各节点相等。当然书上还有更严谨的数学证明。   WPL计算很简单,公式:WPL = ∑ L i × P i (其中L是路径长度,P是权值)。   建立哈夫曼树很简单:初始化节点数据,维护一个最小优先队列,将节点按权值大小加入到优先队列中,然后将队列中的节点弹出,由下而上建立哈夫曼树。   算法伪python代码: ''' class node: int f; //权值 type var; //其他数据类型 node left; ndoe right; ''' def build_Huffman_tree(nodes): """

​LeetCode刷题实战59:螺旋矩阵 II

落花浮王杯 提交于 2020-12-12 17:30:34
算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 ! 今天和大家聊的问题叫做 螺旋矩阵 II ,我们先来看题面: https://leetcode-cn.com/problems/spiral-matrix-ii/ Given a positive integer n, generate a square matrix filled with elements from 1 to n2 in spiral order. 题意 给定一个正整数 n ,生成一个包含 1 到 n 2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。 样例 输入: 3 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ] 解题 模拟法,设定边界 生成一个 n×n 空矩阵 mat,随后模拟整个向内环绕的填入过程: 定义当前左右上下边界 l,r,t,b,初始值 num = 1,迭代终止值 tar = n * n; 当 num <= tar 时,始终按照 从左到右 从上到下 从右到左 从下到上 填入顺序循环,每次填入后: 执行 num += 1:得到下一个需要填入的数字; 更新边界:例如从左到右填完后,上边界 t += 1

c++实验8 哈夫曼编码-译码器

Deadly 提交于 2020-12-12 05:26:30
哈夫曼编码-译码器 此次实验的注释解析多加不少---若对小伙伴们有帮助 希望各位麻烦点个关注 多谢 1.哈夫曼树构造算法为:   (1)由给定的n个权值{w1,w2,…,wn}构造n棵只有根结点的二叉树,从而得到一个二叉树森林F={T1,T2,…,Tn}。   (2)在二叉树森林F中选取根结点的权值最小和次小的两棵二叉树作为新的二叉树的左右子树构造新的二叉树,新的二叉树的根结点权值为左右子树根结点权值之和。   (3)在二叉树森林F中删除作为新二叉树左右子树的两棵二叉树,将新二叉树加入到二叉树森林F中。   (4)重复步骤(2)和(3),当二叉树森林F中只剩下一棵二叉树时,这棵二叉树就是所构造的哈夫曼树。 2.编程实战: [问题描述](设计性实验) 哈夫曼树很易求出给定字符集及其概率(或频度)分布的最优前缀码。哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。该技术一般可将数据文件压缩掉20%至90%,其压缩效率取决于被压缩文件的特征。 利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时,降低传输成本。但是,这要求在发送端通过一个编码系统对待传送电文须预先编码,在接收须将传送来的数据进行译码。请自行设计实现一个具有初始化、编码、译码、输入/输出等功能的哈夫曼码的编码/译码系统。并实现以下报文的编码和译码:“this program is my favorite”。

排序--快速排序分析

走远了吗. 提交于 2020-12-07 19:26:13
快速排序实现代码: 快速排序 可以看到我的代码有一个错误版,我在这里给大家分析一下为什么会出现错误,并且将之记录以便今后进行查阅。 快速排序(错误版分析) int Quick :: process( int array [], int l, int r) { int temp = array [l]; while (l != r) { while ( array [r] >= temp) r--; array [l] = array [r]; l++; while ( array [l] <= temp) l++; array [r] = array [l]; r--; } array [l] = temp; return l; } 如上是我自己实现的单趟快速排序。 快排的算法思想 从待排序列中任意选择一个记录,以该记录为关键字,凡数组中元素小于该关键字的都移动至该关键字前面,反之移动到后面。致使一趟快速排序之后,以关键字为中点将数组分割成左右两个序列。然后分别对两个子序列递归进行快速排序,直至每个子序列中只含有一个元素为止。 为什么上面这个代码会出现段错误,首先我们来看: while ( array [r] >= temp) r --; 我在上面的while循环里面设定了l != r,也就是说一趟快速排序结束的标志就是当l == r的时候,然后在进行元素和关键字记录比较的时候

「PKUSC2018」神仙的游戏

筅森魡賤 提交于 2020-12-04 14:01:59
由于day2在考场上错误的先开了T3,导致T2只打满了暴力。。。T1暴力都没打满。。。 最后T3虽然想出了正解却因为计算几何的某些细节不会处理而gg掉了(平时不学计算几何活该gg),只得了20分。。。 于是只有132分,被大众分虐暴QWQWQWQWQWQ 其实T2的正解只要想到了 最后一个部分分就差不多会做啦。。。。 由于一个1和0 位移差的绝对值的 所以约数的位移差 的border 都不可行,所以正着的[ s[i] == '1' ] 和 倒着的 [ s[i] == '0' ] 卷一下,就可以判断哪些位移是可行的(不考虑被倍数覆盖的),然后再一个调和级数考虑倍数覆盖就好啦。。。 至于卷积写个FFT就ojbk了,注意eps不要开太小。。。不然会gg #include<cstdio> #include<cstdlib> #include<algorithm> #include<ctime> #include<iostream> #include<complex> #include<cmath> #include<cstring> #define ll long long #define D double #define E complex<double> using namespace std; const int maxn=1100005; const D eps=1e-6,pi

LGP4518[JSOI2018]绝地反击

﹥>﹥吖頭↗ 提交于 2020-12-04 11:57:57
题解: 只要确定了每艘飞船的就位位置,就可以用二分+网络流求得答案; 定义偏转角度$a$为离$x$正半轴逆时针最近的边的弧度,$a \in [0,\frac{2\pi}{n})$ 二分一个值,对于一个点可以求出可到达的弧度记为$[l,r]$ 那么在$[0,a]$的移动范围内只有可能前面一个点删除,后面一个点加入; 对$O(n)$个关键点做网络流即可; 复杂度$O(n^4 \ logn)$ 如果将关键点排序,每次只考虑变化的边退流可以优化到:$O(n^3 \log n)$ 1 #include<bits/stdc++.h> 2 #define ld double 3 using namespace std; 4 const int N= 610 ,M= 100010 ,inf= 0x3f3f3f3f ; 5 const ld Pi=acos(- 1 ),eps=1e- 9 ; 6 int n,S,T,vis[N],hd[N],o,cur[N],d[N],que[N],head,tail,flow,cnt; 7 ld R,B; 8 struct Edge{ int v,nt,f;}E[M<< 1 ]; 9 struct poi{ld x,y;}p[N]; 10 ld dis(poi A){ return sqrt(A.x*A.x+A.y* A.y);} 11 struct data{

Leetcode 312.戳气球

孤街醉人 提交于 2020-11-24 19:24:23
戳气球 有 n 个气球,编号为0 到 n-1,每个气球上都标有一个数字,这些数字存在数组 nums 中。 现在要求你戳破所有的气球。每当你戳破一个气球 i 时,你可以获得 nums[left] * nums[i] * nums[right] 个硬币。 这里的 left 和 right 代表和 i 相邻的两个气球的序号。注意当你戳破了气球 i 后,气球 left 和气球 right 就变成了相邻的气球。 求所能获得硬币的最大数量。 说明: 你可以假设 nums[-1] = nums[n] = 1,但注意它们不是真实存在的所以并不能被戳破。 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100 示例: 输入: [3,1,5,8] 输出: 167 解释: nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> [] coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167 思路 考虑最后一个戳破的气球,这个气球的位置可以把整个气球数组分成两部分。 注意是最后一个,不是第一个,之前一直没转过弯来。 利用动态规划思路: 动态规划数组: DP[k][h]:nums[k...h]能戳破气球的最大值 递推关系: 取k<m<h,nums[m]假设是最后一个戳破的气球 则DP[k][h] = for (m = k+1.

loj #117. 有源汇有上下界最小流

元气小坏坏 提交于 2020-11-22 05:22:37
题目链接 有源汇有上下界最小流,-> 上下界网络流 注意细节,边数组也要算上后加到SS,TT边。 1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 7 using namespace std; 8 9 const int N = 150010 ; 10 const int INF = 1e9; 11 12 struct Edge{ 13 int to,nxt,c; 14 }e[ 500100 ]; 15 int head[N],dis[N],cur[N],M[N]; 16 int q[ 500100 ],L,R; 17 int tot = 1 ,n,m,S,T,Sum; 18 19 inline char nc() { 20 static char buf[ 100000 ],*p1 = buf,*p2 = buf; 21 return p1==p2&&(p2=(p1=buf)+fread(buf, 1 , 100000 ,stdin),p1==p2)?EOF:*p1++ ; 22 } 23 inline int read() { 24 int x = 0 ,f = 1 ; char ch = nc(); 25 for (; ch

LeetCode:学生的出勤记录|【551】

早过忘川 提交于 2020-11-17 06:28:03
LeetCode:学生的出勤记录|【551】 题目描述 给定一个字符串来代表一个学生的出勤纪录,这个纪录仅包含以下三个字符: 'A' : Absent,缺勤 'L' : Late,迟到 'P' : Present,到场 如果一个学生的出勤纪录中不超过一个'A'(缺勤)并且不超过两个连续的'L'(迟到),那么这个学生会被奖赏。 你需要根据这个学生的出勤纪录判断他是否会被奖赏。 示例 1: 输入: "PPALLP" 输出: True 示例 2: 输入: "PPALLL" 输出: False 题目分析   对于字符串问题,我们 需要反思,所谓的顽石——正则表达式 。   很多问题明明可以快速得到解决,就是因为我们的下的苦太少了,所以事与愿违。    L{3,}可以表示连续3个及以上L出现,A.*A可以表示出现2次A的情况 ,这样如果正则匹配成功,那么就说明不会被奖赏!   Java题解 class Solution { public boolean checkRecord(String s) { if(s.matches(".*L{3,}.*")) return false; if(s.matches(".*A.*A.*")) return false; return true; } }   但是上面的 对于这道题来说 正则表达式解法简洁却不高效 。   我们循环一次字符串,