简体   繁体   中英

How can I (more) easily compare two sets of numbers?

I have sets of three numbers, and I'd like to compare numbers in a set to another set. Namely, that each number in the first set is less than at least one number in the other set. The caveat is that the next numbers in the first set must be less than a different number in the second set (ie, {6,1,6} would work against {8,8,2}, but {6,2,6} against {8,8,2} wouldn't). I have a working method, but it's brute force and ugly.

If we have setA and setB, and each of those have elements a, b, and c:

if(setB.a < setA.a)
    if(setB.b < setA.b)
        if(setB.c < setA.c)
            return true;
    else if(setB.b < setA.c)
        if(setB.c < setA.b
            return true;

and so on...

EDIT: I just realized you said these sets are hardcoded at 3 values. This is a super general algorithm for sets of any size.

For a 3-value set, you can do the same dumping and sorting of set elements, and then do:

if(setB.a < setA.a)
    if(setB.b < setA.b)
        if(setB.c < setA.c)
            return true;
return false;

======================================================

A general algorithm:

This is the most efficient way I can immediately think of to do this.

pseudocode (more pythonic than java, sorry-- hopefully the comments explain):

list l1 = set1.items() //get the items out
list l2 = set2.items()

l1 = sort(l1)
l2 = sort(l2) //sort the lists

int set2idx1 = l1[0].find_closest_greater_than_value(l2) //binary search or something
if set2idx1 exists:
    l2 = l2[set2idx1+1:] //in python this means l2 is reassigned to a subarray of l2 starting at set2idx1+1 going to the end of l2
else:
    return false

for(int i=1; i<l1.len; i++)
    int set2idxi = l1[i].find_closest_greater_than_value(l2) //binary search or something
    if set2idxi exists:
        l2 = l2[set2idxi+1:]
    else
        return false

return true

comment if anything doesn't make sense

EDIT EDIT:

explanation of the general algorithm for any interested parties:

  1. dump the set elements into arrays
  2. sort those arrays
  3. iterate through the first array, seeing if there is a value in the 2nd array that is greater than the current value. If so, get the index of that value and lop off everything before and including that index and reassign the 2nd array variable to what remains.
  4. if there ever is no such value (either because it doesn't exist or you've run out of values to test, return false). Otherwise, at the end, return true.

The idea here is that since the arrays are sorted, you know that any element that is greater than the matched element in the 2nd array will be greater than the element you're testing against in the 1st array. So you can just chop off the lower values, and since you don't want to use the same value, you can chop off the one you found, too. If you ever return false you know it's because either there were no greater values, either because the numbers in array1 were all greater than the numbers in array2, or because there weren't enough numbers in array2 greater than the numbers in array1.

What about the following pseudocode?

Condition(A : Set, B : Set) : Bool =
    Let a := max(A), b := min(B) In
        // Namely, that each number in the first set is less than at least one number in the other set
        If a <= b Then
            // the next numbers in the first set must be less than a different number in the second set 
            Condition(without(A, a), without(B, b))
        Else
            False
        EndIf

Where without(A, a) means the set A minus the set {a}

It seems that a List would do better than a Set since your example includes duplicate elements. Simply:

1) Sort the two lists.

2) Trim off the first few elements from the second list until the sizes of the first and second list are equal.

3) Directly compare list1[i] with list2[i] for each i .

Code:

import java.util.*;
class Main {
    public static void main (String[] args) {
        List<Integer> list1 = new ArrayList<Integer>();
        List<Integer> list2 = new ArrayList<Integer>();
        list1.add(3); list1.add(7); list1.add(7);
        list2.add(8); list2.add(8); list2.add(2); list2.add(1); list2.add(5);
        //algorithm:
        Collections.sort(list1);
        Collections.sort(list2);
        List<Integer> list3 = list2.subList(list2.size() - list1.size(), list2.size());
        System.out.println(list1.size() + " " + list3.size());
        boolean pass = true;
        for(int i = 0; pass && i < list1.size(); i++)
            if(list1.get(i) >= list3.get(i))
                pass = false;
        System.out.println(pass);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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