How do I find out the position of a char - java

I've got an String ("Dinosaur") and I don't exactly know how, but how do I get the position of the char "o" and is it in all possible to get two positions like if my String was ("Pool")

As for your first question, you can use String#indexOf(int) to get the index of every 'o' in your string.
int oPos = yourString.indexOf('o');
As for your second question, it is possible to get all positions of a given char by making a method which uses String.indexOf(int, int), tracking the previous index so that you don't repeat searched portions of the string. You could store the positions in an array or list.

Use indexOf with a loop:
String s = "Pool";
int idx = s.indexOf('o');
while (idx > -1) {
System.out.println(idx);
idx = s.indexOf('o', idx + 1);
}

Simply:
public static int[] getPositions(String word, char letter)
{
List<Integer> positions = new ArrayList<Integer>();
for(int i = 0; i < word.length(); i++) if(word.charAt(i) == letter) positions.add(i);
int[] result = new int[positions.size()];
for(int i = 0; i < positions.size(); i++) result[i] = positions.get(i);
return result;
}

This is probably going a little over board, but hey ;)
String master = "Pool";
String find = "o";
Pattern pattern = Pattern.compile(find);
Matcher matcher = pattern.matcher(master);
String match = null;
List<Integer[]> lstMatches = new ArrayList<Integer[]>(5);
while (matcher.find()) {
int startIndex = matcher.start();
int endIndex = matcher.end();
lstMatches.add(new Integer[] {startIndex, endIndex});
}
for (Integer[] indicies : lstMatches) {
System.out.println("Found " + find + " # " + indicies[0]);
}
Gives me
Found o # 1
Found o # 2
The great thing is, you could also find "oo" as well

Have you tried converting the String to a char array?
int counter = 0;
String input = "Pool";
for(char ch : input.toCharArray()) {
if(ch == 'o') {
System.out.println(counter);
}
counter += 1;
}

Try this
String s= "aloooha";
char array[] = s.toCharArray();
Stack stack = new Stack();
for (int i = 0; i < array.length; i++) {
if(array[i] == 'o'){
stack.push(i);
}
}
for (int i = 0; i < stack.size(); i++) {
System.out.println(stack.get(i));
}

Related

Function is working in some cases but fails when longest sub-string "reuses" a character

