剑指Offer系列(java版,详细解析)57.和为s的数字
题目一
题目描述
剑指 Offer 57. 和为s的两个数字
难度简单96收藏分享切换为英文接收动态反馈
输入一个递增排序的数组和一个数字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
测试用例
- 功能测试(数组中存在和为s的两个数;数组中不存在和为s的两个数)
- 特殊输入测试(表示数组的指针为空指针)
解题思路
充分数组是递增排序的性质
- 定义两个指针,一个指向数组的第一个数字,一个指向数组的最后一个数字
- 如果两个指针指向的数字加起来等于数字s,则返回结果
- 如果两个指针指向的数字加起来大于数字s,则指向数组后面数字的指针左移
- 如果两个指针指向的数字加起来小于数字s,则指向数组前面数字的指针右移
时间复杂度为O(n)
自己解题
public class Solution {
public ArrayList<Integer> findNumbersWithSum(int [] array, int sum) {
ArrayList<Integer> result = new ArrayList<Integer>();
// 非法输入
if (array == null || array.length < 2) {
return result;
}
for (int i = 0; i < array.length; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[i] + array[j] == sum) {
result.add(array[i]);
result.add(array[j]);
return result;
}
}
}
return result;
}
}
这是大家都能直接想到的解法。它的问题在于时间复杂度过高。
参考解题
class Solution {
public int[] twoSum(int[] nums, int target) {
int i = 0, j = nums.length - 1;
while(i < j) {
int s = nums[i] + nums[j];
if(s < target) i++;
else if(s > target) j--;
else return new int[] { nums[i], nums[j] };
}
return new int[0];
}
}
题目二
题目描述
和为s的连续正数序列
输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数),例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所有打印出3个连续序列15、46和7~8
测试用例
- 功能测试(存在和为s的连续序列,如9、100等;不存在和为s的连续序列,如0,4等)。
- 边界值测试(连续序列的最小和3)
解题思路
- 定义连续正数序列的首尾节点small、big;small初始化为1,big初始化为2
- 如果序列和等于s,则将序列输出,并改变big值,进入新一轮的查找
- 如果序列和大于s,从序列中去掉最小的值,增大small的值,small的值最多加到s/2
- 如果序列和小于s,big加1,然后加入到序列中
自己解题
懵逼态
参考解题
class Solution {
public int[][] findContinuousSequence(int target) {
int i = 1, j = 2, s = 3;
List<int[]> res = new ArrayList<>();
while(i < j) {
if(s == target) {
int[] ans = new int[j - i + 1];
for(int k = i; k <= j; k++)
ans[k - i] = k;
res.add(ans);
}
if(s >= target) {
s -= i;
i++;
} else {
j++;
s += j;
}
}
return res.toArray(new int[0][]);
}
}
题目考点
- 考察应聘者思考复杂问题的思维能力,找规律。
- 考察应聘者的知识迁移能力。有点菜。