23-05-24 刷题
练习刷题思路
Missing Number - LeetCode 【easy】
分析:
- 长度为n的int数组,包含无重复的元素,每个元素范围是[0, n]. 找[0, n] 范围内没有出现在数组中的那个元素。
- 思路1: 用求和公式,计算出0+1+…+n的和,然后遍历数组,减去出现的,最后剩下就是没有出现的。时间 O(n) 空间 O(1)
- 思路2:用异或的性质,两个相同的数异或结果是0,所以先把0…n这些数异或,得到x,然后再跟数组中每个数异或,最后剩下的就是缺失的数。时间 O(n) 空间 O(1)
- 思路3:利用数组(hashMap)记录已经出现的数,遍历一遍看哪个没有出现。时间 O(n) 空间 O(n),不好。
题目变形:
-
要求一样,增加一条,数组递增排序。怎么做?
-
思路:利用二分。如果中间 A[mid] == mid 说明左边没有缺少元素,到右边去查找。否则去左边查找。直到最后剩下一个元素。
-
代码
static int findMissing(int[] A) { int left = 0, right = A.length - 1; while (left <= right) { int mid = (left + right) >>> 1; if (A[mid] == mid) { left = mid + 1; } else { right = mid - 1; } } return left; // why left? just use a sample to find it out }
-
First Missing Positive - LeetCode 【Hard】
分析:
-
题目描述,跟上面的类似,但是更难一点。每个数的范围是int最大范围内,然后找第一个缺失的正数。要求O(n)时间,O(1)空间。
-
思路1:分两步来做,第一步尝试把每个元素归位(修改输入数组,将A[i] 放到 A[i] - 1位置,前提是它在[1,n]范围内,且目标位置也是错位的,如果没有判断目标位置错位,那当数组有重复元素时,可能会出现死循环,这也是一个难点)。第2步,就是从前往后遍历找第一个不满足条件的下标。注意返回的数是i + 1. 如果都满足,则说明缺失的是n + 1
class Solution { public int firstMissingPositive(int[] A) { // 1. move A[i] to correct pos int n = A.length; for(int i = 0; i < n; i++) { while (A[i] > 0 && A[i] <= n && A[i] != i + 1 && A[A[i] - 1] != A[i]) { int t = A[i]; A[i] = A[t - 1]; A[t - 1] = t; } } // 2. find first incorrect one for (int i = 0; i < n; i++) { if (A[i] != i + 1) { return i + 1; } } return n + 1; } }
-
思路2:先过滤掉所有不符合要求的数,把他们标记成0,(并且可以把他们移动到最后面,可省略)。 然后对每个正数,把他们对应下标元素标记成负数,如果那个位置是0,那么标记成-n(也可以是-n-1),然后找第一个>= 0的位置即可。【这个思路时间复杂度也是O(n),空间O(1),也很简单,但是彻底改变了原始的数组了】
-
class Solution { public int firstMissingPositive(int[] A) { // 1. first filter out out-of-range [1, n] number, mark as 0 int n = A.length; for (int i = 0; i < n; i++) { if (A[i] < 1 || A[i] > n) A[i] = 0; } // 2. mark non-zero's pos (A[i] - 1) as negative value for (int val : A) { if (val == 0) continue; int x = Math.abs(val); if (A[x - 1] == 0) A[x - 1] = -n; else if (A[x - 1] > 0) A[x - 1] = -A[x - 1]; // otherwise A[val-1] already neg, it means it has been set by // other pos(i.e. it has duplicated num) } // 3. find first >= 0 pos for (int i = 0; i < n; i++) { if (A[i] >= 0) return i + 1; } return n + 1; } }