我在testdome.com上进行this测试是为了好玩,而且它没有通过效率测试。还有什么更好的方法?我没有计算任何两次的值。似乎唯一的方法是使用强力,这是一种n ^ 2算法。
以下是问题的说明:
编写一个函数,给定一个列表和一个目标总和,返回 任何两个不同元素的从零开始的索引,其总和等于 目标总和。如果没有这样的元素,函数应该 return null。
例如,findTwoSum(new int [] {1,3,5,7,9},12)应该返回 以下任何一组索引: 1,4(3 + 9 = 12), 2,3(5 + 7 = 12), 3,2(7 + 5 = 12)或 4,1(9 + 3 = 12)。
这是我的代码:
public class TwoSum {
public static int[] findTwoSum(int[] list, int sum) {
if (list == null || list.length < 2) return null;
for (int i = 0; i < list.length - 1; i++) { //lower indexed element
for (int j = i + 1; j < list.length; j++) { //higher indexed element
if (list[i] + list[j] == sum) {
return new int[]{i, j};
}
}
}
//none found
return null;
}
public static void main(String[] args) {
int[] indices = findTwoSum(new int[] { 1, 3, 5, 7, 9 }, 12);
System.out.println(indices[0] + " " + indices[1]);
}
}
编辑:所以这是我的最终工作代码。谢谢大家!import java.util.HashMap;
import java.util.Map;
public class TwoSum {
public static int[] findTwoSum(int[] list, int sum) {
if (list == null || list.length < 2) return null;
//map values to indexes
Map<Integer, Integer> indexMap = new HashMap<>();
for (int i = 0; i < list.length; i++) {
indexMap.put(list[i], i);
}
for (int i = 0; i < list.length; i++) {
int needed = sum - list[i];
if (indexMap.get(needed) != null) {
return new int[]{i, indexMap.get(needed)};
}
}
//none found
return null;
}
public static void main(String[] args) {
int[] indices = findTwoSum(new int[] { 1, 3, 5, 7, 9 }, 12);
System.out.println(indices[0] + " " + indices[1]);
}
}
根据Kon的建议,一次通过:
public static int[] findTwoSum(int[] list, int sum) {
if (list == null || list.length < 2) return null;
//map values to indexes
Map<Integer, Integer> indexMap = new HashMap<>();
for (int i = 0; i < list.length; i++) {
int needed = sum - list[i];
if (indexMap.get(needed) != null) {
return new int[]{i, indexMap.get(needed)};
}
indexMap.put(list[i], i);
}
//none found
return null;
}
答案 0 :(得分:2)
看看你在内循环中做了什么,检查列表[i] + list [j] == sum。
如果稍微改变等式,则意味着给定list [i]和sum(它们都是内循环中的常量),你真的在问“是否有一个索引所在的值(sum - list [i])存储“,这就是你的内循环解决的问题。
现在应用基本上使用indexOf(sum - list [i]) - 样式方法在线性时间内解决问题的知识,有一些数据结构可以在比O(N更好的时间内回答这类问题)。
答案 1 :(得分:1)
这是线性解决方案(保存排序为O(n * log(n))):
1)对初始数组a []进行排序
2)让我成为[]的第一个索引,j - 最后一个
i = 0;
j = a[].length - 1;
3)让我们从两端移动:
do{
if(a[i]+a[j] < sum)
i++;
else if(a[i]+a[j] > sum)
j--;
else { // we have found required indexes!
put (i, j) to result set;
i++;
}
} while(i < j);
最终结果 - 给出所需总和的对(i,j)的集合。
你可以在第一对后停下来然后将它归还。
P.S。如果你有像{3,3,3,3,9,9,9,9这样的数组},这个解决方案将不会给出所有组合:)
答案 2 :(得分:0)
public static Map<Integer, Integer> findTwoSum(int[] list, int sum) {
if (list == null || list.length < 2) return null;
Map<Integer, Integer> indexMap = new HashMap<Integer, Integer>();
Map<Integer, Integer> arrayResult = new HashMap<Integer, Integer>();
for (int i = 0; i < list.length; i++) {
indexMap.put(list[i], i);
}
for (int i = 0; i < list.length; i++) {
int needed = sum - list[i];
if (indexMap.get(needed) != null) {
arrayResult.put(i, indexMap.get(needed));
}
}
return arrayResult.isEmpty()?null:arrayResult;
}
public static void main(String[] args) {
Map<Integer, Integer> indices = findTwoSum(new int[] { 1, 3, 5, 7, 9 }, 12);
System.out.println(indices);
}
答案 3 :(得分:0)
这是用C#编写的解决方案。将其转换为Java术语应该足够容易:
static public IEnumerable<Tuple<int, int>> FindAllTwoSumIndexes(IList<int> list, long desiredSum)
{
var count = list?.Count;
if (list == null || count <= 1)
return null;
var results = new List<Tuple<int, int>>(32);
var indexesMap = new ConcurrentDictionary<long, List<int>>(); //0 value-to-indexes
for (var i = 0; i < count; i++)
{
var thisValue = list[i];
var needed = desiredSum - thisValue;
if (indexesMap.TryGetValue(needed, out var indexes))
{
results.AddRange(indexes.Select(x => Tuple.Create(x, i)));
}
indexesMap.AddOrUpdate(
key: thisValue,
addValueFactory: x => new List<int> { i },
updateValueFactory: (x, y) =>
{
y.Add(i);
return y;
}
);
}
return results.Any() ? results.OrderBy(x => x.Item1).ThenBy(x => x.Item2).ToList() : null;
//0 bare in mind that the same value might be found over multiple indexes we need to take this into account
// also note that we use concurrentdictionary not for the sake of concurrency or anything but because we like
// the syntax of the addorupdate method which doesnt exist in the simple dictionary
}
答案 4 :(得分:-1)
这是一个Java程序,它使用Hashtable或Set以最有效的方式查找数组中的值,其总和等于k。
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class ArraySumUsingSet {
public static void main(String args[]) {
prettyPrint(getRandomArray(9), 11);
prettyPrint(getRandomArray(10), 12);
}
/**
* Given an array of integers finds two elements in the array whose sum is equal to n.
* @param numbers
* @param n
*/
public static void printPairsUsingSet(int[] numbers, int n){
if(numbers.length < 2){
return;
}
Set set = new HashSet(numbers.length);
for(int value : numbers){
int target = n - value;
// if target number is not in set then add
if(!set.contains(target)){
set.add(value);
}else {
System.out.printf("(%d, %d) %n", value, target);
}
}
}
/*
* Utility method to find two elements in an array that sum to k.
*/
public static void prettyPrint(int[] random, int k){
System.out.println("Random Integer array : " + Arrays.toString(random));
System.out.println("Sum : " + k);
System.out.println("pair of numbers from an array whose sum equals " + k);
printPairsUsingSet(random, k);
}
/**
* Utility method to return random array of Integers in a range of 0 to 15
*/
public static int[] getRandomArray(int length){
int[] randoms = new int[length];
for(int i=0; i<length; i++){
randoms[i] = (int) (Math.random()*15);
}
return randoms;
}
}
Random Integer array : [0, 14, 0, 4, 7, 8, 3, 5, 7]
Sum : 11
pair of numbers from an array whose sum equals 11
(7, 4)
(3, 8)
(7, 4)
Random Integer array : [10, 9, 5, 9, 0, 10, 2, 10, 1, 9]
Sum : 12
pair of numbers from an array whose sum equals 12
(2, 10)