简体   繁体   English

如何使用hashmaps解决这个问题?

[英]How to solve this using hashmaps?

Suppose you're given a list of the following values: 假设您获得了以下值的列表:

[1,4,5,7,8,9]

and you're given that k=4 where k is the difference between two array elements. 并且你得到k=4 ,其中k是两个数组元素之间的差异。 How would you find how many times k appears? 你怎么知道k出现多少次? For example, in this list k appears 3 times [(5-1),(8-4),(9-5)] 例如,在此列表中k出现3次[(5-1),(8-4),(9-5)]

I was able to solve this using two for loops but that requires O(n^2) time. 我能够使用两个for循环解决这个问题但需要O(n^2)时间。 I heard this could be solved using hashmaps, but am unsure how to would implement it? 我听说这可以用hashmaps解决,但我不确定如何实现它?

Any ideas would be greatly appreciated! 任何想法将不胜感激!

The idea to is to store all the possible differences between the k and each value in the input array ( numbers ). 想法是存储k和输入数组中每个值之间的所有可能差异( numbers )。 Then count the number of values in the input array that fits the difference. 然后计算输入数组中适合差异的值的数量。

This will work: 这将有效:

public class Solution {
    public int twoSum(int[] numbers, int k) {
        if (numbers == null) {
            return null;
        }
        int count = 0;
        HashMap<Integer, Integer> difference = new HashMap<Integer, Integer>();
        for (int i = 0; i < numbers.length; i++) {
            difference.put(k - numbers[i], i);
        }
        for (int i = 0; i < numbers.length; i++) {
            int cur = -numbers[i];
            if (difference.containsKey(cur) && difference.get(cur) != i) {
                count++;
            }
        }
        return count;
    }
}

The catch is to have difference.get(cur) != i condition in place (where i is the index cur ) to avoid the case of having k = 0 and each value would form a pair with itself. 捕获是有difference.get(cur) != i条件就位(其中i是索引cur )以避免k = 0的情况,并且每个值将与自身形成一对。

With HashSet (which internally uses HashMap) we can assume that its contains method is close to O(1) so you could 使用HashSet (内部使用HashMap),我们可以假设它的contains方法接近于O(1)所以你可以

  1. fill such set with all elements 用所有元素填充这样的集合
  2. iterate over elements and calculate values for +4 and -4 differences 迭代元素并计算+4-4差异的值
  3. check if these values exist in set. 检查集合中是否存在这些值。
  4. divide result by 2 since you will get true for pairs 1,5 and 5,1 which in reality is one pair. 将结果除以2,因为对于实际上是一对的对1,55,1 ,你会得到真的。

As shown by Óscar López you can improve it by calculating only one of +4 and -4 and skip last step ÓscarLópez所示,您可以通过仅计算+4-4一个来改进它并跳过最后一步

In fact, it can be solved using just a Set : we have to find if the set contains another element whose difference with the current results in k . 实际上,它可以仅使用Set来解决:我们必须找到该集合是否包含另一个元素,其与当前结果的差异为k Try the following solution, it works assuming that there are at least two elements in an input with no duplicates, and doesn't waste space for a non-needed value as would be the case if we used a HashMap for this problem: 尝试以下解决方案,它假设输入中至少有两个元素没有重复,并且不会浪费空间用于不需要的值,如果我们使用HashMap解决此问题的情况:

int k = 4;
int howMany = 0;
Set<Integer> set = new HashSet<>(Arrays.asList(1, 4, 5, 7, 8, 9));

System.out.printf("k = %d%n", k);   

for (Integer n : set) {
    if (set.contains(n - k)) {
        howMany++;
        System.out.printf("(%d - %d) = k%n", n, n - k);
    }
}

System.out.printf("k appears %d times%n", howMany);

The above results in the following output: 以上结果如下:

k = 4
(5 - 1) = k
(8 - 4) = k
(9 - 5) = k
k appears 3 times

The following method works even if the array contains duplicates. 即使数组包含重复项,以下方法也适用。 It implements Pshemo's final algorithm (without the duplicate work and without the division by 2). 它实现了Pshemo的最终算法(没有重复的工作,没有2的除法)。

First, it stores the contents of the original array in a hashmap. 首先,它将原始数组的内容存储在hashmap中。 The original value is the key, and the number of times the original value appears in the array is the value of the hashmap. 原始值是键,原始值在数组中出现的次数是hashmap的值。 This phase has a runtime O(number of items in the original list), and uses storage O(number of distinct items in the original list). 此阶段具有运行时O(原始列表中的项目数),并使用存储O(原始列表中的不同项目的数量)。

Second, it loops through the hashmap , and finds any items that are ( delta = 4 ) greater than the item being considered. 其次,它循环遍历散列映射 ,并查找( delta = 4 )大于正在考虑的项目的任何项目。 It does some math to increment the result tally. 它做了一些数学运算来增加结果。 It has a special case to handle ( delta == 0 ) scenarios, to deal with the issue Ling Zhong mentioned. 它有一个特殊情况来处理( delta == 0 )场景,以处理凌中提到的问题。 This phase has a runtime O(number of distinct items in the original list). 此阶段具有运行时O(原始列表中的不同项目数)。

public class Solution {
    public int countDifferences(int delta, int[] array) {
        if (array == null) {
            return 0;
        }
        // Load the contents of the array into a hashmap.
        // This process loses the sorting.
        HashMap<Integer, Integer> choices = new HashMap<>();
        for (int arrayItem : array) {
            if (choices.containsKey(arrayItem)) {
                choices.put(arrayItem, 1 + choices.get(arrayItem));
            } else {
                choices.put(arrayItem, 1);
            }
        }

        // Count the result.
        int result = 0;
        for(Map.Entry<Integer, Integer> e : choices.entrySet()) {
            Integer key   = e.getKey();
            Integer value = e.getValue();
            if (delta == 0) {
                result += value * (value - 1) / 2; // add summorial(value - 1)
            } else {
                if (choices.containsKey(key + delta)) {
                    result += value * choices.get(key + delta);
                }
            }
        }
        return result;
    }
}

You can achieve this in single iteration. 您可以在单次迭代中实现此目的。 Apply logic like this, when start iterating say suppose u have a hashmap with k,v pair Ex. 应用这样的逻辑,当开始迭代时说假设你有一个带有k,v对Ex的hashmap。 1,dummyvalue 4,dummyvalue 5, dummy value 1,dummyvalue 4,dummyvalue 5,虚拟值

And say suppose ur k=4 So when start iterating over map u will get say first 1 so do it like 1+k ie 1+4 ie 5 so look back in ur data structure or map for key=5 map.get(5) if map returns the value update another map or another data structure which is holding ur count ok k say suppose we have a map with k=4 so its value will b something like this count = count +1 if we get the key which over here is 4. 并且假设你的k = 4所以当开始迭代地图时你会先说1,所以就像1 + k,即1 + 4即5,所以回顾你的数据结构或映射为key = 5 map.get(5 )如果map返回值更新另一个地图或另一个数据结构,其中保持你的数量ok k说假设我们有一个k = 4的地图所以它的值将是这样的一个像count = count +1如果我们得到的那个键是这是4。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM