这道题如果用暴力解法做非常简单,但是题目有要求:Your solution must run in O(log n) time and O(1) space.

如果看到时间复杂度O(logn),那么就一定要想到binary search。需要注意的是,在做这类找数题的时候,一定要看清楚是让返回index还是数值啊,博主就犯过这样的错误。

binary search查找的规律,例如:

Input: nums = [3,3,7,7,10,11,11,12,12]
Output: 10

1. 如果一个数跟前后都不同,那就是要找的数了。

2. 如果一个数跟前面的数相同,跟后面的数不同,要看这个数的index是奇数还是偶数,如果index是奇数,例如例题中的第二个7,就要往后找,如果index是偶数,例如例题中的第二个11,就要往前找。

3. 如果一个数跟前面的数不同,跟后面的数相同,要看这个数的index是奇数还是偶数,如果index是奇数,例如例题中的第一个11,就要往前找,如果index是偶数,例如例题中的第一个7,就要往后找。

因为既要比较前面的数,又要比较后面的数,数组的第一和最后一个数就要单独判断。所以我的第一个算法是这样的:

    public int singleNonDuplicate(int[] nums) {
        int n = nums.length;
        if (nums.length <= 2)
            return nums[0];
        if (nums[0] != nums[1])
            return nums[0];
        if (nums[n - 1] != nums[n - 2])
            return nums[n - 1];
        int l = 1, r = nums.length - 2, mid = 0;
        while (l <= r) {
            mid = (l + r) / 2;
            if (nums[mid] != nums[mid - 1] && nums[mid] != nums[mid + 1])
                return nums[mid];
            else if (nums[mid] == nums[mid - 1] && nums[mid] != nums[mid + 1]) {
                if (mid % 2 == 1)
                    l = mid + 1;
                else
                    r = mid - 1;
            } else if (nums[mid] != nums[mid - 1] && nums[mid] == nums[mid + 1]) {
                if (mid % 2 == 1)
                    r = mid - 1;
                else
                    l = mid + 1;
            }
        }
        return -1;
    }

我们能不能只跟前面或者后面比较呢,还是上面的例子, 我们试试只跟前面比较:

Input: nums = [3,3,7,7,10,11,11,12,12]
index: [0,1,2,3,4, 5, 6, 7, 8] Output: 10

1. 如果一个数跟前面的数相同,要看这个数的index是奇数还是偶数,如果index是奇数,例如例题中的第二个7,就要往后找,如果index是偶数,例如例题中的第二个11,就要往前找。

2. 如果一个数跟前面的数不同,要看这个数的index是奇数还是偶数,如果index是奇数,例如例题中的第一个11,就要往前找,如果index是偶数,例如例题中的第一个7,就要往后找。

3. 目标的index一定是偶数。

    public int singleNonDuplicate2(int[] nums) {
        int l = 0, r = nums.length - 1, mid = 0;
        while (l < r) {
            mid = (l + r) / 2;
            if (nums[mid] == nums[mid - 1]) {
                if (mid % 2 == 1)
                    l = mid + 1;
                else
                    r = mid;
            } else if (nums[mid] != nums[mid - 1]) {
                if (mid % 2 == 1) {
                    r = mid - 1;
                } else
                    l = mid;
            }
        }
        return nums[l];
    }
posted on 2022-01-18 15:29  阳光明媚的菲越  阅读(12)  评论(0编辑  收藏  举报