What is the easiest way to compare two string except one character? - java

I'm new to java.
Can anybody tell me that is the easiest way to compare two string except one character?
like:
'test' 'text' //only one character different
should return true
==============================
like input:
'test' 'txxt' //two character different return false
should return false
I know we can compare with a for loop. Is there any other way to do that?
Thx for your help. : )

Assuming the Strings are the same size, here is a solution. This solution will need to be altered slightly for uneven String lengths
boolean compareStrings(String str1, String str2) {
if (str1.length() != str2.length())
return false;
int differences = 0;
for (int i = 0; i < str1.length(); i++) {
if(str1.charAt(i) != str2.charAt(i))
if(++differences > 1)
return false;
}
//if the execution is here, then there are 0, or 1 differences, so return true
return true;
}

Try this method.
It should work for every string combination but, depending on usage, maybe a performance tuning is needed.
public static boolean compare(String s1, String s2) {
if((s1 != null && s2==null) || (s1 == null && s2!=null)){
//exact one is null
return false;
}
if((s1 == null && s2==null) || s1.equals(s2)){
//both are null or equal
return true;
}
if(Math.abs(s1.length() - s2.length()) > 1){
//A different length of more than one is more than one difference, right ?
return false;
}
//Here you have two different strings. Maybe one is a character larger than the other.
if(s1.length() != s2.length()) {
//They differ in length, so they must be equal in the first minLen charcaters.
int minLen = Math.min(s1.length(), s2.length());
return s1.substring(0,minLen).equals(s2.substring(0,minLen));
}
//Here you have two different strings of the same length.
int diff = 0;
for(int i = 0; i < s1.length() && diff < 2; i++){
if(s1.charAt(i) != s2.charAt(i)){
diff++;
}
}
return diff < 2;
}

Related

conditional changes behavior when converted to ternary operator?

I am writing a function that compares the number of vowels in the first half of a string and compares it with the second half, and returns a boolean based on if the number is equal.
Example:
Input: "book"
Output: true
because bo | ok, numVowels = 1, one 'o' in both halves.
My code that works is here
class Solution {
public boolean halvesAreAlike(String s) {
Set<Character> set = new HashSet<>(Arrays.asList('a','e','i','o','u','A','E','I','O','U'));
int vowelCount = 0, length = (s.length()%2 == 0) ? s.length()/2 : s.length()/2+1;
boolean pastHalf = false;
for (int i = 0; i < s.length(); i++) {
if (i == length) pastHalf = true;
if (pastHalf && set.contains(s.charAt(i))) vowelCount--;
else if (!pastHalf && set.contains(s.charAt(i))) vowelCount++;
}
return vowelCount == 0;
}
}
In the if (i == length) pastHalf = true; line, I am checking to see if I have hit the middle of the String. This is a simple boolean. I changed it to this ternary pastHalf = (i == length) ? true : false; and the output was wrong for the test case Ieai. Does anyone know why? I believe that the statements are equivalent.
if (i == length) pastHalf = true;
is most definitely NOT the same as
pastHalf = (i == length) ? true : false
In the first case, pastHalf is changed only when i is exactly equal to length, so as you iterate beyond length, pastHalf remains true.
In the second, at each iteration pastHalf is reset, so pastHalf is true only when i is exactly equal to length.
Other improvements:
length = (s.length()+1) % 2; // Think about this one carefully
and
if (set.contains(s.charAt(i)))
vowelCount += pastHalf ? -1 : +1;

Searching Algorithm (better than linear)