I have a function called lengthOfLongestSubstring and its job is to find the longest substring without any repeated characters. For the most part, it works, but when it gets an input like "dvdf" it prints out 2 (rather than 3) and gives [dv, df] when it should be [d, vdf].
So, I first go through the string and see if there are any unique characters. If there are, I append it to the ans variable. (I think this is the part that needs some fixing). If there is a duplicate, I store it in the substrings linked list and reset the ans variable to the duplicate string.
Once the whole string has been traversed, I find the longest substring and return its length.
public static int lengthOfLongestSubstring(String s) {
String ans = "";
int len = 0;
LinkedList<String> substrings = new LinkedList<String>();
for (int i = 0; i < s.length(); i++) {
if (!ans.contains("" + s.charAt(i))) {
ans += s.charAt(i);
} else {
substrings.add(ans);
ans = "" + s.charAt(i);
}
}
substrings.add(ans); // add last seen substring into the linked list
for (int i = 0; i < substrings.size(); i++) {
if (substrings.get(i).length() >= len)
len = substrings.get(i).length();
}
System.out.println(Arrays.toString(substrings.toArray()));
return len;
}
Here are some test results:
//correct
lengthOfLongestSubstring("abcabcbb") -> 3 ( [abc, abc, b, b])
lengthOfLongestSubstring("pwwkew") -> 3 ([pw, wke, w]).
lengthOfLongestSubstring("ABDEFGABEF"); -> 6 ([ABDEFG, ABEF])
// wrong
System.out.println(lengthOfLongestSubstring("acadf")); -> 3, ([ac, adf]) *should be 4, with the linked list being [a, cadf]
Any suggestions to fix this? Do I have to redo all my logic?
Thanks!
You code is mistakenly assuming that when you find a repeated character, the next candidate substring starts at the repeated character. That is not true, it starts right after the original character.
Example: If string is "abcXdefXghiXjkl", there are 3 candidate substrings: "abcXdef", "defXghi", and "ghiXjkl".
As you can see, the candidate substrings ends before a repeating character and starts after a repeating character (and begin and end of string).
So, when you find a repeating character, the position of the previous instance of that character is needed to determine the start of the next substring candidate.
The easiest way to handle that, is to build a Map of character to last seen position. That will also perform faster than continually performing substring searches to check for repeating character, like the question code and the other answers are doing.
Something like this:
public static int lengthOfLongestSubstring(String s) {
Map<Character, Integer> charPos = new HashMap<>();
List<String> candidates = new ArrayList<>();
int start = 0, maxLen = 0;
for (int idx = 0; idx < s.length(); idx++) {
char ch = s.charAt(idx);
Integer preIdx = charPos.get(ch);
if (preIdx != null && preIdx >= start) { // found repeat
if (idx - start > maxLen) {
candidates.clear();
maxLen = idx - start;
}
if (idx - start == maxLen)
candidates.add(s.substring(start, idx));
start = preIdx + 1;
}
charPos.put(ch, idx);
}
if (s.length() - start > maxLen)
maxLen = s.length() - start;
if (s.length() - start == maxLen)
candidates.add(s.substring(start));
System.out.print(candidates + ": ");
return maxLen;
}
The candidates is only there for debugging purposes, and is not needed, so without that, the code is somewhat simpler:
public static int lengthOfLongestSubstring(String s) {
Map<Character, Integer> charPos = new HashMap<>();
int start = 0, maxLen = 0;
for (int idx = 0; idx < s.length(); idx++) {
char ch = s.charAt(idx);
Integer preIdx = charPos.get(ch);
if (preIdx != null && preIdx >= start) { // found repeat
if (idx - start > maxLen)
maxLen = idx - start;
start = preIdx + 1;
}
charPos.put(ch, idx);
}
return Math.max(maxLen, s.length() - start);
}
Test
System.out.println(lengthOfLongestSubstring(""));
System.out.println(lengthOfLongestSubstring("x"));
System.out.println(lengthOfLongestSubstring("xx"));
System.out.println(lengthOfLongestSubstring("xxx"));
System.out.println(lengthOfLongestSubstring("abcXdefXghiXjkl"));
System.out.println(lengthOfLongestSubstring("abcabcbb"));
System.out.println(lengthOfLongestSubstring("pwwkew"));
System.out.println(lengthOfLongestSubstring("ABDEFGABEF"));
Output (with candidate lists)
[]: 0
[x]: 1
[x, x]: 1
[x, x, x]: 1
[abcXdef, defXghi, ghiXjkl]: 7
[abc, bca, cab, abc]: 3
[wke, kew]: 3
[ABDEFG, BDEFGA, DEFGAB]: 6
Instead of setting ans to the current char when a character match is found
ans = "" + s.charAt(i);
You should add the current char to all the characters after the first match of the current char
ans = ans.substring(ans.indexOf(s.charAt(i)) + 1) + s.charAt(i);
The full method thus becomes
public static int lengthOfLongestSubstring(String s) {
String ans = "";
int len = 0;
LinkedList<String> substrings = new LinkedList<>();
for (int i = 0; i < s.length(); i++) {
if (!ans.contains("" + s.charAt(i))) {
ans += s.charAt(i);
} else {
substrings.add(ans);
// Only the below line changed
ans = ans.substring(ans.indexOf(s.charAt(i)) + 1) + s.charAt(i);
}
}
substrings.add(ans); // add last seen substring into the linked list
for (int i = 0; i < substrings.size(); i++) {
if (substrings.get(i).length() >= len)
len = substrings.get(i).length();
}
System.out.println(Arrays.toString(substrings.toArray()));
return len;
}
Using this code the acceptance criteria you specified passed successfully
//correct
lengthOfLongestSubstring("dvdf") -> 3 ( [dv, vdf])
lengthOfLongestSubstring("abcabcbb") -> 3 ([abc, bca, cab, abc, cb, b])
lengthOfLongestSubstring("pwwkew") -> 3 ([pw, wke, kew]).
lengthOfLongestSubstring("ABDEFGABEF"); -> 6 ([ABDEFG, BDEFGA, DEFGAB, FGABE, GABEF])
lengthOfLongestSubstring("acadf"); -> 4 ([ac, cadf])
Create a nested for loop to check at each index in the array.
public static int lengthOfLongestSubstring(String s) {
String ans = "";
int len = 0;
LinkedList<String> substrings = new LinkedList<String>();
int k = 0;
for (int i = 0; i < s.length(); i++) {
if(k == s.length()) {
break;
}
for(k = i; k < s.length(); k++) {
if (!ans.contains("" + s.charAt(k))) {
ans += s.charAt(k);
} else {
substrings.add(ans);
ans = "";
break;
}
}
}
substrings.add(ans); // add last seen substring into the linked list
for (int i = 0; i < substrings.size(); i++) {
if (substrings.get(i).length() >= len)
len = substrings.get(i).length();
}
System.out.println(Arrays.toString(substrings.toArray()));
return len;
}
Example:
lengthOfLongestSubstring("ABDEFGABEF"); -> 6 ([ABDEFG, BDEFGA, DEFGAB, EFGAB, FGABE, GABEF])

Java program to find the letter that appears in the most words?

