AlgorithmExperiment

算法分析课实验
分治法的核心思想是将问题分为若干子问题去,使规模一步步缩小,最终分到一步就能得出结果。要注意每个子问题需要性质相同而且相互不重复。
采用分治法完成如下任务:

i. 中位数问题

问题描述

设X[ 0 : n - 1]和Y[ 0 : n – 1 ]为两个数组,每个数组中含有n个已排好序的数。找出X和Y的2n个数的中位数。

编程任务

利用分治策略试设计一个O (log n)时间的算法求出这2n个数的中位数。

数据输入

由文件input.txt提供输入数据。文件的第1行中有1个正整数n(n<=200),表示每个数组有n个数。接下来的两行分别是X,Y数组的元素。

结果输出

程序运行结束时,将计算出的中位数输出到文件output.txt中。

输入文件示例1

input.txt

3
5 15 18
3 14 21

输出文件示例1

output.txt

14.5

输入文件示例2

input.txt

4
5 15 18 24
3 10 21 30

输出文件示例2

output.txt

16.5

实现提示

比较两个序列的中位数大小,如果两个数相等,则该数为整个2n个数据的中位数,否则通过比较,分别减少两个序列的查找范围,确定查找的起止位置,继续查找。

直接折半存在的问题

第一次折半

5 15 18 24

3 10 21 30

第二次折半

5 15 18 24

3 10 21 30

当X Y中各自有偶数个时,折半操作可能会去除掉正确结果。如示例2 所示,第一直接折半将去掉5,15,21,30这四个数。第二次折半去掉3,24。得出最终结果(18+10)/2 = 14。然而简单排序后发现正确的中位数应该是(15+18)/2 = 16.5。显然直接折半的过程中,去掉了正确结果的一部分15,所以判断能否直接折半非常有必要。


ii. Gray码问题

问题描述

Gray码是一个长度为2n的序列。序列中无相同的元素,每个元素都是长度为n位的串,相邻元素恰好只有一位不同。用分治策略设计一个算法对任意的n构造相应的Gray码。

编程任务

利用分治策略试设计一个算法对任意的n构造相应的Gray码。

数据输入

由文件input.txt提供输入数据n。

结果输出

程序运行结束时,将得到的所有编码输出到文件output.txt中。

输入文件示例

input.txt

3

输出文件示例

output.txt

0   0   0
0   0   1
0   1   1
0   1   0
1   1   0
1   1   1
1   0   1
1   0   0

实现提示

把原问题分解为两个子问题,分别对两个子问题的每个数组后一位加0和1。

代码实现