I have to write a method which returns true if three 3s are present in an integer array(provided they are not consecutive).
I have written this code here: However, it is returning true (which it should not do). Can someone point out my mistake?
arr[]={{4,3,5,2,3,3};
Also, this is a linear algorithm. Can it be done better?
public static boolean consecutiveThree(int[] arr) {
int x=0;
for(int i=0;i<arr.length-1;i++) {
if((arr[i]!=3 && arr[i+1]==3) || (arr[i]==3 && arr[i+1]!=3)) {
x++;
//continue;
}
if(x==3)
return true;
}
return false;
}
You said:
returns true if three 3s are present in an integer array(provided they are not consecutive)
I interpret that as having at least three 3s, and no two 3s are adjacent.
public static boolean hasThreeNonconsecutiveThrees(int... values) {
int count = 0, streak = 0;
for (int value : values) {
if (value != 3)
streak = 0;
else if (++streak == 2)
return false; // Found two consecutive (adjacent) 3s
else
count++;
}
return (count >= 3);
}
Test
System.out.println(hasThreeNonconsecutiveThrees(4,3,5,2,3,3)); // false
System.out.println(hasThreeNonconsecutiveThrees(4,3,5,3,2,3)); // true
System.out.println(hasThreeNonconsecutiveThrees(1,2,3,4,3)); // false
System.out.println(hasThreeNonconsecutiveThrees(4,3,5,3,3,3)); // false
Output
false
true
false
false
At worst case the correct array will end with ... 3 3 X 3. Unless the array is somewhat sorted or somewhat special you will have to look at every single element to reach the last three 3s. If the array is random, you need linear complexity since you have to review every single element in the array.
Your algorithm is not checking the whether arr[i-1] is '3'. That is your algorithm's mistake.
Try this:-
public static boolean consecutiveThree(int[] arr) {
int x = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 3) {
if (i == 0) { // zero 'th element do not have arr[i-1].
if(arr[i + 1] != 3) {
x++;
}
} else if (i == arr.length - 1) { // last element do not have arr[i+1].
if((arr[i - 1] != 3)) {
x++;
}
} else if ((arr[i + 1] != 3) && (arr[i - 1] != 3)) {
x++;
}
}
if (x == 3) // may be x >= 3
return true;
}
return false;
}

My code does not correctly compare strings of different length

