making a string samefrom both ends by shifting characters - java

I am given a string S and I have to make it a palindrome by re-arranging the characters of the given string.
If the given string can not be converted into a palindrome by re-arranging characters, print false and if it is possible to make it a palindrome, print true
My code:
String a=new String(br.readLine()); //given string
int n= a.length();
int j=0,k=n-1,count=0;
boolean flag=false;
for(int i=0;i<n;i++)
{
if(a.charAt(i)=='*')
continue; //for skipping already shifted chars
int ix = a.indexOf(a.charAt(i), i+1);
if(ix >= 0)
{ a=a.substring(0,i+1)+a.substring(i+1, ix) + "*" + a.substring(ix+1);
}
else
{
count++; //number of unique chars which can only be 1 or 0
if(count<=1 && n%2==1)
{
a=a.replaceFirst(a.substring(i,i+1),"*"); //giving middle position to the only unique char at center and replacing it with *
}
else
{
System.out.println("false"); //if more than one unique char, palindrome not possible
flag=true; // shows not possible
break;
}
}
}
if(!flag) // if possible
{
System.out.println("true");
}

One obvious optimization would replace:
if(a.substring(i+1).contains(a.substring(i,i+1)))
{
ans[j++]=i; //storing new positions in ans array
ans[k--]=a.substring(i+1).indexOf(a.charAt(i))+1+i;
a=a.substring(0,i+1)+a.substring(i+1).replaceFirst(a.substring(i,i+1),"*"); //replacing the shifted char with *
}
with:
int ix = a.indexOf(a.charAt(i), i+1);
if(ix >= 0)
{
ans[j++]=i; //storing new positions in ans array
ans[k--]=ix;
a=a.substring(0,i+1)+a.substring(i+1, ix) + "*" + a.substring(ix+1);
}
UPDATE
I wonder if the following code would be faster. There is no indexOf on arrays, so I had to do a loop, but there is no string manipulation:
char[] c = a.toCharArray();
int n= c.length;
int ans[]=new int[n]; // for storing new positions after shifting
int j=0,k=n-1,count=0;
boolean flag=false;
for(int i=0; i < n; i++)
{
char ch = c[i];
if(ch=='*')
continue; //for skipping already shifted chars
int ix = i;
do {
++ix;
} while (ix < n && c[ix] != ch);
if(ix < n)
{
ans[j++]=i;
ans[k--]=ix;
c[ix] = '*';
}
else
{
count++; //number of unique chars which can only be 1 or 0
if(count<=1 && n%2==1)
{
ans[(int)n/2]=i;
c[i] = '*';
}
else
{
System.out.println("-1"); //if more than one unique char, palindrome not possible
flag=true; // shows not possible
break;
}
}
}
UPDATE 2
You can also stop when j has reached n/2:
char[] c = a.toCharArray();
int n= c.length;
int ans[]=new int[n]; // for storing new positions after shifting
int j=0,k=n-1,count=0,half=n/2;
boolean flag=false;
for(int i=0; i < n; i++)
{
char ch = c[i];
if(ch=='*')
continue; //for skipping already shifted chars
int ix = i;
do {
++ix;
} while (ix < n && c[ix] != ch);
if(ix < n)
{
ans[j++]=i;
ans[k--]=ix;
c[ix] = '*';
if (j > half) {
break;
}
}
else
{
count++; //number of unique chars which can only be 1 or 0
if(count<=1 && n%2==1)
{
ans[half]=i;
c[i] = '*';
}
else
{
System.out.println("-1"); //if more than one unique char, palindrome not possible
flag=true; // shows not possible
break;
}
}
}

Related

I am not getting desired output what is the problem in the code

Given a string. Find the longest palindrome subsequence. The string contains an only lowercase letter.
Here, I am creating the array with the length of 26 and keeping track of all lowercase letters (i.e how many times they occur in the string). Finally, I count the number of even letters and if one is odd then (odd-1) is added to it.
public int count(String input1){
int res = 0;
int temp = 0;
char chr [] = input1.toCharArray();
int arr[] = new int[26];
for(int i=0;i<chr.length;i++){
arr[chr[i] - 97]++;
}
for(int val:arr){
if(val%2 != 0) temp++;
if(val%2 ==0){
res=res+val;
}
else{
res = res+(val-1);
}
}
if(temp != 0) res++;
return res;
}
}
it's showing undesired output
It's much easier to understand where is the problem, just split activities in separate methods. E.g. isPalindrome() could be in separate method:
public static int findLongestPalindrome(String str) {
int max = 1;
for (int i = 0; i < str.length(); i++) {
for (int j = str.length() - 1; j > i; j--) {
if (!isPalindrome(str, i, j))
continue;
max = Math.max(max, j - i + 1);
break;
}
}
return max;
}
private static boolean isPalindrome(String str, int i, int j) {
while (i < j)
if (str.charAt(i++) != str.charAt(j--))
return false;
return true;
}

