给定目标总和,找出给定数组中是否存在一对总和的元素

时间:2011-04-22 22:39:53

标签: java hashmap complexity-theory

import java.util.HashMap;

public class target 
{
    public static void hash(int []a,int sum)
    {
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();

        int i;

        for (i = 0; i < a.length; ++i) 
            map.put(a[i], sum-a[i]);

        for (i = 0; i < a.length; ++i) 
            if(map.containsValue(a[i]) && map.get(a[i])!=null)
             {
                System.out.println("("+a[i]+","+map.get(a[i])+")");
                map.remove(a[i]);
             }
    }

public static void main(String[] args)
{
    int []a={1, 2, 13, 34, 9, 3, 23, 45, 8, 7, 8, 3, 2};
    hash(a,11);
}
}

我想知道是否有更好,更有效的解决方案。这种复杂性是n。我能做得更好吗?

9 个答案:

答案 0 :(得分:1)

您的实施错过了重复的对。


你可以

  1. 对数组进行排序
  2. 从头开始迭代并为每个元素

    • 计算所需的补数(sum - element)
    • 进行反向二分搜索(从排序数组末尾)寻找精确值

    • 如果找到,请同时删除

  3. 归结为观察结果:

     n1 < n2 < n3 < n4 < n5 < n6
    

    最可能的对从两端到中间对称。现在,最坏的情况仍然很糟糕,但至少你没有哈希表开销

答案 1 :(得分:1)

正如我评论的那样,你的sollution不是O(N),因为containsValue搜索存储在HashMap中的所有值。为了解决这个问题,我使用您的解决方案采用了不同的方法:

  public static void newVersion(int[] a, int sum){
        HashMap<Integer, Boolean> map = new HashMap<Integer, Boolean>();


        for (int i= 0; i< a.length; i++) {
            map.put(sum - a[i], true);
        }

        for (int i = 0; i < a.length; i++) {
            if (map.containsKey(a[i]) && map.get(a[i])) {
                System.out.println("("+(sum-a[i])+","+a[i]+")");
                map.put(a[i], false);
                map.put(sum-a[i], false);
            }
        }

    }

在第一步,它存储每个整数的“补码值”,在第二步,它检查补码是否存在。如果存在,请将两个对标记为已使用。

这种复杂性是:

* O(N) for the first looping
* O(N) * (O(1) + O(1)) for the second loop and the containsValue and get.
* Finally: O(N) + O(N) .:.  O(N) solution,

答案 2 :(得分:1)

我有这个问题的以下解决方案。时间复杂度应为O(N),因为HashMap操作put,get和keySet都是O(1)。

import java.util.HashMap;
import java.util.Map;


/**
 * Find a pair of numbers in an array given a target sum
 * 
 *
 */

public class FindNums {

    public static void findSumsForTarget(int[] input, int target)
    {
        // just print it instead of returning

        Map<Integer, String> myMap = populateMap(input);

        // iterate over key set
        for (Integer currKey : myMap.keySet()) {
            // find the diff
            Integer diff = target - currKey;

            // check if diff exists in the map
            String diffMapValue = myMap.get(diff);
            if(diffMapValue!=null)
            {
                // sum exists
                String output = "Sum of parts for target " + target + " are " + currKey + " and " + diff;   
                System.out.println(output);
                return; // exit; we're done - unless we wanted all the possible pairs and permutations
            }
//          else
                // keep looking                         
        }
        System.out.println("No matches found!");

    }

    private static Map<Integer, String> populateMap(int[] input) 
    {
        Map<Integer,String> myMap = new HashMap<Integer,String>();
        for (int i = 0; i < input.length; i++) {
             String currInputVal = myMap.get(input[i]);
             if(currInputVal!=null) // value already exists
             {
                 // append current index location to value
                 currInputVal = currInputVal + ", " + i;
                 // do a put with the updated value
                 myMap.put(input[i], currInputVal);
             }
             else
             {
                 myMap.put(input[i], Integer.toString(i)); // first argument is autoboxed to Integer class               
             }          
        }               

        return myMap;
    }


    // test it out!
    public static void main(String[] args)
    {
        int[] input1 = {2,3,8,12,1,4,7,3,8,22};
        int[] input2 = {1,2,3,4,5,6,7,8,9,10};
        int[] input3 = {2,-3,8,12,1,4,7,3,8,22};
        int target1 = 19;
        int target2 = 16;

        // test
        FindNums.findSumsForTarget(input1, target1);
        FindNums.findSumsForTarget(input1, -1);
        FindNums.findSumsForTarget(input2, target2);
        FindNums.findSumsForTarget(input3, target1);


    }


}

答案 3 :(得分:1)

