5

Assume we have a list of integers, for example:

L = [13,13,4,13,4,2]

I want to find the set of all palindromes, where each palindrome is a sub-list of L containing contiguous integers. For the above list that would be:

S = {[13], [4], [2], [13,13], [13,4,13], [4,13,4]}

Because the inverse of L would be L' = [2,4,13,4,13,13], and every element of S appears in L' in the correct order.

How can I find the set of all palindromes in general? My naive approach would be to check if each element of the power set of L appears in L', but this is inefficient and I am sure that there is a better solution.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
oiale
  • 67
  • 1
  • Note that you don't need to check all sub lists (why?). Hint: What can you learn about `L` when you checking: `[[13],[13,13,4],[13,13,4,13,4],[13,4,13,4,2],[13,4,2],[2]]`? – Micha Wiedenmann Dec 11 '18 at 16:13

2 Answers2

2

I think my solution is pretty similar to solution from MC Emperor, but I focused on not creating temporary objects like lists.

I select sub-arrays of given array using left and right indices and check it for palindrome.

public static Set<List<Integer>> findAllPalindromes(int[] arr) {
    Set<List<Integer>> res = new LinkedHashSet<>();

    for (int length = 1; length < arr.length; length++)
        for (int left = 0, right = left + length - 1; right < arr.length; left++, right++)
            if (isPalindrome(arr, left, right))
                res.add(sublist(arr, left, right));

    return res;
}

This method check is given sub-array palindrome or not:

private static boolean isPalindrome(int[] arr, int left, int right) {
    for (; left < right; left++, right--)
        if (arr[left] != arr[right])
            return false;

    return true;
}

This method create separate list for given sub-array:

private static List<Integer> sublist(int[] arr, int left, int right) {
    List<Integer> res = new ArrayList<>(right - left);

    for (; left <= right; left++)
        res.add(arr[left]);

    return res;
}
Oleg Cherednik
  • 17,377
  • 4
  • 21
  • 35
0

You need two steps to do that.

First, you'll need to find all sublists within the list:

List<Integer> input = Arrays.asList(13, 13, 4, 13, 4, 2);

List<List<Integer>> subLists = new ArrayList<>();
for (int subListSize = 1; subListSize < input.size(); subListSize++) {
    for (int startIndex = 0; startIndex < input.size() - subListSize + 1; startIndex++) {
        List<Integer> subList = input.subList(startIndex, startIndex + subListSize);
        subLists.add(subList);
    }
}
// Also test the whole list:
subLists.add(input);

Then you need to check for each element if the list is a palindrome. To test if a list is a palindrome, element n must be compared to element listSize - 1 - n.

We only need to check half of the elements.

static boolean isPalindrome(List<Integer> subList) {
    for (int i = 0; i < subList.size() / 2; i++) {
        if (!Objects.equals(subList.get(i), subList.get(subList.size() - 1 - i))) {
            return false;
        }
    }
    return true;
}

If you want to remove duplicates, then you can put the elements into a Set.

MC Emperor
  • 22,334
  • 15
  • 80
  • 130