-1

I have an integer arrayList which is 5, 12, 5, 17, 5, 5, 5, 39 and I tried to find the most repeating number and it works which will print 5.

However, I want to write it by using divide and conquer approach.

Any tips would be helpful (pseudocode, Java code or any help...)

public static void main(String[] args) {

        int[] repetitive = { 5, 12, 5, 17, 5, 5, 5, 39 };
        int counter = 1;
        int temp = 0;
        int checker = 1;

        Arrays.sort(repetitive);
        int cont = repetitive[0];

        for (int i = 1; i < repetitive.length; i++) {
            if (repetative[i] == repetitive[i - 1] && cont == repetitive[i]) {
                counter++;
                temp = repetitive[i];

            } else if (repetitive[i] == repetitive[i - 1]) {
                checker++;

                if (checker > counter) {
                    temp = repetitive[i];
                } else if (repetitive[i] != repetitive[i - 1]) {
                    checker = 1;
                }
            }
        }

        System.out.println(temp);
    }
john tame
  • 21
  • 4
  • Do you mean that you want to find the mode? – ifly6 May 30 '18 at 18:13
  • In your example, both 5 and 12 occur three times. For clarity, you probably should ensure that there is only one "most repeating" number in your example. – Jim Mischel May 30 '18 at 18:25
  • Thanks for warning @JimMischel I fixed it. – john tame May 30 '18 at 18:28
  • @johntame What you're describing is the mode, i.e. "the value that appears most often". https://en.wikipedia.org/wiki/Mode_(statistics) – ifly6 May 30 '18 at 18:33
  • For everybody who has suggested using a map, that's not what the OP asked. He's asking how to do it using divide-and-conquer. The point you're all missing is that, if `Arrays.sort()` uses Quicksort (a divide-and-conquer algorithm), then he's already solved his problem. The OP could have said that he wants to solve the problem without using any explicit extra memory, such as the O(n) memory required by the map. That would have clarified things quite a bit. – Jim Mischel May 30 '18 at 18:44

5 Answers5

0

Why are you sorting it in your example code? At that point, you can just walk through it from the beginning to find the most repeated.

Assuming that you aren't going to sort it before divide and conquer, you should be taking the size of the list, finding the mid-point. Generally divide/conquer is something used for like a merge sort and you use recursion. In this case, you are trying to use it to count each value - it doesn't seem like the best fit because you need to somehow maintain state of what has the highest count while you do the recursion (which means passing something in).

What exactly is the motivation here vs just walking through the array and keeping count in a map or something. That would be O(n) time and O(n) space.

0

Divide and conquer isn't an appropriate technique to apply here, because there's no guarantee that the same result will be derived from any 2 subdivisions of the whole list. Not even if you sort the list, because you may split the largest group between sub-lists, at which point you'll find a different largest group in each sublist and miss the correct result entirely.

As suggested by thejavagirl, enumerating the list and counting occurrences is definitely the simplest and best approach.

DavidW
  • 1,413
  • 10
  • 17
0

this code counts occurrences of given number in array (it is not very efficient but this should get you started)

public static void main(String[] args) {
    int[] repetitive = { 5, 12, 5, 17, 12, 12, 5, 39 };
    System.out.println(countOccurences(repetitive));
}

public static Map<Integer, Integer> countOccurences(int[] arr) {
    if (arr.length == 1) {
        Map<Integer, Integer> result = new HashMap<>();
        result.put(arr[0], 1);
        return result;
    } else {

        int to = arr.length / 2;
        Arrays.copyOfRange(arr, 0, to);

        Map<Integer, Integer> left = countOccurences(Arrays.copyOfRange(arr, 0, to));
        Map<Integer, Integer> right = countOccurences(Arrays.copyOfRange(arr, to, arr.length));
        return merge(left, right);
    }
}

static Map<Integer, Integer> merge(Map<Integer, Integer> left, Map<Integer, Integer> right) {
    right.forEach((number, count) -> {
        left.compute(number, (num, c) -> c == null ? count : c + count);
    });
    return left;
}
Michal
  • 970
  • 7
  • 11
0

You could adapt quick-sort to perform this slightly more efficiently(*) than first sorting the array and then finding the longest sequence. The idea is as follows:

In quick-sort you normally select an element, x, and put elements <x to the left and the other ones to the right - and then sort the left and right arrays recursively.

Here you trisect the elements: left <x, right >x and just count number of elements equal to x, and then you have the left and right arrays to handle.

In itself this does not gain anything, but can be optimized to skip sorting any array that does not have more elements than your currently most repeating number - and if you have more memory you can maintain a priority queue of the remaining arrays - to always consider the array with most elements first, and as soon as all arrays have no more element than the currently most recurring element you are done.

*: Note: it will only be more efficient if there actually are highly repeating numbers.

Hans Olsson
  • 11,123
  • 15
  • 38
-3

it makes no sense what you want to do...

"Divide and conquer" that i believe is a metaphor for "Binary seach" is used for [as the name says] search it makes no sense use it to count.

If you want to have a better performance aproach you have several options that doesn't require sorting.

  1. If memory is not a constraint and you know the maximum number that might comes in your list, create an array and at each index count the number of accurs of that index
  2. If you have memory restrictions, negative numbers or you doens't know the maximum possible value, use a Map to use the same approach. at each key you count the number of repetitions of that value
Rafael Lima
  • 3,079
  • 3
  • 41
  • 105
  • This answer is just wrong. First, divide and conquer is more than just binary search. Your first suggestion makes the unrealistic assumption that memory is not an issue, and your second "memory saving" suggestion ignores the possibility that the Map might be too large for memory. – Jim Mischel May 30 '18 at 18:41
  • @JimMischel, please mister phd in algoritms and crazy structures answer the original question... i will be glad mark it up... if you can do that and use less memory than a map – Rafael Lima May 30 '18 at 21:47
  • The OP already showed how to do it with less memory than a map: sort and count. – Jim Mischel May 30 '18 at 21:58
  • my approach is O(n) his is O(nlogn)... plus it is not "divide and conquer" at the end you proved yourself you are not able to provide an answer that satisfies your own requirements... good job fat guy – Rafael Lima May 31 '18 at 17:13
  • 1
    I'm not the OP. The OP's question isn't answerable because there is no divide-and-conquer solution. That there is a more time efficient solution that doesn't use divide-and-conquer is irrelevant, and doesn't alter my opinion that your answer is wrong, for the reasons I pointed out. Just your assertion about divide and conquer is enough to warrant a downvote. But, hey, no skin off my nose. If you want to continue advertising your ignorance even after given the opportunity to correct it, more power to ya. https://en.wikipedia.org/wiki/Divide_and_conquer_algorithm – Jim Mischel May 31 '18 at 19:53