题目-1. 两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map=new HashMap<>();
for(int i=0;i<nums.length;i++){
if(map.containsKey(target-nums[i])){
return new int[]{map.get(target-nums[i]),i};
}
map.put(nums[i],i);
}
return new int[0];
}
}
复杂度
时间复杂度O(n):遍历数组
空间复杂度O(1) :map占n个空间
题目-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-双指针
class Solution {
public int[] twoSum(int[] nums, int target) {
int l=0;
int r=nums.length-1;
while(l<r){
if(nums[l]+nums[r]==target){
return new int[]{nums[l],nums[r]};
}else if(nums[l]+nums[r]>target){
r--;
}else{
l++;
}
}
return null;
}
}
复杂度
时间复杂度O(n)
空间复杂度O(1)
解2-二分
class Solution {
public int[] twoSum(int[] nums, int target) {
for(int i=0;i<nums.length;i++){
int l=i+1;
int r=nums.length-1;
int e=target-nums[i];
while(l<=r){
int mid=l+(r-l)/2;
if(e==nums[mid]){
return new int[]{nums[i],nums[mid]};
}else if(e>nums[mid]){
l=mid+1;
}else{
r=mid-1;
}
}
}
return new int[]{};
//return new int[0];
}
}
复杂度
时间复杂度O(n log n)
空间复杂度O(1)
解3-HashMap
class Solution {
public int[] twoSum(int[] nums, int target) {
Set<Integer> set=new HashSet<>();
for(int x:nums){
set.add(x);
}
for(int x:nums){
int e=target-x;
if(set.contains(e)){
return new int[]{x,e};
}
}
return null;
}
}
复杂度
时间复杂度O(n)
空间复杂度O(n):HashSet需要n的空间
题目-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]]
思路-双指针+滑动窗口
- 初始化:左边界left=1;右边界right=2;窗口和s=3
- 循环i>=j跳出(题目要求至少两个元素)
- s==target,滑动窗口序列加入结果集, left后移
- s> target left后移 窗口和s减去左边界
- s<target right后移 窗口和加上右边界
- 返回结果集
class Solution {
public int[][] findContinuousSequence(int target) {
int left=1;
int right=2;
int s=3;
List<int[]> list=new ArrayList<>();
while(left<right){
if(s==target){
int[] res=new int[right-left+1];
for(int k=left;k<=right;k++){
res[k-left]=k;
}
list.add(res);
}
//相等也要后移
if(s>=target){
s-=left;
left++;
}else{
right++;
s+=right;
}
}
//二维数组必须指定第一维大小
return list.toArray(new int[0][]);
}
}
复杂度
时间复杂度O(n)
空间复杂度O(1): left,right,s均是常数阶