Find all positive integers with at least one 7 and 9 under 1,000,000 but how to fix duplicates?

So, for class I have to code a program that determines how many positive integers are
1) Under 1,000,000
2) Have at least one 7 and a 9 in the number
3) Has to be done with the brute-force method.
While the answer is supposed to be 199,262, I keep getting 228530 due to duplicates, can someone take a look to see where I went wrong here? Thanks!
Similar problem but not the same: Java - numbers with at least one 7 and one 9 in its digit
boolean sevNine = false; // a combination of seven and nine in a number
boolean oneNine;
boolean oneSeven;
int counter = 0;
for (int i = 0; i<1000000; i++) //Runs numbers 1-1000000
{
oneSeven = false;
oneNine = false;
String number2 = " " + (i); //sets a nmber to a string
int length = number2.length() -1; //length goes up to the last character 0-j
for (int j= 0; j <= length; j++) //looking for the first 7 or 9 in string
{
char a = number2.charAt(j); //sets char to the next "letter"
if (a == '7' && oneSeven != true) //if the number is a 7 and there isnt already a seven
{
oneSeven = true; //now there is a seven,
for (int k = j+1; k <= length; k++) //checks from the next char up to the length for a 9
{
char b = number2.charAt(k);
if (b == '9')
{
sevNine = true;
}
}
}
else if (a == '9' && oneNine != true)
{
oneNine = true;
for (int l = j+1; l <= length; l++)
{
char b = number2.charAt(l);
if (b == '7')
{
sevNine = true;
}
}
}
if (sevNine == true)
{
counter++;
sevNine = false;
System.out.println(number2);
}
}
}
System.out.println(counter);
In Java 8 you can try:
public static void main(String[] args) {
final long count = IntStream.rangeClosed(0, 10_00_000)
.filter(i -> String.valueOf(i).contains("7") && String.valueOf(i).contains("9"))
.count();
System.out.println(count);
}
You are not breaking out of the loop once the sevNine is set to true and you increment the counter, so it keeps iterating over each digit on the same number even if it has already included the number... Just add a break statement to exit the for loop iterating over each digit once you increment the counter...
Here's the code.
public static void main(String[] args) {
boolean sevNine = false; // a combination of seven and nine in a number
boolean oneNine;
boolean oneSeven;
int counter = 0;
for (int i = 0; i < 1000000; i++) // Runs numbers 1-1000000
{
oneSeven = false;
oneNine = false;
String number2 = " " + (i); // sets a nmber to a string
int length = number2.length() - 1; // length goes up to the last character 0-j
for (int j = 0; j <= length; j++) // looking for the first 7 or 9 in string
{
char a = number2.charAt(j); // sets char to the next "letter"
if (a == '7' && oneSeven != true) // if the number is a 7 and there isnt already a seven
{
oneSeven = true; // now there is a seven,
for (int k = j + 1; k <= length; k++) // checks from the next char up to the length for a 9
{
char b = number2.charAt(k);
if (b == '9') {
sevNine = true;
}
}
} else if (a == '9' && oneNine != true) {
oneNine = true;
for (int l = j + 1; l <= length; l++) {
char b = number2.charAt(l);
if (b == '7') {
sevNine = true;
}
}
}
if (sevNine == true) {
counter++;
sevNine = false;
System.out.println(number2);
break;
}
}
}
System.out.println(counter);
}
If you run with the break statement, you should get 199262 as the resulting number.

How to calculate possible missing characters?

