个人记录-LeetCode 33. Search in Rotated Sorted Array

问题:
Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).
You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array.

代码示例:
1、这个问题并不困难,如果不用高级的数据结构,主要思路就是:
重新调整数组,使之有序。
然后在有序的数组中,找出target值对应的index。
然后,将该index映射成原数组的值。

194个测试用例,耗时17ms。

缺点是细节太多,第一次觉得写测试用例,比写代码本身还有难度。

public class Solution {
    public int search(int[] nums, int target) {
        if (nums == null || nums.length < 1) {
            return -1;
        }

        if (nums.length == 1) {
            if (nums[0] != target) {
                return -1;
            } else {
                return 0;
            }
        }

		//判断数组如果没有rotated,是否是升序
        boolean asc = isAsc(nums);

		//找到出现rotated的位置
		//如果没有rotated,那么pivotIndex的值为0
        int pivotIndex = getPivotIndex(nums, asc);

		//getNewArray将rotated的数组,变换成有序数组
		//就是将pivot~length-1的数字,平移到0~length-1-pivot
		//将0~pivot平移到length-pivot~length-1
		//然后,在有序数组中找到index
        int result = getIndex(getNewArray(nums, pivotIndex), 0, nums.length-1, asc, target);

		//没找到坐标,或没发生平移,直接返回结果
        if (result != -1 && pivotIndex != 0) {
	        //按上面的平移规则,逆向得到原下标
            int len = nums.length - 1 - pivotIndex;
            if (result <= len) {
                result = result + pivotIndex;
            } else {
                result = result + pivotIndex - nums.length;
            }
        }

        return result;
    }

    private static boolean isAsc(int[] nums) {
        if (nums.length == 2) {
            return nums[0] < nums[1];
        }

        boolean result = false;

		//这个就不细说了,大家将可能的情况画个图就能明白
        if (nums[0] < nums[1]) {
            if (nums[1] < nums[2]) {
                result = true;
            } else if (nums[0] > nums[nums.length-1]) {
                result = true;
            }
        } else if (nums[1] < nums[2] ){
            result = true;
        }

        return result;
    }

	//找到第一个不符合顺序的点
    private static int getPivotIndex(int[] nums, boolean asc) {
        int pivotIndex = 0;
        if (asc) {
            for (int i = 0; i < nums.length - 1; ++i) {
                if (nums[i + 1] < nums[i]) {
                    pivotIndex = i + 1;
                    break;
                }
            }
        } else {
            for (int i = 0; i < nums.length - 1; ++i) {
                if (nums[i+1] > nums[i]) {
                    pivotIndex = i + 1;
                    break;
                }
            }
        }

        return pivotIndex;
    }

	//构造新的有序数组
    private static int[] getNewArray(int nums[], int pivotIndex) {
        if (pivotIndex == 0) {
            return nums;
        }

        int[] newArray = new int[nums.length];

        int j = 0;
        for (int i = pivotIndex; i < nums.length; ++i) {
            newArray[j] = nums[i];
            ++j;
        }

        for (int i = 0; i < pivotIndex; ++i) {
            newArray[j] = nums[i];
            ++j;
        }

        return newArray;
    }

	//二分法,结合排序方式,递归查找结果
    private static int getIndex(int nums[], int beginIndex, int endIndex, boolean asc, int target) {
        if (beginIndex > endIndex) {
            return -1;
        }

        int middle = (beginIndex + endIndex) / 2;
        if (nums[middle] == target) {
            return middle;
        } else if (middle == beginIndex && middle == endIndex) {
            return -1;
        } else {
            if (((nums[middle] > target) && asc)
                    || (nums[middle] < target && !asc)){
                return getIndex(nums, beginIndex, middle-1, asc, target);
            }  else {
                return getIndex(nums, middle + 1, endIndex, asc, target);
            }
        }
    }
}

2、HashMap无脑求解

思路就不用解释了。

194个测试用例,耗时19ms。
缺点:稍微耗时一点,有种拿着神器作弊的感觉。。。

public class Solution {
    public int search(int[] nums, int target) {
        if (nums == null || nums.length < 1) {
            return -1;
        }

        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; ++i) {
            map.put(nums[i], i);
        }

        if (map.containsKey(target)) {
            return map.get(target);
        } else {
            return -1;
        }
    }
}

3、新的题目描述中,定义原数组是升序的,直接二分法即可。

class Solution {
    public int search(int[] nums, int target) {
        if (nums == null || nums.length < 1) {
            return -1;
        }

        if (nums.length == 1) {
            return target == nums[0] ? 0 : -1;
        }

        int leftIndex = 0;
        int rightIndex = nums.length - 1;

        while (leftIndex <= rightIndex) {
            int midIndex = (leftIndex + rightIndex) / 2;
            int middleValue = nums[midIndex];
            if (middleValue == target) {
                return midIndex;
            }

            //Middle处于第一段上升沿
            if (nums[0] <= middleValue) {
                if (target >= nums[0] && target < middleValue) {
                    rightIndex = midIndex - 1;
                } else {
                    leftIndex = midIndex + 1;
                }
            //Middle处于Rotate上升沿
            } else {
                if (target > middleValue && target <= nums[nums.length - 1]) {
                    leftIndex = midIndex + 1;
                } else {
                    rightIndex = midIndex - 1;
                }
            }
        }

        return -1;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值