阿里巴巴面试题--数组

给定一个排好序的数组,A[1],A[2],...A[n],起元素数值两两不等,设计一个高效算法找出中间所有A[i]=i的下标,并分析其复杂度(必须分析复杂度)。

package com.patrick.bishi;

import java.util.HashSet;
import java.util.Set;

/**
 * @date 22/09 2013
 * @author patrick
 * 
 */
public class FindMatch {
	private int a[];
	private float b[];
	private static Set<Integer> set = new HashSet<Integer>();

	public int[] getA() {
		return a;
	}

	public void setA(int[] a) {
		this.a = a;
	}

	public float[] getB() {
		return b;
	}

	public void setB(float[] b) {
		this.b = b;
	}

	public FindMatch(float a[]) {
		this.b = a;
	}

	public FindMatch(int a[]) {
		this.a = a;
	}

	public FindMatch() {

	}

	public static void main(String[] args) {
		int a[] = { -4, -3, -1, 0, 2, 3, 6, 7, 8, 9, 11, 12, 14, 15, 17 };
		float b[] = { 1.1f, 1.2f, 1.3f, 2.0f, 4, 5, 6, 6.1f, 8.0f };
		FindMatch fm = new FindMatch();
		fm.setA(a);
		fm.setB(b);
		fm.testB();
	}

	public void testA() {
		for (int i = 0; i < a.length; i++) {
			System.out.println("A[" + i + "] = " + a[i]);
		}
		int minPos = 0;
		int maxPos = a.length - 1;
		find(minPos, maxPos);
		int count = set.size();
		System.out.println("A[i]=i count=" + count);
		for (int pos : set) {
			System.out.print(pos + ", ");
		}
	}

	public void testB() {
		for (int i = 0; i < b.length; i++) {
			System.out.println("B[" + i + "] = " + b[i]);
		}
		int minPos = 0;
		int maxPos = b.length - 1;
		findF(minPos, maxPos);
		int count = set.size();
		System.out.println("B[i]=i count=" + count);
		for (int pos : set) {
			System.out.print(pos + ", ");
		}
	}

	private void find(int minPos, int maxPos) {
		int midVal, minVal, maxVal, d, p;
		if (maxPos < minPos) {
			return;
		}
		minVal = a[minPos];
		maxVal = a[maxPos];
		if (minVal > maxPos || maxVal < minPos) {
			return;
		}
		int midPos = minPos + (maxPos - minPos) / 2;
		midVal = a[midPos];
		if (midVal == midPos) {
			System.out.println("add one:" + midPos);
			set.add(midPos);
		}

		if (midVal <= 0) {
			minPos = midPos + 1;
			find(minPos, maxPos);
		} else if (midVal >= maxPos) {
			maxPos = midPos - 1;
			find(minPos, maxPos);
		} else {
			// 整形可以进一步优化
			if (midVal < midPos) {
				d = midPos / midVal;
				if (d != 1) {
					p = midVal * (d - 1);
					find(minPos, midPos - p - 1);
					find(midPos + 1, maxPos);
					return;
				}
			} else {
				d = midVal / midPos;
				if (d != 1) {
					p = midPos * (d - 1);
					find(minPos, midPos);
					find(midPos + p + 1, maxPos);
					return;
				}
			}
			find(minPos, midPos - 1);
			find(midPos + 1, maxPos);
		}

	}

	private void findF(int minPos, int maxPos) {
		float midVal, minVal, maxVal;
		int d, p;
		if (maxPos < minPos) {
			return;
		}
		minVal = b[minPos];
		maxVal = b[maxPos];
		if (minVal > maxPos || maxVal < minPos) {
			return;
		}
		int midPos = minPos + (maxPos - minPos) / 2;
		midVal = b[midPos];
		if (midVal == midPos) {
			System.out.println("add one:" + midPos);
			set.add(midPos);
		}

		if (midVal <= 0) {
			minPos = midPos + 1;
			find(minPos, maxPos);
		} else if (midVal >= maxPos) {
			maxPos = midPos - 1;
			find(minPos, maxPos);
		} else {
			if (midVal < midPos) {
				d = (int) (midPos / midVal);
				if (d != 1) {
					p = (int) (midVal * (d - 1));
					findF(minPos, midPos - p - 1);
					findF(midPos + 1, maxPos);
					return;
				}
			} else {
				d = (int) (midVal / midPos);
				if (d != 1) {
					p = midPos * (d - 1);
					findF(minPos, midPos);
					findF(midPos + p + 1, maxPos);
					return;
				}
			}
			findF(minPos, midPos - 1);
			findF(midPos + 1, maxPos);
		}

	}
}

复杂度:

空间复杂度:不考虑用Set保存下标,中间过程中用到了8个变量,分别保存最大、中间、最小位置和它们各自的值,还有两个缩小范围的计算变量。

时间复杂度:用到了递归,二分法,因为本身最差的时间复杂度就是O(n),在本实现下平均复杂度应该小于O(n/2)。

希望得到更好的实现,和对复杂度的分析。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值