这是我参与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^51 <= 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)
方法二
双指针:
- 设置两个指针
i,j,分别从数组的头和尾开始 - 当
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)