leetCode -1
leetCode -15
题目一:两数之和,返回下标
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].
// 方法一:
public int[] twoSum1(int[] nums, int target) {
// 利用Map的key-value结构
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int need = target - nums[i];
if (map.containsKey(need)) {
// 满足则返回
return new int[]{map.get(need), i};
}
// key=值,value=下标
map.put(nums[i], i);
}
return new int[]{};
}
// 方法二:
public int[] twoSum2(int[] nums, int target) {
// 先排序,利用指针
Arrays.sort(nums);
// 第一个元素下标
int l = 0;
// 最后一个元素下标
int h = nums.length - 1;
while (l < h) {
int sum = nums[l] + nums[h];
if (sum > target) {
h--;
} else if (sum < target) {
l++;
} else if (sum == target) {
// 满足则返回
return new int[]{l, h};
}
}
return new int[]{};
}
变形题:返回所有满足条件的两个值,且不重复
Input: nums = [1,3,1,2,2,3], target = 4
Output: [[1,3],[2,2]]
public static void main(String[] args) {
int[] nums = new int[]{1,3,1,2,2,3};
int target = 4;
List<List<Integer>> result = new ArrayList();
// 先排序,利用指针
Arrays.sort(nums);
// 第一个元素下标
int l = 0;
// 最后一个元素下标
int h = nums.length - 1;
HashMap<Integer, Integer> valToIndex = new HashMap<>();
while (l < h) {
int sum = nums[l] + nums[h];
int left = nums[l] ; right = nums[h];
// 求和 大于 目标数,高位往前移一位
if (sum > target ) {
// 防止数组越界 && 去重
if (l < h && nums[h] == right){
h--;
}
} else if (sum < target ) { // 求和 小于 目标数,低位往后移一位
if (l < h && nums[l] == left){
l++;
}
} else if (sum == target ) {
// 满足
if (!valToIndex.containsKey(nums[l])) {
valToIndex.put(nums[l], nums[h]);
result.add(Arrays.asList(nums[l], nums[h]));
}
if (l < h && nums[h] == right){
h--;
}
if (l < h && nums[l] == left){
l++;
}
}
}
System.out.println(JSONObject.toJSONString(result));
}
变形:N个数求和:
Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
思路:
-
- 先排序
-
- 利用两数相加的思想,将n个元素,每次固定一个数,递归(n - 1)个数求和,将结果汇总
public List<List<Integer>> threeSum(int[] nums) {
// 排序
Arrays.sort(nums);
return nSumTarget(nums, 3, 0, 0);
}
/**
* @param nums 数组元素
* @param n 元素累加个数
* @param index 从数组元素那个下标开始
* @param target 元素求和的值
*/
public List<List<Integer>> nSumTarget(int[] nums, int n, int index, int target) {
List<List<Integer>> result = new ArrayList();
int length = nums.length;
// 数组的长度小于计算的n个元素操作 || 至少大于两个个元素求和
if (length < n || n < 2) {
return result;
}
// 两个元素相加
if (n == 2) {
// 初始下标
int i = index;
// 数组长度
int j = length - 1;
while (i < j) {
int sum = nums[i] + nums[j];
int left = nums[i], right = nums[j];
if (sum > target) {
// 防止数组越界 && 去重(如果不需要去重则去掉该条件)
if (i < j && nums[j] == right){
j--;
}
} else if (sum < target) {
// 防止数组越界 && 去重(如果不需要去重则去掉该条件)
if (i < j && nums[i] == left) {
i++;
}
} else {
result.add(new ArrayList<>(Arrays.asList(nums[i], nums[j])));
// 防止数组越界 && 去重(如果不需要去重则去掉该条件)
while (i < j && nums[i] == left) {
i++;
}
// 防止数组越界 && 去重(如果不需要去重则去掉该条件)
while (i < j && nums[j] == right) {
j--;
}
}
}
} else {
// 遍历数组,每次取一个元素,从该元素之后的元素看成一个新的数组,进行n-1个元素求和 = target - nums[i]
for (int i = index; i < length; i++) {
// 递归:
// 参数一:原数组
// 参数二:元素个数
// 参数三:下标,从第几个元素开始
// 参数四:目标值,元素值累加
List<List<Integer>> subList = nSumTarget(nums, n - 1, i + 1, target - nums[i]);
// 遍历元素,拼接需要的值,
for (List<Integer> arr : subList) {
// 将 nums[i] 添加到 对应的数组中
arr.add(nums[i]);
result.add(arr);
}
// 防止越界 && 过滤当前元素=下一个元素
while (i < length - 1 && nums[i] == nums[i + 1]) {
i++;
}
}
}
return result;
}
}