剑指Offer 57

90 阅读1分钟

这是我参与8月更文挑战的第29天,活动详情查看:8月更文挑战

剑指 Offer 57. 和为s的两个数字

题目

输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[2,7] 或者 [7,2]

示例 2:

输入:nums = [10,26,30,31,47,60], target = 40
输出:[10,30] 或者 [30,10]

限制:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^6

方法一

哈希表:遍历一遍数组,并用哈希表记录下数组的数;第二次遍历时,去哈希表中查找有无target-x这个数,有则返回答案;

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] res = new int[2];
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int x : nums) map.put(x, 1);
        for (int x : nums) 
            if (map.containsKey(target - x)) {
                res[0] = x;
                res[1] = target - x;
                break;
            }
        return res;
    }
}

时间复杂度: O(n)

空间复杂度: O(n)

方法二

双指针:

  • 设置两个指针ij,分别从数组的头和尾开始
  • nums[i] + nums[j] == target时,返回两个指针所指的数值
  • <target时,i右移
  • 否则,j左移
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] res = new int[2];
        int n = nums.length;
        for (int i = 0, j = n - 1; i < j; ) {
            if (nums[i] + nums[j] == target) {
                res[0] = nums[i];
                res[1] = nums[j];
                break;
            }else if (nums[i] + nums[j] > target) {
                j --;
            }else i ++;
        }
        return res;
    }
}

时间复杂度: O(n)

空间复杂度: O(1)

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

题目

输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。

序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。

示例 1:

输入:target = 9
输出:[[2,3,4],[4,5]]

示例 2:

输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]

限制:

  • 1 <= target <= 10^5

方法一

双指针:

  • 设置两个指针,初始位置都指向1
  • 当两个指针的数字之间的和等于target时,记录到答案中
  • 和小于target时,尾指针往后移,使和变大
  • 和大于target时,头指针往后移,使和变小
class Solution {
    public int[][] findContinuousSequence(int target) {
        List<int[]> res = new ArrayList<>();
        for (int i = 1, j = 1; i <= target / 2 + 1; ) {
            int sum = (i + j) * (j - i + 1) / 2;
            if (sum == target) {
                int[] tmp = new int[j - i + 1];
                for (int k = i, idx = 0; k <= j; k ++ )
                    tmp[idx ++] = k;
                res.add(tmp);
                i ++;
            }else if (sum > target) i ++;
            else j ++;  
        }
        return res.toArray(new int[0][]);
    }
}

时间复杂度: O(n)

空间复杂度: O(1)