算法4代码
⑴ 1,2,3,4依次进栈,出栈随时,写一算法求出所有可能出栈序列
代码如下:
#define N 4
int m=0,a=0,b=N;/*m表示种数,a表示栈中元素个数,b表示外面还有需要进栈的个数*/
main()
{
inS(a,b);/*首先入栈*/
printf("%d",m);
getch();
}
int inS(int a,int b)/*入栈*/
{
a++;b--;/*入栈栈中元素+1,栈外元素-1 */
if(b>0)/*若栈外有元素,可以入栈*/
inS(a,b);
if(a>0)/*若栈中有元素,可以出栈*/
outS(a,b);
}
int outS(int a,int b)/*出栈*/
{
a--;/*出栈栈中元素-1*/
if(a==0&&b==0)/*若栈中元素和栈外元素都为0个*/
{
m++;/*则此种情况的序列满足条件,种数+1*/
return;
}
if(b>0)
inS(a,b);
if(a>0)
outS(a,b);
}
(1)算法4代码扩展阅读
栈的相关知识点:
顺序栈内容包含数据和栈顶指针(int),因此采用结构体。
注意:
1、初始时,top指向-1;
2、入栈让敏橡时,先判断顺序栈是否已满(判断条件:top=maxsize-1);如果没满,则top++,并将元素值赋给s.top;
3、出栈时,先判断顺序栈是否已拿圆空(判断条件:top=-1);如果没空,则先返回栈顶元素,再top- -。
共享栈
两个顺序栈共坦旁享一个一维数组空间,而栈底位置相对不变,两个栈底分别设为一维数组的两端。
note:
(1)栈空:top1==-1&&top2==maxsize;
(2)栈满:top2-top1= 1(此时两个栈顶指针相邻);
(3)入栈:S.data[++top1]=x或S.data[–top2]=x;
(4)出栈:x=S.data[top1–]或x=S.data[top2++];
(5)共享栈可以更好的利用存储空间,整个存储空间被占满时发生上溢。
⑵ 经典笔试面试知识整理,数据结构与算法(代码演示)
题目描述:
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
输入描述: array: 待查找的二维数组 target:查找的数字
输出描述:
查找到返回true,查找不到返回false
题目描述:
请实现一个函数,将漏祥一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
题目描述: 输入一个链表,从尾到头打印链表每个节点的值。
输入描述: 输入为链表的表头
输出描述: 输出为需要打印的“新链表”的表头
题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
题目描述:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一喊搜铅个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
1、题目描述:
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。n<=39
2、题目描述:
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
3、题目描述:
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
4、题目描述:
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
1、题目描述:
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
2、题目描述:
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
题目描述:
输入一个整数数组,实现一个函数来调整郑好该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
题目描述:
用两个栈来实现一个队列,完成队列的Push和Pop操作, 队列中的元素为int类型。
题目描述:
输入一个链表,输出该链表中倒数第k个结点。
⑶ 算法(第4版)给的两个jar包stdlib.jar和algs4.jar要怎么用
我只是导入了stdlib.jar,是导入到external(外部的) jars,然后编译时还是会有问题,不过按照错误给的提示(忘记提示是什么了),然后enter一下就可以了,之后编译成功,并且在我所创建的项目中多了一个“引用 的库”。
⑷ 求:用java语言编写的银行家算法的源代码
import java.util.*;
class ThreadTest {
static int type = 4, num = 10; //定义资源数目和线程数目
static int[] resource = new int[type]; //系统资源总数
//static int[] Resource = new int[type]; //副本
static Random rand = new Random();
static Bank[] bank = new Bank[num]; //线程组
Bank temp = new Bank();
public void init() {
//初始化组中每个线程,随机填充系统资源总数
for(int i = 0; i < type; i++)
resource[i] = rand.nextInt(10) + 80;
System.out.print("Resource:");
for(int i = 0; i < type; i++)
System.out.print(" " + resource[i]);
System.out.println("");
for(int i = 0; i < bank.length; i++)
bank[i] = new Bank("#" + i);
}
public ThreadTest4() {
init();
}
class Bank extends Thread {
//银行家算法避免死锁
public int[]
max = new int[type], //总共需求量
need = new int[type], //尚需资源量
allocation = new int[type]; //已分配量
private int[]
request = new int[type], //申请资源量
Resource = new int[type]; //资源副本
private boolean isFinish = false; //线程是否完成
int[][] table = new int[bank.length][type*4]; //二维资源分配表
private void init() {
// 随机填充总共、尚需、已分配量
synchronized(resource) {
for(int i = 0; i < type; i++) {
max[i] = rand.nextInt(5) + 10;
need[i] = rand.nextInt(10);
allocation[i] = max[i] - need[i];
resource[i] -= allocation[i]; //从系统资源中减去已分配的
}
printer();
for(int i = 0; i < type; i++) {
if(resource[i] < 0) {
//若出现已分配量超出系统资源总数的错误则退出
System.out.println("The summation of Threads' allocations is out of range!");
System.exit(1);
}
}
}
}
public Bank(String s) {
setName(s);
init();
start();
}
public Bank() {
//none
}
public void run() {
try {
sleep(rand.nextInt(2000));
}
catch(InterruptedException e) {
throw new RuntimeException(e);
}
while(true) {
//程序没有完成时一直不断申请资源
if(askFor() == false) {
try {
sleep(1000);
}
catch(InterruptedException e) {
throw new RuntimeException(e);
}
}
else
tryRequest();
if(noNeed() == true)
break;
}
//休眠一段时间模拟程序运行
try {
sleep(1000);
}
catch(InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(getName() + " finish!");
synchronized(resource) {
//运行结束释放占有资源
for(int i = 0; i < type; i++) {
resource[i] += allocation[i];
need[i] = allocation[i] = max[i] = 0;
}
}
}
private void printer() {
//打印当前资源信息
System.out.print(getName() + " Max:");
for(int i = 0; i < type; i++)
System.out.print(" " + max[i]);
System.out.print(" Allocation:");
for(int i = 0; i < type; i++)
System.out.print(" " + allocation[i]);
System.out.print(" Need:");
for(int i = 0; i < type; i++)
System.out.print(" " + need[i]);
System.out.print(" Available:");
for(int i = 0; i < type; i++)
System.out.print(" " + resource[i]);
System.out.println("");
}
private boolean askFor() {
//随机产生申请资源量并检测是否超标
boolean canAsk = false;
for(int i = 0; i < type; i++) {
request[i] = rand.nextInt(20);
//防止申请量超过所需量
if(request[i] > need[i])
request[i] = need[i];
}
for(int i = 0; i < type; i++) //防止随机申请资源全为0
if(request[i] > 0)
canAsk = true;
synchronized(resource) {
//锁住可供资源检查是否超标
for(int i = 0; i < type; i++) {
if(request[i] > resource[i])
//如果申请资源超过可供资源则等待一段时间后重新申请
return false;
}
}
return canAsk;
}
private void tryRequest() {
//创建副本尝试分配请求
synchronized(resource) {
for(int i = 0; i < type; i++)
//依然要防止请求量超出范围
if(request[i] > resource[i])
return;
for(int i = 0; i < type; i++) {
//复制资源量并减去需求量到一个副本上
Resource[i] = resource[i];
Resource[i] -= request[i];
}
System.out.print(getName() + " ask for:");
for(int i = 0; i < type; i++)
System.out.print(" " + request[i]);
System.out.println("");
if(checkSafe() == true) {
//如果检查安全则将副本值赋给资源量并修改占有量和需求量
for(int i = 0; i < type; i++) {
resource[i] = Resource[i];
allocation[i] += request[i];
need[i] -= request[i];
}
System.out.println(getName() + " request succeed!");
}
else
System.out.println(getName() + " request fail!");
}
}
private boolean checkSafe() {
//银行家算法检查安全性
synchronized(bank) {
//将线程资源信息放入二维资源分配表检查安全性,0~type可用资源/type~type*2所需资源/type*2~type*3占有资源/type*3~-1可用+占用资源
for(int i = 0; i < bank.length; i++) {
for(int j = type; j < type*2; j++) {
table[i][j] = bank[i].need[j%type];
}
for(int j = type*2; j < type*3; j++) {
table[i][j] = bank[i].allocation[j%type];
}
}
//冒泡排序按需求资源从小到大排
for(int i = 0; i < bank.length; i++) {
for(int j = i; j < bank.length-1; j++) {
sort(j, 4);
}
}
//进行此时刻的安全性检查
for(int i = 0; i < type; i++) {
table[0][i] = Resource[i];
table[0][i+type*3] = table[0][i] + table[0][i+type*2];
if(table[0][i+type*3] < table[1][i+type])
return false;
}
for(int j = 1; j < bank.length-1; j++) {
for(int k = 0; k < type; k++) {
table[j][k] = table[j-1][k+type*3];
table[j][k+type*3] = table[j][k] + table[j][k+type*2];
if(table[j][k+type*3] < table[j+1][k+type])
return false;
}
}
}
return true;
}
private void sort(int j, int k) {
//递归冒泡排序
int tempNum;
if(table[j][k] > table[j+1][k]) {
for(int i = type; i < type*2; i++) {
tempNum = table[j][i];
table[j][i] = table[j+1][i];
table[j+1][i] = tempNum;
}
/*temp = bank[j];
bank[j] = bank[j+1];
bank[j+1] = temp;*/
}
else if(table[j][k] == table[j+1][k] && k < type*2) //此资源量相同时递归下一个资源量排序并且防止超出范围
sort(j, k+1);
}
private boolean noNeed() {
//是否还需要资源
boolean finish = true;
for(int i = 0; i < type; i++) {
if(need[i] != 0) {
finish = false;
break;
}
}
return finish;
}
}
public static void main(String[] args) {
ThreadTest t = new ThreadTest();
//后台线程,设定程序运行多长时间后自动结束
new Timeout(30000, "---Stop!!!---");
}
}
⑸ 用C++编写一个洗牌发牌的函数,玩家可能有两个、三个和四个
几乎所有的程序员都写过类似于“洗牌”的算法,也就是将一个数组随机打乱后输出,虽然很简单,但是深入研究起来,这个小小的算法也是大有讲究。我在面试程序员的时候,就会经常让他们当场写一个洗牌的函数,从中可以观察到他们对于这个问题的理解和写程序的基本功。
在深入讨论之前,必须先定义出一个基本概念:究竟洗牌算法的本质是什么?也就是说,什么样的洗牌结果是“正确”的?
云风曾经有一篇博文,专门讨论了这个问题,他也给出了一个比较确切的定义,在经过洗牌函数后,如果能够保证每一个数据出现在所有位置的概率是相等的,那么这种算法是符合要求的。在这个前提下,尽量降低时间复杂度和空间复杂度就能得到好的算法。
第一个洗牌算法:
随机抽出一张牌,检查这张牌是否被抽取过,如果已经被抽取过,则重新抽取,直到找到没被抽出过的牌,然后把这张牌放入洗好的队列中,重复该过程,直到所有的牌被抽出。
大概是比较符合大脑对于洗牌的直观思维,这个算法经常出现在我遇到的面试结果中,虽然它符合我们对于洗牌算法的基本要求,但这个算法并不好,首先它的复杂度为O(N2),而且需要额外的内存空间保存已经被抽出的牌的索引。所以当数据量比较大时,会极大降低效率。
第二个算法:
设牌的张数为n,首先准备n个不容易碰撞的随机数,然后进行排序,通过排序可以得到一个打乱次序的序列,按照这个序列将牌打乱。
这也是一个符合要求的算法,但是同样需要额外的存储空间,在复杂度上也会取决于所采用的排序算法,所以仍然不是一个好的算法。
第三个算法:
每次随机抽出两张牌交换,重复交换一定次数次后结束
void shuffle(int* data, int length)
{
for(int i=0; i<SWAP_COUNTS; i++)
{
//Rand(min, max)返回[min, max)区间内的随机数
int index1 = Rand(0, length);
int index2 = Rand(0, length);
std::swap(data[index1], data[index2]);
}
}
这又是一个常见的洗牌方法,比较有意思的问题是其中的“交换次数”,我们该如何确定一个合适的交换次数?简单的计算,交换m次后,具体某张牌始终没有被抽到的概率为((n-2)/n)^m,如果我们要求这个概率小于1/1000,那么 m>-3*ln(10)/ln(1-2/n),对于52张牌,这个数大约是176次,需要注意的是,这是满足“具体某张牌”始终没有被抽到的概率,如果需要满足“任意一张牌”没被抽到的概率小于1/1000,需要的次数还要大一些,但这个概率计算起来比较复杂,有兴趣的朋友可以试一下。
Update: 这个概率是,推算过程可以参考这里,根据这个概率,需要交换280次才能符合要求
第四个算法:
从第一张牌开始,将每张牌和随机的一张牌进行交换
void shuffle(int* data, int length)
{
for(int i=0; i<length; i++)
{
int index = Rand(0, length);
std::swap(data[i], data[index]);
}
}
很明显,这个算法是符合我们先前的要求的,时间复杂度为O(N),而且也不需要额外的临时空间,似乎我们找到了最优的算法,然而事实并非如此,看下一个算法。
第五个算法:
void shuffle(int* data, int length)
{
for(int i=1; i<length; i++)
{
int index = Rand(0, i);
std::swap(data[i], data[index]);
}
}
一个有意思的情况出现了,这个算法和第三种算法非常相似,从直觉来说,似乎使数据“杂乱”的能力还要弱于第三种,但事实上,这种算法要强于第三种。要想严格的证明这一点并不容易,需要一些数学功底,有兴趣的朋友可以参照一下这篇论文,或者matrix67大牛的博文,也可以这样简单理解一下,对于n张牌的数据,实际排列的可能情况为n! 种,但第四种算法能够产生n^n种排列,远远大于实际的排列情况,而且n^n不能被n!整除,所以经过算法四所定义的牌与牌之间的交换程序,很可能一张牌被换来换去又被换回到原来的位置,所以这个算法不是最优的。而算法五输出的可能组合恰好是n!种,所以这个算法才是完美的。
事情并没有结束,如果真的要找一个最优的算法,还是请出最终的冠军吧!
第六个算法:
void shuffle(int* data, int length)
{
std::random_shuffle(data, data+length);
}
没错,用c++的标准库函数才是最优方案,事实上,std::random_shuffle在实现上也是采取了第四种方法,看来还是那句话,“不要重复制造轮子”
不想写 - -
⑹ JAVA实现整数拆分算法,例如输入一个4会输出4 , 3 1, 2 2, 2 1
importjava.util.Scanner;//输入的
publicclassABS{//外面建的点java的文件名必须和这个一样
publicstaticinta[]=newint[12000];
staticvoidp(intn,intindex)//搜索
{
inti;
if(n<=0)//当n为0的时候输出这种情况
{
System.out.print(a[0]);
for(i=1;i<index;System.out.print("+"+a[i++]));
System.out.print(" ");
return;//返回到函数调用的地方
手简亩}
for(i=index>咐橘0&&(n>=a[index-1])?a[index-1]:n;i>0;i--)
{//如果数组下标大于0且n剩余的值大于等于上一个的值,那么i就等于上一个的值,否则i就等于n
a[index]=i;
p(n-i,index+1);//在次调用
}
}
publicstaticvoidmain(String[]args){
Scannerin=newScanner(System.in);//从控制台中读取输入数据
intt;
t=in.nextInt();//输入一个整数
if(t>=10000)
{
System.out.println("你输入的数据超过1万,太大咯!!!");
return;
}
p(t,0);
in.close();//关闭输入
return;
}
}
这个只是毕森可以实现10000 以内的数, 如果想大一点 就把数组开大一点局可以了!
⑺ 数独 算法 C语言 代码
一、步骤:
1.对每一个空格,根据规则推断它可能填入的数字,并存储它的所有可能值;
2.根据可能值的个数,确定填写的顺序。比如说,有些空格只有一种可能,那必然是正确的结果,首先填入。
3.将所有只有一种可能的空格填写完毕以后,回到步骤1,重新确定剩下空格的可能值;
4.当没有只有一种可能的空格时(即每个空格都有两种以上可能),按照可能值个数从小到大的顺序,使用深度(广度)优先搜索,完成剩下空格。
二、例程:
#include<windows.h>
#include<stdio.h>
#include<time.h>
charsd[81];
boolisok=false;
//显示数独
voidshow()
{
if(isok)puts("求解完成");
elseputs("初始化完成");
for(inti=0;i<81;i++)
{
putchar(sd[i]+'0');
if((i+1)%9==0)putchar(' ');
}
putchar(' ');
}
//读取数独
boolInit()
{
FILE*fp=fopen("in.txt","rb");
if(fp==NULL)returnfalse;
fread(sd,81,1,fp);
fclose(fp);
for(inti=0;i<81;i++)
{
if(sd[i]>='1'&&sd[i]<='9')sd[i]-='0';
elsesd[i]=0;
}
show();
returntrue;
}
//递归解决数独
voidforce(intk)
{
if(isok)return;
if(!sd[k])
{
for(intm=1;m<=9;m++)
{
boolmm=true;
for(intn=0;n<9;n++)
{
if((m==sd[k/27*27+(k%9/3)*3+n+n/3*6])||(m==sd[9*n+k%9])||(m==sd[k/9*9+n]))
{
mm=false;
break;
}
}
if(mm)
{
sd[k]=m;
if(k==80)
{
isok=true;
show();
return;
}
force(k+1);
}
}
sd[k]=0;
}
else
{
if(k==80)
{
isok=true;
show();
return;
}
force(k+1);
}
}
intmain()
{
system("CLS");
if(Init())
{
doublestart=clock();
force(0);
printf("耗时%.0fms",clock()-start);
}
elseputs("初始化错误");
getchar();
}