По заданной сумме найдите, есть ли в данном массиве пара элементов, суммирующих до нее - PullRequest
3 голосов
/ 23 апреля 2011
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 ]

1 голос
/ 16 октября 2012
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--;
    }

}
1 голос
/ 19 сентября 2012
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");
}
}
1 голос
/ 26 мая 2011

У меня есть следующее решение этой проблемы. Временная сложность должна быть 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);


    }


}
1 голос
/ 07 мая 2011

Как я уже говорил, ваше решение - это не 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,
1 голос
/ 23 апреля 2011

Ваша реализация пропускает дублированные пары.


Вы могли бы

  1. сортировка массива
  2. итерация от начала и для каждого элемента

    • рассчитать необходимое дополнение (сумма - элемент)
    • выполнить обратный двоичный поиск (от конца отсортированного массива), ища это точное значение

    • если найдено, удалите оба

Это сводится к наблюдению, что с отсортированными элементами:

 n1 < n2 < n3 < n4 < n5 < n6

наиболее вероятные пары идут симметрично с обоих концов к середине. Теперь наихудший случай все еще плох, но, по крайней мере, у вас нет издержек хеш-таблицы

0 голосов
/ 17 декабря 2017

Мы можем легко определить, существует ли какая-либо пара при заполнении самого массива. Используйте хэш-карту, и для каждого входного элемента проверьте, существует ли в хэш-карте элемент разности суммы ввода.

import java.util.*;

class findElementPairSum{
    public static void main(String[] args){

        Map<Integer, Integer> hm = new HashMap<Integer, Integer>();

        Scanner sc = new Scanner(System.in);

        System.out.println("Enter the sum key: ");
        int sum=sc.nextInt();

        for(int i=0; i<10; i++){
            int x = sc.nextInt();
            if(!hm.containsKey(sum-x)){
                hm.put(x, 1);
            } else {
                System.out.println("Array contains two elements with sum equals to: "+sum);
                break;
            }
        }
    }
}
0 голосов
/ 11 ноября 2015

Нам не нужно иметь две петли.Совпадение может быть обнаружено в том же цикле при заполнении карты самостоятельно.

   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);
    }
0 голосов
/ 04 августа 2015

Рекурсивно найти подмножество, сумма которого является целевой суммой из данного массива.

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;
    }
}
0 голосов
/ 28 октября 2011

Решение: 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;
}
...