For some reason my if statement is not even being executed at all. Cannot figure out what is wrong, I am trying to test a word called "fuor" and do some manipulations in the hash table I have.
if(table[getHashIndex(c.toString())].contains(c.toString()))
this is the line that is not executing
Tableclass
char[] c = word.toCharArray();
for(int i=0;i<word.length()-1;i++)
{
char tempChar= c[i];
c[i]=c[i+1];
c[i+1]=tempChar;
if(table[getHashIndex(c.toString())].contains(c.toString()))
{
list.add(c.toString());
System.out.println("GOT IT BABY");
}
c = word.toCharArray();
}
public int getHashIndex(String word){
int key = 7;
//Adding ASCII values of string
//To determine the index
for(int i = 0 ; i < word.length(); i++){
key = key*BASE+(int)word.charAt(i);
//Accounting for integer overflow
if(key<0)
{
key*=-1;
}
}
key %= sizeOfTable;
return key;
}
//Bucket class
public boolean contains(String word){
Node insert = start;
//Traversing the list to find a match
while(insert!=null){
if(word.equalsIgnoreCase(insert.item))
return true;
insert = insert.next;
}
//did not find a match
return false;
}
The toString on a Java Array returns the default Object toString() (because arrays are not a primitive type e.g. c.toString() looks like this),
char[] t = new char[] { 'a' };
System.out.println(t.toString());
Output (for example)
[C#25f45022
I think you really wanted something like
char[] t = new char[] { 'a' };
System.out.println(java.util.Arrays.toString(t));
Which outputs
[a]
Or, maybe you wanted something like this
char[] t = new char[] { 'a' };
System.out.println(new String(t));
Which outputs
a
Related
I am having an issue with a particular leetcode problem called Valid Palindrome. My code works for all test cases except the last test case 479/480.
In this test case a 106890 length string is passed in but my code takes too long to solve it.
I decided to try take a different approach and use the StringBuilder class to reverse the string and then simply use reversedString.equals(originalString) to compare whether they are a palindrome. This approach solves the question and passes all testcases
Why doesn't my two pointer approach work? Why does it fail on the last test case?
Here is my solution (Two Pointer)
class Solution {
public static boolean isPalindrome(String s) {
String fixedString = "";
for (char c : s.toCharArray()) {
if (Character.isDigit(c) || Character.isLetter(c)) {
fixedString += c;
}
}
fixedString = fixedString.toLowerCase();
int i = 0;
int j = fixedString.length() - 1;
System.out.println(fixedString.toCharArray());
while (i <= j) {
if (fixedString.toCharArray()[i] != fixedString.toCharArray()[j]) {
return false;
}
i += 1;
j -= 1;
}
return true;
}
}
Here is my second solution using StringBuilder.
public class Valid_Palindrome {
public static void main(String args[]){
System.out.println(isPalindrome("A man, a plan, a canal: Panama"));
}
public static boolean isPalindrome(String s) {
String fixedString = "";
for(char c : s.toCharArray()){
if(Character.isDigit(c) || Character.isLetter(c)){
fixedString += c;
}
}
fixedString = fixedString.toLowerCase();
StringBuilder sb = new StringBuilder(fixedString);
sb = sb.reverse();
System.out.println(sb);
return sb.toString().equals(fixedString);
}
}
Technically speaking, isn't the second solution supposed to be much slower since it is using StringBuilder?
How do I optimize my first solution?
Here is the input string that is passed in my leetcode.
Don't build or reverse or do anything with the string, except iterate over half its characters.
In pseudo code:
Loop over the first half of the characters
For the ith character, compare it with the (length - i - 1)th character
If different, return false
If loop ends, return true
It is generally slow to perform string concatenation in a loop. Use a StringBuilder instead in the first loop to create the filtered string.
StringBuilder sb = new StringBuilder(s.length());
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (Character.isLetterOrDigit(c))
sb.append(Character.toLowerCase(c));
}
for (int i = 0, j = sb.length() - 1; i < j; i++, j--)
if (sb.charAt(i) != sb.charAt(j))
return false;
return true;
There are a couple of statements in your code that are probably slowing it down.
fixedString += c;
This creates a new StringBuilder object. The contents of fixedString are copied to it. Then the character (c) is appended. Then the StringBuilder is converted to a String and that String is assigned to variable fixedString.
if (fixedString.toCharArray()[i] != fixedString.toCharArray()[j])
Method toCharArray creates a new char[] and copies the contents of the String to it.
I suggest that you create the char[] once only and work with it. Of-course you need to remove the non-letters and non-digits from the original string as well as convert to lower case.
Here is my rewrite of your [two pointer] solution.
(Note that I assume that a null or empty string is not a palindrome.)
public static boolean isPalindrome(String s) {
if (s != null && !s.isEmpty()) {
char[] chars = s.toCharArray();
char[] temp = new char[chars.length];
int count = 0;
for (char c : chars) {
if (Character.isDigit(c) || Character.isLetter(c)) {
temp[count++] = Character.toLowerCase(c);
}
}
char[] letters = new char[count];
System.arraycopy(temp, 0, letters, 0, count);
int i = 0;
int j = count - 1;
System.out.println(letters);
while (i < j) {
if (letters[i] != letters[j]) {
return false;
}
i++;
j--;
}
return true;
}
return false;
}
I'm new at coding. And I'm doing an exercise, where I create a random ADN this n length (the one the user inputs). This this, I have to generate a new complementary adn.
The principal ADN uses just = A, C, G, T. In my new complementary ADN, I have to change every char, because 'A' needs to be replaced with 'T',every 'T' needs to be replaced this 'A', every 'G' has to ve replaced with 'C', and every 'C' need to be replaced with 'G'.
Example:
My random ADN would be = ACCGTTTTAAG. My new complementary ADN would be = TGGCAAAATTC.
This is my code where I'm trying to use a for to iterate inside my string and to replace the letters. No success though. But I think I have the idea. How can I proceed?
public String cadenaComplementaria(String ADN) {
this.ADN = ADN;
String ADNComplementario = "";
for (int i = 0; i <= ADN.length(); i++) {
if(this.ADN.charAt(i)=='A'){
this.ADN.replace('A','T');
ADNComplementario = this.ADN;
}
else if(this.ADN.charAt(i)=='C'){
this.ADN.replace('C', 'G');
}
else if(this.ADN.charAt(i)=='G'){
this.ADN.replace('G','C');
}
else if (this.ADN.charAt(i)=='T'){
this.ADN.replace('T','A');
}
return ADNComplementario;
}
So I'm trying to use a for to iterate inside my string, I'm trying to read what char is in the position so it can be replaced, it's not working though. I was trying to transfer the ADN value to the ADNComplementario to call it in my main, maybe I'm doing it wrong.
As you can see its a function, I'm learning programming oriented to object.
Easy peasy!
You just need to use replace method which you used quite well.
public String cadenaComplementaria(String adn) {
return adn.replace("C", "B").replace("G", "C").replace("B", "G")
.replace("A", "D").replace("T", "A").replace("D", "T");
}
In this solution we first replace C with B so that we can replace all the G with C. And then we already know that B used to be C, so we replace B with G.
And we do same thing with A and T using letter D as temporary letter.
Try this:
StringBuilder ADNComplementario = new StringBuilder();
for (int i = 0; i <= ADN.length(); i++) {
if(this.ADN.charAt(i)=='A'){
ADNComplementario.append("T");
}
else if(this.ADN.charAt(i)=='C'){
ADNComplementario.append("G");
}
else if(this.ADN.charAt(i)=='G'){
ADNComplementario.append("C");
}
else if (this.ADN.charAt(i)=='T'){
ADNComplementario.append("A");
}
return ADNComplementario.toString();
The easiest way to do this would be to convert the string to a char array and iterate through it a replace the chars there. To show you what I'm talking about here it is:
public String cadenaComplementaria(String ADN) {
this.ADN = ADN;
char[] ADNarr = ADN.toCharArray();
for (int i = 0; i <= ADN.length(); i++) {
if (ADNarr[i] == 'A'){
ADNarr[i] = 'T';
}
else if (ADNarr[i] == 'C'){
ADNarr[i] = 'G';
}
else if (ADNarr[i] == 'G'){
ADNarr[i] = 'C';
}
else if (ADNarr[i] == 'T'){
ADNarr[i] = 'A';
}
}
String converted = new String(ADNarr);
this.ADN = converted;
return converted;
}
This is a great way to replace everything without a problem.
In Java, Strings are "immutable" which means that after you have created a string you cannot change it. Methods like replace return new strings.
That means, this line of code does nothing: it creates the new string, and then throws it away.
this.ADN.replace('A','T');
One of many ways to solve this is by building the DNA sequence using a char array. You can then create a String from the array. Example:
char[] adnComplementario = new char[ADN.length()];
for (int i = 0; i < ADN.length(); i++) {
if (ADN.charAt(i)=='A'){
adnComplementario[i] = 'T';
}
if (ADN.charAt(i)=='T'){
adnComplementario[i] = 'A';
}
// add cases for C and G
}
return new String(adnComplementario);
try this using a lookup table map (java9):
String adn = "ACCGTTTTAAG";
Map<Character, Character> adnComplementLookup = Map.of('A', 'T','T', 'A','G', 'C','C', 'G');
StringBuffer adnComplement = new StringBuffer();
for(int i = 0; i < adn.length(); i++) {
adnComplement.append(adnComplementLookup.get(adn.charAt(i)));
}
System.out.println(adnComplement.toString());
Scanner _in = new Scanner(System.in);
System.out.println("Enter an Equation of variables");
String _string = _in.nextLine();
char[] cArray = _string.toCharArray();
I want to remove the symbols "+,=" and I want to remove any repeating variables.
so far I have:
for(int i = 0; i < cArray.length; i++){
if(cArray[i].equals(+)|| cArray[i].equals(=)){
cArray[i] = null;
}
}
However, I dont know how to condence the array to remove any gaps and I don't know how to remove repeating characters, I think I am making this harder than it needs to be
You can use:
_string.replaceAll("[+,=]","");
This sounds like a good use for regular expressions:
String result = _string.replaceAll("[+=]", "");
Here, the [+=] is a character class that consists of + and =. You can add other characters as required.
Try the next:
public static void main(String[] args) {
String input = "a+a+b=c+d-a";
char[] cArray = input.replaceAll("[-+=]", "") // gaps
.replaceAll("(.)(?=.*\\1)", "") // repeating
.toCharArray();
System.out.println(Arrays.toString(cArray));
}
Output:
[b, c, d, a]
Or you can se another array, like this:
Scanner in = new Scanner(System.in);
String s = in.nextLine();
char [] cArray = s.toCharArray();
int count = 0;
char [] cArray2 = new char[cArray.length];
for (int i = 0; i < cArray.length; i++){
if (cArray[i] != '+' || cArray[i] != '='){
cArray2[count++] = cArray[i];
}
}
for (int i = 0; i < count; i++){
boolean repeated = false;
for (int j = i + 1; j < count; j++){
if (cArray2[i] == cArray2[j]){
repeated = true;
break;
}
}
if (!repeated){
//do what you want
}
}
You can extend LinkedHashSet (Which enforces uniqueness and retains order). Override the add() function to not accept any characters that you don't want to use. Then put the contents in a char array.
public static char[] toCharArray(String str) {
// Here I am anonymously extending LinkedHashSet
Set<Character> characters = new LinkedHashSet<Character>() {
// Overriding the add method
public boolean add(Character character) {
if (!character.toString().matches("[\\+=]")) {
// character is not '+' or '='
return super.add(character);
}
// character is '+' or '='
return false;
}
};
// Adding characters from str to the set.
// Duplicates, '+'s, and '='s will not be added.
for (int i = 0; i < str.length(); i++) {
characters.add(str.charAt(i));
}
// Put Characters from set into a char[] and return.
char[] arrayToReturn = new char[characters.size()];
int i = 0;
for (Character c : characters) {
arrayToReturn[i++] = c;
}
return arrayToReturn;
}
Language : Java
Key Notes: *Needs to loop through a String using either a For loop or While loop
*It removes the duplicate letter(s) of the String and returns the word without the dupilcates.
Eg: The string is HELLO - The method then loops through and removes any duplicates, in this case " L " and returns in the end HELO
i have this so far
private String removeAnyDuplicates(String userWord)
{
//Code goes here?
return "" ; // Need to return the new string
}
You can do that with regular expressions. e.g.:
private static final Pattern REGEX_PATTERN =
Pattern.compile("(.)\\1*");
public static void main(String[] args) {
String input = "HELLO, AABBCC";
System.out.println(
REGEX_PATTERN.matcher(input).replaceAll("$1")
); // prints "HELO, ABC"
}
I'm assuming that removing duplicates means that the result contains at most one occurrence of any character. (Some of the other answers assume that adjacent duplicates only need to be reduced to single occurrences.) The basic algorithm would be:
initialize the result to the empty string
loop through each character of the input and if the character is not already present in the result, append it to the result
return the result
A naive (and very inefficient) implementation would be:
private String removeAnyDuplicates(String userWord)
{
String result = "";
for (int i = 0; i < userWord.length(); ++i) {
char c = result.charAt(i);
if (result.indexOf(c) < 0) {
// negative index indicates not present
result += String.valueOf(c);
}
}
return result;
}
This has two major sources of inefficiency: it creates many intermediate String objects and it has to scan the entire result so far for each character of the input. These problems can be solved by using some other built-in Java classes—a StringBuilder to more efficiently accumulate the result and a Set implementation to efficiently record and test which characters have already been seen:
private String removeAnyDuplicates(String userWord)
{
int len = userWord.length();
StringBuilder result = new StringBuilder(len);
Set<Character> unique = new HashSet<Character>();
for (int i = 0; i < len; ++i) {
char c = result.charAt(i);
// try to add c to set of unique characters
if (unique.add(c)) {
// if it succeeds, this is the first time seeing c
result.append(c);
}
}
return result.toString();
}
private String removeAnyDuplicates(String userWord)
{
CharSequence inputStr = userWord;
int length = inputStr.length();
Set<Character> uniqueChars = new HashSet<Character>();
for(int i=0; i < length; ++i) {
uniqueChars.add(inputStr.charAt(i));
}
return uniqueChars.size() >= 3;
}
check out this answer
Convert the string to an array of char, and store it in a LinkedHashSet. That will preserve your ordering, and remove duplicates.
Like this:
private static String removeAnyDuplicates(String userWord)
{
char[] chars = userWord.toCharArray();
Set<Character> charSet = new LinkedHashSet<Character>();
for (char c : chars) {
charSet.add(c);
}
StringBuilder sb = new StringBuilder();
for (Character character : charSet) {
sb.append(character);
}
return sb.toString();
}
Remember:
import java.util.LinkedHashSet;
import java.util.Set;
You can try this
public static void main(String args[]){
System.out.println(removeAnyDuplicates("HELLO"));
}
private static String removeAnyDuplicates(String userWord)
{
char[] arr=userWord.toCharArray();
List<String> list=new ArrayList<>();
for(int i=0;i<arr.length;i++){
if(!list.contains(String.valueOf(arr[i]))){
list.add(String.valueOf(arr[i]));
}
}
return list.toString().replaceAll("\\[|\\]|\\,","") ;
}
Try this one liner:
private String removeAnyDuplicates(String userWord) {
return userWord.replaceAll("(.)\\1+", "$1");
}
This uses a regular expression to find repeated (2 or more) letters and replaces them with a single instance of the letter.
It is unclear if "repeated" means appearing immediately after or anywhere after. For anywhere, use this:
private String removeAnyDuplicates(String userWord) {
return userWord.replaceAll("(.)(?=.*\\1)", "");
}
I was trying out this question :
Write a function using Recursion to display all anagrams of a string entered by the user, in such a way that all its vowels are located at the end of every anagram. (E.g.: Recursion => Rcrsneuio, cRsnroieu, etc.) Optimize it.
From this site :
http://erwnerve.tripod.com/prog/recursion/magic.htm
This is what i have done :
public static void permute(char[] pre,char[] suff) {
if (isEmpty(suff)) {
//result is a set of string. toString() method will return String representation of the array.
result.add(toString(moveVowelstoEnd(pre)));
return;
}
int sufflen = getLength(suff); //gets the length of the array
for(int i =0;i<sufflen;i++) {
char[] tempPre = pre.clone();
char[] tempSuf = suff.clone();
int nextindex = getNextIndex(pre); //find the next empty spot in the prefix array
tempPre[nextindex] = tempSuf[i];
tempSuf = removeElement(i,tempSuf); //removes the element at i and shifts array to the left
permute(tempPre,tempSuf);
}
}
public static char[] moveVowelstoEnd(char[] input) {
int c = 0;
for(int i =0;i<input.length;i++) {
if(c>=input.length)
break;
char ch = input[i];
if (vowels.contains(ch+"")) {
c++;
int j = i;
for(;j<input.length-1;j++)
input[j] = input[j+1];
input[j]=ch;
i--;
}
}
return input;
}
Last part of the question is 'Optimize it'. I am not sure how to optimize this. can any one help?
Group all the vowels into v
Group all consonants into w
For every pair of anagrams, concat the results