中位数问题
package MidNum;import java.io.*;
import java.util.ArrayList;
import java.util.Comparator;public class MidNum {public static ArrayList<Integer> ReadInput() throws IOException {BufferedReader in = null;try {in = new BufferedReader(new FileReader("src\\MidNum\\in.txt"));String sb;ArrayList<Integer> nums = new ArrayList<Integer>();while (in.ready()) {sb = (new String(in.readLine()));String[] s;s = sb.split(" ");for(String i : s){nums.add(Integer.parseInt(i));}}in.close();return nums;} catch (FileNotFoundException e) {e.printStackTrace();}return null;}// 求单个数组的中位数public static double mid(ArrayList<Integer> arrayList){int len = arrayList.size();int mid = len/2;if(mid*2 == len){return (arrayList.get(mid) + arrayList.get(mid-1))/2.0;}else {return (double)arrayList.get(mid);}}// 取数组的一半,front为真则取前一半,反之取后一半public static ArrayList<Integer> half(ArrayList<Integer> arrayList, boolean front, boolean safe){int len = arrayList.size();int mid = len/2;ArrayList<Integer> list = new ArrayList<Integer>();if(front) {if (mid * 2 == len) {for (int i = 0; i < mid; i++) {list.add(arrayList.get(i));}if(!safe){// 不能直接折半则保留中间的数list.add(arrayList.get(mid));}} else {for (int i = 0; i <= mid; i++) {list.add(arrayList.get(i));}}return list;} else {if (mid * 2 == len) {if (!safe){// 不能直接折半则保留中间的数list.add(arrayList.get(mid-1));}for (int i = mid; i < len; i++) {list.add(arrayList.get(i));}} else {for (int i = mid; i < len; i++) {list.add(arrayList.get(i));}}return list;}}// 判断能否直接折半public static boolean safe_to_cut(ArrayList<Integer> X, ArrayList<Integer> Y){int len = X.size();int mid = len/2;if (mid*2 == len){int x1 = X.get(mid-1);int x2 = X.get(mid);int y1 = Y.get(mid-1);int y2 = Y.get(mid);if (mid(X) > mid(Y)) {if (x2 < y2) {return false;}if (x1 < y1){return false;}}else if (mid(X) < mid(Y)){if (y2 < x2){return false;}if (y1 < x1){return false;}}}return true;}// 计算合并后的中位数public static double getMid(ArrayList<Integer> X, ArrayList<Integer> Y){double mid_x = mid(X);double mid_y = mid(Y);ArrayList<Integer> array = null;// 如果X Y只有一个数,则返回他们平均数if (X.size() == 1 && Y.size() == 1){return (mid_x + mid_y)/2.0;}// 如果X Y 各自剩余2个 考虑到折半安全问题,剩余2个时可能已经不能再次折半if (X.size() == 2 && Y.size() == 2){array = new ArrayList<Integer>();array.addAll(X);array.addAll(Y);array.sort(new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o1.compareTo(o2);}});return (array.get(1) + array.get(2))/2.0;}if (mid_x > mid_y){// 如果X的中位数大于Y的,取X的前半部分,Y的后半部分if (safe_to_cut(X, Y)) {// 如果可以直接折半X = half(X, true, true);Y = half(Y, false, true);} else {X = half(X, true, false);Y = half(Y, false, false);}return getMid(X, Y);} else if ( mid_x == mid_y){// 如果X Y中位数相等,返回这个值return (double) mid_x;} else {// 如果X的中位数小于Y的,取X的后半部分,Y的前半部分if (safe_to_cut(X, Y)) {// 如果可以直接折半X = half(X, false, true);Y = half(Y, true, true);} else {X = half(X, false, false);Y = half(Y, true, false);}return getMid(X, Y);}}public static void output(double x) throws IOException {BufferedWriter out = new BufferedWriter(new FileWriter("src\\MidNum\\out.txt"));out.write(String.format("%f", x));out.close();}public static void main(String[] args) {// 读取输入ArrayList<Integer> nums = null;try {nums = ReadInput();} catch (IOException e) {e.printStackTrace();}// 将输入写入X YArrayList<Integer> X = new ArrayList<Integer>();ArrayList<Integer> Y = new ArrayList<Integer>();for (int i = 1; i <= nums.get(0); i++) {X.add(nums.get(i));Y.add(nums.get(i + nums.get(0)));}// 计算中位数double result = getMid(X, Y);// 输出结果try {output(result);} catch (IOException e) {e.printStackTrace();}}
}

格雷码问题

