I came across the following question in Cracking the Coding Interview, 1.1:
Implement an algorithm to determine if a string has all unique characters. What if you can not use additional data structures?
Here is the book's solution:
Here is my solution:
public boolean allUnique(String input) {
HashSet<Character> set = new Hashset<Character>();
char c;
for (int i = 0; i < input.length(); i++) {
c = input.charAt(i);
if (set.contains(c)) return false;
set.add(c);
}
return true;
Does my solution work, and how efficient is it? I was also wondering if someone could explain ASCII and how it is relevant to this problem, since it was briefly mentioned in the book's solution. Is this why we are able to type-cast each char in the String to an integer?
Thank you!
To show how not to use an array (unknown if this is really fast or not) you can:
function boolean allUnique(String input){
for( int i=0; i<input.length(); i++ ){
if( input.indexOf(input.charAt(i),i) > -1 ){ return false; }
}
return true;
}
The above is not tested, but should work. The ",i)" may need to be ",i+1)" to put it past the current character. But I think just ",i)" should work.
Related
I'd like some feedback on a method I tried to implement that isn't working 100%. I'm making an Android app for practice where the user is given 20 random letters. The user then uses these letters to make a word of whatever size. It then checks a dictionary to see if it is a valid English word.
The part that's giving me trouble is with showing a "hint". If the user is stuck, I want to display the possible words that can be made. I initially thought recursion. However, with 20 letters this can take quite a long time to execute. So, I also implemented a binary search to check if the current recursion path is a a prefix to anything in the dictionary. I do get valid hints to be output however it's not returning all possible words. Do I have a mistake here in my recursion thinking? Also, is there a recommended, faster algorithm? I've seen a method in which you check each word in a dictionary and see if the characters can make each word. However, I'd like to know how effective my method is vs. that one.
private static void getAllWords(String letterPool, String currWord) {
//Add to possibleWords when valid word
if (letterPool.equals("")) {
//System.out.println("");
} else if(currWord.equals("")){
for (int i = 0; i < letterPool.length(); i++) {
String curr = letterPool.substring(i, i+1);
String newLetterPool = (letterPool.substring(0, i) + letterPool.substring(i+1));
if(dict.contains(curr)){
possibleWords.add(curr);
}
boolean prefixInDic = binarySearch(curr);
if( !prefixInDic ){
break;
} else {
getAllWords(newLetterPool, curr);
}
}
} else {
//Every time we add a letter to currWord, delete from letterPool
//Attach new letter to curr and then check if in dict
for(int i=0; i<letterPool.length(); i++){
String curr = currWord + letterPool.substring(i, i+1);
String newLetterPool = (letterPool.substring(0, i) + letterPool.substring(i+1));
if(dict.contains(curr)) {
possibleWords.add(curr);
}
boolean prefixInDic = binarySearch(curr);
if( !prefixInDic ){
break;
} else {
getAllWords(newLetterPool, curr);
}
}
}
private static boolean binarySearch(String word){
int max = dict.size() - 1;
int min = 0;
int currIndex = 0;
boolean result = false;
while(min <= max) {
currIndex = (min + max) / 2;
if (dict.get(currIndex).startsWith(word)) {
result = true;
break;
} else if (dict.get(currIndex).compareTo(word) < 0) {
min = currIndex + 1;
} else if(dict.get(currIndex).compareTo(word) > 0){
max = currIndex - 1;
} else {
result = true;
break;
}
}
return result;
}
The simplest way to speed up your algorithm is probably to use a Trie (a prefix tree)
Trie data structures offer two relevant methods. isWord(String) and isPrefix(String), both of which take O(n) comparisons to determine whether a word or prefix exist in a dictionary (where n is the number of letters in the argument). This is really fast because it doesn't matter how large your dictionary is.
For comparison, your method for checking if a prefix exists in your dictionary using binary search is O(n*log(m)) where n is the number of letters in the string and m is the number of words in the dictionary.
I coded up a similar algorithm to yours using a Trie and compared it to the code you posted (with minor modifications) in a very informal benchmark.
With 20-char input, the Trie took 9ms. The original code didn't complete in reasonable time so I had to kill it.
Edit:
As to why your code doesn't return all hints, you don't want to break if the prefix is not in your dict. You should continue to check the next prefix instead.
Is there a recommended, faster algorithm?
See Wikipedia article on "String searching algorithm", in particular the section named "Algorithms using a finite set of patterns", where "finite set of patterns" is your dictionary.
The Aho–Corasick algorithm listed first might be a good choice.
I have some code that I would like to make more efficient by recursion. Trouble is I don't know where to start. The code compares two arraylists a and b to see if they are equal. Assume the sizes of both arrays are equal.
The code is
public boolean isEqual(A B) {
boolean answer = false;
if (lessThanOrEqualTo(B) == true);
for (int i = 0; i < DList.size(); i++) {
if (DList.get(i) == B.DList.get(i)) answer = true;
else answer = false;
}
return answer;
}
I have currently written
public boolean isEqualRecursion(A B) {
if DList.size() == 0;
return false();
} else {
}
I know the stopping case is 0 as when size is 0 nothing happens. I have no idea what to write next
Any help will be appreciated
Thanks
I have some code that I would like to make more efficient by recursion.
It is unlikely that you can make it more efficient by recursion. The chances are that it will be less efficient, and also fragile. This is because standard Java compilers don't implement tail-call optimization. The fragility occurs because a recursive comparison algorithm is liable to trigger a stack overflow if the input arrays are large enough.
However, if you want to continue with this as "an exercise", then my HINT is to add an index argument to the isEqualRecursion signature ...
I think that this is a pretty good start for you. This looks through all your elements, assuming they are an array, and then checks if they are equal in size.
public boolean isEqual(ArrayList<?> a, ArrayList<?> b) {
if (a.size() != b.size())
return false;
for (int i = 0; i < a.size(); i++) {
if (!isEqual((ArrayList<?>)a.get(i), (ArrayList<?>)b.get(i))) {
return false;
}
}
return true;
}
Now a couple of things to consider:
This assumes that the content of a(and b) must be an ArrayList at line (ArrayList<?>)a.get(i) what if our ArrayList actually contains something else, like an Integer?
What if our array lists contain null as an item?
What if we pass in two null ArrayLists? (or even just one?)
I'm not sure the point of your function lessThanOrEqualTo(B) is this part of the question or did you write this down wrong?
Also what is a DList?
This is a typical recursion question. You might want to try something like this:
int x = 0;
if(Dlist.get(x) != B.Dlist.get(x)) {
return false;
} else {
x+1;
}
if( x!= dList.size()) {
recursion;
}
return true;
This particular interview-question stumped me:
Given two Strings S1 and S2. Find the longest Substring which is a Prefix of S1 and suffix of S2.
Through Google, I came across the following solution, but didnt quite understand what it was doing.
public String findLongestSubstring(String s1, String s2) {
List<Integer> occurs = new ArrayList<>();
for (int i = 0; i < s1.length(); i++) {
if (s1.charAt(i) == s2.charAt(s2.length()-1)) {
occurs.add(i);
}
}
Collections.reverse(occurs);
for(int index : occurs) {
boolean equals = true;
for(int i = index; i >= 0; i--) {
if (s1.charAt(index-i) != s2.charAt(s2.length() - i - 1)) {
equals = false;
break;
}
}
if(equals) {
return s1.substring(0,index+1);
}
}
return null;
}
My questions:
How does this solution work?
And how do you get to discovering this solution?
Is there a more intuitive / easier solution?
Part 2 of your question
Here is a shorter variant:
public String findLongestPrefixSuffix(String s1, String s2) {
for( int i = Math.min(s1.length(), s2.length()); ; i--) {
if(s2.endsWith(s1.substring(0, i))) {
return s1.substring(0, i);
}
}
}
I am using Math.min to find the length of the shortest String, as I don't need to and cannot compare more than that.
someString.substring(x,y) returns you the String you get when reading someString beginning from character x and stopping at character y. I go backwards from the biggest possible substring (s1 or s2) to the smallest possible substring, the empty string. This way the first time my condition is true it will be biggest possible substring the fulfills it.
If you prefer you can go the other way round, but you have to introduce a variable saving the length of the longest found substring fulfilling the condition so far:
public static String findLongestPrefixSuffix(String s1, String s2) {
if (s1.equals(s2)) { // this part is optional and will
return s1; // speed things up if s1 is equal to s2
} //
int max = 0;
for (int i = 0; i < Math.min(s1.length(), s2.length()); i++) {
if (s2.endsWith(s1.substring(0, i))) {
max = i;
}
}
return s1.substring(0, max);
}
For the record: You could start with i = 1 in the latter example for a tiny bit of extra performance. On top of this you can use i to specify how long the suffix has at least to be you want to get. ;) If you writ Math.min(s1.length(), s2.length()) - x you can use x to specify how long the found substring may be at most. Both of these things are possible with the first solution, too, but the min length is a bit more involving. ;)
Part 1 of your question
In the part above the Collections.reverse the author of the code searches for all positions in s1 where the last letter of s2 is and saves this position.
What follows is essentially what my algorithm does, the difference is, that he doesn't check every substring but only those that end with the last letter of s2.
This is some sort of optimization to speed things up. If speed is not that important my naive implementation should suffice. ;)
Where did you find that solution? Was it written by a credible, well-respected coder? If you're not sure of that, then it might not be worth reading it. One could write really complex and inefficient code to accomplish something really simple, and it will not be worth understanding the algorithm.
Rather than trying to understand somebody else's solution, it might be easier to come up with it on your own. I think you understand the problem much better that way, and the logic becomes your own. Over time and practice the thought process will start to come more naturally. Practice makes perfect.
Anyway, I put a more simple implementation in Python here (spoiler alert!). I suggest you first figure out the solution on your own, and compare it to mine later.
Apache commons lang3, StringUtils.getCommonPrefix()
Java is really bad in providing useful stuff via stdlib. On the plus side there's almost always some reasonable tool from Apache.
I converted the #TheMorph's answer to javascript. Hope this helps js developer
if (typeof String.prototype.endsWith !== 'function') {
String.prototype.endsWith = function(suffix) {
return this.indexOf(suffix, this.length - suffix.length) !== -1;
};
}
function findLongestPrefixSuffix(s2, s1) {
for( var i = Math.min(s1.length, s2.length); ; i--) {
if(s2.endsWith(s1.substring(0, i))) {
return s1.substring(0, i);
}
}
}
console.log(findLongestPrefixSuffix('abc', 'bcd')); // result: 'bc'
I want to search or select specific itmes from a list/array. So on constructing the function for searching in AS3 in flash, I got stuck..Please help to solve this problem...Thanks in advance
var ar:Array = new Array();
ar=[ "bhati", "malav", "vinod"];
//Searching Function
function findIndexOfValue( array:Array, _value:* ):int {
var _length:uint = array.length;
for(var i:uint=0; i < _length; i++) {
if(array[i] == _value) {
return i;
}
else{
return -1;
}
}
}
trace(findInndexOfValue( ar, "bhati" )); // it should output 0 .
//compiler error:- 1170:Function doesn't return a value., I tried my best, but unable to solve this.
How about
function findIndexOfValue( array:Array, _value:* ):int {
var _length:uint = array.length;
for(var i:uint=0; i < _length; i++) {
if(array[i] == _value) {
return i;
}
}
return -1;
}
Why bother with this? This functionality is built right into the Array class in AS3 (And most, if not all, OOP languages).
trace( this.ar.indexOf( "bhati" ) ); //will output 0
Array#indexOf()
As to why your script doesn't work, you have to return a value. You can't have all the returns in conditionals or loops. There must be a return in within the base level of the function.
EDIT: Just took a closer look at your function and there is more wrong with it than just the return. You will never make it beyond the first item in the array because it will always return a value (thanks to the else conditional). Simply remove the else bit and move the return in it to after the for loop runs and you will have a rough duplication of how indexOf works
this is my first question on stack overflow but I have some experience in Java. I am making a Java application at the moment (575 lines and counting!) and am trying to search through an ArrayList for a string. But I do not want it to be exact! Let me clarify: I want to iterate through each ArrayList element and search that string for another string. if the string is found in the ArrayList element, (for now) I want it printed to the console. I hope I have been clear enough.
Following is the relevant code. All variables are defined and the code compiles, just no output (from the search function) is printed. I am pretty sure that it is because the for loop doesn't execute, but I am puzzled as to why.
//the keylistener that calls the search() function, attached to a JTextField that the query is entered into
class searchFieldListener implements KeyListener {
searchFieldListener() {
}
public void keyTyped(KeyEvent event) {
if (event.getID() == KeyEvent.KEY_TYPED) {
query = searchField.getText()+Character.toString(event.getKeyChar());
System.out.println(query);
for (i = 0; i == nameList.size(); i++) {
search(query, i);
}
}
}
public void keyReleased(KeyEvent event) {
}
public void keyPressed(KeyEvent event) {
}
}
//the troublesome search() function
void search(String query, int iter) {
searchString = nameList.get(iter);
System.out.println(searchString);
if (searchString.indexOf(query) != -1) {
System.out.println(Integer.toString(iter));
} else {
System.out.println("not found \n");
}
}
Variables/Objects and uses:
searchFieldListener
The KeyListener for the JTextField called searchField for obvious reasons.
query
The string of the text to be searched for.
i
Why does everyone use i in loops? I guess it's a coding tradition.
nameList
The ArrayList of names (well, duh).
searchString
The string to be searched in (as in, try to find query in searchString).
iter
The number of iterations the for loop has been through so far.
Once again I hope I have been clear enough. Thanks!
The reason why your for loop is not executing is because of the condition used in the loop:
for (i = 0; i == nameList.size(); i++)
^^
Since the size method of the ArrayList class returns the number of elements you might want to have
i < nameList.size() instead.
for (i = 0; i == nameList.size(); i++)
should be
for (i = 0; i < nameList.size(); i++)
Not sure if you need < or <= though, you just modify it to you needs.
have have a typo in your for-loop. shouldn't this:
for (i = 0; i == nameList.size(); i++) {
look like this:
for (i = 0; i < nameList.size(); i++) {
Several correct answers, but one aspect is missing:
for (i = 0; i < nameList.size(); i++)
This is an old-school loop. Starting from Java 1.5, you should use this idiom to iterate over an array or iterable (a List is an Iterable):
for(String s: strings){
}
This simpler syntax is a) much less error-prone and b) a common way to iterate over many different data structures, including arrays and collections.
Internally this is a shortcut for this code:
for(Iterator<String> it = strings.iterator(); it.hasNext();){
String s = it.next();
// your code here
}