经典算法问题的java实现 (二)
1.1 r进制数
数N的r进制可以表示为:
1.2 十进制转换为r进制
十进制数N和其他r进制数的转换是计算机实现计算的基本问题,基解决方案很多,其中一个简单算法基于下列原理:
N = (N div d) * r + N mod r (其中: div为整除运算,mod为求余运算)
问题:如何将非负十进制(Decimal)整数转化为八进制数(Octonary Number)?
将十进制转化为r进制:
- /**
- * 非负十进制整数转换为r进制数
- * @param n 待转换的十进制数
- * @param r 进制数(基数)
- * @return 返回转换后对应r进制数各位数字。
- */
- byte [] dec2RNumber(int n,byte r) {
- if(n < 0 || r < 0) {
- throw new IllegalArgumentException(" the parameter is valid!");
- }
- Stack<Byte> s = new Stack<Byte>();
- while( n != 0){
- s.push(Byte.valueOf((byte) (n%r)));//求余
- n = n/r;//求商
- }
- byte [] rr = new byte[s.size()];
- for (int i = 0; i < rr.length; i++) {
- rr[i] = s.pop();
- }
- return rr;
- }
十进制非负整数转换为八进制:
- dec2RNumber(1348,8)
2.斐波那契数列(Fibonacci Sequence)
2.1 斐波那契数列是以递归的方法来定义:
斐波那契数列是从第0项和第1项开始,之后的项等于其前面相邻两项之和。
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946,......
2.2 兔子生育问题:
- 第一个月初有一对刚诞生的兔子
- 第二个月之后(第三个月初)它们可以生育
- 每月每对可生育的兔子会诞生下一对新兔子
- 兔子永不死去
2.3 兔子问题的分析:
斐波那契数列的java非递归实现:
- int Fibs(int n) {
- if(n < 0) {
- throw new IllegalArgumentException(" the parameter is valid!");
- }
- int n1 = 0;//F(n-2)
- int n2 = 1;//F(n-1)
- int r = n1;//F(n)
- if(n == 1) {
- r = n2;
- }
- for (int i = 2; i <= n; i++) {
- r = n1 + n2 ;//F(n)=F(n-1)+F(n-2)
- n1 = n2;
- n2 = r;
- }
- return r;
- }
3.秦九韶算法求一元n次多项式的值(Compute Polynomial's value)
3.1 秦九韶算法介绍:
秦九韶算法是中国南宋时期的数学家秦九韶提出的一种多项式简化算法。在西方被称作霍纳算法。
秦九韶算法:
一般地,一元n次多项式的求值需要经过[n(n+2)]/2次乘法和n次加法,而从上面的演算可以看出秦九韶算法只需要n次乘法和n次加法。极大地降低了算法复杂度。
参照:http://zh.wikipedia.org/wiki/%E9%9C%8D%E7%B4%8D%E6%BC%94%E7%AE%97%E6%B3%95
3.2 秦九韶算法实现:
- /**
- * 秦九绍算法求一元n次多项式的值
- * f(x) = a[0]*x^n + a[1]*x^(n-1) + ... + a[n]
- * @param a 系数
- * @param x 基数
- * @return
- */
- double qinjiushao(double [] a ,double x) {
- double v = a[0];
- for (int i = 1; i < a.length; i++) {
- v = v * x + a[i];
- }
- return v;
- }
3.3 秦九韶算法应用:
在Java中字符串的hashcode计算中就用到了秦九韶算法。其中基数为31(质数),系数为字符串对应的ASCII值。
- public int hashCode() {
- int h = hash;
- if (h == 0) {
- int off = offset;
- char val[] = value;
- int len = count;
- for (int i = 0; i < len; i++) {
- h = 31*h + val[off++];
- }
- hash = h;
- }
- return h;
- }
测试:
- System.out.println("abc".hashCode());
- 结果:96354 = ax^2 + bx +c //其中( [a,b,c]=[97,98,99];x =31)
- = 97 * 961 + 98 * 31 +99
4.全排列(Full Permutation)
从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。
问题:给定字符串S,生成该字符串的全排列。
以上全排列的算法采用了交换,回溯,递归的方法。
参照地址:http://www.haogongju.net/art/37504
- int count = 0;//统计字符串的全排列数目
- int len = 0;//字符串的长度
- /**
- * 字符串的全排列算法。
- * @param c字符串对应的字符数组
- * @param start 起始位置
- */
- void fullPermutation(char[] c, int start ) {
- if(start == len){
- count++;
- System.out.println(new String(c));//打印当前排列
- } else {
- char temp=' ';
- boolean bool = false;
- for(int i = start; i < c.length; i++){
- bool = (i != start); //i与start相等时不交换。
- //为避免生成重复排列,当不同位置的字符相同时不再交换
- if(bool && c[i] == c[start]) {
- continue;
- }
- if(bool) {//交换
- temp = c[start];
- c[start] = c[i];
- c[i] = temp;
- }
- fullPermutation(c, start + 1);//递归
- if(bool) {//回溯
- c[i] = c[start];
- c[start] = temp;
- }
- }
- }
- }
- /**
- * 测试全排列
- * @param s
- */
- void testFullPermutation(String s) {
- count = 0;
- len = s.length() -1;
- long t1 = Calendar.getInstance().getTimeInMillis();
- fullPermutation(s.toCharArray(), 0);
- long t2 = Calendar.getInstance().getTimeInMillis();
- System.out.println("全排列数:"+count);
- System.out.println("耗时:"+(t2-t1)+"ms");
- }
5.八皇后问题(Eight Queens)
八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法?
上图为八皇后问题的一个例子。
八皇后问题的java实现如下。该算法支持n皇后。当n>=16以后计算时间会很长。
- import java.util.Calendar;
- public class EightQueens {
- //统计解的个数
- int count ;
- //皇后数
- static int N = 8;
- //记录皇后的位置,x[i]表示皇后i放在棋盘的第i行的第x[i]列
- int [] X = new int[N];
- /**
- * 测试皇后k在第k行第x[k]列时是否与前面已放置好的皇后相攻击.
- * (X[j] == X[k]时,两皇后在同一列上,
- * k-j == Math.abs(X[j] - X[k])时,两皇后在同一斜线上。
- * @param k
- * @return
- */
- boolean check(int k) {
- for (int row = 0; row < k; row ++) {
- if ((X[row] == X[k] || k-row == Math.abs(X[row] - X[k]))) {
- return false ;
- }
- }
- return true;
- }
- /**
- * 回溯求皇后的放置方案。
- * 对于八皇后t的最大值为8.
- * @param row row -> [0,1,2,3,4,5,6,7,8]
- */
- void backtrack(int row) {
- //row == N 时,算法搜索至叶结点,得到一个新的N皇后互不攻击的放置方案
- if(row == N) {
- count++;
- printQueen();
- } else {
- for (int col = 0; col < N; col++) {
- X[row] = col;//第row行的皇后放在col列上
- if(check(row)) {//放置成功再放row+1行的
- backtrack(row+1);
- }
- }
- }
- }
- /**
- * 打印皇后
- */
- void printQueen() {
- System.out.println("==================第"+count+"种皇后图==================");
- for (int row = 0; row < N; row++) {
- for (int col = 0; col < N; col++) {
- if (col == X[row]) {
- System.out.print("@ ");
- } else {
- System.out.print("* ");
- }
- }
- System.out.println();
- }
- }
- /**
- * @param args
- */
- public static void main(String[] args) {
- EightQueens queen = new EightQueens();
- long t1 = Calendar.getInstance().getTimeInMillis();
- //从0开始回溯
- queen.backtrack(0);
- long t2 = Calendar.getInstance().getTimeInMillis();
- //打印花费的时间。
- System.out.println("花费:"+(t2-t1)+"ms");
- //打印方案总数
- System.out.println(queen.count);
- }
- }
有兴趣的读者可以参照以下连接,去研究八皇后算法。
- http://www.animatedrecursion.com/advanced/the_eight_queens_problem.html
- http://www.durangobill.com/N_Queens.html
- http://jsomers.com/nqueen_demo/nqueens.html
- http://www.math.utah.edu/~alfeld/queens/queens.html
- http://bridges.canterbury.ac.nz/features/eight.html
- http://c2.com/cgi/wiki?EightQueensInManyProgrammingLanguages
- http://baike.baidu.com/view/698719.htm
- EightQueens.rar (1018 Bytes)
- 下载次数: 23
- TypicalCode1.rar (1.5 KB)
经典算法问题的java实现 (二)的更多相关文章
- 经典算法问题的java实现 (一)
原文链接: http://liuqing-2010-07.iteye.com/blog/1396859 1.如何计算闰年(Leap Year)? 四年一闰:百年不闰:四百年再闰. 具体参照 ...
- 经典算法--冒泡排序(Java)
原理:将相邻元素的较大值赋给右边 思路:① 1.将集合或数组内的第一个元素与第二个元素进行比较,较大值赋给右边: 2.将第二个元素与第三个元素进行比较,较大值赋给右边: ....... (N-1).将 ...
- JAVA经典算法40题及解答
JAVA经典算法40题 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分 ...
- Java经典算法四十例编程详解+程序实例
JAVA经典算法40例 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程 ...
- JAVA经典算法40题
1: JAVA经典算法40题 2: [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 3 ...
- JAVA经典算法40题(原题+分析)之分析
JAVA经典算法40题(下) [程序1] 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分析: ...
- JAVA经典算法40题(原题+分析)之原题
JAVA经典算法40题(上) [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? [程 ...
- JAVA经典算法50题(转)
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/51097928 JAVA经典算法50题 [程序1] 题目:古典问题:有一对兔子, ...
- JAVA经典算法40题面向过程
JAVA经典算法40题 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分 ...
随机推荐
- Go etcd初探
1.etcd集群的配置 SET IP1_2380=http://127.0.0.1:2380 SET IP1_2379=http://127.0.0.1:2379 SET IP2_2380=http: ...
- docker参数注解
# docker --help Usage: docker [OPTIONS] COMMAND [arg...] docker daemon [ --help | ... ] docker [ -h ...
- Java 中的泛型
泛型的一般意义: 泛型,又叫 参数多态或者类型参数多态.在强类型的编程语言中普遍作用是:加强编译时的类型安全(类型检查),以及减少类型转换的次数. Java 中的 泛型: 编译时进行 类型擦除 生成与 ...
- 用 ArrayList 集合调用商品类
public class Commodity{ //定义商品类 String name; //定义商品名字 double size; //定义商品尺寸 double price; //定义商品 ...
- Android 四大布局属性介绍
线性布局 控件距离布局底,左,右,顶部部的距离 android:paddingBottom="35.0dip" android:paddingLeft=" ...
- Broadcast
静态注册广播接收器 1. 活动中创建内部类继承BroadcastReceiver实现 onReceive函数 2. new 一个内部类的对象 3. registerReceiver注册内部类 4. 在 ...
- DWZ富客户端框架+DWZ简介及其使用+DWZ讨论组
DWZ富客户端框架+DWZ简介及其使用+DWZ讨论组 地址: DWZ富客户端框架:http://jui.org/#_blank DWZ简介及其使用:http://blog.sina.com.cn/s/ ...
- Mac 启动或者禁用翻盖自动开关机
从 2016 新款 MacBook Pro 起,预设打开笔电上盖或连接电源供应器时,电脑就会自动开机而且开机时没有启动声,本文教你如何将这些东西调整回原本的样子. 以下指令都是通过「应用程序」→「终端 ...
- java框架之SpringBoot(12)-消息及整合RabbitMQ
前言 概述 大多数应用中,可通过消息服务中间件来提升系统异步通信.扩展解耦的能力. 消息服务中两个重要概念:消息代理(message broker)和目的地(destination).当消息发送者发送 ...
- python基础(10)-匿名函数&内置函数
匿名函数 例子 返回两个数的和 def add(x, y): return x + y # 等价于 add = lambda x, y: x + y 返回字典中值最大的key dic = {'a': ...