[leetCode]剑指 Offer 57. 和为s的两个数字、II. 和为s的连续正数序列

在这里插入图片描述

解法 双指针

由于数组是递增排序的所以可以设置两个指针,一个指向头部,一个指向尾部。两指针所指元素相加,若大于目标值则跳转尾部指针向前移动。若小于目标值则调整头部指针向后移动。

class Solution {
    public int[] twoSum(int[] nums, int target) {
        if (nums == null || nums.length == 0) 
            return new int[]{};
        // 向前移动的指针
        int ahead = nums.length - 1;
        // 向后移动的指针
        int behind = 0;
        int[] ans = new int[2];
        while (ahead > behind) {
            int sum = nums[ahead] + nums[behind];
            if (sum == target) {
                ans[0] = nums[behind];
                ans[1] = nums[ahead];
                return ans;
            } else if (sum > target) {
                --ahead;
            } else {
                ++behind;
            }
        }
        return new int[]{};
    }
}

剑指 Offer 57 - II. 和为s的连续正数序列

在这里插入图片描述

解法

与上面解法类似,可以使用一个指针small先指向1,一个指针big指向2。将small~big之间的数字相加,如果其和sum等于目标值则将此序列添加到结果中,如果sum小于目标值则调整small指针,使其增大。目标和大于目标值则调整big指针使其减小。由于序列至少要有两个数字所以增加small到(target + 1)/2 为止。

class Solution {
    public int[][] findContinuousSequence(int target) {
        if (target < 3) return new int[][]{};
        int small = 1;
        int big = 2;
        int middle = (target + 1) >> 1;
        int sum = small + big;
        List<int[]> ans = new LinkedList<>(); 
        while (small < middle) {
            if (sum == target) 
                addOneAns(ans, small, big);
            while (sum > target && small < middle) {
                sum -= small;
                ++small;
                if (sum == target) 
                    addOneAns(ans, small, big);
            }
            ++big;
            sum += big;
        }
        return ans.toArray(new int[ans.size()][]);
    }
    private void addOneAns(List<int[]> ans, int small, int big) {
        int[] row = new int[big - small + 1];
        for (int i = small; i <= big; ++i) {
            row[i - small] = i;
        }
        ans.add(row);
    }
}
posted @ 2020-09-21 09:45  消灭猕猴桃  阅读(68)  评论(0编辑  收藏  举报