您的位置:首页 > 职场人生

Java工程师面试---面试算法题(一)

2017-11-02 17:37 477 查看

一、阶乘问题:

阶乘结果包含零的个数:

首先想到零是怎么出现的10的倍数相乘即可,即 (5*2)*n n为任意的数。

1、2 只要是偶数 都包含2.而包括5的只存在位数为0或者5的数里面

2、所有2的个数 远远多于5的个数,故只要统计五的个数

3、每加一个五,数字就多一个5,减少乘法运算。

需要消耗o(1)的空间和o(n/5)的时间

public void countZero(int n){
int k=0,sum=0;
if(n<5)
retrurn 0;
for(int i=5;i<n;i+=5){
k++;
sum=k;
}
return sum;
}


二、 求给定数组的总和:

使用for循环、while循环和递归写出3个函数来计算给定数列的总和。

就是叠加数组:

public int sum(int[] k) {
int sum = 0;
for (int i = 0; i < k.length; i++)
sum += k[i];
return sum;
}

public int sum2(int[] k) {
int sum = 0, i = 0;
while (i < k.length)
sum += k[i++];
return sum;
}

public int sum3(int[] k, int m) {
if (k.length == m + 1) {
return k[m];
}
return k[m] + sum3(k, m + 1);
}


三、交错合并数组

编写一个交错合并列表元素的函数。例如:给定的两个列表为[a,B,C]和[1,2,3],函数返回[a,1,B,2,C,3]。

有点类似于归并排序,合并两个数组。这里面使用交错排序。

第一步:按照最短的数 完成2*min(length)长度,

第二步:再将剩余的数copy进余下的空间

(第二步
1041f
在数组相等长度的时候 忽略)

public int[] merge(int[] arr1, int[] arr2) {
int length = arr1.length + arr2.length;
int n = arr1.length > arr2.length ? arr2.length : arr1.length;
int[] m = new int[length];
int i=0;
int k=0;
for(;i<n && k<length;i++,k+=2){
m[k]=arr1[i];
m[k+1]=arr2[i];
}
for(;i<arr1.length&& k<length;i++,k++){
m[k]=arr1[i];
}
for(;i<arr2.length&& k<length;i++,k++){
m[k]=arr2[i];
}
return m;
}


四、斐波拉契数

编写一个计算前100位斐波那契数的函数。根据定义,斐波那契序列的前两位数字是0和1,随后的每个数字是前两个数字的和。例如,前10位斐波那契数为:0,1,1,2,3,5,8,13,21,34。

首先想到暴力算法:反复计算之前的数值,然后计算出结果。

4、1暴力算法

4.2.1、前一百个拉斐波切数:

public Long[] f() {
Long[] arr = new Long[100];
int n = 0;

arr[n++] = 0L;

arr[n++] = 1L;

for (int i = n; i < 100; i++)
arr[i] = arr[i - 1] + arr[i-2];
return arr;
}


算到第94个的时候,数据越界了。没办法8个字节的long都不够用。该方法走不通。

第91个值是: 4660046610375530309
第92个值是: 7540113804746346429
第93个值是: -6246583658587674878
第94个值是: 1293530146158671551


4.2.2、使用BigDecimal方法计算:

public String[] f() {
String[] arr = new String[100];
int n = 0;

arr[n++] = "0";

arr[n++] = "1";

for (int i = n; i < 100; i++)
arr[i] = add(arr[i - 1] , arr[i - 2]);
return arr;
}

public String add(String a, String b) {
BigDecimal d1 = new BigDecimal(a);
BigDecimal d2 = new BigDecimal(a);
return d1.add(d2).toString();
}


结果是:

花费时间 7ms

第90个值是: 618970019642690137449562112
第91个值是: 1237940039285380274899124224
第92个值是: 2475880078570760549798248448
第93个值是: 4951760157141521099596496896
第94个值是: 9903520314283042199192993792
第95个值是: 19807040628566084398385987584
第96个值是: 39614081257132168796771975168
第97个值是: 79228162514264337593543950336
第98个值是: 158456325028528675187087900672
第99个值是: 316912650057057350374175801344


4.2.3使用BigInteger

public BigInteger[] f2() {
BigInteger[] arr = new BigInteger[100];
int n = 0;

arr[n++] = new BigInteger("0");

arr[n++] = new BigInteger("1");

for (int i = n; i < 100; i++)
arr[i] =  arr[i - 1].add(arr[i - 2]);
return arr;
}


时间是3ms

4.2 扩展–计算第几位的斐波拉契数

1、暴力算法,使用上面的算法,打印第几次的结果

