find number in close proximity to a given number - java

I have a number (int y = 12345). I want to find how I can shuffle y to find the number that is the middle of all possible combinations that can be made when shuffling. In this case, the answer would be 32541.
I initially tried to put 1,2,3,4,5 in a list and use Collections.shuffle to get all options and put them in a sortedSet. Then get the index at size()/2. But this doesn't work well for numbers larger than 123456789...
I also tried to use recursion to switch around all the numbers using heap's algorithm. That worked slightly better, but still couldn't process large numbers. See below. (I switched the integer to a string abcdefghij)
public static SortedSet<String> allStrings = new TreeSet<>();
public static SortedSet<String> findMidPerm(String strng) {
permutation("", strng);
return allStrings;
}
private static void permutation(String prefix, String str) {
int n = str.length();
if (n == 0) {
allStrings.add(prefix);
} else {
for (int i = 0; i < n; i++)
permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i + 1, n));
}
}
public static void main(String[] args) {
System.out.println(findMidPerm("abcdefghij"));
}
My current idea is to not create all possible numbers, but find the exact center of all possible combinations (int x = 33333). And then see which combination of numbers is closest to that number. In this case, this is either 32541 OR 34125. Both numbers are 792 steps away from x.
This is what I have so far:
public static float findMidPerm(String strng) {
float maxNum = findMaxNum(strng);
float minNum = findMinNum(strng);
float middleNum = findMiddleNum(minNum, maxNum);
return middleNum;
}
private static float findMiddleNum(float minNum, float maxNum) {
return (minNum+maxNum)/2;
}
private static float findMinNum(String strng) {
String s = "";
for (int i = 0; i <= strng.length(); i ++) {
s += i;
}
return Float.parseFloat(s);
}
private static Float findMaxNum(String strng) {
String s = "";
for (int i = strng.length(); i> 0; i --) {
s += i;
}
return Float.parseFloat(s);
}
public static void main(String[] args) {
System.out.println(findMidPerm("abcdefghijklmnop"));
}
Now for the difficult part of creating the algorithm that finds the order of integers closest to x. Does anyone have any ideas how this can be achieved?