I have a sentence, and I want to find the char that appears in the most words, and how many words it appears in.
For example: "I like visiting my friend Will, who lives in Orlando, Florida."
Which should output I 8.
This is my code:
char maxChar2 = '\0';
int maxCount2 = 1;
for (int j=0; j<strs2.length; j++) {
int charCount = 1;
char localChar = '\0';
for (int k=0; k<strs2[j].length(); k++) {
if (strs2[j].charAt(k) != ' ' && strs2[j].charAt(k) != maxChar2) {
for (int l=k+1; l<strs2[j].length(); l++) {
if (strs2[j].charAt(k)==strs2[j].charAt(l)) {
localChar = strs2[j].charAt(k);
charCount++;
}
}
}
}
if (charCount > maxCount2) {
maxCount2 = charCount;
maxChar2 = localChar;
}
}
, where strs2 is a String array.
My program is giving me O 79. Also, uppercase and lowercase do not matter and avoid all punctuation.
As a tip, try using more meaningful variable names and proper indentation. This will help a lot especially when your program is not doing what you thought it should do. Also starting smaller and writing some tests for it will help a bunch. Instead of a full sentence, get it working for 2 words, then 3 words, then a more elaborate sentence.
Rewriting your code to be a bit more readable:
// Where sentence is: "I like".split(" ");
private static void getMostFrequentLetter(String[] sentence) {
char mostFrequentLetter = '\0';
int mostFrequentLetterCount = 1;
for (String word : sentence) {
int charCount = 1;
char localChar = '\0';
for (int wordIndex = 0; wordIndex < word.length(); wordIndex++) {
char currentLetter = word.charAt(wordIndex);
if (currentLetter != ' ' && currentLetter != mostFrequentLetter) {
for (int l = wordIndex + 1; l < word.length(); l++) {
char nextLetter = word.charAt(l);
if (currentLetter == nextLetter) {
localChar = currentLetter;
charCount++;
}
}
}
}
if (charCount > mostFrequentLetterCount) {
mostFrequentLetterCount = charCount;
mostFrequentLetter = localChar;
}
}
}
Now all I did was rename your variables and change your for loop to a for-each loop. By doing this you can see more clearly your algorithm and what you're trying to do. Basically you're going through each word and comparing the current letter with the next letter to check for duplicates. If I run this with "I like" i should get i 2 but instead I get null char 1. You aren't properly comparing and saving common letters. This isn't giving you the answer, but I hope this makes it more clear what your code is doing so you can fix it.
Here is a somewhat more elegant solution
public static void FindMostPopularCharacter(String input)
{
String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
input = input.toUpperCase();
HashMap<Character, Integer> charData = new HashMap<>();
char occursTheMost = 'A'; //start with default most popular char
int maxCount = 0;
//create the map to store counts of all the chars seen
for(int i = 0; i < alphabet.length(); i++)
charData.put(alphabet.charAt(i), 0);
//first find the character to look for
for(int i = 0; i < input.length(); i++)
{
char c = input.charAt(i);
//if contained in our map increment its count
if(charData.containsKey(c))
charData.put(c, charData.get(c) + 1);
//check for a max count and set the values accordingly
if(charData.containsKey(c) && charData.get(c) > maxCount)
{
occursTheMost = c;
maxCount = charData.get(c);
}
}
//final step
//now split it up into words and search which contain our most popular character
String[] words = input.split(" ");
int wordCount = 0;
CharSequence charSequence;
for(Character character : charData.keySet())
{
int tempCount = 0;
charSequence = "" + character;
for(int i = 0; i < words.length; i++)
{
if(words[i].contains(charSequence))
tempCount++;
}
if(tempCount > wordCount)
{
occursTheMost = character;
wordCount = tempCount;
}
}
System.out.println(occursTheMost + " " + wordCount);
}
Output of
String input = "I like visiting my friend Will, who lives in Orlando, Florida.";
FindMostPopularCharacter(input);
is
I 8
Note: If there are ties this will only output the character that first reaches the maximum number of occurrences.
FindMostPopularCharacter("aabb aabb aabb bbaa");
Outputs
B 4
because B reaches the max first before A due to the last word in the input.
FindMostPopularCharacter("aab aab b")
B 3

How would I splice and add these two char arrays?

