给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
审题:求数组中的两数之和是给定的数字
思考:
解题:
方法一:暴力破解,循环两次
/*
* 方法一暴力破解法,循环两次数组,依此相加求结果是否为给定的整数,时间复杂度较高。
*/
public int[] twoSums(int[] nums, int target) {
// 依此往后遍历
for (int i = 0; i < nums.length; i++) {
for (int j = i; j < nums.length; j++) {
if (nums[j] == target - nums[i]) {
return new int[] { i, j };
}
}
}
// 非法参数异常
throw new IllegalArgumentException("No two sum solution");
}
方法二:两遍哈希表
/*
* 遍历两遍哈希表,第一次迭代将元素值和索引添加到表中, 第二次检查目标元素(target-nums[i])是否存在表中。 目标元素不能是nums[i]本身。
*/
public int[] twoSums(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
// 迭代将元素值和索引添加到表中
for (int i = 0; i < nums.length; i++) {
// 数组里的项充当了key,for循环的i充当了value。
map.put(nums[i], i);
}
// 迭代查找有没有target-nums[i]
for (int i = 0; i < nums.length; i++) {
// 判断这个值是否是map中的key
int complement = target - nums[i];
// 判断是否包含指定的键值,并且通过指定的键获取map的值(0,1,2)
//看是否和这个for循环作用域里循环到的一样,防止同一个数的和等于结果。
if (map.containsKey(complement) && map.get(complement) != i) {
return new int[] { i, map.get(complement) };
}
}
throw new IllegalArgumentException("No two sum solution");
}
方法三: 一遍哈希表
/*
* 一遍哈希表,在进行迭代并将元素插入到表中的同时,
* 还会回过头来检查表中是否已经存在当前元素所对应的目标元素
*/
public int[] twoSums(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < nums[i]; i++) {
int complement = target - nums[i];
// 因为最初map里并没有元素,所以直接跳过,put到map里,以后每次运行到这的时候,就会去已经有数据的map里查找。
if (map.containsKey(complement)) {
return new int[] { map.get(complement), i };
}
map.put(nums[i], i);
}
// 没有返回值返回这个。
throw new IllegalArgumentException("No two sum solution");
}
完整解题过程:
package com.sunjianlong.july.LeetCode;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
/*
* Given nums = [2, 7, 11, 15], target = 9,
* Because nums[0] + nums[1] = 2 + 7 = 9,
* return [0, 1].
*/
class Solution {
/*
* 第一种方法:Brute Force 暴力破解,时间复杂度比较高。
*/
public int[] twoSum(int[] nums, int target) {
for (int i = 0; i < nums.length; i++) {
for (int j = i; j < nums.length; j++) {
if (nums[j] == target - nums[i]) {
return new int[] { i, j };
}
}
}
// 非法参数异常
throw new IllegalArgumentException("No two sum solution");
}
}
class Solution_1 {
/*
* 两遍哈希表:Two-pass Hash Table 一个简单的实现使用了两次迭代。在第一次迭代中,我们将每个元素的值和它的索引添加到表中。
* 然后,在第二次迭代中,我们将检查每个元素所对应的目标元素(target - nums[i]target−nums[i])是否存在于表中。
* 注意,该目标元素不能是 nums[i]nums[i] 本身!
*/
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < nums.length; i++) {
// 数组里的项充当了key,for循环的i充当了value。
map.put(nums[i], i);
}
// 第二次循环查找看target-nums[i]
// 是否存在与数组之中,是否是key,前提是数组中的值和新建的map中的不可以是同一个数,同一个数就是自己本身相加了。
for (int i = 0; i < nums[i]; i++) {
// 判断这个值是否是map中的key
int complement = target - nums[i];
// 判断是否包含指定的键值,并且通过指定的键获取map的值(0,1,2)看是否和这个for循环作用域里循环到的一样,防止同一个数的和等于结果。
if (map.containsKey(complement) && map.get(complement) != i) {
return new int[] { i, map.get(complement) };
}
}
throw new IllegalArgumentException("No two sum solution");
}
}
class Solution_2 {
/*
* 一遍哈希表:One-pass Hash Table 在进行迭代并将元素插入到表中的同时,我们还会回过头来检查表中是否已经存在当前元素所对应的目标元素。
* 如果它存在,那我们已经找到了对应解,并立即将其返回。 [2, 7, 11, 15]9
*/
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < nums[i]; i++) {
int complement = target - nums[i];
//因为最初map里并没有元素,所以直接跳过,put到map里,以后每次运行到这的时候,就会去已经有数据的map里查找。
if (map.containsKey(complement)) {
return new int[] { map.get(complement), i };
}
map.put(nums[i], i);
}
// 没有返回值返回这个。
throw new IllegalArgumentException("No two sum solution");
}
}
public class TwoSum_1 {
// 方法的作用是将输入的字符串转换为Integer的Array
public static int[] StringToIntegerArray(String input) {
// trim() 方法用于删除字符串的头尾空白符。
input = input.trim();
// 截取字符串
input = input.substring(1, input.length() - 1);
// 如果输入的字符串长度为0
if (input.length() == 0) {
return new int[0];
}
// 将字符串按","切割,赋值给字符串数组。
String[] parts = input.split(",");
int[] output = new int[parts.length];
// 将字符串数字转换为Integer数组
for (int index = 0; index < parts.length; index++) {
String part = parts[index].trim();
output[index] = Integer.parseInt(part);
}
return output;
}
public static String integerArrayToString(int[] nums, int length) {
if (length == 0) {
return "[]";
}
String result = "";
for (int index = 0; index < length; index++) {
int number = nums[index];
result += Integer.toString(number) + ",";
}
return "[" + result.substring(0, result.length() - 1) + "]";
}
public static String integerArrayToString(int[] nums) {
return integerArrayToString(nums, nums.length);
}
public static void main(String[] args) throws IOException {
// 缓冲字符输入流 读取输入流
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = in.readLine()) != null) {
int[] nums = StringToIntegerArray(line);
line = in.readLine();
int target = Integer.parseInt(line);
long startTime = System.nanoTime(); // 获取开始时间
int[] ret = new Solution_2().twoSum(nums, target);
long endTime = System.nanoTime(); // 获取结束时间
String out = integerArrayToString(ret);
System.out.println(out);
System.out.println("程序运行时间: " + (endTime - startTime) + "ns");
}
}
}
知识点:HashMap