(This is an answer to the original problem, how to find the median of all permutations, not for the XY-problem, how to find the permutation closest to a given number.)
I think, if you want to find exactly the median of the permutations, there is good and bad news: Good news: There seems to be an easy algorithm for that. Bad news: There is no exact median, as the number of permutations is always even (as it is 1 x 2 x 3 x ... x n)
Sort the input number so the digits are in ascending order
If the number has an odd number of digits, pick the middle digit as the first digit
The number now has an even number of digits; you have to pick either of the two middle digits, but this will skew the result (see the bad news above)
If you picked the lower of the middle digits, form the largest possible number from the remaining digits, otherwise the lowest possible number.
For your example: 12345 -> 3 1245 --> 32 145 --> 32541, or 12345 -> 3 1245 --> 34 125 --> 34125.
The intuition behind this is as follows: You can subdivide the n! (sorted) permutations of a number with n digits into n groups, each starting with the ith digit and having (n-1)! elements. As those groups are ordered, and each has the same number of elements, the median has to be in the middle group for an odd-numbered input, and right in between the middle two groups for an even-numbered input. So you have to pick either the largest of the smaller, or the smallest of the larger middle group. (And for an odd-numbered input, do the same for the n-1 sub-groups of the middle group.)
Here's a sample code (in Python, because I'm too lazy...)
# above algorithm
def med_perm(n):
lst = sorted(str(n)) # step 1
res = [lst.pop(len(lst)//2)] if len(lst) % 2 == 1 else [] # step 2
res.append(lst.pop(len(lst)//2)) # step 3
res.extend(lst) # step 4
return int(''.join(res))
# for reference
import itertools
def med_perm2(n):
perms = list(map(''.join, itertools.permutations(sorted(str(n)))))
return int(perms[len(perms)//2])
# testing
import random
n = random.randint(1, 100000000)
x, y = med_perm(n), med_perm2(n)
print(n, x, y, x==y)

I actually found a sneaky way to do this. I was writing everything down on paper and recognized a pattern. This is the first draft of the code and it can probably be done way more efficient. Feel free to adjust!
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Kata {
public static String findMidPerm(String strng) {
strng = sortString(strng);
StringBuilder sb = new StringBuilder();
List<Integer> s = createNum(strng);
for(int i =0; i <s.size(); i++) {
int b = s.get(i);
sb.append(strng.charAt(b-1));
}
return sb.toString();
}
private static String sortString(String strng) {
char[] ar = strng.toCharArray();
Arrays.sort(ar);
String sorted = String.valueOf(ar);
return sorted;
}
public static List<Integer> createNum(String strng) {
List<Integer> list = new ArrayList<>();
int s = strng.length() / 2;
int s2 = (strng.length() / 2) + 1;
if (strng.length() % 2 == 0) {
list.add(s);
for (int i = strng.length(); i > 0; i--)
if (i != s) {
list.add(i);
}
} else {
list.add(s2);
list.add(s);
for (int i = strng.length(); i > 0; i--)
if (i != s && i != s2) {
list.add(i);
}
}
return list;
}
public static void main(String[] args) {
System.out.println(findMidPerm("cmafilezoysht")); // cmafilezoysht is an input string in this case.
}
}

Related

JAVA code for the possible number of combinations of a 6-digit code between ranges of two integers

Conditions of the 6-digit code:
None of the digits are 0
Each digit of the combination is different
The 6-digit number is divisible by each one of the digits
Input:
Two integers, L and H
L is the limit on the smallest number on the range
H is the limit on the largest number on the range
Output:
C, which defines the number of possible combinations where L<=c<=H
I thought I could use arrays as the condition check, then realized I couldn't use it to find the number of possible combinations. Tried using loops, but couldn't figure it out, all I got for the pseudocode is the input, then a condition if L is less or equal to H. Then I sort of ran to a brick wall.
Here's the code.
''''''''
public static void main(String[] args) {
Scanner FF = new Scanner(System.in);
List<Integer> result = new ArrayList<>();
int l = FF.nextInt();
int h = FF.nextInt();
for (int i = l; i <= h; i++) {
result.add(i);
}
for (int i=l; i<=h; i++){
if (result.get(i) == result.get(i)){
result.remove(i);
}
int temp = result.get(i);
while (result.get(i)>0){
int k = result.get(i)%10;
if (temp % k != 0){
result.remove(i);
}
}
if (String.valueOf(result.get(i)).contains("0")){
result.remove(i);
}
}
System.out.println(result);
}
}
You can create a stream of integers, here 111111 to 1000000 and then filter out everything what doesnot meet your conditions.
public class SixDigitCode {
public static void main(String[] args) {
IntStream.iterate(111111, i -> i < 1000000, i -> i + 1)
.filter(containsZero.negate())
.filter(digitDifferent)
.filter(divideByDigits)
.forEach(System.out::println);
}
static IntPredicate containsZero = i -> Integer.toString(i).contains("0");
static IntPredicate digitDifferent = i -> Integer.toString(i).chars().boxed().collect(Collectors.toSet()).size() == 6;
static IntPredicate divideByDigits = i -> Integer.toString(i).chars().boxed()
.filter( x -> i%Character.getNumericValue(x) ==0)
.count() ==6;
}
There are multiple ways to solve this problem.
Let's start with an easy, but inefficient one:
boolean isOk(int number){
String numberStr = Integer.toString(number);
if(numberStr.contains("0"))
return false;
for(int i = 0; i < numberStr.length(); i++){
for(int j = i + 1; j < numberStr.length(); j++){
if(numberStr.charAt(i) == numberStr.charAt(j))
return false;
}
}
return true;
}
...
int count = 0;
for(int i = L; i <= H; i++){
if(isOk(i))
count ++;
}
Note: this code is by no means optimal, but I think it is a straight forward easy to understand solution.
However, I cannot test it right now, so it may contain minor issues.

Having trouble in printing the largest array number from the 20 randomly generated numbers

Ok so I been working on this assignment all day for the past 3 days but I haven't had any luck. I wasn't going to ask for help but I finally gave up. But there is also one more thing I need to implement to the code. This is what I gotta implement "Find the length of the longest continuous series of positive numbers in the array data. If the contents were: 4 5 0 2 . . . -1 88 78 66 -6. The length would be 3. For this problem, 0 is considered non-negative but not positive". Plus I have an issue where I can't print the largest int in the array of 20.
import java.util.Random;
import java.util.ArrayList;
public class arrayops {
public static int findLargest(ArrayList<Integer> nums) {
int greatestnum = nums.get(0);
for (Integer item : nums) {
if (item > greatestnum) {
greatestnum = item;
}
}
return greatestnum;
}
public static int randomData(ArrayList<Integer> nums) {
int[] array = new int [20];
Random random = new Random();
for (int i = 0; i < array.length; i++) {
array[i] = -100 + random.nextInt(201);
}
return -100 + random.nextInt(201);
}
public static void main(String[] args) {
ArrayList<Integer> nums = new ArrayList<Integer>();
nums.add(1);
nums.add(4);
nums.add(13);
nums.add(43);
nums.add(-25);
nums.add(17);
nums.add(22);
nums.add(-37);
nums.add(29);
System.out.println("The Greatest Number from the hardcoded numbers " + findLargest(nums));
System.out.println("The Greatest number from the random numbers " + randomData(nums));
}
}
The findLargest method:
public static int findLargest(ArrayList<Integer> nums) {
int greatestnum = 0;
int greatestLen = 0;
for (Integer item : nums) {
if (item > 0) {
greatestLen++ ;
if(greatestLen > greatestnum)
greatestnum = greatestLen;
}
else
greatestLen = 0;
}
return greatestnum;
}
Logic used:
Keep the length of the longest chain encountered, and the length of current chain, in two separate variables (greatestnum and greatestLen respectively)
Increment greatestLen every time a positive number is encountered. If the number if less than or equal to zero, reset this count.
If the length of current chain is greater than the previous longest chain, sent the longest chain size to current chain size.
The problem is you created a list with random numbers but never put that list into the findLargest method. You also never created a method to find the consecutive positive numbers. If you didn't know how to go about coding it, I recommend drawing out an algorithm on paper.
Largest value in ArrayList...
public static int findL(ArrayList<Integer> nums)
{
int top = nums.get(0);
for(int i = 0; i<nums.size(); i++)
{
if(nums.get(i)>top)
{
top = nums.get(i);
}
}
return top;
}
Largest number of consecutive positives...
public static int positiveString(ArrayList<Integer> nums)
{
int longest = 0;
int count = 0;
for(int i = 0; i<nums.size(); i++)
{
if(nums.get(i) > 0)
{
count++;
}
else
{
if(longest<count)
{
longest = count;
}
count = 0;
}
}
return longest;
}
If you want to arrange the numbers into order you can simply use java.util.TreeSet. Then use the method last() to get the largest number.
public static int findLargest(ArrayList<Integer> nums) {
return new TreeSet<Integer>(nums).last();
}

Java power set through backtrack algorithm

I seem to be having an issue regarding implementing a power set algorithm using backtrack. What I am trying to achieve is rather simple, generate the power set of any given numbers:
Ex. [1 2 3] => [1] [2] [3] ; [1,2] [1,3] [2,3] ; [1,2,3]
My algorithm is using a stack to place the numbers, it adds the numbers to the stack and sends them for calculations. The code is as follows:
public int calculatePowerSet(int x, LinkedList<Integer> arr)
{
int size = 1;
int nrOfTimes=0;
int calculate =0;
boolean goOn=true;
Stack<Integer> stack = new Stack<Integer>();
int k=0, len = arr.size();
double temp=0.0f;
while(size<=len)
{
goOn=true;
stack.push(arr.get(0));
k = arr.indexOf(stack.peek());
temp = size; //ignore these as they are for calculating time
temp/=len; //ignore these as they are for calculating time
temp*=100; //ignore these as they are for calculating time
setPowerSetPrecentage((int)temp);
while(goOn)
{
if(isStopProcess())return 0;
if((k==len)&&(stack.size()==0)) goOn=false;
else if(stack.size()==size)
{
String sign = "";
if((stack.size()%2)==0) sign="+";
else sign="-";
calculate =calculateSets(stack.toArray(), sign, calculate, x);
k = arr.indexOf(stack.pop())+1;
}
else if(k==len)
k = arr.indexOf(stack.pop())+1;
else
{
prepereStack(stack,arr.get(k));
k++;
}
}
size++;
}
return calculate;
}
Here is the calculate method:
private int calculate(int[] arr2, int x)
{
int calc=1;
float rez = 0;
for(int i=0;i<arr2.length;i++)
calc*=arr2[i];
rez = (float)(x/calc);
calc = (int) (rez+0.5d);
return calc;
}
The code seems to be working perfectly for all numbers bellow 20, but after that i seem to be getting wrong results. I cannot check manually through the numbers as there are hundreds of combinations. For example for one input of 25 numbers i should get a result of 1229, instead i get 1249. I am not sure what i am missing as i think the algorithm should be working in theory, so if anyone has any suggestions that would be great.
I would recommend separating out the generation of the power sets from your calculation. While there are some very efficient algorithms for generating power sets I would suggest keeping it quite simple until you need the efficiency.
private void forEachSet(List<Integer> currentSet, List<Integer> rest) {
if (rest.isEmpty()) {
process(currentSet);
} else {
Integer nextInt = rest.remove(0);
forEachSet(currentSet, rest);
currentSet.add(nextInt);
forEachSet(currentSet, rest);
current.remove(nextInt);
rest.add(nextInt);
}
}
public forEachSet(List<Integer> set) {
forEachSet(new ArrayList<>(), new ArrayList<>(set));
}

Find all substrings that are palindromes

If the input is 'abba' then the possible palindromes are a, b, b, a, bb, abba.
I understand that determining if string is palindrome is easy. It would be like:
public static boolean isPalindrome(String str) {
int len = str.length();
for(int i=0; i<len/2; i++) {
if(str.charAt(i)!=str.charAt(len-i-1) {
return false;
}
return true;
}
But what is the efficient way of finding palindrome substrings?
This can be done in O(n), using Manacher's algorithm.
The main idea is a combination of dynamic programming and (as others have said already) computing maximum length of palindrome with center in a given letter.
What we really want to calculate is radius of the longest palindrome, not the length.
The radius is simply length/2 or (length - 1)/2 (for odd-length palindromes).
After computing palindrome radius pr at given position i we use already computed radiuses to find palindromes in range [i - pr ; i]. This lets us (because palindromes are, well, palindromes) skip further computation of radiuses for range [i ; i + pr].
While we search in range [i - pr ; i], there are four basic cases for each position i - k (where k is in 1,2,... pr):
no palindrome (radius = 0) at i - k
(this means radius = 0 at i + k, too)
inner palindrome, which means it fits in range
(this means radius at i + k is the same as at i - k)
outer palindrome, which means it doesn't fit in range
(this means radius at i + k is cut down to fit in range, i.e because i + k + radius > i + pr we reduce radius to pr - k)
sticky palindrome, which means i + k + radius = i + pr
(in that case we need to search for potentially bigger radius at i + k)
Full, detailed explanation would be rather long. What about some code samples? :)
I've found C++ implementation of this algorithm by Polish teacher, mgr Jerzy WaƂaszek.
I've translated comments to english, added some other comments and simplified it a bit to be easier to catch the main part.
Take a look here.
Note: in case of problems understanding why this is O(n), try to look this way:
after finding radius (let's call it r) at some position, we need to iterate over r elements back, but as a result we can skip computation for r elements forward. Therefore, total number of iterated elements stays the same.
Perhaps you could iterate across potential middle character (odd length palindromes) and middle points between characters (even length palindromes) and extend each until you cannot get any further (next left and right characters don't match).
That would save a lot of computation when there are no many palidromes in the string. In such case the cost would be O(n) for sparse palidrome strings.
For palindrome dense inputs it would be O(n^2) as each position cannot be extended more than the length of the array / 2. Obviously this is even less towards the ends of the array.
public Set<String> palindromes(final String input) {
final Set<String> result = new HashSet<>();
for (int i = 0; i < input.length(); i++) {
// expanding even length palindromes:
expandPalindromes(result,input,i,i+1);
// expanding odd length palindromes:
expandPalindromes(result,input,i,i);
}
return result;
}
public void expandPalindromes(final Set<String> result, final String s, int i, int j) {
while (i >= 0 && j < s.length() && s.charAt(i) == s.charAt(j)) {
result.add(s.substring(i,j+1));
i--; j++;
}
}
So, each distinct letter is already a palindrome - so you already have N + 1 palindromes, where N is the number of distinct letters (plus empty string). You can do that in single run - O(N).
Now, for non-trivial palindromes, you can test each point of your string to be a center of potential palindrome - grow in both directions - something that Valentin Ruano suggested.
This solution will take O(N^2) since each test is O(N) and number of possible "centers" is also O(N) - the center is either a letter or space between two letters, again as in Valentin's solution.
Note, there is also O(N) solution to your problem, based on Manacher's algoritm (article describes "longest palindrome", but algorithm could be used to count all of them)
I just came up with my own logic which helps to solve this problem.
Happy coding.. :-)
System.out.println("Finding all palindromes in a given string : ");
subPal("abcacbbbca");
private static void subPal(String str) {
String s1 = "";
int N = str.length(), count = 0;
Set<String> palindromeArray = new HashSet<String>();
System.out.println("Given string : " + str);
System.out.println("******** Ignoring single character as substring palindrome");
for (int i = 2; i <= N; i++) {
for (int j = 0; j <= N; j++) {
int k = i + j - 1;
if (k >= N)
continue;
s1 = str.substring(j, i + j);
if (s1.equals(new StringBuilder(s1).reverse().toString())) {
palindromeArray.add(s1);
}
}
}
System.out.println(palindromeArray);
for (String s : palindromeArray)
System.out.println(s + " - is a palindrome string.");
System.out.println("The no.of substring that are palindrome : "
+ palindromeArray.size());
}
Output:-
Finding all palindromes in a given string :
Given string : abcacbbbca
******** Ignoring single character as substring palindrome ********
[cac, acbbbca, cbbbc, bb, bcacb, bbb]
cac - is a palindrome string.
acbbbca - is a palindrome string.
cbbbc - is a palindrome string.
bb - is a palindrome string.
bcacb - is a palindrome string.
bbb - is a palindrome string.
The no.of substring that are palindrome : 6
I suggest building up from a base case and expanding until you have all of the palindomes.
There are two types of palindromes: even numbered and odd-numbered. I haven't figured out how to handle both in the same way so I'll break it up.
1) Add all single letters
2) With this list you have all of the starting points for your palindromes. Run each both of these for each index in the string (or 1 -> length-1 because you need at least 2 length):
findAllEvenFrom(int index){
int i=0;
while(true) {
//check if index-i and index+i+1 is within string bounds
if(str.charAt(index-i) != str.charAt(index+i+1))
return; // Here we found out that this index isn't a center for palindromes of >=i size, so we can give up
outputList.add(str.substring(index-i, index+i+1));
i++;
}
}
//Odd looks about the same, but with a change in the bounds.
findAllOddFrom(int index){
int i=0;
while(true) {
//check if index-i and index+i+1 is within string bounds
if(str.charAt(index-i-1) != str.charAt(index+i+1))
return;
outputList.add(str.substring(index-i-1, index+i+1));
i++;
}
}
I'm not sure if this helps the Big-O for your runtime, but it should be much more efficient than trying each substring. Worst case would be a string of all the same letter which may be worse than the "find every substring" plan, but with most inputs it will cut out most substrings because you can stop looking at one once you realize it's not the center of a palindrome.
I tried the following code and its working well for the cases
Also it handles individual characters too
Few of the cases which passed:
abaaa --> [aba, aaa, b, a, aa]
geek --> [g, e, ee, k]
abbaca --> [b, c, a, abba, bb, aca]
abaaba -->[aba, b, abaaba, a, baab, aa]
abababa -->[aba, babab, b, a, ababa, abababa, bab]
forgeeksskeegfor --> [f, g, e, ee, s, r, eksske, geeksskeeg,
o, eeksskee, ss, k, kssk]
Code
static Set<String> set = new HashSet<String>();
static String DIV = "|";
public static void main(String[] args) {
String str = "abababa";
String ext = getExtendedString(str);
// will check for even length palindromes
for(int i=2; i<ext.length()-1; i+=2) {
addPalindromes(i, 1, ext);
}
// will check for odd length palindromes including individual characters
for(int i=1; i<=ext.length()-2; i+=2) {
addPalindromes(i, 0, ext);
}
System.out.println(set);
}
/*
* Generates extended string, with dividors applied
* eg: input = abca
* output = |a|b|c|a|
*/
static String getExtendedString(String str) {
StringBuilder builder = new StringBuilder();
builder.append(DIV);
for(int i=0; i< str.length(); i++) {
builder.append(str.charAt(i));
builder.append(DIV);
}
String ext = builder.toString();
return ext;
}
/*
* Recursive matcher
* If match is found for palindrome ie char[mid-offset] = char[mid+ offset]
* Calculate further with offset+=2
*
*
*/
static void addPalindromes(int mid, int offset, String ext) {
// boundary checks
if(mid - offset <0 || mid + offset > ext.length()-1) {
return;
}
if (ext.charAt(mid-offset) == ext.charAt(mid+offset)) {
set.add(ext.substring(mid-offset, mid+offset+1).replace(DIV, ""));
addPalindromes(mid, offset+2, ext);
}
}
Hope its fine
public class PolindromeMyLogic {
static int polindromeCount = 0;
private static HashMap<Character, List<Integer>> findCharAndOccurance(
char[] charArray) {
HashMap<Character, List<Integer>> map = new HashMap<Character, List<Integer>>();
for (int i = 0; i < charArray.length; i++) {
char c = charArray[i];
if (map.containsKey(c)) {
List list = map.get(c);
list.add(i);
} else {
List list = new ArrayList<Integer>();
list.add(i);
map.put(c, list);
}
}
return map;
}
private static void countPolindromeByPositions(char[] charArray,
HashMap<Character, List<Integer>> map) {
map.forEach((character, list) -> {
int n = list.size();
if (n > 1) {
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
if (list.get(i) + 1 == list.get(j)
|| list.get(i) + 2 == list.get(j)) {
polindromeCount++;
} else {
char[] temp = new char[(list.get(j) - list.get(i))
+ 1];
int jj = 0;
for (int ii = list.get(i); ii <= list
.get(j); ii++) {
temp[jj] = charArray[ii];
jj++;
}
if (isPolindrome(temp))
polindromeCount++;
}
}
}
}
});
}
private static boolean isPolindrome(char[] charArray) {
int n = charArray.length;
char[] temp = new char[n];
int j = 0;
for (int i = (n - 1); i >= 0; i--) {
temp[j] = charArray[i];
j++;
}
if (Arrays.equals(charArray, temp))
return true;
else
return false;
}
public static void main(String[] args) {
String str = "MADAM";
char[] charArray = str.toCharArray();
countPolindromeByPositions(charArray, findCharAndOccurance(charArray));
System.out.println(polindromeCount);
}
}
Try out this. Its my own solution.
// Maintain an Set of palindromes so that we get distinct elements at the end
// Add each char to set. Also treat that char as middle point and traverse through string to check equality of left and right char
static int palindrome(String str) {
Set<String> distinctPln = new HashSet<String>();
for (int i=0; i<str.length();i++) {
distinctPln.add(String.valueOf(str.charAt(i)));
for (int j=i-1, k=i+1; j>=0 && k<str.length(); j--, k++) {
// String of lenght 2 as palindrome
if ( (new Character(str.charAt(i))).equals(new Character(str.charAt(j)))) {
distinctPln.add(str.substring(j,i+1));
}
// String of lenght 2 as palindrome
if ( (new Character(str.charAt(i))).equals(new Character(str.charAt(k)))) {
distinctPln.add(str.substring(i,k+1));
}
if ( (new Character(str.charAt(j))).equals(new Character(str.charAt(k)))) {
distinctPln.add(str.substring(j,k+1));
} else {
continue;
}
}
}
Iterator<String> distinctPlnItr = distinctPln.iterator();
while ( distinctPlnItr.hasNext()) {
System.out.print(distinctPlnItr.next()+ ",");
}
return distinctPln.size();
}
Code is to find all distinct substrings which are palindrome.
Here is the code I tried. It is working fine.
import java.util.HashSet;
import java.util.Set;
public class SubstringPalindrome {
public static void main(String[] args) {
String s = "abba";
checkPalindrome(s);
}
public static int checkPalindrome(String s) {
int L = s.length();
int counter =0;
long startTime = System.currentTimeMillis();
Set<String> hs = new HashSet<String>();
// add elements to the hash set
System.out.println("Possible substrings: ");
for (int i = 0; i < L; ++i) {
for (int j = 0; j < (L - i); ++j) {
String subs = s.substring(j, i + j + 1);
counter++;
System.out.println(subs);
if(isPalindrome(subs))
hs.add(subs);
}
}
System.out.println("Total possible substrings are "+counter);
System.out.println("Total palindromic substrings are "+hs.size());
System.out.println("Possible palindromic substrings: "+hs.toString());
long endTime = System.currentTimeMillis();
System.out.println("It took " + (endTime - startTime) + " milliseconds");
return hs.size();
}
public static boolean isPalindrome(String s) {
if(s.length() == 0 || s.length() ==1)
return true;
if(s.charAt(0) == s.charAt(s.length()-1))
return isPalindrome(s.substring(1, s.length()-1));
return false;
}
}
OUTPUT:
Possible substrings:
a
b
b
a
ab
bb
ba
abb
bba
abba
Total possible substrings are 10
Total palindromic substrings are 4
Possible palindromic substrings: [bb, a, b, abba]
It took 1 milliseconds

Optimize Code for longest common sequence

I was trying to solve this practice problem, it is also quoted below.
The Chef is planning a buffet for the DirectiPlex inauguration party,
and everyone is invited. On their way in, each guest picks up a sheet
of paper containing a random number (this number may be repeated). The
guests then sit down on a round table with their friends.
The Chef now decides that he would like to play a game. He asks you to pick a random person from your table and have them read their
number out loud. Then, moving clockwise around the table, each person
will read out their number. The goal is to find that set of numbers
which forms an increasing subsequence. All people owning these
numbers will be eligible for a lucky draw! One of the software
developers is very excited about this prospect, and wants to maximize
the number of people who are eligible for the lucky draw. So, he
decides to write a program that decides who should read their number
first so as to maximize the number of people that are eligible for the
lucky draw. Can you beat him to it?
Input The first line contains t, the number of test cases (about 15). Then t test cases follow. Each test case consists of two
lines:
The first line contains a number N, the number of guests invited to
the party.
The second line contains N numbers a1, a2, ..., an separated by
spaces, which are the numbers written on the sheets of paper in
clockwise order.
Output For each test case, print a line containing a single number which is the maximum number of guests that can be eligible for
participating the the lucky draw.
Here's the solution that I have come up with
// http://www.codechef.com/problems/D2/
import java.io.*;
import java.util.*;
public class D2
{
public static void main(String [] args)
throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int numTestCases = Integer.parseInt(br.readLine());
for(int _t=0; _t<numTestCases; ++_t)
{
int N = Integer.parseInt(br.readLine());
StringTokenizer strtok = new StringTokenizer(br.readLine());
int [] originalArray = new int[N*2];
for(int i=0; i<N; ++i)
{
//this concatenates the array with itself at the time of reading the input itself
originalArray[i] = originalArray[N+i] = Integer.parseInt(strtok.nextToken());
}
//Now we calculate the length of the longest increasing sequence
int maxWinners = new LongestIncreasingSequence(originalArray).lengthOfLongestIncreasingSequence();
System.out.println(maxWinners);
}
}
}
class LongestIncreasingSequence
{
private int [] array;
private int [] longest;
private int subsequence_size;
public LongestIncreasingSequence(int [] A)
{
array = A;
longest = new int[array.length / 2];
longest[0] = array[0];
subsequence_size = 1;
}
public int lengthOfLongestIncreasingSequence()
{
for(int i=1; i<array.length; ++i)
{
if(array[i] < longest[0])
{
longest[0] = array[i];
}
else if(array[i] > longest[subsequence_size - 1])
{
longest[subsequence_size++] = array[i];
}
else
{
//Make the replacement with binary search
longest[getReplacementIndex(array[i])] = array[i];
}
}
return subsequence_size;
}
//Method to find the correct index using binary search
private int getReplacementIndex(int elem)
{
int left, right, mid;
left = 0; right = subsequence_size - 1;
while(right - left > 1)
{
mid = 1 + (right - left) / 2;
if(array[mid] >= elem)
{
if(mid != right) right = mid;
else --right;
}
else
{
left = mid;
}
}
return right;
}
}
The complexity is O(n(log(n)) I'm finding the Longest Increasing Sequence by concatenating the array with itself.
This however doesn't pass the time requirement, can someone help me speed up this implementation.
I would not do N rotations, but instead determine the longest (cyclic) run in one go. It is certainly doable, you just have to take care warping around at the end of the array.

Categories