I have this array.
char [] cornStrand = {'G','G','A','G','T','T','C','C','C','A'};
I also have this array, for which the values are inputted by the user running the program.
char [] bacteriaStrand = new char [5];
String strBases = scan.nextLine();
for (int s=0; s <bacteriaStrand.length; s++)
{
char c = strBases.charAt(s);
bacteriaStrand[s]= c ;
}
The second block of code essentially inputs the values that the user entered into the bacteria strand array.
Now comes the tricky part. I need to "splice" and combine both arrays. By this I mean:
If the first character of
char [] bacteriaStrand
is A, then I have to insert
char [] bacteriaStrand
After the first G in
char [] cornStrand
Now, after I splice this, I have to put what I spliced into a new array, called
char [] combinedStrand
This is where I am becoming confused. If anyone can help, please do so! I would gladly appreciate it!
Maybe do something like this:
public char[] combine(char[] bacteriaStrand, char[] cornStrand) {
char[] result = new char[bacteriaStrand.length + cornStrand.length];
if (bacteriaStrand[0] == 'A') {
for (int i = 0; i < cornStrand.length; i++) {
boolean insertedBacteria = false;
if (cornStrand[i] == 'G') {
insertedBacteria = true;
for (int j = 0; j < bacteriaStrand.length; j++) {
result[i + 1 + j] = bacteriaStrand[j];
}
if (insertedBacteria)
i += bacteriaStrand.length;
result[i] = cornStrand[i];
}
}
}
return result;
}
If that is the only rule, it seems pretty simple to do.
if (bacteriaStrand[0] == 'A') {
int totalLength = cornStrand.length + bacteriaStrand.length;
char [] combinedStrand = new char [totalLength];
for(int i=0; i<cornStrand.length; i++){
combinedStrand[i] = cornStrand[i]; //fill in corn until you find the first G
if (cornStrand[i] == 'G') {
int j = 0;
for(; j<bacteriaStrand.length; j++){
combinedStrand[i+j+1] = bacteriaStrand[j]; //fill in bacteria
}
i++;
for(;i<cornStrand.length;i++){
combinedStrand[i+j+1] = cornStrand[i] //fill in the rest of corn
}
}
}//now this loop will break, since you increased i, so you won't get duplicates
}

Replacing characters of a string in a particular sequence

The String word contains a character ] at more than one place. I want to replace any character before the ] by l, and any character after by r.
For example, the String defined below:
String word="S]RG-M]P";
Should be converted to:
String word="l]rG-l]r";
When I tried by the following code:
String word="S]RG-M]P";
char[] a = word.toCharArray();
for(int i=0; i<a.length; i++){
if (a[i]==']'){
a[i+1]='r';
a[i-1]='l';
}
}
It changes the right side of ] by r, but fails left to it by l. I need help to get the required results.
public static void main(String[] args) {
String word = "S]RG-M]P";
char[] a = word.toCharArray();
for (int i = 1; i < a.length-1; i++) {//#Jon Skeet again is right X2 :)
//no need now, for loop bound changed
//if(i+1>a.length){
// continue;
// }
if (a[i] == ']') {
//no need now, for loop bound changed
//#Jon Skeet you are right, this handles the case :)
//if(i==0 || i == a.length-1){
//continue;
//}
a[i + 1] = 'r';
a[i - 1] = 'l';
}
}
String outt = new String(a);
System.out.print(outt);
}// main
StringBuilder word = new StringBuilder("S]RG-M]P");
int index = word.indexOf("]");
while(index > 0){
word.setCharAt(index-1, 'l');
word.setCharAt(index+1, 'r');
index = word.indexOf("]", index+1);
}
System.out.println(word);
String word="S]RG-M]P";
word.replaceAll(".]." , "l]r");
using regex and string methods is useful in this situation
for(int i=0 ; i<word.length();i++){
char a = word.charAt(i);
String after =null;
if( Character.toString(a).equals("]")){
int j = i-1;
int k = i+1;
char b = word.charAt(j);
char c = word.charAt(k);
modifyword= word.replace( Character.valueOf(b).toString(), "l");
after= modifyword.replace( Character.valueOf(c).toString(), "r");
word = after;
}
}

Pattern Matcher - Split on specified length

I need to Split my string into some specified length(10 char).
Below is my code:
Pattern p = Pattern.compile(".{0,10}");
Matcher m = p.matcher("012345678901234567890123456");
List<String> emailStr = new ArrayList<String>();
while(m.find())
{
System.out.println(m.group());
}
As for my requirment I will get max of 3 Strings. I want to assign this "n" number of strings to separate variable. I donot have any idea on this. Please help on it.
You can use this do get what you want:
public static String[] splitter(String str, int len) {
String[] array = new String[(int) str.length() / len + 1];
for (int i = 0; i < str.length() / len + 1; i++) {
String s = "";
for (int j = 0; j < len; j++) {
int index = i * len + j;
if (index < str.length())
s += str.charAt(i * len + j);
else
break;
}
array[i] = s;
}
return array;
}
Building on the answer Jack gave:
public List<String> splitter(String str, int len) {
ArrayList<String> lst = new ArrayList<String>((str.length() - 1)/len + 1);
for (int i = 0; i < str.length(); i += len)
lst.add(str.substring(i, Math.min(str.length(), i + len)));
return lst;
}
Don't use a Pattern Matcher for this. Don't use regular expressions where they are not needed, in languages where regular expressions are not a fundamental concept. In perl, you do everything you can using regular expressions, but otherwise don't.

Categories