对撞类,灌水类,two sum类

对撞型指针的本质是,不需要扫描多余的状态。在两边指针的判断之后,可以直接跳过其中一个指针与所有另外一面 index 组成的 pair。

将时间复杂度从 O(n^2) -> O(n)

if(A[i]和A[j] 满足某个状态) {
    do something;
    j--; // 不用考虑[i+1, j-1] 和 j组成的pair
} else if(A[i]和A[j] 不满足某个状态) {
    do something;
    i++;
} else {
    do something;
    i++ or j--;
}

Two Sum

unsorted array 其实和two pointer无关,但是为了引出下一题就放在这儿了

public class Solution {
    public int[] twoSum(int[] nums, int target) {
        if(nums == null || nums.length == 0) {
            return new int[2];
        }

        int[] result = new int[2];
        HashMap<Integer, Integer> map = new HashMap<>();

        for(int i = 0; i < nums.length; i++) {
            if(map.containsKey(target - nums[i])) {
                result[0] = map.get(target - nums[i]);
                result[1] = i;
                return result;
            } else if(!map.containsKey(nums[i])) {
                map.put(nums[i], i);
            }
        }

        return result;
    }
}

Two Sum II

sorted array

  • 如果 nums[i] + nums[j] > target,那么 nums[i ~ j-1] + nums[j] > target.
  • 因此 i,j 指向的不仅仅是元素,也代表了利用单调性,i,j 之间所有的 pair.
public class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int[] result = new int[2];

        if(numbers == null || numbers.length == 0) {
            return result;
        }

        int start = 0;
        int end = numbers.length - 1;

        while(start < end) {
            int sum = numbers[start] + numbers[end];

            if (sum == target) {
                result[0] = start + 1;
                result[1] = end + 1;
                return result;
            } else if(sum > target) {
                end--;
            } else {
                start++;
            }
        }

        return result;
    }
}

Container With Most Water

暴力解法就是找到所有的可能pair,计算他们之间的盛水容量,这是O(n^2)的。

利用木桶原理,盛水的最大容量取决于最短的那块板。两个指针分别置于头尾,这时候我们面临着移动长板还是短板的问题。 移动长板没有意义的,因为移动任意一个指针都会导致宽度减小,而长度没有变化(取决于短板),所以面积是必然减小的。所以这时候我们应该移动短板。

public class Solution {
    public int maxArea(int[] height) {
        if(height == null || height.length == 0){
            return 0;
        }

        int start = 0;
        int end = height.length - 1;
        int max = 0;
        while(start < end) {
            // update max area
            max = Math.max(max, Math.min(height[start], height[end]) * (end - start));
            if(height[start] < height[end]) {
                start++;
            } else {
                end--;
            }
        }
        return max;
    }

    // second version 
    // 应对大数据集的prune 写法
    // 优化方法
    public int maxArea(int[] height) {
        if(height == null || height.length == 0){
            return 0;
        }

        int start = 0;
        int end = height.length - 1;
        int max = 0;
        while(start < end) {
            // update max area
            int min = Math.min(height[start], height[end]);
            max = Math.max(max, min * (end - start));
            // 如果比最小值还要小,那么这个值就没必要再去计算了
            while(start < end && height[start] <= min) start++;
            while(start < end && height[end] <= min) end--;
        }
        return max;
    }
}

results matching ""

    No results matching ""