数字成环算法
㈠ 用java编程:输入1~20的整数n,把从1到n的n个整数摆成环,使得该环上任意
不用了,这个是一个常规算法题,早就有标准代码了
publicclassPrimeTest{
//判断某整数是不是质数
publicstaticbooleanisp(intn){
for(inti=2;i<Math.sqrt(n)+1;i++){
if(n%i==0){
颤颂首returnfalse;
}
}
returntrue;
}
publicstaticintn=20;
publicstaticboolean[]vis=newboolean[n+1];//存储某数是否被使用
publicstaticint[]arr=newint[n+1];//存放数列
publicstaticvoiddfs(intcur){
if(cur==n+1&&isp(arr[1]+arr[n])&&樱亏arr[1]==1){//如果最后一个数放进去了,并且最后一个数和第一个的和为质数,并且第一个数是1(因为我们只输出开头是1的,避免重复)
for(inti=1;i<=n;i++){//打印出数列
System.out.print(arr[i]+",");
}
System.out.println();
}else{
for(inti=1;i<=n;i++){//尝试放置每个数i
if(!vis[i]&&isp(i+arr[cur-1])){//如果这个数没有被使用,并且与前一个数的和是质数
vis[i]=true;//标明这个数被使用
arr[cur]=i;//将这个数加入队列
茄数dfs(cur+1);//求下一个数
vis[i]=false;//取消这个数
}
}
}
}
publicstaticvoidmain(String[]args){
arr[0]=0;
for(inti=0;i<=n;i++){
vis[i]=false;
}
dfs(1);
}
}
1,2,3,4,7,6,5,8,9,10,13,16,15,14,17,20,11,12,19,18,
1,2,3,4,7,6,5,8,9,10,13,16,15,14,17,20,11,18,19,12,
1,2,3,4,7,6,5,8,9,10,13,18,19,12,11,20,17,14,15,16,
1,2,3,4,7,6,5,8,9,10,19,12,11,20,17,14,15,16,13,18,
1,2,3,4,7,6,5,8,9,10,19,18,13,16,15,14,17,20,11,12,
1,2,3,4,7,6,5,8,9,14,15,16,13,10,19,12,17,20,11,18,
1,2,3,4,7,6,5,8,9,14,15,16,13,10,19,18,11,20,17,12,
1,2,3,4,7,6,5,8,9,14,15,16,13,18,11,20,17,12,19,10,
1,2,3,4,7,6,5,8,9,20,11,12,17,14,15,16,13,10,19,18,
1,2,3,4,7,6,5,8,9,20,11,12,17,14,15,16,13,18,19,10,
1,2,3,4,7,6,5,8,9,20,11,18,13,10,19,12,17,14,15,16,
1,2,3,4,7,6,5,8,9,20,11,18,13,16,15,14,17,12,19,10,
底下还有好几页
㈡ 环和算法是什么
顶点是两个图的顶点的并集,但是边要去掉相同的边,也即是两个图是没有共同的边。
㈢ 贪心算法:最小生成树,霍夫曼编码
连通图: 在无向图中,若任意两个顶点vi与vj都有路径相通,则称该无向图为连通图。
强连通图(Strongly Connected Graph) 是指在有向图G中,如果对于每一对vi、vj,vi≠vj,从vi到vj和从vj到vi都存在路径,则称G是强连通图。
连通网: 在连通图中,若图的边具有一定的意义,每一条边都对应着一个数,称为权;权代表着连接连个顶点的代价,称这种连通图叫做连通网。
生成树: 一个连通图的生成树是指一个连通子图,它含有图中全部n个顶点,但只有足以构成一棵树的n-1条边。一颗有n个顶点的生成树有且仅有n-1条边,如果生成树中再添加一条边,则必定成环。
最小生成树: 在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树。
示例:
分别使用 Kruskal算法 和 Prim算法 ,找出下图的最小生成树。
使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。
具体步骤
1.将信源符号的概率按减小的顺序排队。
2.把两个最小的概率相加,并继续这一步骤,始终将较高的概率分支放在右边,直到最后变成概率1。
3.画出由概率1处到每个信源符号的路径,顺序记下沿路径的0和1,所得就是该符号的霍夫曼码字。
4.将每对组合的左边一个指定为0,右边一个指定为1(或相反)。
示例:
假设字符a,b,c,d,e出现的概率分别为1/2,1/4,1/8,1/16,1/16。
1.求出各字符哈夫曼编码表。
2.假设一个文件有1,000,000个字符,求出编码之后文件的字节长度。
A:0
B:10
C:110
D:1110
E:1111
a所占长度l1为:(1,000,000/2) 1
b所占长度l2为:(1,000,000/4) 2
c所占长度l3为:(1,000,000/8) 3
d所占长度l4为:(1,000,000/16) 4
e所占长度l5为:(1,000,000/16)*4
文件的总长度l = l1 + l2 + l3 + l4 + l5 = 1875000
㈣ 判环算法以及链表常见算法题
由于涉及到Floyd判环算法,故先简单阐述一下Floyd判环算法原理。
Floyd判环算法
算法原理:设置两个指针同时从头结点向后访问(当两指针后继不为null),不过两指针的访问速度不一致,第一个指针每次后移一个元素,第二个指针每次后移两个元素。若链表成环,则两指针在某一时刻必然相遇,否则不相遇
计算环长度:
当指针相遇时,保持其中一个指针不动,另一个指针向后访问,每次后移一个单位,当两指针再次相遇时,该指针移动的单位即为环的长度
计算环起始节点:
第一次相遇后,慢指针从头结点向后访问,快指针从相遇点同时向后访问,不过两者的移动速度都为1,当两者再次相遇时,该缓伍相遇的节点即为环的起始节点,分析如下:
如下图所示,假设h为链表头结点,p为两指针第一次相遇节点,m为头结点到起始节点走过的路程(经过的节点个数),n为环起始节点到p的路程,则对于第一次相遇有:
慢指针走过的路程:s=m+n+a C
快指针走过的路程:2 s=m+n+b C
a,b分别表示两指针相遇前第一次经过p点后绕环的圈数,C表示环的长度,由于快指针的速度是慢指针的两倍,时间一样,故快指针走过的路程是慢指针的两倍。
两式相减有s=(b-a) C=m+n+a*C
故m+n恰为环长度的整数倍
慢指针从头结点到起始节点走了m,由于同时同速伍哪余度快指针也走了m,而移动前快指针距起始节点距离为n,m+n恰为环长度的整数倍,故快指针移动m后也到了起始节点,即此时相遇点为起始节点
2.1判断链表是否以null结尾,是否包含环
2.2判断给定的链表是否以null结束。如果链表中存在环,找到环的起始节点
2.3判断链表是否存在环,若存在,则返回环的长度,否则返回0
3.将一个循环链表变成两个循环链表
4.有序链表中插入一个节点
5.1链表逆置
5.2逐对逆置链表,假如初始链表为1 2 3 4 x,逐对逆置后为2 1 4 3 x
6.判断两个链表是否相交成为一个单链表,若相交,得出两链表的相交节点
7.寻找链表的中间节点:设置两个指针,第一个指针的移动速度是第二个指针的两倍,当第一个指针到达表尾,第二个指针即指向中间节点
8.检查链表长度是奇数还是偶数,每腔滚次后移两个元素,返回1表示奇数,返回0表示偶数
9.合并两个有序链表
10.从表尾开始输出链表
㈤ 急!一个Java题(在下图中的九个点上,空出中间的点...)
import javax.swing.JFrame ;
import javax.swing.JPanel ;
import java.awt.Graphics ;
import java.awt.BorderLayout ;
import java.awt.Color ;
import java.util.ArrayList ;
public class MobileSorter extends JFrame {
//上边距
public static final int TOP_SPA = 100 ;
//左边距
public static final int LEFT_SPA = 100 ;
public static void main(String args[]) {
JFrame.(true) ;
MobileSorter ms = new MobileSorter() ;
ms.setVisible(true) ;
}
public MobileSorter() {
//设置窗体大小
this.setSize(400 ,400) ;
//new出组件
MyPanel p = new MyPanel() ;
//布置窗体
this.setLayout(new BorderLayout()) ;
this.add(p ,BorderLayout.CENTER) ;
//启动线程
Thread t = new Thread(p) ;
t.start() ;
}
}
class MyPanel extends JPanel implements Runnable {
//存储圆数据的数组
private ArrayList ca = new ArrayList(9);
/**
* 中心圆
*/
private Circle cCenter = null ;
public MyPanel() {
init() ;
}
public void paint(Graphics g) {
//画与5号位的斜连接线
for (int i = 0; i<9; i++) {
if (i == 4) continue ;
Circle.drawLine(g ,(Circle)ca.get(4) ,(Circle) ca.get(i)) ;
}
//垂直和横线和竖线
g.setColor(Color.BLACK) ;
for (int i = 0; i<9; i++)
for (int j = 0; j<9; j++)
if (i != j && i < j)
if (j - i ==3 || (i + 1 == j && j%3 != 0))
Circle.drawLine(g , (Circle) ca.get(i) ,(Circle) ca.get(j)) ;
/** 画圆 */
for (int i = 0; i<9; i++)
((Circle) ca.get(i)).drawMe(g) ;
}
/**
* 初始化
*/
public void init() {
//创建圆
for (int i = 1; i<10; i++)
this.ca.add(new Circle(i)) ;
//生成圆内的数
int[] n = new int[9] ;
for (int i = 0; i<n.length; ) {
int c ;
c = (int)(Math.random() * 8) + 1 ;
boolean isRepeat = false ;
for (int j = 0; j<i; j++)
if (n[j] == c) {
isRepeat = true ;
break ;
}
if (isRepeat) continue ;
if (i == 4) i ++ ;
((Circle)this.ca.get(i)).setNum(c) ;
n[i] = c ;
i ++ ;
}
}
/**
* 线程
*/
public void run() {
int oPos = 0 ; //值为1的圆的标号
int sPos ; //值为1的圆的下一个圆的标号
int ePos ; //终端圆标号
int cPos = 0 ; //操作圆标号
cCenter = (Circle)this.ca.get(4) ; //中心圆
//找出圆内数字的1的圆
for (int i = 0; i<this.ca.size(); i++)
if (((Circle)this.ca.get(i)).getNum() == 1) {
oPos = i ;
break ;
}
sPos = Circle.getNextDeasil(oPos) ;
ePos = oPos ;
while (true) {
cPos = sPos ;
while (true) {
Circle c = (Circle)this.ca.get(cPos) ;
Circle n = (Circle)this.ca.get(Circle.getNextDeasil(cPos)) ;
checkSwap(c ,n) ;
cPos = Circle.getNextDeasil(cPos) ;
if(ePos == Circle.getNextDeasil(cPos)) {
ePos = cPos ;
break ;
}
}
if (ePos == Circle.getNextDeasil(sPos)) {
System.out.println ("OVER!") ;
break ;
}
}
}
/**
* 延迟
*/
private void animation() {
this.repaint() ;
try { Thread.sleep(1000) ;}catch (Exception ex) { }
}
/**
* 交换
*/
private void checkSwap(Circle c ,Circle n) {
int cNum = c.getNum() ;
int nNum = n.getNum() ;
if (cNum > nNum) {
cCenter.setNum(n.getNum()) ;
n.setNum(0) ;
this.animation() ;
n.setNum(c.getNum()) ;
c.setNum(0) ;
this.animation() ;
c.setNum(cCenter.getNum()) ;
cCenter.setNum(0) ;
this.animation() ;
}
}
}
class Circle {
/**
* 各圆之间的间距
*/
public static final int CIR_SPA_BET = 60 ;
/**
* 圆的直径
*/
public static final int CIR_WD = 30 ;
/**
* 圆的标号 ,1-9
*/
private int pos ;
/**
* 圆的左上角x坐标
*/
private int x ;
/**
* 圆的左上角y坐标
*/
private int y ;
/**
* 圆内的数
*/
private int num ;
public Circle(int pos) {
this.pos = pos ;
this.x = MobileSorter.LEFT_SPA + (pos-1) % 3 * CIR_SPA_BET ;
this.y = MobileSorter.TOP_SPA + (pos-1) / 3 * CIR_SPA_BET ;
}
/**
* 画圆与圆中的数字
*/
public void drawMe(Graphics g) {
//圆
g.setColor(Color.BLACK) ;
g.fillOval(x ,y ,CIR_WD ,CIR_WD) ;
//数字
g.setColor(Color.WHITE) ;
if (num != 0)
g.drawString(String.valueOf(num)
,x + CIR_WD / 2 - 3 ,y + CIR_WD / 2 + 5) ;
else
g.drawString("空"
,x + CIR_WD / 2 - 3 ,y + CIR_WD / 2 + 5) ;
}
/**
* 画两个圆之间的连接线
*/
public static void drawLine(Graphics g ,Circle a , Circle b) {
g.drawLine(a.getX() + Circle.CIR_WD / 2
,a.getY() + Circle.CIR_WD / 2
,b.getX() + Circle.CIR_WD / 2
,b.getY()+ Circle.CIR_WD / 2) ;
}
public void setNum(int num) {
this.num = num ;
}
public int getX() {
return x ;
}
public int getY() {
return y ;
}
public int getPos() {
return pos ;
}
public int getNum() {
return num ;
}
public static int getNextDeasil(int pos) {
if (pos >=0 && pos <=8 && pos != 4) {
if (pos == 0)
return 1 ;
else if (pos == 1)
return 2 ;
else if (pos == 2)
return 5 ;
else if (pos == 3)
return 0 ;
else if (pos == 5)
return 8 ;
else if (pos == 6)
return 3 ;
else if (pos == 7)
return 6 ;
else if (pos == 8)
return 7 ;
}
return -1 ;
}
/**
* 根据顺时针方向返回下个圆的标号
*/
public int getNextDeasil() {
if (pos >=0 && pos <=8 && pos != 4) {
if (pos == 0)
return 1 ;
else if (pos == 1)
return 2 ;
else if (pos == 2)
return 5 ;
else if (pos == 3)
return 0 ;
else if (pos == 5)
return 8 ;
else if (pos == 6)
return 3 ;
else if (pos == 7)
return 6 ;
else if (pos == 8)
return 7 ;
}
return -1 ;
}
}
㈥ 回溯算法 求1-20这2个数摆成环,要求相邻的两个数的和是素数。我的代码如下:没有语法错误,但是死循环
intsearch(int)、intprint()、intmain()这三个函数名前都有返回值类型符,但函数体内却都没有返回语句。你也写复杂了,下面的代码就可以了:
#include"stdio.h"
intprime(intn){
inti;
if(n>2&&!(n&1)||n<2)
return0;
for(i=3;i*i<=n;i+=2)
if(!(n%i))
return0;
return1;
}
intmain(void){
inti,j;
for(i=1;i<20;i++)
if(prime(j=(i<<1)+1))
printf("%2d+%2d=%2d ",i,i+1,j);
return0;
}
㈦ 排列组合五组围成环且每组的两个人必须靠在一起
都是错的.
正确应为 A22*A44
甲乙岁配两人随即排A22
剩下甲乎搏指乙(看做一人)银中丙丁戊A44
第二种是从五人中随即选两人站在一起的解法 甲乙已确定,无需再选取组合了