import java.util.*;
import java.io.*;
class hashsum
{
public static void main(String arg[])throws IOException
{
    HashMap h1=new HashMap();
    h1.put("1st",new Integer(10));
    h1.put("2nd",new Integer(24));
    h1.put("3rd",new Integer(12));
    h1.put("4th",new Integer(9));
    h1.put("5th",new Integer(43));
    h1.put("6th",new Integer(13));
    h1.put("7th",new Integer(5));
    h1.put("8th",new Integer(32));

    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

    System.out.println("Enter no.");
    int no=Integer.parseInt(br.readLine());

    Iterator i=h1.entrySet().iterator();

    boolean flag=false;
    while(i.hasNext())
    {

        Map.Entry e1=(Map.Entry)i.next();
        Integer n1=(Integer)e1.getValue();


        Iterator j=h1.entrySet().iterator();
        while(j.hasNext())
        {
            Map.Entry e2=(Map.Entry)j.next();

            Integer n2=(Integer)e2.getValue();


            if(no==(n1+n2))
            {
                System.out.println("Pair of elements:"+n1 +" "+n2);
                flag=true;
            }
        }
    }   
    if(flag==false)
    System.out.println("No pairs");
}
}

答案 4 :(得分:1)

public static void hash1(int[] a, int num) {
    Arrays.sort(a);
    // printArray(a);

    int top = 0;
    int bott = a.length - 1;

    while (top < bott) {

        while (a[bott] > num)
            bott--;

        int sum = a[top] + a[bott];

        if (sum == num) {
            System.out.println("Pair " + a[top] + " " + a[bott]);
            top++;
            bott--;
        }

        if (sum < num)
            top++;
        if (sum > num)
            bott--;
    }

}

答案 5 :(得分:0)

解决方案:O(n)时间和O(log(n))空间。

public static boolean array_find(Integer[] a, int X)   
{
        boolean[] b = new boolean[X];
        int i;
        for (i=0;i<a.length;i++){
                int temp = X-a[i]; 
                 if(temp >= 0 && temp < X) //make sure you are in the bound or b
                        b[temp]=true;
        }
        for (i=0;i<a.length;i++)
                if(a[i]<X && b[a[i]]) return true;      
        return false;
}

答案 6 :(得分:0)

递归地找到其总和是来自给定数组的目标和的子集。

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Main {
    public static Set<List<Integer>> set = new HashSet<>();

    public static void main(String[] args) {
        int[] biggerArray = {1, 2, 1, 1};
        int targetedSum = 3;
        findSubset(biggerArray, targetedSum);
    }

    public static void findSubset(int[] biggerArray, int targetedSum) {
        for (int i = 0; i < biggerArray.length; i++) {
            List<Integer> subset = new ArrayList<>();
            if (biggerArray[i] > targetedSum)
                continue;
            else
                subset.add(biggerArray[i]);
            if (i + 1 < biggerArray.length)
                find(subset, i, biggerArray, targetedSum, i);
        }
        System.out.println(set);
    }

    public static List<Integer> find(List<Integer> subset, int startIndex, final int[] biggerArray, final int targetedSum, final int skipIndex) {
        if (skipIndex == startIndex) {
            find(subset, startIndex + 1, biggerArray, targetedSum, skipIndex);
            return null;
        }

        int subsetSum = findSumOfList(subset);
        int remainedSum = targetedSum - subsetSum;
        int i = startIndex;

        if (remainedSum == 0) {
            set.add(subset);
            return null;
        }

        if ((startIndex < biggerArray.length) && (biggerArray[startIndex] == remainedSum)) {
            List<Integer> temp = new ArrayList<Integer>(subset);
            temp.add(biggerArray[i]);
            set.add(temp);
        }
        else if ((startIndex < biggerArray.length) && (biggerArray[startIndex] < remainedSum)) {
            while (i + 1 <= biggerArray.length) {
                List<Integer> temp = new ArrayList<Integer>(subset);
                if (i != skipIndex) {
                    temp.add(biggerArray[i]);
                    find(temp, ++i, biggerArray, targetedSum, skipIndex);
                }
                else {
                    i = i + 1;
                }
            }
        }
        else if ((startIndex < biggerArray.length) && (biggerArray[startIndex] > remainedSum)) {
            find(subset, ++i, biggerArray, targetedSum, skipIndex);
        }

        return null;
    }

    public static int findSumOfList(List<Integer> list) {
        int i = 0;
        for (int j : list) {
            i = i + j;
        }
        return i;
    }
}

答案 7 :(得分:0)

我们不需要两个for循环。可以在同一个循环中检测匹配,同时自己填充地图。

   public static void matchingTargetSumPair(int[] input, int target){
        Map<Integer, Integer> targetMap = new HashMap<Integer, Integer>();
        for(int i=0; i<input.length; i++){
            targetMap.put(input[i],target - input[i]);
            if(targetMap.containsKey(target - input[i])){
                System.out.println("Mathcing Pair: "+(target - input[i])+" , "+input[i]);
            }
        }
   }


    public static void main(String[] args) {
        int[] targetInput = {1,2,4,5,8,12};
        int target = 9;
        matchingTargetSumPair(targetInput, target);
    }

答案 8 :(得分:0)

我们可以在填充数组本身时轻松找到是否存在任何对。使用散列映射,并为每个输入元素检查散列映射中是否存在sum-input差异元素。

#!/bin/bash
domain=$1
output="$(curl -Isk $domain | grep HTTP | cut -d ' ' -f2)"
echo "$output"