java简单实现整数的随机重排

介绍

有时需要用到整数1-n的随机排列,如决定出场顺序等。这里用java做一个简单的小界面,显示整数1-n的随机排列。

这里界面用javafx工具实现。

原理

整数1-n的排列,共n!种,所以我们的目的相当于是从n!个样本点构成的总体中,随机等概率地抽取一个样本点。

当然,我们的实现算法不采取上述的n!的方式,需要采用计算量合理的算法。

一个可能出现的误区是:不断地产生1~n之间的随机整数;如果遇到与已经产生的整数出现重复,则舍弃掉这个整数,并继续产生,一直到产生n个不同的整数(>=1, <=n)。这个方法简单也直观,但从概率的角度看,这样产生的结果与上述的随机等概率抽样并不等价。

这里采用一种比较简单的方法:让计算机产生n个0~1均匀分布的随机数(一般我们使用的n较小,那么计算机产生的这n个随机并不重复),得到一个随机数序列。按顺序记录着n个随机数,即为每一个随机数贴上“标签”,标签上记录的是它在这个序列中的序号。

然后对这n个随机数排序。排序之后,随机数的位置自然发生了变换,我们按现在的位置顺序把它们的“标签”取出来,就得到一个1-n整数的随机排列。

实现

输入n后,建立一个数组和一个哈希表。n轮产生随机数,在第i轮中,将产生的这个随机数添加到数组,同时将其作为键添加到哈希表中,键对应的值为轮次,即整数i。

对数组排序。这里我用的是二路归并排序的方法。

按顺序取出排好序后的数组中的数,之后查找它在哈希表中对应的值。这样得到的值序列,就是我们想要的一个整数随机排列。

代码

package random;

import java.util.*;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class RandomPermutation extends Application {
	private Text text = new Text("Enter the maximun integer:");
	private TextField tfInput = new TextField();
	private TextArea ta = new TextArea();
	private Button btRun = new Button("Run");
	private Button btClear = new Button("Clear");
	private boolean allow = true;
	
	@Override
	public void start(Stage primaryStage) {
		// UI
		ta.setEditable(false);
		ta.setWrapText(true);
		
		BorderPane pane = new BorderPane();
		
		HBox hBox = new HBox();
		hBox.getChildren().addAll(text, tfInput, btRun, btClear);
		pane.setBottom(hBox);
		pane.setCenter(ta);
		
		Scene scene = new Scene(pane, 700, 400);
		primaryStage.setTitle("Random");
		primaryStage.setScene(scene);
		primaryStage.show();
		
		btRun.setOnAction(e -> runAction());
		btClear.setOnAction(e -> clearAction());
	}
	
	public static void main(String[] args) {
		Application.launch(args);
	}
	
	// Clear
	public void clearAction() {
		allow = true;
		ta.clear();
		tfInput.clear();
	}
	
	// Run
	public void runAction() {
		if(allow) {
			Integer n = Integer.parseInt(tfInput.getText());
			if(n instanceof Integer) {
				// Hash map to store key(random_number)-value(integer)
				Map<Double, Integer> hashMap = new HashMap<>();
				// Array to store random_number
				double[] randomNumbers = new double[n];
				for(int i = 1; i <= n; i++) {
					double r = Math.random();
					hashMap.put(r, i);
					randomNumbers[i - 1] = r;
				}
				// Sort the array
				mergeSort(randomNumbers);
				
				// Get the value(integer) sequence
				for(int i = 1; i <=n; i++) {
					double randomNumber = randomNumbers[i - 1];
					Integer integer = hashMap.get(randomNumber);
					ta.appendText(integer.toString() + "   ");
					if( i % 15 == 0) {
						ta.appendText("\n");
					}			
				}
			}
		
		allow = false;
		}
	}
	
	// Merge sort method
	public static void mergeSort(double[] list) {
		if(list.length > 1) {
			double[] firstHalf = new double[list.length / 2];
			System.arraycopy(list, 0, firstHalf, 0, list.length / 2);
			mergeSort(firstHalf);
			
			int secondHalfLength = list.length - list.length / 2;
			double[] secondHalf = new double[secondHalfLength];
			System.arraycopy(list, list.length / 2, secondHalf, 0,
					secondHalfLength);
			mergeSort(secondHalf);
			
			merge(firstHalf, secondHalf, list);
		}
	}
	
	public static void merge(double[] list1, double[] list2, double[] temp) {
		int current1 = 0;
		int current2 = 0;
		int current3 = 0;
		
		while(current1 < list1.length && current2 < list2.length) {
			if(list1[current1] < list2[current2])
				temp[current3++] = list1[current1++];
			else
				temp[current3++] = list2[current2++];
		}
		
		while(current1 < list1.length)
			temp[current3++] = list1[current1++];
		
		while(current2 < list2.length)
			temp[current3++] = list2[current2++];
	}
	
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值