【LeetCode】1095. 山脈數組中查找目標值(二分查找)

題目:1095. 山脈數組中查找目標值

public class FindMountainArray_1095 {

	public static void main(String[] args) {

//		int[] array = { 1, 3, 5, 4, 3, 2, 1 };
//		int[] array = { 1, 2, 3, 4, 5, 3, 1 };
		int[] array = { 0, 1, 2, 4, 2, 1 };
		int target = 3;
		MountainArray mountainArray = new MountainArrayImpl(array);

		System.out.println(findInMountainArray(target, mountainArray));
	}

	public static int findInMountainArray(int target, MountainArray mountainArray) {

		int len = mountainArray.length();

		// 1.用二分法找到mountaninTop山頂下標
		int top = findMountainTop(mountainArray, 0, len - 1);

		// 2.然後對左邊升序數組二分查找target目標下標
		int res = findAscArray(mountainArray, 0, top, target);
		// 找到target直接返回
		if (res != -1) {
			return res;
		}

		// 3.對右邊降序數組二分查找target目標下標
		return findDecArray(mountainArray, top + 1, len - 1, target);
	}

	/**
	 * 二分法查找最大元素
	 * @param mountainArr 山峯數組
	 * @param left 數組最小下標
	 * @param right 數組最大下標
	 * @return 最大元素下標
	 */
	public static int findMountainTop(MountainArray mountainArr, int left, int right) {

		while (left < right) {
			// 取左中位數
			int mid = left + (right - left) / 2;

			// 左中位數和後面一位比較,確定下一次查找範圍
			if (mountainArr.get(mid) < mountainArr.get(mid + 1)) {
				// 山頂在右邊,去右邊查找
				left = mid + 1;
			} else {
				// 去左邊查找,需要包含mid,因爲mid可能是最大值
				right = mid;
			}
		}

		// 最後left=right
		return left;
	}

	/**
	 * 二分法查找升序數組中的目標值
	 * @param mountainArr 山峯數組
	 * @param left 數組最小下標
	 * @param right 數組最大下標
	 * @param target 目標值
	 * @return 目標值下標
	 */
	public static int findAscArray(MountainArray mountainArr, int left, int right, int target) {

		while (left < right) {
			// 取左中位數
			int mid = left + (right - left) / 2;

			// 左中位數和後面一位比較,確定下一次查找範圍
			if (mountainArr.get(mid) < target) {
				// 山頂在右邊,去右邊查找
				left = mid + 1;
			} else {
				// 去左邊查找,需要包含mid,因爲mid可能是最大值
				right = mid;
			}
		}

		// 最後left=right
		// 因爲不確定區間縮爲一個之後,是否找到target,所以需要判斷
		if (mountainArr.get(left) == target) {
			return left;
		}

		return -1;
	}

	/**
	 * 二分法查找降序數組中的目標值
	 * @param mountainArr 山峯數組
	 * @param left 數組最小下標
	 * @param right 數組最大下標
	 * @param target 目標值
	 * @return 目標值下標
	 */
	public static int findDecArray(MountainArray mountainArr, int left, int right, int target) {

		while (left < right) {
			// 取左中位數
			int mid = left + (right - left) / 2;

			// 左中位數和後面一位比較,確定下一次查找範圍
			if (mountainArr.get(mid) > target) {
				// 去右邊查找
				left = mid + 1;
			} else {
				// 去左邊查找,需要包含mid,因爲mid可能是最大值
				right = mid;
			}
		}

		// 最後left=right
		// 因爲不確定區間縮爲一個之後,是否找到target,所以需要判斷
		if (mountainArr.get(left) == target) {
			return left;
		}

		return -1;
	}
}

class MountainArrayImpl implements MountainArray {
	private int[] array;
	private int length;

	public MountainArrayImpl(int[] array) {
		this.array = array;
		this.length = array.length;
	}

	@Override
	public int get(int index) {
		return this.array[index];
	}

	@Override
	public int length() {
		return this.length;
	}
}

interface MountainArray {
	public int get(int index);

	public int length();
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章