时间复杂度是 o(n),空间复杂度是o(1)

2、 简化算法:

前几位斐波拉契数:0 1 1 2 3 5 8…..

当n大于2的时候,第n位数等于第n-1位+第n-2位之和。

第一种思路:使用递归算法 计算出

时间复杂度是o(n),空间复杂度时o(2*n)

function a(n){
if(n<=0)
return;
if(n==1)
return 0;
else if(n==2)
return 1;
else
return a(n-1)+a(n-2);
}


第二种算法:

(1 ,0) *()=(3,1)

(3 ,1) ()=(5, 3) (1 ,0) ()*()=(5, 3)

….

以此类推,只要计算出()里面的数,就可以用公式一步计算出最终的结果。

很容易的使用行列式(不会的可以看看线性代数 )就计算出()={{1,1},{1,0}}

划分计算模块

n<3直接得出结果

n>2

1、行列式幂次方的计算方法

2、幂次方的结果乘以(1,0)即可得到(f
,f[n-1]) (n>2)



五、组建最大的数

编写一个能将给定非负整数列表中的数字排列成最大数字的函数。例如,给定[50,2,1,9],最大数字为95021。

此处最大突破点就是比较两个数 顺序 导致结果变化,(前+后 ).compareTo(后+前)

public void co(String[] a){
String temp="";
//排序法:冒泡泡排序,从小到大
for(int i=0;i<a.length-1;i++){
for(int j=0;j<a.length-i-1;j++){
if(compare(a[j+1],a[j])>0){
temp=a[j+1];
a[j+1]=a[j];
a[j]=temp;
}
}
}
StringBuffer sb=new StringBuffer();
for(int i=0;i<a.length ;i++)
sb.append(a[i]);
System.err.println(sb.toString());
}
//比较哪个数大
public int compare(String a1,String a2){
return (a1+a2).compareTo(a2+a1);
}


六、算出指定的数

编写一个在1,2,…,9(顺序不能变)数字之间插入+或-或什么都不插入,使得计算结果总是100的程序,并输出所有的可能性。例如:1 + 2 + 34 – 5 + 67 – 8 + 9 = 100。

1、暴力算法,穷举

/**
* 采取穷举的方法,测试是否符合条件
*/
@Test
public void aa() {
byte[] c = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
byte[] b = new byte[8];
String res = "";
for (int i = 0; i < 6561; i++) {
if ((res = getRes(b, c)) != null) {
System.err.println(res);
}
addBy3(b);
}

}

/**
*
* @param b
*            数字字符集
* @param c
*            数字之间的操作可能
* @return 等于100的操作的四则运算
*/
public String getRes(byte[] b, byte[] c) {
ArrayList<String> list = new ArrayList<String>();
ArrayList<String> opeator = new ArrayList<String>();
list.add(String.valueOf(c[0]));

// 合并无操作符的位置
for (int j = 0; j < b.length; j++) {
if (b[j] == 0) {
list.set(list.size() - 1,
list.get(list.size() - 1) + String.valueOf(c[j + 1]));
} else if (b[j] == 1) {
list.add(String.valueOf(c[j + 1]));
opeator.add("+");
} else if (b[j] == 2) {
list.add(String.valueOf(c[j + 1]));
opeator.add("-");
}
}

// 记录本次操作的情况
StringBuilder sb = new StringBuilder();
// 因为最大结果是9位数 超出int
BigInteger sum = new BigInteger(list.get(0));
sb.append(list.get(0));
// 计算
for (int j = 0; j < opeator.size(); j++) {
sb.append(opeator.get(j) + list.get(j + 1));
if (opeator.get(j).equals("+")) {
sum = sum.add(new BigInteger(list.get(j + 1)));
} else if (opeator.get(j).equals("-")) {
sum = sum.subtract(new BigInteger(list.get(j + 1)));
} else {

}
}
String s = sum.toString();

if ("100".equals(s))
return sb.toString();
else
return null;
}

/**
* 三进制加法,满2 清零 进一;最长为8位数
*
* @param c
*/
public void addBy3(byte[] c) {
for (int i = c.length - 1; i >= 0; i--) {
if (c[i] == 2) {
c[i] = 0;
continue;
} else {
c[i] += (byte) 1;
break;
}
}
}


123+45-67+8-9
123+4-5+67-89
123-45-67+89
123-4-5-6-7+8-9
12+3+4+5-6-7+89
12+3-4+5+67+8+9
12-3-4+5-6+7+89
1+23-4+56+7+8+9
1+23-4+5+6+78-9
1+2+34-5+67-8+9
1+2+3-4+5+6+78+9


运算时间43 毫秒
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: