I got a school assignment that I have to create a program that prints the first recurring character in a given string.
For example, if the input is "helloo", then it should output as "l". I wrote the following code but it prints "l" and "o" both.
String text = "helloo";
int length = text.length();
for (int i = 0; i <= length - 1; i++) {
char curChar = text.charAt(i);
for (int j = i + 1; j <= length - 1; j++) {
if (curChar == text.charAt(j)) {
System.out.println(curChar);
break;
}
}
}
Can someone help me out with this? Thanks for any answers!
You're breaking just the inner loop but not the outer loop. You can use break with a label for the outer loop. For example:
String text = "helloo";
int length = text.length();
outerloop:
for (int i = 0; i <= length - 1; i++) {
char curChar = text.charAt(i);
for (int j = i + 1; j <= length - 1; j++) {
if (curChar == text.charAt(j)) {
System.out.println(curChar);
break outerloop;
}
}
}
Get more information here - How to break out of nested loops in Java?
Hope this helps, but you should try doing your school assignments yourself.
I realize that you are asking for a direct fix to your current approach. But for those who might read this question in the future, there is a very sleek approach here using regular expressions:
String text = "helloo";
String match = text.replaceAll("^.*?(.)\\1.*", "$1");
System.out.println(match);
l
Demo
The basic idea of the pattern ^.*?(.)\1 is to consume the least number of characters in the string until we hit a single character which is followed by that same character.
Here's another variant:
String text = "helloo";
ArrayList<String> a = new ArrayList<String>(Arrays.asList(text.split(Pattern.quote(""))));
for(int i = 0; i < a.size()-1;i++) {
if(a.get(i).compareTo(a.get(i+1)) == 0) {
System.out.println(a.get(i));
break;
}
class FirstRepeatingChar
{
public static void main(String args[])
{
String s="hello";
for(int i=0;i<s.length();i++)
{
for(int j=0;j<s.length();j++)
{
if(s.charAt(i)==s.charAt(j))
{
System.out.println(" the First non repeating character is " +s.charAt(i));
break;
}
}
}
}
}
Related
I'm writing a java code currently for class and I'm trying to figure out how to implement a run length encoding on a user input. The main problem I'm having it with comparing the first letter with the next and that letter with the next and so on to see if they're the same letter. Currently I have:
System.out.print("Enter a string: ");
String s1 = reader.nextLine();
int sum = 0;
char ast = '*';
//System.out.println("Run length encoded version of string: ");
for (int counter = 0; s1.charAt(counter) <= s1.length()-1; counter++) {
for (int j = 0; s1.charAt(counter) == s1.charAt(j)+1; j++) {
sum++;
counter++;
}
if (sum >= 4) {
System.out.print(ast + s1.charAt(counter) + sum);
}
else {
System.out.print(s1.charAt(counter));
}
}
I know where the big problem comes from in this and why it doesn't work but, namely from the
for (int j = 0; s1.charAt(counter) == s1.charAt(j)+1; j++) {
sum++;
counter++;
}
segment as it just goes infinitely. Is there a proper way to do this? The professor mentioned it can be done without loops and while I can see it being possible I can't see it being short. Any help would be appreciated, thanks!
String str="ayyusaab";
char[] ch=str.toCharArray();
for(int i=0;i<ch.length-1;i++){
for(int j=i+1;j<ch.length-1;j++){
if(ch[i]==ch[j]) {
System.out.println(ch[i]+" at Index "+i +"with j at "+j);
}
}
}
This question already has answers here:
Java: Print a unique character in a string
(20 answers)
Closed 4 years ago.
I am trying to print a character from a string which occurs only one time in the string. Here is the code I am using, but it is showing the answer always as H.
How can I fix this?
class StringRepeat {
static int i,j;
public static void main(String[] args) {
String s1 = "How are How";
outer:for(i=0;i<=s1.length(); i++)
{
inner:for(j=1;j<s1.length(); j++)
{
if (s1.charAt(i) != s1.charAt(j))
break outer;
}
}
System.out.println(s1.charAt(i));
}
}
Basically you can solve this in 2 ways - brute force (using arrays) and a bit more intelligently (using maps).
Brute force way
For every character in the input string check if it is the same as some other character:
public void uniqueCharsBruteForce(String input) {
for (int i = 0; i < input.length(); ++i) {
char candidate = input.charAt(i);
if (!contains(input, candidate, i)) {
System.out.println(candidate);
}
}
}
private boolean contains(String input, char candidate, int skipIndex) {
for (int i = 0; i < input.length(); ++i) {
if (i == skipIndex) {
continue;
}
if (candidate == input.charAt(i)) {
return true;
}
}
return false;
}
Code is simple but very slow, so use only for short strings. Time complexity is O(n^2).
Using maps
As you iterate through the input, count how many times each character appears. At the end, print only those who appear once only:
public void uniqueCharsBetter(String input) {
Map<Character, Integer> occurences = new HashMap<>();
for (int i = 0; i < input.length(); ++i) {
Character key = Character.valueOf(input.charAt(i));
occurences.put(key, occurences.getOrDefault(key, 0) + 1);
}
occurences.entrySet().forEach(entry -> {
if (entry.getValue().intValue() == 1) {
System.out.println(entry.getKey());
}
});
}
This can be optimized further but it's possible this is enough for your requirements. Time complexity is O(n).
This will give an StringIndexOutOfBoundsException if no unique
char is found:
outer:for(i=0;i<=s1.length(); i++)
replace it with
int i = 0;
outer: for(;i<s1.length(); i++)
There's no need for an inner label, and you need to start the search
from 0, not 1, so replace
inner:for(j=1;j<s1.length(); j++)
with
for(int j=0;j<s1.length(); j++)
You have your test inverted. If the characters at i and j are
the same, you need to continuue with the outer loop. Also, you need to
make sure you don't compare when i==j. So your test changes from:
if (s1.charAt(i) != s1.charAt(j))
break outer;
to
if (i!=j && s1.charAt(i) == s1.charAt(j))
continue outer;
If the inner for loop terminates, i.e. gets to the end of the
string, then the character at i is unique, so we need to break out
of the outer loop.
When you exit the outer loop you need to determine if you found a unique element, which will be the case if i < s1.length().
Putting this all together we get:
String s1= "How are How";
int i = 0;
outer: for(;i<s1.length(); i++)
{
for(int j=0;j<s1.length(); j++)
{
if (i!=j && s1.charAt(i) == s1.charAt(j))
continue outer;
}
break;
}
if(i<s1.length()) System.out.println(s1.charAt(i));
Here a link to the code (IDEOne).
This will print out every character that appears only once in the text.
final String s1 = "How are How";
outer:for(int i = 0; i < s1.length(); i++)
{
for(int j = 0; j < s1.length(); j++)
{
if(s1.charAt(i) == s1.charAt(j) && i != j)
{
continue outer;
}
}
System.out.println(s1.charAt(i);
}
Try this
String s = inputString.toLowerCase();
boolean[] characters = new boolean[26];
for(int i = 0; i < 26; i++)
characters[i] = true;
for(int i = 0; i < s.length(); i++)
{
if(characters[s.charAt(i) - 'a'])
{
System.out.println(s.charAt(i));
characters[s.charAt(i) - 'a'] = false;
}
}
Hope this helps. I have assumed that u treat lowercase and uppercase as same else u can modify accordingly
OK, i know this question was asked many times here, but i still don't get it, how to find the first repeated character in a string ?
I did something which was close, but it gave me all repeated characters instead of only the first one.
Here's what i did :
private static void stringChar(){
String s = "sababa";
int count = 0;
char c[] = s.toCharArray();
System.out.println("Duplicate characters are :");
for(int i = 0; i < s.length(); i++){
for(int j = i + 1; j < s.length(); j++){
if(c[i] == c[j]) {
System.out.println(c[j]);
count++;
break;
}
}
}
}
One quick and dirty (yet effective) approach which comes to mind is to maintain a map whose keys are the characters. In this case, we don't even need a formal map, because we can use an integer array which maps to the underlying ASCII values of the characters.
The basic idea here is to walk down the string, and check the array if we have seen it before. If so, then print that character and exit.
int[] nums = new int[128]; // assuming only basic ASCII characters
String str = "stuff";
for (int i=0; i < str.length(); ++i) {
int index = str.charAt(i);
if (nums[index] != 0) {
System.out.println("The first repeated character is: " + str.charAt(i));
break;
}
++nums[index];
}
Demo
You need to break the outer loop if you have already found the repeating character.
boolean found = false;
for(int i = 0; i < s.length(); i++){
for(int j = i + 1; j < s.length(); j++){
if(c[i] == c[j]) {
System.out.println(c[j]);
found = true;
break;
}
}
if (found) {
break;
}
}
If you want the count of it
int count = 0;
char repeatingChar = '0'; //dummy to overcome compiler warning
for(int i = 0; i < s.length(); i++){
for(int j = i + 1; j < s.length(); j++){
if(c[i] == c[j]) {
repeatingChar = c[j];
count++;
}
}
if (count > 0) {
System.out.println("Repeating char is " + repeatingChar + ". Occurred " + count + " times");
break;
}
}
The first repeated char is one you have seen before as you iterate the chars in the string. You can keep track of the first time you see a char with a Boolean array. The array is indexed with the char value. Java automatically "widens" char to int. So, for each char, check if it's been seen before and if not, mark that it has been seen.
String s = "sababa";
boolean[] seenChars = new boolean[Character.MAX_VALUE + 1]; // initialized to all false.
for (char c : s.toCharArray()) {
if (Character.isSurrogate(c)) throw new IllegalArgumentException("No first char seen before seeing a surrogate. This algorithm doesn't work for codepoints needing surrogates in UTF-16.");
if (seenChars[c]) {
System.out.println("First repeated char is: " + c);
break;
}
seenChars[c] = true;
}
You might notice that I've been saying char instead of character. Character is not a well-defined term. Java's text datatypes use the UTF-16 encoding of the Unicode character set. Some Unicode codepoints require two UTF-16 code units (char), which are sometimes called surrogate pairs. Since they are not all unique as individual chars, the algorithm doesn't work if they are present. For example, try String s = "sab🚲aba"; (You can also write it as "sab\uD83D\uDEB2aba".) The answer would be "a", again. But now try String s = "sab🚲🚶aba"; (You can also write it as "sab\uD83D\uDEB2\uD83D\uDEB6aba".) The answer should still be "a" but the algorithm would say "\uD83D" (which of course can't be displayed because it is only part of a codepoint).
Short and Simple >
void findFirstDupChar() {
String s = "google";
Integer dupIndex = s.length() - 1;
boolean isDuplicateExists = false;
Map<Character, Integer> map = new LinkedHashMap<>();
char[] words = s.toCharArray();
for (int i = 0; i < words.length; i++) {
Integer index = map.put(words[i], i);
if (index != null) {
if (index < dupIndex) {
dupIndex = index;
isDuplicateExists = true;
}
}
}
System.out.println(isDuplicateExists ? words[dupIndex] + ", index=" + dupIndex : "No duplicateds found");
}
This will print output as following >
g, index=0
Here am finding the middle letter of each element of the array and making it upper case and merge it so that it'll give me a result like e:g- {bOy, inDia, apPle}
Following is the code am trying till now.
public class FindMiddle {
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();
al.add("boy india apple");
String str[] = al.toArray(new String[al.size()]);
String newar[];
String delimiter = " ";
newar = str[0].split(delimiter);
for (int i = 0; i < newar.length; i++) {
char[] c = newar[i].toCharArray();
for (int j = 0; j < c.length; j++) {
if (j == c.length / 2) {
c[j] = Character.toUpperCase(c[c.length / 2]);
System.out.println(c[j]);
}
newar[i] += c[j];
}
}
}
}
It's only giving me O D P.
I want them merged with the original elements like bOy inDia apPle.
that's because you print only the middle char (the println is inside the if statement)
if (j == c.length / 2) {
c[j] = Character.toUpperCase(c[c.length / 2]);
System.out.println(c[j]);
}
I would suggest using StringBuilder.setCharAt
for (int i = 0; i < newar.length; i++) {
StringBuilder updateString = new StringBuilder(newar[i]);
int middleIndex = newar[i].length /2;
updateString.setCharAt(middleIndex, Character.toUpperCase(newar[i].charAt(middleIndex));
System.out.println(updateString);
}
you could use the charAt function of the String object and replace function
using the full String.length is not accurate when you will be accessing the middle index of the String since index are length - 1 (because it starts with 0) so you need to deduct 1 from the length and then divide it by half.
for(int i=0;i<newar.length;i++){
int index = (newar[i].length()-1)/2;
newar[i] = newar[i].replace(newar[i].charAt(index), Character.toUpperCase(newar[i].charAt(index)));
System.out.println(newar[i]);
}
output:
bOy
inDia
aPPle
Try this :
for (int i = 0; i < newar.length; i++) {
char[] c = newar[i].toCharArray();
for (int j = 0; j < c.length; j++) {
if (j == c.length / 2) {
c[j] = Character.toUpperCase(c[c.length / 2]);
//System.out.print(c[j]); <--- you keep getting O D P because you
print them here
}
// newar[i] += c[j]; <-- here you just concat changed elements to newar
System.out.print(c[j]); <--- print the value of array none middle and middle one
}
if (i != newar.length-1) { <-- avoid printing , for last item
System.out.print(",");
}
}
output:
bOy,inDia,apPle
My explanations are as comment inside the code.
Note: when you are in a for loop, you are checking whether you ecnounter the middle character. if you encountered, you will make it uppercase other wise nothing is changed, and each character is printed out on the console.
import java.util.ArrayList;
public class Test
{
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();
al.add("boy india apple");
String str[] = al.toArray(new String[al.size()]);
String newar[];
String delimiter = " ";
newar = str[0].split(delimiter);
for (int i = 0; i < newar.length; i++) {
char[] c = newar[i].toCharArray();
for (int j = 0; j < c.length; j++) {
if (j == c.length / 2) {
c[j] = Character.toUpperCase(c[c.length / 2]);
// System.out.println(c[j]);
// (1)
}
System.out.print(c[j]);
// (2)
newar[i] += c[j];
}
System.out.println();
// (3)
}
}
}
(1) - I got rid of this because it would only print out the uppercase letter. You had set the middle characters in all 3 words to uppercase, but, you need to print out the whole word, not just one letter.
(2) - You do, however, want to print out the whole word, which is what this line is doing. Instead of doing println, it only does print. Reason is because we are taking advantage of that for loop that is going through each character in the specific word to be able to print out each letter after we are done checking if it's the middle letter.
(3) - We have this line here because we want to be able to separate between words. I am not sure how you want these words separated so change this as you feel it's necessary, I just separated them so you could see.
There are a lot of things wrong with your code, so here is a simplified rewrite:
public static void main(String[] args) {
String s = "boy india apple";
String[] split = s.split( " " );
String[] toReturn = new String[split.length];
for (int i = 0; i < split.length;i++)
{
String word = split[i];
char[] chars = word.toCharArray();
chars[chars.length/2] = Character.toUpperCase( chars[chars.length/2] );
toReturn[i] = String.valueOf( chars );
}
System.out.println(Arrays.toString( toReturn ));
}
In order to correct your code you can start by removing the useless ArrayList and moving the System.out outside of the for loop. There are some other issues like you are appending the new result to the original so newar after this runs will look like {boybOy, indiainDia, appleapPle}.
EDIT:
For teaching purposes, here is your code modified so that it will work; however inefficient.
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();
al.add("boy india apple");
String str[] = al.toArray(new String[al.size()]);
String newar[];
String delimiter = " ";
newar = str[0].split(delimiter);
System.out.print("{");
for (int i = 0; i < newar.length; i++) {
char[] c = newar[i].toCharArray();
for (int j = 0; j < c.length; j++) {
if (j == c.length / 2) {
c[j] = Character.toUpperCase(c[c.length / 2]);
}
System.out.print(c[j]);
}
newar[i] = String.valueOf(c);
if (i < newar.length - 1)
System.out.print(",");
}
System.out.println("}");
}
String temp = ""; //define temp string as "" (don't assign null)
for (int j = 0; j < c.length; j++) {
...
//newar[i] += c[j]; //don't append to existing String in array
temp += c[j];
newar[i] = temp;
}
//after replacement is done
//now can print replaced string in array by looping
for (String string : newar) {
System.out.println(string);
}
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I am trying to check to see if, entered a string, that the string is a palindrome
if it is display something positive
if not... something negative (invalid)
I am currently getting the answer invalid both times (no matter what is entered)
i'm not quite sure if there is a problem with the for loops or the boolean statement.
//ACTION FROM BUTTON PERFORMED HERE
private void ButtonActionPerformed(ActionEvent evt) {
//creating variables
String myString = textField1.getText();
int stringLength = myString.length();
char arrayOne[] = new char[stringLength];
char arrayTwo[] = new char[stringLength];
boolean palindrome = false;
//for loop to setup ARRAY ONE
for(int i = 0; i < stringLength-1; i++){
arrayOne[i] = myString.charAt(i);
}
//for loop to setup ARRAY TWO
for(int i = stringLength-1; stringLength-1 > i; i--){
arrayTwo[i] = myString.charAt(i);
}
//for loop checking if array indexes are equivalent in value (char)
for(int i = 0; i < stringLength-1; i++){
if(arrayOne[i] != arrayTwo[i]){
palindrome = false;
}
else{
palindrome = true;
}
}
//assigning text to the text boxes based on boolean palindrome
if(palindrome == true){
textField2.setText("Valid");
}
if(palindrome ==false){
textField2.setText("Invalid");
}
}
}
i think i commented it descently
Change
for(int i = stringLength-1; stringLength-1 > i; i--)
to
for(int i = 0; i < stringLength-1; i++)
and change
for(int i = stringLength-1; i-1 > 0; i--)
to
for(int i = stringLength-1; i-1 >= 0; i--)
EDIT:
That was a debugging fest!!
Here is a working code:
String myString = textField1.getText();
int stringLength = myString.length();
char arrayOne[] = new char[stringLength];
char arrayTwo[] = new char[stringLength];
boolean palindrome = true;
//for loop to setup ARRAY ONE
for(int i = 0; i <= stringLength-1; i++){
arrayOne[i] = myString.charAt(i);
}
//for loop to setup ARRAY TWO
for(int i = stringLength-1, pos = 0; i >= 0; i--, pos++){
arrayTwo[pos] = myString.charAt(i);
}
//for loop checking if array indexes are equivalent in value (char)
for(int i = 0; i <= stringLength-1; i++){
if(arrayOne[i] != arrayTwo[i]){
palindrome = false;
break;
}
}
//assigning text to the text boxes based on boolean palindrome
if(palindrome == true){
textField2.setText("Valid");
}
else{
textField2.setText("Invalid");
}
I agree with the other answers about your error, but I think a more concise solution would be
boolean isPalindrome(String myString) {
int n = myString.length;
for( int i = 0; i < n/2; i++ )
if (myString.charAt(i) != myString.charAt(n-i-1)) return false;
return true;
}
Your code would now be
private void ButtonActionPerformed(ActionEvent evt) {
String myString = textField1.getText();
textField2.setText( isPalindrome(myString) ? "Valid" : "Invalid" );
}
//for loop to setup ARRAY TWO
for(int i = stringLength-1; stringLength-1 > i; i--){
arrayTwo[i] = myString.charAt(i);
}
This falls over after the first iteration.
You need to change it to something like:
//for loop to setup ARRAY TWO
for(int i = stringLength-1; i > 0; i--){
arrayTwo[i] = myString.charAt(i);
}
This loop copies all characters except the last one which probably is not what you wanted:
//for loop to setup ARRAY ONE
for(int i = 0; i < stringLength-1; i++){
arrayOne[i] = myString.charAt(i);
}
It should probably be fixed like this:
//for loop to setup ARRAY ONE
for(int i = 0; i < stringLength; i++)
{
arrayOne [i] = myString.charAt (i);
}
Body of this loop:
//for loop to setup ARRAY TWO
for (int i = stringLength-1; stringLength-1 > i; i--)
{
arrayTwo [i] = myString.charAt (i);
}
is never executed, because initial value of i: stringLength - 1 does not satisfy loop condition: stringLength - 1 > i.
You should probably change it to be:
// For loop to setup ARRAY TWO
for (int i = 0; i < stringLength; i++)
{
arrayTwo [i] = myString.charAt (stringLength - i - 1);
}
Also, after this loop:
// for loop checking if array indexes are equivalent in value (char)
for (int i = 0; i < stringLength-1; i++)
{
if (arrayOne [i] != arrayTwo [i])
{
palindrome = false;
}
else
{
palindrome = true;
}
}
variable palindrome will contain result of last comparison only, so if all characters except the last ones were different but last characters were equal, palindrome will be true which is probably not what you wanted. Probably you should change the code like this:
palindrome = true;
for (int i = 0; i < stringLength; i++)
{
if (arrayOne [i] != arrayTwo [i])
{
palindrome = false;
}
}
Note that I also changed stringLength - 1 to stringLength, otherwise you were ignoring last characters.
The easiest way to test for a palindrome in java
String str = "Able was I ere I saw Elba"
boolean palindrome = str.equalsIgnoreCase(new StringBuilder(str).reverse().toString());
Yep, that's it.
public static void main(String[] args) {
String s = "akaq";
boolean b = false;
for (int i = 0, j = s.length() - 1; i < j; i++, j--) {
if (s.charAt(i) == s.charAt(j)) {
b = true;
continue;
} else {
b = false;
break;
}
}
if (b)
System.out.println("Palindrome");
else
System.out.println("Not Palindrome");
}
Try something like this instead of 2-3 for loops.
Change the first for loop from stringLength-1 to just stringLength because you are using < and not <=
Change the second for loop to
if(int i = stringLength-1; i>=0; i--)
Also, set palindrome to true by default and remove the
else{
palindrome = true;
}
part because now if the first and last characters of the loop are the same, but not the middle, it will return true.
EDIT: Also the third for loop should be stringLength and not stringLength-1 because you are using < and not <=
There's no need to copy everything into arrays. String is basically an array itself. You can access the individual characters with charAt().
Also there is no need to loop the entire length of the String since equality is associative.
So simply use :
public boolean isPalindrome(String s) {
for (int i = 0; i < s.length() / 2; i++) { // only until halfway
if (s.charAt(i) != s.charAt(s.length() - i - 1)) { // accessing characters of String directly
return false;
}
}
return true;
}
One last remark : if the String's length is odd, you don't need to check the middle chracter. So in the code above the diision by