I'm trying to get possible missing characters e.g:
input --> aa??bb there should be possible characters aaaabb & aaabbb & aabbbb so the result would be 3, Also ?a? would be 1.
Note:
aababb would be wrong, because it's not a right path for alphabet.
I'v done some code here but i couldn't get the perfect result yet.
may someone help me?
Scanner input = new Scanner(System.in);
String s = input.nextLine();
int possibleAlphabet = 1, oldPossibleAlphabet = 0;
for (int i = 0; i < s.length(); i++) {
oldPossibleAlphabet = 0;
System.out.print(s.charAt(i));
if (s.charAt(i) >= 'a' && s.charAt(i) <= 'z' || s.contains("?")) {
if (s.charAt(i) == '?'){
for (int j = 0; j < i; j++) {
if (s.charAt(i - 1) == '?' && s.charAt(i + 1) == '?')
oldPossibleAlphabet++;
}
}
}else {
System.out.print( " ");
System.exit(0);
}
possibleAlphabet += oldPossibleAlphabet;
}
System.out.println(possibleAlphabet);
Check my code
public class Solution {
public static void main(String[] args) {
String str = "abc??cde???g?"; // Example
char[] arr = str.toCharArray();
int length = arr.length;
// Init value for count, start and end
int count = 0;
char start = 'a';
char end = 'a';
for (int i = 0; i < length; i++) {
if (arr[i] == '?') { // We found a question mark
boolean foundEnd = false;
int total = 1; // Currently the total of question mark is 1
for (int j = i + 1; j < length; j++) { // Count the total question mark for our method and the end character
if (arr[j] != '?') { // Not question mark
end = arr[j]; // Update end;
i = j -1;
foundEnd = true;
break;
} else {
total++;
}
}
if (!foundEnd) { // Change end to start in the case our question mark continue to the end of string
end = start;
}
// Start to counting and reset end to 'z'
int result = countPossibleCharacters(total, start, end);
if (count > 0) {
count *= result;
} else {
count += result;
}
end = 'z';
} else {
start = arr[i];
}
}
System.out.println("The total is : " + count);
}
/**
* Count the possible characters
* #param total the total question mark
* #param start the character in the left side of question mark
* #param end the character in the right side of question mark
* #return
*/
static int countPossibleCharacters(int total, char start, char end) {
if (total == 0) {
return 0;
}
if (total == 1) {
return end - start + 1;
}
if (total >= 2) {
int count = 0;
/**
* We have a range of characters from start to end
* and for each character we have 2 options: use or don't use it
*/
// We use it, so the total of question mark will be decrement by 1
count += countPossibleCharacters(total - 1, start, end);
// We don't use it, so the range of characters will be decrement by 1
if (start < end) {
count += countPossibleCharacters(total, ++start, end);
}
return count;
}
return 0;
}
}
Rules apply in my code
All characters in string are lowercase
Character on the left side must be lower than character on the right side
If we have a question mark in the beginning of string, we'll loop from 'a' to the next non question mark character
If we have question mark in the end of string, we'll replace it with previous non question mark character

Big theta run time of string concatenation?

I have an assignment to create my own implementation of a class to handle integers of unlimited size, and then to compare my implementation's runtime to that of Java's BigInteger. When I measured and graphed the runtime of my add function it was a parabola, implying a big theta running time of Ө(n^2). I have no nested loops so I expected it to be Ө(n) and cannot figure out why it isn't. I suspect it might be that I use
string += integer
in my add method inside a loop. I am not quite sure how that operation is implemented, is it a runtime of Ө(n)? If not, can anyone spot why my code isn't Ө(n)?
Here is my add method and the constructor it calls.
public HugeInteger(String val) throws IllegalArgumentException{
String temp = "";
boolean leading = true;
//check valid input
for(int i=0; i<val.length(); i++){
if(val.charAt(i) < '0' || val.charAt(i) > '9') //checks if each digit is a number from 0 to 9
if(i!=0 || val.charAt(i) != '-') //doesn't throw if the digit is a '-' at the first character of string
throw new IllegalArgumentException("Input string must be a number");
}
//remove leading zeros
for(int i=0; i<val.length(); i++){
if(!leading || val.charAt(i) != '0')
temp += val.charAt(i);
if(val.charAt(i) > '0' && val.charAt(i) <= '9') //reached first non-zero digit
leading = false;
}
if(temp == "") //this happens when the input was just a string of zeros
temp = "0";
val = temp;
if(val.charAt(0) != '-'){ //no negative sign
digits = new int[val.length()];
for(int i=0; i<val.length(); i++){
digits[i] = (int)(val.charAt(val.length()-1-i) - 48); //in ASCII the char '0' == 48
}
negative = false;
}
else{
digits = new int[val.length() - 1];
for(int i=1; i<val.length(); i++){ //for loop starts after the '-' sign
digits[i-1] = (int)(val.charAt(val.length()-i) - 48); //in ASCII the char '0' == 48
}
negative = true;
}
}
public HugeInteger add(HugeInteger h){
int carry = 0;
int size = digits.length>h.digits.length?digits.length:h.digits.length; //choose larger # of digits
String sum = "";
String sumFlipped = "";
int bigger = 0;
boolean swapped = false;
int temp;
int sign = 1;
int hsign = 1;
//assign sign based on negative or not
if(negative && !h.negative)
sign = -1;
if(!negative && h.negative)
hsign = -1;
//compare magnitudes. 1 means this is biger and -1 means h is bigger
if(digits.length>h.digits.length)
bigger = 1;
else if(digits.length<h.digits.length)
bigger = -1;
else{ //same length
for(int i=0; i<digits.length; i++){ //both digits arrays are same length
if(digits[digits.length-1-i] > h.digits[h.digits.length-1-i]){
bigger = 1;
break;
}
if(digits[digits.length-1-i] < h.digits[h.digits.length-1-i]){
bigger = -1;
break;
}
}
}
//positive number must be bigger than negative number for long subtraction
//if not, swap signs
if(bigger == 1 && negative && !h.negative){ //this is bigger and negative
swapped = true;
sign *= -1;
hsign *= -1;
}
if(bigger == -1 && !negative && h.negative){ //h is bigger and negative
swapped = true;
sign *= -1;
hsign *= -1;
}
for(int i=0; i<size; i++){
if(i>=digits.length)
temp = h.digits[i]*hsign + carry;
else if(i>=h.digits.length)
temp = digits[i]*sign + carry;
else
temp = digits[i]*sign + h.digits[i]*hsign + carry;
if(temp>9){ //adds the digit to the string, then increments carry which is used in next iteration
temp -= 10;
sum += temp;
carry = 1;
}
else if(temp<0){
temp += 10;
carry = -1;
sum += temp;
}
else{
sum += temp;
carry = 0;
}
}
if(carry == 1)
sum += 1;
if(negative && h.negative || swapped)
sum += '-';
//flip string around
for(int i=0; i < sum.length(); i++){
sumFlipped += sum.charAt(sum.length() - 1 - i);
}
HugeInteger sumHugeInteger = new HugeInteger(sumFlipped);
return sumHugeInteger;
}

