算法笔记_036:预排序(Java)
目录
1 问题描述
在计算机科学中,预排序是一种很古老的思想。实际上,对于排序算法的兴趣很大程度上是因为这样一个事实:如果列表是有序的,许多关于列表的问题更容易求解。显然,对于包含了排序操作,这种算法的时间效率依赖于所选用的排序算法的效率。
对于预排序的具体思想应用请参考下文。
2 解决方案
2.1 检验数组中元素的唯一性
此问题,首先使用合并排序对数组中元素进行一次从小到大的排序,然后,依次检查数组中的元素,看是否有重复元素,如果有这说明该元素不具有唯一性,否则说明该数组中的所有元素具有元素的唯一性。
具体代码如下:
package com.liuzhen.chapter6;
public class PresortElementUniqueness {
//归并排序
public void mergeSort(int[] A){
if(A.length > 1){
int[] leftA = getHalfArray(A,0); //数组A的左半部分
int[] rightA = getHalfArray(A,1); //数组A的右半部分
mergeSort(leftA);
mergeSort(rightA);
getMerge(A,leftA,rightA);
}
}
/*
* 参数A:要进行折半的数组
* 参数judge:judge == 0表示返回数组A左上半部分,judge != 0表示返回数组A的右半部分
* 函数功能:把数组按照长度均分为上半部分和下半部分
*/
public int[] getHalfArray(int[] A,int judge){
int[] result;
if(judge == 0){
result = new int[A.length/2];
for(int i = 0;i < A.length/2;i++)
result[i] = A[i];
}
else{
result = new int[A.length - A.length/2];
for(int i = 0;i < A.length - A.length/2;i++)
result[i] = A[i+A.length/2];
}
return result;
}
/*
*参数A:给定待排序数组
*参数leftA:数组A的左半部分
*参数rightA:数组的右半部分
*函数功能:返回数组A的从小到大排序
*/
public void getMerge(int[] A,int[] leftA,int[] rightA){
int i = 0; //用于计算当前遍历leftA的元素个数
int j = 0; //用于计算当前遍历rightA的元素个数
int count = 0; //用于计算当前得到按从小到大排序的A的元素个数
while(i < leftA.length && j < rightA.length){
if(leftA[i] < rightA[j]){
A[count++] = leftA[i];
i++;
}
else{
A[count++] = rightA[j];
j++;
}
}
if(i < leftA.length){
while(i < leftA.length)
A[count++] = leftA[i++];
}
if(j < rightA.length){
while(j < rightA.length)
A[count++] = rightA[j++];
}
}
//判断数组A(PS:数组A已是有序数组)中元素是否具有唯一性
public boolean judgeOnlyElement(int[] A){
for(int i = 0;i < A.length-1;i++){
if(A[i] == A[i+1])
return false;
}
return true;
}
public static void main(String[] args){
PresortElementUniqueness test = new PresortElementUniqueness();
int[] A = {3,2,1,8,7,4,3,6,1,7,3,3,7,7,7,7};
test.mergeSort(A);
System.out.println("使用归并排序后数组A的结果:");
for(int i = 0;i < A.length;i++)
System.out.print(A[i]+" ");
if(test.judgeOnlyElement(A))
System.out.println("\n数组A中的元素具有唯一性");
else
System.out.println("\n数组A中的元素不具有唯一性");
int[] B = {9,8,7,6,5,4,3,2,1};
test.mergeSort(B);
System.out.println("使用归并排序后数组B的结果:");
for(int i = 0;i < B.length;i++)
System.out.print(B[i]+" ");
if(test.judgeOnlyElement(B))
System.out.println("\n数组B中的元素具有唯一性");
else
System.out.println("\n数组B中的元素不具有唯一性");
}
}
运算结果:
使用归并排序后数组A的结果:
1 1 2 3 3 3 3 4 6 7 7 7 7 7 7 8
数组A中的元素不具有唯一性
使用归并排序后数组B的结果:
1 2 3 4 5 6 7 8 9
数组B中的元素具有唯一性
2.2 模式计算
在给定的数组列表中最经常出现的一个数值称为模式。例如,对于5,1,5,7,6,5,7来说,模式是5(如果若干个不同的值都是最经常出现的,它们中的任何一个都可以看作模式。)
此处,首先对给定数组中元素使用合并排序进行从小到大排序,然后,依次遍历其中的元素,计算其中重复元素的最大个数,返回该元素的值,即为所求的模式。
具体代码如下:
package com.liuzhen.chapter6;
public class PresortElementUniqueness {
//归并排序
public void mergeSort(int[] A){
if(A.length > 1){
int[] leftA = getHalfArray(A,0); //数组A的左半部分
int[] rightA = getHalfArray(A,1); //数组A的右半部分
mergeSort(leftA);
mergeSort(rightA);
getMerge(A,leftA,rightA);
}
}
/*
* 参数A:要进行折半的数组
* 参数judge:judge == 0表示返回数组A左上半部分,judge != 0表示返回数组A的右半部分
* 函数功能:把数组按照长度均分为上半部分和下半部分
*/
public int[] getHalfArray(int[] A,int judge){
int[] result;
if(judge == 0){
result = new int[A.length/2];
for(int i = 0;i < A.length/2;i++)
result[i] = A[i];
}
else{
result = new int[A.length - A.length/2];
for(int i = 0;i < A.length - A.length/2;i++)
result[i] = A[i+A.length/2];
}
return result;
}
/*
*参数A:给定待排序数组
*参数leftA:数组A的左半部分
*参数rightA:数组的右半部分
*函数功能:返回数组A的从小到大排序
*/
public void getMerge(int[] A,int[] leftA,int[] rightA){
int i = 0; //用于计算当前遍历leftA的元素个数
int j = 0; //用于计算当前遍历rightA的元素个数
int count = 0; //用于计算当前得到按从小到大排序的A的元素个数
while(i < leftA.length && j < rightA.length){
if(leftA[i] < rightA[j]){
A[count++] = leftA[i];
i++;
}
else{
A[count++] = rightA[j];
j++;
}
}
if(i < leftA.length){
while(i < leftA.length)
A[count++] = leftA[i++];
}
if(j < rightA.length){
while(j < rightA.length)
A[count++] = rightA[j++];
}
}
//返回数组A(PS:数组A是有序数组)中模式
public int presortMode(int[] A){
int i = 0;
int modeFrequency = 0;
int modeValue = 0;
while(i < A.length){
int temp = i;
int count = 0;
while(temp < A.length && A[temp] == A[i]){
count++;
temp++;
}
if(count > modeFrequency){
modeFrequency = count;
modeValue = A[i];
}
i = i+count;
}
return modeValue;
}
public static void main(String[] args){
PresortElementUniqueness test = new PresortElementUniqueness();
int[] A = {3,2,1,8,7,4,3,6,1,7,3,3,7,7,7,7};
test.mergeSort(A);
System.out.println("使用归并排序后数组A的结果:");
for(int i = 0;i < A.length;i++)
System.out.print(A[i]+" ");
System.out.println("\n数组A中模式为:"+test.presortMode(A));
int[] B = {9,8,7,6,5,4,3,2,1};
test.mergeSort(B);
System.out.println("使用归并排序后数组B的结果:");
for(int i = 0;i < B.length;i++)
System.out.print(B[i]+" ");
System.out.println("\n数组B中模式为:"+test.presortMode(B));
}
}
运算结果:
使用归并排序后数组A的结果:
1 1 2 3 3 3 3 4 6 7 7 7 7 7 7 8
数组A中模式为:7
使用归并排序后数组B的结果:
1 2 3 4 5 6 7 8 9
数组B中模式为:1
算法笔记_036:预排序(Java)的更多相关文章
- 算法笔记_023:拓扑排序(Java)
目录 1 问题描述 2 解决方案 2.1 基于减治法实现 2.2 基于深度优先查找实现 1 问题描述 给定一个有向图,求取此图的拓扑排序序列. 那么,何为拓扑排序? 定义:将有向图中的顶点以线性方式进 ...
- 算法笔记_018:旅行商问题(Java)
目录 1 问题描述 2 解决方案 2.1 蛮力法 2.2 减治法 2.2.1 Johson-Trotter算法 2.2.2 基于字典序的算法 1 问题描述 何为旅行商问题?按照非专业的说法,这个问 ...
- 算法练习5---快速排序Java版
基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成 ...
- 算法笔记_014:合并排序(Java)
1 问题描述 给定一组数据,使用合并排序得到这组数据的非降序排列. 2 解决方案 2.1 合并排序原理简介 引用自百度百科: 合并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Div ...
- 算法笔记_145:拓扑排序的应用(Java)
目录 1 问题描述 2 解决方案 1 问题描述 给出一些球,从1~N编号,他们的重量都不相同,也用1~N标记加以区分(这里真心恶毒啊,估计很多WA都是因为这里),然后给出一些约束条件,< a ...
- 算法笔记_129:计数排序(Java)
目录 1 问题描述 2 解决方案 2.1比较计数排序 2.2 分布计数排序 1 问题描述 给定一组数据,请使用计数排序,得到这组数据从小到大的排序序列. 2 解决方案 2.1比较计数排序 下面算法 ...
- 算法练习4---冒泡排序java版
冒泡排序的基本思想:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒.即:每当两相邻的数比较后发现它们的排序与排序要求相反 ...
- 算法笔记_015:快速排序(Java)
目录 1 问题描述 2 解决方案 2.1 快速排序原理简介 2.2 具体编码 1 问题描述 给定一组数据,使用快速排序得到这组数据的非降序排列. 2 解决方案 2.1 快速排序原理简介 引用自百度百科 ...
- 算法笔记_010:插入排序(Java)
1 问题描述 给定一组数据,使用插入排序得到这组数据的非降序排列. 2 解决方案 2.1 插入排序原理简介 引用自百度百科: 有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求 ...
随机推荐
- 【UOJ 117】欧拉回路
#117. 欧拉回路 有一天一位灵魂画师画了一张图,现在要你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次. 一共两个子任务: 这张图是无向图.(50分) 输入格式 第一行一个整数 t, ...
- 如何使用Eclipse插件—Easy Explorer
Easy Explorer是一个Eclipse插件,主要用于快速浏览项目文件的目录,实用性比较强. 使用方法如下: 1.下载Easy Explorer,从此处下载EasyExplorer:http:/ ...
- zoj 3329 概率dp
题意:有三个骰子,分别有k1,k2,k3个面.每个面值为1--kn每次掷骰子,如果三个面分别为a,b,c则分数置0,否则加上三个骰子的分数之和.当分数大于n时结束.求游戏的期望步数.初始分数为0 链接 ...
- bzoj 1030
dp[i][j] 表示,在AC自动机中,从根节点开始,走了i条边,并且经过的点不包含危险节点,走到了j节点的路径数. 收获: 1.正难则反 2.一个字符串不包含给定pattern中的任何一个,则该字符 ...
- 69.广搜练习: 最少转弯问题(TURN)
[问题描述] 给出一张地图,这张地图被分为n×m(n,m<=100)个方块,任何一个方块不是平地就是高山.平地可以通过,高山则不能.现在你处在地图的(x1,y1)这块平地,问:你至少需要拐几个弯 ...
- 集成学习中的 stacking 以及python实现
集成学习 Ensemble learning 中文名叫做集成学习,它并不是一个单独的机器学习算法,而是将很多的机器学习算法结合在一起,我们把组成集成学习的算法叫做“个体学习器”.在集成学习器当中,个体 ...
- 厄拉多塞筛法和普通方法求素数表(python实现)
厄拉多赛筛法(sieve of Eratosthenes): 想要得到一个不大于N的数所有素数,可以先找到不超过根号N的所有素数,设2 = p1 < p2 < ......<pk ≤ ...
- nodejs中间件拦截,express不登录无法进入后台页面
22.设置拦截 只有登录才能进入到后台页面,不登录无法进入 如果登陆成功, 写入session, 参数 uid uid=123dsfjksldfjsl 检测登陆, 请求中 session 是否包含 u ...
- [HTML]不让TD中的文本撑开表格(转)
我经常会遇到这样的问题:在设计好宽度的表格中,因为有些文本信息过长,而把表格撑开(弄的面目全非)!很让人头疼.其实解决这个问题很简单,只要在<td>的样式中加入word-break: br ...
- CSS基础知识解析
一.基础知识 1.1 CSS组成 css 样式由选择符和声明组成,而声明又由属性和值组成,如下图所示: 选择符:又称选择器,指明网页中要应用样式规则的元素,如本例中是网页中所有的段(p)的文字将变成蓝 ...