package Grey;import java.io.*;
import java.util.ArrayList;public class Grey {public static int ReadInput() throws IOException {BufferedReader in = null;try {in = new BufferedReader(new FileReader("src\\Grey\\in.txt"));String s;if (in.ready()) {s = (new String(in.readLine()));in.close();return Integer.parseInt(s);}} catch (FileNotFoundException e) {e.printStackTrace();}return 0;}public static ArrayList<StringBuffer> getGrey(int n){ArrayList<StringBuffer> list = new ArrayList<StringBuffer>();if (n==1){list.add(new StringBuffer("0"));list.add(new StringBuffer("1"));return list;}ArrayList<StringBuffer> new_list = new ArrayList<StringBuffer>();ArrayList<StringBuffer> next_list = getGrey(n-1);for(StringBuffer s: next_list){new_list.add(new StringBuffer("0").append(s));}for (int i = next_list.size() - 1; i > -1 ; i--) {new_list.add(new StringBuffer("1").append(next_list.get(i)));}return new_list;}public static void output(StringBuffer sb) throws IOException {BufferedWriter out = new BufferedWriter(new FileWriter("src\\Grey\\out.txt"));out.write(String.valueOf(sb));out.close();}public static void main(String[] args) {int n = 0;//读取输入try {n = ReadInput();} catch (IOException e) {e.printStackTrace();}if (n<1){System.out.println("Invalid Input!");return;}StringBuffer sb = new StringBuffer();for(StringBuffer s: getGrey(n)){sb.append(s);sb.append("\n");}//输出try {output(sb);} catch (IOException e) {e.printStackTrace();}}
}

目录结构

代码github链接

个人博客

【分治法】解决中位数问题、格雷码问题以及分治法直接折半存在的问题讨论————武汉理工大学算法分析实验1相关推荐

  1. 【分治法】中位数问题和Gray码问题——武汉理工大学算法分析与设计课程实验

    i. 中位数问题  问题描述 设X[ 0 : n - 1]和Y[ 0 : n – 1 ]为两个数组,每个数组中含有n个已排好序的数.找出X和Y的2n个数的中位数.  编程任务 利用分治策略试设计一 ...

  2. 分治法解决组合总和问题(leetcode216)

    nums数组中元素是正整数 大问题转换为小问题 思路和分治法解决组合相同,代码也相似 分治法解决组合问题(递归)_m0_52043808的博客-CSDN博客 只不过递归出口时需要判断组合总和是否为n ...

  3. Java 算法 格雷码

    目录标题 题目描述 解题思路 代码 题目描述 格雷码是以n位的二进制来表示数. 与普通的二进制表示不同的是,它要求相邻两个数字只能有1个数位不同. 首尾两个数字也要求只有1位之差. 有很多算法来生成格 ...

  4. 电商物流一分四分拣机的开发和源码

    电商物流一分四分拣机的开发和源码 简介 一分四分拣机,是分拣机设备中的一种,是一种小型化的分拣设备.一分四,顾名思义,就是带有四个分拣口.本文将要介绍的这款设备,体积非常小巧,因此只需要很小的场地面积 ...

  5. 分治法解决最大子数组问题

    分治法解决最大子数组问题 参考文章: (1)分治法解决最大子数组问题 (2)https://www.cnblogs.com/Christal-R/p/Christal_R.html (3)https: ...

  6. 减治法在生成子集问题中的应用(JAVA)--递归、二进制反射格雷码

    减治法在生成组合对象问题中的应用 生成子集问题:经典的背包问题就是求解一个最优子集的问题,这里我们来讨论一个更简单的问题.对于任意一个集合来说,它都存在2^n个子集(一个集合所有的子集集合称为幂集). ...

  7. 分治法解决循环赛日程表

    分治法解决循环赛日程表 问题描述 设有n=2^k个运动员要进行羽毛球循环赛,现要设计一个满足以下要求的比赛日程表: (1)每个选手必须与其他n-1个选手各赛一次. (2)每个选手一天只能比赛一次. ( ...

  8. 分治法解决矩阵乘法问题

    分治法解决矩阵乘法问题 传统for循环: #include<iostream> #include<cstdio> #include <vector> #includ ...

  9. 分治法解决棋盘覆盖问题

    分治法解决棋盘覆盖问题 问题描述: 在一个2k×2k(k≥0)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格.显然,特殊方格在棋盘中出现的位置有4k中情形,因而有4k中不同的棋盘. ...

最新文章

  1. 远程服务器端口怎么修改,如何修改远程服务器端口号
  2. [五] JavaIO之InputStream OutputStream简介 方法列表说明
  3. 高级性能服务器编程模型【IOCP完成端口】开发实现【二】
  4. 操作系统常用调度算法
  5. Navicat——连接SQL Server数据库方法
  6. Android ViewModel详解
  7. Activity Intent相关FLAG介绍
  8. PRML-系列一之1.5
  9. 安装dollar toolbox
  10. c# 整数除法取整_Java 如何取整整数除法的结果?
  11. Linux 7.x 防火墙端口
  12. JavaScript 开发工具webstrom使用指南
  13. Win11如何设置系统还原点?
  14. 正大期货:期货交易常用的软件
  15. mysql函数名称顿号,快速统计一个单元格内有多少个名字,你不会是一个一个数的吧...
  16. 这个将996反对到极致的网站,在GitHub上的Star数已经狂飙到 10 万+了
  17. 牛客_美团点评2020校招前端笔试题(仅个人学习记录)
  18. 哈夫曼树、哈夫曼编码与压缩比
  19. jmeter中运行出现Typed variable declaration : Method Invocation t.cOutputFile
  20. 移动硬盘提示:需要格式化才能打开 解决方法

热门文章

  1. 解决 另一个程序正在使用此文件,进程无法访问
  2. 三、kubernetes 集群 YAML 文件详解
  3. 初中计算机硬件教学设计,初中计算机教学设计
  4. 阿里校招内推简历筛选的筛选标准
  5. Docker暴露2375端口导致服务器被攻击解决方法!
  6. 为什么刘彻会成为一代名君?
  7. LLVM PASS 分析【1】:Rotate Loops
  8. (10分钟感受) 对极几何 PnP ICP的用法
  9. 【技巧】CSDN博客如何快捷设置首行缩进
  10. 如何查看.dat文件内容