How to count unique characters (only letters and numbers)

// I have a program where I am supposed to count unique characters, only letters and numbers and don't count repeating numbers or letters. However, I have a problem finding out a way for the program not to count spaces and symbols such as "!" "#" "#" "$". So If i type in Hello! I only want the program to say "4", but it says "5" because it counts the exclamation point. Here is my code so far:
public static int countUniqueCharacters(String text1) {
int count = 0;
for (int i = 0; i < text1.length(); i++) {
if (text1.substring(0, i).contains(text1.charAt(i) + ""))
System.out.println();
else
count++;
}
return count;
}
In your else block add a condition that the count will be incremented only if the given character is a letter or a digit.
if (Character.isLetter(text1.charAt(i)) || Character.isDigit(text1.charAt(i))) {
count++;
}
In your example:
public static int countUniqueCharacters(String text1) {
int count = 0;
for (int i = 0; i < text1.length(); i++) {
if (text1.substring(0, i).contains(text1.charAt(i) + "")) {
System.out.println();
} else if (Character.isLetter(text1.charAt(i)) || Character.isDigit(text1.charAt(i))) {
count++;
}
}
return count;
}
here's a sample code written in C# try and understand it. It compares with ascii and adds in a list
string input = Console.ReadLine();//input
List<char> CountedCharacters = new List<char>();
for (int i = 0; i < input.Length; i++)
{ //checking for numerics //checking for alphabets uppercase //checking for alphabets lowercase
if ((input[i] >= 45 && input[i] <= 57) || (input[i] >= 65 && input[i] <= 90) || (input[i] >= 97 && input[i] <= 122))
{
bool AlreadyExists = false;
for (int j = 0; j < CountedCharacters.Count; j++)
{
////checking if already exists
if (CountedCharacters[j]==input[i])
{
AlreadyExists = true;
break;
}
}
////adding in list if doesnt exists
if (!AlreadyExists)
{
CountedCharacters.Add(input[i]);
}
}
}
for (int i = 0; i < CountedCharacters.Count; i++)
{
Console.WriteLine(CountedCharacters[i]);
}
Try this one using regex. You can add and remove the characters you need from the expression to count what you need.
public static int countUniqueCharacters(String text1) {
String newText = text1.replaceAll("[^A-Za-z0-9()\\[\\]]", "");
Set<Character> tempSet = new HashSet<>();
for (char item : newText.toCharArray()) {
tempSet.add(item);
}
return tempSet.size();
}

Categories

Resources