I am supposed to write a compare method that essentially does what the compareTo method does. I have written the code but it does not compare strings of different length.
This is my code:
public static int compare(String a, String b)
{
int result = 0;
a = a.toLowerCase();
b = b.toLowerCase();
//program assumes strings are equal
for (int i = 0; i<a.length() && i<a.length(); i++) {
int c = a.charAt(i);
int d = b.charAt(i);
if (c < d){
result = -1;
break;
}
if (a.length() > b.length()) {
result = -1;
break;
}
if (a.length() < b.length()) {
result = +1;
break;
}
if (c > d) {
result = 1;
break;
}
}
return result;
}
I have done an if loop comparing 2 strings of different lengths but, yet, the program ignores that.
Im trying to understand my mistake so please don't just give me the answer without explaining for I will not learn anything.
Thanks, in advance.
First, you want to make sure, when comparing character by character, that i is less than both a's length and b's length. Right now, you're comparing i to a's length twice.
Try:
// *
for (int i = 0; i<a.length() && i<b.length(); i++){
Second, you only want to compare lengths if you have compared each character equal until one of them has ended. Place the length comparisons after the for loop.
Third, "mars" comes before "marshall", so if a's length is less than b's length, then it compares less also.
// After the for loop ends:
if(a.length() > b.length()){
result = 1;
break; }
if(a.length() < b.length()){
result = -1;
break;

java ID check method

Im trying to write a method that takes in an ID of the form "xxxx-xxxx" (x being any number 1-9) and checks to see if the ID entered is valid. For example, 1111-1111 would be valid, but 111p-1111 or 11111-1111 would not be. However, after I have written this method, it comes out as true even when the ID is of the form 111p-1111.
public static boolean idCheck(String ID){
char[] idChar = ID.toCharArray();
boolean firstHalf = false;
boolean secHalf = false;
for (int i = 0; i < 5; ++i){//Check first half
if ((idChar[i] > 47 && idChar[i] < 58)){//Checks ascii vals to see if valid ID
firstHalf = true;
}
}
for (int i = 5; i < idChar.length; ++i){//Check second half
if ((idChar[i] > 47 && idChar[i] < 58)){//Checks ascii vals to see if valid ID
secHalf = true;
}
}
//If all values are valid, returns true.
if (firstHalf == true && secHalf == true && idChar[4] == '-' && ID.length() == 9){
return true;
}
return false;
}
Using a regular expression would be much simpler in this case:
\d{4}-\d{4}
In Java:
static boolean idCheck(String id) {
return id.matches("\\d{4}-\\d{4}");
}
If you're unfamiliar with regular expressions, here's an explanation:
\d Match a digit 0-9
{4} Repeat last token 4 times (matches 4 digits)
- Match a hyphen literally
\d Match a digit 0-9
{4} Repeat last token 4 times (matches 4 digits)
Your if statements only look at one number to determine if it sets the boolean to true. So if any of the numbers in each half are valid, the boolean will be set to true.
You are probably better off using regular expressions. regexr.com is a great resource to get started! :)
Something like:
[1-9]{4}-[1-9]{4} (You can also use \d)
You only check if there is at least one character that matches, not if any of the input characters are failing.
To have a quick solution that is easy to understand for any Java developer after you you could use a Regex and check if your input matches:
public static boolean idCheck(String id){
return Pattern.matches("\\d{4}-\\d{4}", id);
}
If you want to keep your way of checking you should start with true booleans and check if they stay true.
boolean firstHalf = true;
boolean secHalf = true;
and therefrom use firstHalf &= true for your updates and use a else{ firstHalf = false; } branch.
To keep your method I would prefer to always back out fast if you know the result:
public static boolean idCheck(String id)
{
//check length
if (id.length() != 9)
return false;
char[] idChar = id.toCharArray();
//check for dash
if (idChar[4] != '-')
return false;
//check first half
for (int i = 0; i < 5; ++i)
{
if (!(idChar[i] > 47 && idChar[i] < 58))
return false;
}
//check second half
for (int i = 5; i <= 10; ++i)
{
if (!(idChar[i] > 47 && idChar[i] < 58))
return false;
}
}

count uppercase chars in string recursively

I have to solve an exercise, counting all the uppercase chars in a String - recursively - Anyhow I thought I might have found a solution - but it won't work…
Probably you might help me? Thanks!
public static int CountCapitals(String s) {
int counter = 0;
// if (Character.isUpperCase(s.charAt(0)))counter+=1;
if (s.length() == 0)
return counter;
if (s.length() == 1 && s.charAt(0) < 65 && s.charAt(0) > 90)
return 0;
if (s.charAt(0) < 'A' && s.charAt(0) > 'Z') {
return CountCapitals(s.substring(1));
}
if (s.charAt(0) >= 'A' && s.charAt(0) <= 'Z')
counter++;
return CountCapitals(s.substring(1));
}
The problem with your code is the use of counter: each level of invocation has its own counter, initially set to zero. The ++ operator at the bottom has no effect.
You need to compute the result of this invocation based on the result of the previous invocation. Your base case (i.e. s.length() == 0) is fine; the rest of your code needs to change so that it returns whatever CountCapitals(s.substring(1)) when the first letter is non-capital; when the first letter is capital, your function should return 1 + CountCapitals(s.substring(1)).
You need to consider the case when the length of string is 1 and the only character is uppercase (in this case, you should return 1).
Also you need to pass in the counter as a parameter rather than expecting it to "carry over" into other function calls.
This recursion should do just what you want:
public static int countCapitals(String s) {
if (s.length() == 0) return 0;
int cap = Character.isUpperCase(s.charAt(0)) ? 1 : 0;
return countCapitals(s.substring(1)) + cap;
}
If this wasn't a home assignment, you could try an iterative approach which is about 5-10 times faster:
public static int countCapitals(String s) {
int count = 0;
for (int idx = 0; idx < s.length(); idx++) {
if (Character.isUpperCase(s.charAt(idx))) {
count++;
}
}
return count;
}
You don't really need to use a counter variable to keep track of the number of capitals. Instead, you can just the recursive calls, themselves, to keep track of the total:
public static int CountCapitals(String s)
{
if (s.length() == 1)
return (Character.isUpperCase(s.charAt(0)) ? 1 : 0);
else
return CountCapitals(s.substring(1)) +
(Character.isUpperCase(s.charAt(0)) ? 1 : 0);
}
If this is for an assignment and you have to use ASCII values, then fine, but if not, you really should just Character.isUpperCase(char c). In case you're not familiar with the conditional operator, it's defined as follows:
if(someExpression == true)
{
//output 1
}
else
{
//output 0
}
is represented succinctly as:
(someExpression == true) ? 1 : 0
NB:
In your example, counter is set to 0 at the beginning of each method call, so that's why it's not working. If you really want to use a counter, pass it as a parameter to the method instead, and update the parameter with each method call. When you get to the end of the String, simply return the parameter.
You try this
public class HelloWorld{
public static int isUpperCase(String str){
if(str.length()==0) return 0;
boolean check =Character.isUpperCase(str.charAt(0));
if(check){
return isUpperCase(str.substring(1))+1;
}
return isUpperCase(str.substring(1));
}
public static void main(String []args){
String n= "FSAsdsadASdcCa";
System.out.println(isUpperCase("FSAsdsadASdcCa"));
}
}

Categories

Resources