Problem statement:
To find maximum length substring in an input string which could be arranged into a palindrome, only even length palindromes are expected.
Input is one line String which contains only integers.
Output is the length of the substring which could be arranged in palindrome.
Example:
Input:
123456546
Output:
6
(substring456546
can be rearranged to an even palindrome)
My approach (I am not sure if this is the most optimal way to do it, please point out any modifications):
- Find the integers which are occurring in pairs in the original input string
- For each possible length look for a possible palindrome by starting from each integer (which we listed earlier as possible palindrome members) and searching for the required length.
Although this approach and the code works, I don't think it is optimal at all (I am using multiple nested for
loops and the code doesn't look good at all). Should I use some other data structures? Can someone please help in optimising the solution?
public class Code2 {
public static int lengthofPalindrome(String input1)
{
/*Check if the input is valid
* return 0 : if length = 0 ,
* contains anything other than numbers
* */
if(input1.length() <= 0 )
return 0;
if (input1.matches("[0-9]+"))
;
else
return 0;
Integer[] input_array = new Integer[input1.length()]; // copy of the input string used to compare
List<Integer> input_array_2 = Arrays.asList(input_array); //copy of the input string in array list
List<Integer> tempString = new ArrayList(); // temp arrayList
List<Integer> sub1 = new ArrayList(); // contains unique digits getting repeated 2 times
List<Integer> sub2 = new ArrayList(); // contains all digits getting repeated 2 times
int flag_2 =0;
//copy the string into integer array
for (int i = 0 ; i < input1.length(); i ++) {
input_array[i] = Integer.parseInt(String.valueOf(input1.charAt(i)));
}
//find the int which have even occurences in the input array and populate sub1 arrayList with the values
for(int i =0 ; i < input1.length(); i++) {
if(i==0) {
tempString.add(input_array[0]);
}
else {
for(int j = 0; j <tempString.size(); j++) {
if(input_array[i]==tempString.get(j)) {
tempString.remove(j);
sub1.add(input_array[i]);
tempString.add(j, -2);
flag_2 = 1;
}
if(flag_2 ==1) {
break;
}
}
if(flag_2 ==1) {
flag_2=0;
}
else {
tempString.add(input_array[i]);
}
}
}
//Make a copy of sub1 and populate sub2
for(Integer a : sub1) {
sub2.add(a);
}
//Remove duplicates from the sub1
for (int i =0 ; i < sub1.size(); i ++) {
for(int j =i+1 ; j <sub1.size();j++) {
if(sub1.get(i)==sub1.get(j)) {
sub1.remove(j);
}
}
}
/*Length of sub2: used to calculate the legths of possible pallindrome substrings
Eg. If the length of sub2(contains the ints which occur in pairs in the input string) = 3
Lengths of possible substrings : 6, 4, 2
*/
int length = sub2.size();
int value =0;
// value is the length of the substring that can be rearranged as a palindrome
for (int i =length; i >= 1; i--) {
value = find_sub(i*2, sub1,input_array_2 );
if(value !=0) {
break;
}
}
return value;
}
/*Parameters
* length : Length of the substring to be found
* subString : Contains the int which could be part of the substring
* input1 : Original input string
* This function finds the length of the substring of given length inside the main String, if it exists otherwise returns 0
* */
public static int find_sub(int length, List<Integer> subString, List<Integer> input1) {
if(length ==0 || subString.size() == 0 || input1.size()==0) {
return 0;
}
int index = -2;
int sum = 0;
List<Integer> allIndex = new ArrayList<Integer>();
int breakFlag =-2;
// List of all the indices of input1 string which are present in subString (occur in pair)
for(int j =0; j < subString.size();j++) {
for (int i =0; i < input1.size(); i ++) {
if (input1.get(i) == subString.get(j)) {
allIndex.add(i);
}
}
}
Collections.sort(allIndex);
// Store the values of the integer elements and its occurence if the substring exists
Map<Integer, Integer> palin ;
int val, finalFlag =-2;
int bound;
List<Integer> subList= new ArrayList<Integer>();
// Main loop to chcek from each index value for the substring of desired length
for(int j =0; j < allIndex.size(); j++) {
//gets the first index of the substring
index = allIndex.get(j);
//check if the length to search doesnot fit in the main string break;
if(index+length-1 >= input1.size()) {
break;
}
//make a sublist with the desired length
subList = input1.subList(index, index+length-1);
//check if the substring of given length contain anything other than the ints in the subString
for(int i =0; i < subList.size(); i++) {
for(int m =0 ; m < subString.size(); m++) {
if(subList.get(i)==subString.get(m)) {
breakFlag =0;
break;
}
else {
breakFlag =1;
}
}
//subList contains other int
if(breakFlag ==1) {
break;
}
}
//breakFlag : is set when the substring in input1 contains any other integer than what is expected (subString)
if(breakFlag ==0) {
//logic to check if the pallindrome can be formed from this index and this length
//add all the recuring values in the map with number of occurences
palin= new HashMap<Integer, Integer>();
for(int n =index; n <= index+length-1; n++) {
if(palin.containsKey(input1.get(n))) {
val = palin.get(input1.get(n));
palin.put(input1.get(n), val+1); }
else {
palin.put(input1.get(n), 1);
}
}
for(Map.Entry<Integer, Integer> entry: palin.entrySet()) {
}
sum=0;
for(Map.Entry<Integer, Integer> entry: palin.entrySet()) {
if(entry.getValue() %2 !=0) {
finalFlag = 0;
break;
}
else {
//string can be rearranged into a pallindrome
finalFlag =1;
sum = sum+entry.getValue();
}
}
}
if(finalFlag ==1) {
break;
}
}
if(finalFlag ==1) {
return sum;
}
else
return 0;
}
public static void main(String[] args) throws IOException{
Scanner in = new Scanner(System.in);
int output = 0;
String ip1 = in.nextLine().trim();
output = lengthofPalindrome(ip1);
System.out.println(String.valueOf(output));
}
}