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

##一、阶乘问题:
阶乘结果 从个位到倒数 连续为零的个数:
首先想到零是怎么出现的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

##二、 求给定数组的总和:
使用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进余下的空间
(第二步 在数组相等长度的时候 忽略)

	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

##四、斐波拉契数
编写一个计算前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[n],f[n-1]) (n>2)

 

##五、组建最大的数
编写一个能将给定非负整数列表中的数字排列成最大数字的函数。例如,给定[50,2,1,9],最大数字为95021。
此处最大突破点就是比较两个数 顺序 导致结果变化,(前+后 ).compareTo(后+前)

	public void co(String[] a){
		String temp="";
		//排序法:冒泡泡排序,从小到大
		for(int i=0;i0){
					temp=a[j+1];
					a[j+1]=a[j];
					a[j]=temp;
				}
			}
		}
		StringBuffer sb=new StringBuffer();
		for(int i=0;i

##六、算出指定的数
编写一个在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 list = new ArrayList();
		ArrayList opeator = new ArrayList();
		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 毫秒

你可能感兴趣的:(java,算法)