目录

1 问题描述

2 解决方案

2.1 检验数组中元素的唯一性

2.2 模式计算

 


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)的更多相关文章

  1. 算法笔记_023:拓扑排序(Java)

    目录 1 问题描述 2 解决方案 2.1 基于减治法实现 2.2 基于深度优先查找实现 1 问题描述 给定一个有向图,求取此图的拓扑排序序列. 那么,何为拓扑排序? 定义:将有向图中的顶点以线性方式进 ...

  2. 算法笔记_018:旅行商问题(Java)

    目录 1 问题描述 2 解决方案 2.1 蛮力法 2.2 减治法 2.2.1 Johson-Trotter算法 2.2.2 基于字典序的算法   1 问题描述 何为旅行商问题?按照非专业的说法,这个问 ...

  3. 算法练习5---快速排序Java版

    基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成 ...

  4. 算法笔记_014:合并排序(Java)

    1 问题描述 给定一组数据,使用合并排序得到这组数据的非降序排列. 2 解决方案 2.1 合并排序原理简介 引用自百度百科: 合并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Div ...

  5. 算法笔记_145:拓扑排序的应用(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 给出一些球,从1~N编号,他们的重量都不相同,也用1~N标记加以区分(这里真心恶毒啊,估计很多WA都是因为这里),然后给出一些约束条件,< a ...

  6. 算法笔记_129:计数排序(Java)

    目录 1 问题描述 2 解决方案 2.1比较计数排序 2.2 分布计数排序   1 问题描述 给定一组数据,请使用计数排序,得到这组数据从小到大的排序序列. 2 解决方案 2.1比较计数排序 下面算法 ...

  7. 算法练习4---冒泡排序java版

    冒泡排序的基本思想:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒.即:每当两相邻的数比较后发现它们的排序与排序要求相反 ...

  8. 算法笔记_015:快速排序(Java)

    目录 1 问题描述 2 解决方案 2.1 快速排序原理简介 2.2 具体编码 1 问题描述 给定一组数据,使用快速排序得到这组数据的非降序排列. 2 解决方案 2.1 快速排序原理简介 引用自百度百科 ...

  9. 算法笔记_010:插入排序(Java)

    1 问题描述 给定一组数据,使用插入排序得到这组数据的非降序排列. 2 解决方案 2.1 插入排序原理简介 引用自百度百科: 有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求 ...

随机推荐

  1. PHP 笔记——String 字符串

    1. 定义 单引号括起来的字符串被原样输出. 双引号字符串中的变量被PHP解析为变量值. 2. 获取字符串长度 strlen(string $string): int 在utf-8下,汉字占3个字符, ...

  2. 「2017 山东一轮集训 Day4」基因

    设置 \(\sqrt{n}\) 个关键点,维护出关键点到每个右端点之间的答案以及Pam的左指针,每次暴力向左插入元素即可,为了去重,还需要记录一下Pam上每个节点在每个关键点为左端点插入到时候到最左边 ...

  3. Codeforces Round #478 (Div. 2) ABCDE

    A. Aramic script time limit per test 1 second memory limit per test 256 megabytes input standard inp ...

  4. CodeForces - 1017D The Wu

    题面在这里! 比较显而易见的暴力,O(2^(2n) + 2^n * 100) 就可以直接做了 #include<bits/stdc++.h> #define ll long long us ...

  5. PostgreSQL与MySQL的区别收集(转)

    特性 MySQL PostgreSQL 实例 通过执行 MySQL 命令(mysqld)启动实例.一个实例可以管理一个或多个数据库.一台服务器可以运行多个 mysqld 实例.一个实例管理器可以监视 ...

  6. MySQL MyISAM和InNodb备份与恢复技巧

    1. 为什么要备份数据库 对数据库来说,最重要也最容易被忽视的就是备份.由于不可预测性,偶然的事件可能会导致非常惨重的损失. 数据越是重要,数据的变化越频繁,备份越发需要经常进行. 备份周期根据不同业 ...

  7. 使用apache htpasswd生成加密的password文件,并使用.htaccess控制文件夹訪问

    htpasswd 是apache的小工具.在apache安装文件夹bin下可找到. Usage: htpasswd [-cmdpsD] passwordfile username htpasswd - ...

  8. HttpClient使用例子

    HttpClient client = new HttpClient(); String url = http://localhost:8080/ana/workFlowOaInterface.do? ...

  9. 单击行,自己主动选中当前行中的单选框button

    需求:单击行,自己主动选中当前行中的单选框button. aspx页面: <asp:Repeater ID="rptRecordList" runat="serve ...

  10. eclipse 中添加自定义 classpath 的方法,以及 javac 和 java 的一些使用细节

    目标: 将 ~/java 加入classpath eclipse: 右键选中 Project, Properties, Java Build Path, Libraries, Add External ...