I'm writing a program where you can enter a words which will get stored in an ArrayList. You can then search for these words, by entering them in a textField and pressing a button. (You can also sort them, if pressing another button). If the word is found the place in the ArrayList of the word should be printed out and if it's not found that should be printed out. I thought this worked until just recently when I tested it (it have worked before): I entered a word I knew was in the ArrayList which made it print out the position of the word in the ArrayList (which is what I want it to do). I then entered a word which I knew didn't exist in the ArrayList which made it print out that the word doesn't exist (which is also what I want it to do). But when I after that searched for a word I knew existed in the ArrayList, it printed out that the word couldn't be found. I then tried this with another word I knew existed in the ArrayList, but I couldn't find that either. I have after this restarted the program several times and sometimes it works and sometimes it doesn't and I have no idea why or why not...
The array gets sorted before I run the algorithm so I know that's not the problem...
Down below is the class with my search algorithm:
public class SearchAlg {
public static String binary (ArrayList<String> list, String user) {
int first = 0;
int found = 0;
int middle = 0;
int last = list.size();
String strFound = "";
while (first < last && found == 0) {
middle = ((first + last) / 2);
if (user.compareTo(list.get(middle)) > 0) {
first = middle + 1;
} else if (user.compareTo(list.get(middle)) == 0) {
found = 1;
} else if (user.compareTo(list.get(middle)) < 0) {
last = middle - 1;
}
}
if (found == 1) {
strFound = "The word " + user + " exists on the place " + middle + " in the Arraylist";
} else {
strFound = "The word " + user + " does not exist in the Arraylist";
}
return strFound;
}
}
Here is my sorting algorithm:
public class Sort {
static private String strTemp;
static private int i;
static private int n;
public static ArrayList bubbelSort (ArrayList<String> list) {
for (i = 0; i < list.size(); i++) {
for (n = 0; n < list.size() - i - 1; n++) {
if (list.get(n).compareTo(list.get(n + 1)) > 0) {
strTemp = list.get(n);
list.set(n, list.get(n + 1));
list.set(n + 1, strTemp);
}
}
}
return list;
}
And this is my Main class:
ArrayList<String> list = new ArrayList();
private void btnEnterActionPerformed(java.awt.event.ActionEvent evt) {
txtaOutput.setText("");
String wrd = txtfEnter.getText();
list.add(wrd);
for (int i = 0; i < list.size(); i++) {
txtaOutput.append(list.get(i) + "\n");
}
}
private void btnSortActionPerformed(java.awt.event.ActionEvent evt) {
txtaOutput.setText("");
Sort.bubbelSort(list);
}
private void btnSearchActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
String user = txtfSearch.getText();
txtaOutput.setText("");
String bin = SearchAlg.binary(list, user);
txtaOutput.append(bin);
}
I have no idea what's causing this, so any help is appreciated!
EDIT: I now know that the problem is that the first item in the ArrayList ins't searchable. So if the ArrayList consists of a, b, c for example, then only b and c are searchable. If I try and search for a, it says that it can't be found.
int first= 0;
int last= a.length - 1;
while (first<= last) {
int middle = first+ (last- first) / 2;
if (user.compareTo(list.get(middle)) < 0) last = middle - 1;
else if (user.compareTo(list.get(middle)) > 0) first= middle + 1;
else {
found =1 ;
break;
}
}
and don't forget to sort your list as mentioned in the previous post
The problem is in the very last step of your search. There is a chance you update the 'first' and 'last', and in the next iteration you would find the value, but instead you break from the loop.
Solution: remove the variable found entirely, and also these two lines:
} else if (user.compareTo(list.get(middle)) == 0) {
found = 1;
and where you now write...
if (found == 1) {
...instead do...
if (user.compareTo(list.get(first)) == 0) {
You're off by one.
You initialize the method with last = list.size(), implying that you're searching the half open interval [first, last> (from and including first, to but excluding last).
However, in your loop, you set last = middle - 1, which would work if your search range was the closed interval [first, last] (from and including first, to and including last).
You should make up your mind as to whether last should point on the last element, or after the last element. Here's your loop if you go with the latter:
while (first < last && found == 0) {
middle = ((first + last) / 2);
if (user.compareTo(list.get(middle)) > 0) {
first = middle + 1;
} else if (user.compareTo(list.get(middle)) == 0) {
found = 1;
} else if (user.compareTo(list.get(middle)) < 0) {
last = middle; // <-- Remove -1
}
}
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am solving a problem on leetcode.Here is the question link
https://leetcode.com/problems/longest-substring-without-repeating-characters/
Below is my solution which is not passing some test-cases:
abcabcbb -- not correct
pwwkew -- correct
bbbbb -- not correct
Any help would be thankful:)
And also I am a newbie here so you can suggest me about my problem statement.
class Solution {
public int lengthOfLongestSubstring(String s) {
int i,max=0;
List<Character> list = new ArrayList<>();
String x = "";
for(i=0;i<s.length();i++)
{
if(!list.contains(s.charAt(i)))
{
x += s.charAt(i);
list.add(s.charAt(i));
System.out.println(x);
}
else
{
if(x != null && x.length() > max)
{
max = x.length();
System.out.println(max);
x = "";
list.clear();
System.out.println("x : "+ x);
System.out.println("list : "+ list);
}
// else
// {
// list.add(s.charAt(i));
// x += s.charAt(i);
// System.out.println("x in else : "+ x);
// System.out.println("list in else : "+ list);
// }
list.add(s.charAt(i));
x += s.charAt(i);
System.out.println("x in else : "+ x);
System.out.println("list in else : "+ list);
}
}
return max;
}
}
Sometimes it's helpful to remain in the problem domain as much as possible. This approach creates a solution before any thought of coding. This approach leaves us with a set of minimally complex logical operations which then require implementation.
First our initial condition. Columns should be clear: Input (always same), Current (the current substring without repeating characters), Answer (the current answer in String form) and Logic (what logic is applied for this step:
So first iteration starts the same as rest : get next character in Input. Check if it is in the Current substring and since it is not add to Current. Here we also ask the question: Is Answer shorter than Current and if so set Answer to Current.
Note in the Logic column we are developing operations which we'll need to implement in the solution.
Repeat for second character input (no new operations):
And again for third - (no new operations):
Ok now we find next CH in the current substring so we need a new operation: 'Remove chars in current up to but not including CH. Note that "add CH to current" is done in this case as well. Note also some new logic (answer was as long or longer than current so "Do Nothing").
And finish things out - no new operations.
So now we reach the end of input and simply ask the question "How long is the Answer" and that is the result.
So now looking at the Logic column we see operations to perform:
// Initial condition
String answer = "";
String current = "";
Let's work completely in Strings to keep things simple - optimization can come later..
Let's define the "next CH (nextChar)" operation:
// Get the ith character (0-based) from 's' as a String.
private static String nextChar(String s, int i) {}
We'll need an operation which "checks if 'Current contains CH'":
// Does the 'current' String contain the 'nextChar' String?
private static boolean currentContainsCh(String current, String nextChar) {}
We'll need to check if current Answer is shorter than Current:
// True if the 'answer' String is short in length than the 'current' string.
private static boolean isAnswerShorterThanCurrent(String current, String answer) {}
And the ability to append the nextChar to Current:
// Append the 'nextChar' to the 'current' String and return the String.
private static String addChToCurrent(String current, String nextChar) {}
And finally the ability to remove all characters up to but not including current char in Current:
// #return a String which has all characters removed from 'current' up to but not including 'ch'
private static String removeUpToChar(String current, String ch) {}
So putting it all together (essentially still in the problem domain since we haven't implemented any operations but just projected the problem into structure):
public int lengthOfLongestSubstring(String s) {
String answer = "";
String current = "";
for (int i = 0; i < s.length(); i++) {
String nextChar = nextChar(s,i);
if (currentContainsCh(current, nextChar)) {
current = removeUpToChar(current, nextChar);
}
current = addChToCurrent(current,nextChar);
if (isAnswerShorterThanCurrent(current,answer)) {
answer = new String(current);
}
}
return answer.length();
}
And now implementing the "operations" becomes easier (and fun) since they are isolated and not complex. This is left for you. When implemented it passes the problem.
The next logical step after verifying correctness is to consider optimizations - if needed.
Although the pictures in answer by Andy are useful and mostly correct, the code is sub-optimal.
The code in the question, as well as in both current answers, builds a lot of substrings, using string concatenation. That is detrimental to performance.
Here is an O(n) solution that doesn't build any substrings:
public static int lengthOfLongestSubstring(String s) {
Map<Character, Integer> lastPos = new HashMap<>();
int start = 0, maxLen = 0, i = 0;
for (; i < s.length(); i++) {
Integer pos = lastPos.put(s.charAt(i), i);
if (pos != null && pos >= start) {
if (i > start + maxLen)
maxLen = i - start;
start = pos + 1;
}
}
return (i > start + maxLen ? i - start : maxLen);
}
This works by remembering the last position of each character, so the potential longest substring's starting position can be adjusted to start right after the previous position of a repeating character.
Since HashMap.put(...) is O(1) (amortized), the solution is O(n).
Since it would be nice to see the substring, we can easily modify the code to return the (first1) longest substring:
public static String longestSubstring(String s) {
Map<Character, Integer> lastPos = new HashMap<>();
int start = 0, maxStart = 0, maxLen = 0, i = 0;
for (; i < s.length(); i++) {
Integer pos = lastPos.put(s.charAt(i), i);
if (pos != null && pos >= start) {
if (i > start + maxLen) {
maxStart = start;
maxLen = i - start;
}
start = pos + 1;
}
}
return (i > start + maxLen ? s.substring(start) : s.substring(maxStart, maxStart + maxLen));
}
1) To return the last of multiple longest substrings, change both i > to i >=
The above solutions cannot handle strings with Unicode characters from the supplemental planes, e.g. emoji characters.
Emoji's such as 😀 and 😁 are stored as "\uD83D\uDE00" and "\uD83D\uDE01", so the char value '\uD83D' will be seen as a repeating character.
To make it correctly handle all Unicode characters, we need to change it to:
public static String longestSubstring(String s) {
Map<Integer, Integer> lastPos = new HashMap<>();
int start = 0, maxStart = 0, maxLen = 0, i = 0;
for (int cp; i < s.length(); i += Character.charCount(cp)) {
cp = s.codePointAt(i);
Integer pos = lastPos.put(cp, i);
if (pos != null && pos >= start) {
if (i > start + maxLen) {
maxStart = start;
maxLen = i - start;
}
start = pos + Character.charCount(cp);
}
}
return (i > start + maxLen ? s.substring(start) : s.substring(maxStart, maxStart + maxLen));
}
Test
for (String s : new String[] { "abcabcbb", "pwwkew", "bbbbb", "aab", "abba", "xabycdxefghy", "aXbXcdXefgXh", "😀😁😂😀😁😂" }) {
String substr = longestSubstring(s);
System.out.printf("%s: %s (%d)%n", s, substr, substr.length());
}
Output
abcabcbb: abc (3)
pwwkew: wke (3)
bbbbb: b (1)
aab: ab (2)
abba: ab (2)
xabycdxefghy: abycdxefgh (10)
aXbXcdXefgXh: cdXefg (6)
😀😁😂😀😁😂: 😀😁😂 (6)
I want to append certain string in the last item of the foreach array.
The program works perfectly fine. Given the items in the "pending" array, it should append the out value in the last item in the pending value:
String a = out + "-" + rptdate + "-";
for (String pn : pending) {
//checks if total value + pending length value is less than 160
if (a.length() + pn.length() < 160) { // < to leave room for the comma as well
if (a.length() != 0) {
if (a.length() != 14) {
a += ",";
}
}
a += pn;
} else {
resultingStrings.add(a);
a = pn;
Log.d("messages", a);
}
}
resultingStrings.add(a);
for (String r : resultingStrings) {
sendSMS(r);
}
Try simple code
int size = pending.size();
int index = 0;
for (String pn : pending) {
if(index == size - 1){
// it is last foreach => add your last string here
}
index++;
...
}
Hope this help
You could also do,
for(int i = 0; i < array.length; i++) {
if(i = (array.length - 1)) {
//this is the last element in the array
}
}
If all you need to do is grab the last element of a Collection and append some text to it then this should work.
String out = "Some value";
int lastIndex = pending.getSize() -1; // < 0 indexed
String lastItem = pending.get(lastIndex)
String newLastItem = lastItem + out; // < String concatenation
but from your snippet I don't think that's what your after because if we remove some of the magic numbers and correct the indentation, and make some assumptions about what your trying to do your left with
String a = out + "-" + rptdate + "-";
int prefixLength = a.length();
for (String pn : pending) {
//checks if total value + pending length value is less than 160
if (a.length() + pn.length() < MAX_LENGTH) { // < to leave room for the comma as well
if (a.length() > prefixLength) {
a += ",";
}
a += pn;
} else {
// have string longer than max length, so save and start a new sms.
resultingStrings.add(a);
Log.d("messages", a); // < log a before you overwrite it.
a = pn;
}
}
// DO YOU WANT TO APPEND out AS A SUFFIX TO a HERE ???
// a += out;
// but if so youll want to consider the case if a is now > MAX_LENGTH
resultingStrings.add(a); // add the last string
// send all composed strings
for (String r : resultingStrings) {
sendSMS(r);
}
I am picking your relatively new to coding so I'd suggest first you start off with some pseudo-code of what your trying to do, it can then become comments in your code. Always keep your code formatted nicely so that indents are matched, and use descriptive names for your variables, and constants.
I am practicing object orientation here entering in basketball player names and how many points scored and rebounds grabbed.
How would I go through each element in an array of objects to find the last player with an even amount of points?
This is the code I have so far to enter the information. What do I need to do in my second forloop to examine each element and then display the last element that fits my criteria?
class basketballObj
{
public static void main (String[]args)
{
Basketball bbArray[];
String theName;
int thePoints;
int theRebounds;
int index;
int noOfElements = 0;
bbArray = new Basketball[3];
for(index = 0; index < bbArray.length; index++)
{
System.out.println("Enter a name ");
theName = EasyIn.getString();
System.out.println("Enter points scored ");
thePoints = EasyIn.getInt();
System.out.println("Enter rebounds grabbed ");
theRebounds = EasyIn.getInt();
bbArray[index] = new Basketball(theName, thePoints, theRebounds);
noOfElements++;
}
for(index = 0; index < bbArray.length; index++)
{
if(bbArray[index].getPoints() % 2 == 0)
{
}
}
}
}
Well if you want to find the last player with an even amount of points, you don't actually want to go through each element ;-). Try:
for(index = bbArray.length-1; index >= 0; index--)
{
if(bbArray[index].getPoints() % 2 == 0)
{
//add whatever relevant code here.
break; //this line breaks the for loop (because you've found a player with an even amount of score
}
}
we start at bbArray.length-1 because while you array contains 3 elements, arrays are zero-indexed. Meaning that to get the first element, you will have to call bbArray[0]. Similarly call bbArray[2] for the last element.
Simple. Iterated your array backwards.
boolean found = false;
for(int index=array.length-1; index>-1 && !found; index--) {
if(array[index].getPoints()%2 == 0) {
// found element. Break out of for loop
found=true;
}
}
You've pretty much got it.
Create a temporary, uninitialized variable Basketball temp; before the for loop that iterates through the bbArray and then set it equal to the bbArray[index] if the if condition is met.
If you want to save the index it was found at then create an int indexFound; as well.
Looping through it backwards as user2651804 suggested yields this:
public class basketballObj
{
public static void main(String[] args)
{
...
Basketball temp;
int indexFound = -1;
...
for(index = bbArray.length - 1; index >= 0; index++)
{
if(bbArray[index].getPoints() % 2 == 0)
{
temp = bbArray[index];
indexFound = index;
break;
}
}
//note temp will be null if no scores were even
//if (temp != null)
//you can use the above if statement if you don't want to use indexFound
//you can also just check if indexFound == -1
if (indexFound != -1)
{
System.out.println("Found at index: " + indexFound);
//
}
}
}
Sorry if this all seems hard to understand but I am new to programming and I have looked in several books and websites and from my understanding what I am trying to do should work. The assignment I am working on is classes calling classes. Without putting all my code in here I will try to be as specific as possible in unclear areas. The null pointer exception is for this particular line of code:
if(CDList[i].getArtist().equals(artist) == true)
//CDList is an array of CD objects (which are created in another class)
//getArtist() is a method of the CD class which returns a String
//the artist in the equals() is the Scanner object the user has inputed, also a String
The point of this particular method is to search through the array CDList and compare the artist String stored to the artist String scanned in and then the same for the title. If found then the contents of that portion of the array will be deleted. Here is the rest of the method if it will help:
void delete()
{
Scanner input = new Scanner(System.in);
System.out.println("Enter artist and title to be deleted: ");
String artist = input.nextLine();
String title = input.nextLine();
for(int i = 0; i <= numOfCDs; i++)
{
if(CDList[i].getArtist().equals(artist) == true)
{
for(int j = 0; j <= numOfCDs; j++)
{
if(CDList[j].getTitle().equals(title) == true)
{
System.out.println("Found CD: " + CDList[j].getArtist() + " " +
CDList[j].getTitle());
System.out.println("Would you like to delete it? Y/1 N/0 ");
if(input.nextInt() == 1)
{
CDList[j] = null;
numOfCDs--;
}
}
else
System.out.println("CD not found.");
}
}
else
System.out.println("CD not found.");
}
}
Sorry, here is the rest of the code. Just thought it was so much I'd leave it out.
CD Class:
package assignment3;
public class CD
{
public String artist;
public String title;
private tracklist listOfTracks = new tracklist();
CD(String artistName, String titleName)
{
artist = artistName;
title = titleName;
}
public String getArtist()
{
return artist;
}
public String getTitle()
{
return title;
}
public boolean addTrack(String trackInfo)
{
boolean result = false;
if(listOfTracks.add(trackInfo) == true)
result = true;
return result;
}
public int numTracks()
{
int count = listOfTracks.count();
return count;
}
public void display()
{
System.out.println(" ");
System.out.println(getArtist() + " : " + getTitle());
listOfTracks.display(7);
}
}
trackList Class:
package assignment3;
public class tracklist
{
public String[] tracks;
public int numElements;
tracklist()
{
tracks = new String[99];
numElements = 0;
}
public boolean add(String track)
{
boolean result = true;
int index = 0;
while(tracks[index] != null)
{
index++;
}
tracks[index] = track;
numElements++;
if(numElements > 99)
result = false;
return result;
}
public int count()
{
return numElements;
}
public void display(int indent)
{
for(int i = 1; i < numElements; i++)
{
System.out.print(i);
if(i >= 10)
{
for(int j = 0; j < (indent - 1); j++)
{
System.out.print(" ");
}
}
else
{
for(int j = 0; j < indent; j++)
{
System.out.print(" ");
}
}
System.out.println(tracks[i]);
}
}
}
CDList Class:
package assignment3;
import java.util.Scanner;
public class CDList
{
public int numOfCDs;
private CD[] CDList;
private int front,rear;
CDList(int size)
{
CDList = new CD[size];
numOfCDs = 0;
front = 0;
rear = size - 1;
}
boolean add()
{
boolean result;
Scanner input = new Scanner(System.in);
System.out.println("Enter the Artist Name and CD Title: ");
CD userCD = new CD(input.nextLine(), input.nextLine());
System.out.println("Enter the number of tracks: ");
int trackNumber = input.nextInt();
System.out.println("Enter your track titles: ");
for(int i = 0; i <= trackNumber; i++)
{
userCD.addTrack(input.nextLine());
}
if(rear == front)
result = false;
else
{
if(CDList[rear] != null)
rear--;
else
CDList[rear] = userCD;
result = true;
}
return result;
}
void delete()
{
Scanner input = new Scanner(System.in);
System.out.println("Enter artist and title to be deleted: ");
String artist = input.nextLine();
String title = input.nextLine();
for(int i = 0; i <= CDList.length - 1; i++)
{
if((CDList[i].getArtist().equals(artist)) &&
(CDList[i].getTitle().equals(title)))
{
System.out.println("Found CD of: " + CDList[i].getArtist() + " " +
CDList[i].getTitle());
System.out.println("Would you like to delete it? Y/1 N/0 ");
if(input.nextInt() == 1)
{
CDList[i] = null;
numOfCDs--;
}
}
else
System.out.println("CD not found.");
}
}
void SortArtist()
{
CD temp = new CD(" ", " ");
for(int i = 0; i < numOfCDs; i++)
if(CDList[i].getArtist().compareTo(CDList[i + 1].getArtist()) < 0)
{
temp = CDList[i];
CDList[i] = CDList[i + 1];
CDList[i + 1] = temp;
}
}
void SortTitle()
{
CD temp = new CD(" ", " ");
for(int i = numOfCDs; i > 0; i--)
{
int x = 0;
for(int j = 1; j <= i; j++)
{
if(CDList[i].getTitle().compareTo(CDList[i + 1].getTitle()) < 0)
x = j;
}
temp = CDList[x];
CDList[x] = CDList[i];
CDList[i] = temp;
}
}
void Display()
{
for(int i = 0; i <= numOfCDs; i++)
{
while(CDList[i] == null)
i++;
CDList[i].display();
}
}
int size()
{
return numOfCDs;
}
}
if(CDList[i].getArtist().equals(artist) == true)
If you are getting NPE, here are the possibilities:
CDList is null
CDList[i] is null
CDLIst[i].getArtist() returns null
Class Artist overrides equals() and has a bug that results in NPE, but in that case the NPE would point to a statement in equals().
You haven't shown the class Artist so we can see if it overrides equals(), and haven't posted the stack trace so we can see exactly where the exception is thrown.
As others have commented, the == true is superfluous.
I would recommend using a LinkedList<CD> or ArrayList<CD> instead of CD[].
This will allow you to easily remove items, like so:
LinkedList<CD> cdList = new LinkedList<CD>();
// add items with cdList.add(...);
Iterator<CD> cdListIterator = cdList.iterator();
// Loop while the list still contains elements.
while (cdListIterator.hasNext()) {
CD thisCd = iterator.next();
// do some operation on the cd to tell whether you want to delete it
// for example:
if (thisCd.getArtist().equals(artist) && thisCd.getTitle().equals(title)) {
iterator.remove(); // it's that simple
// Don't have to mess with `cdCount--` or anything.
}
}
And, as some have commented, you don't need a.equals(b) == true; you can just use a.equals(b).
there's nothing wrong with if condition. Its your loop that has the problem.
Use a single for loop:
for(int i = 0; i <= numOfCDs; i++)
{
if(CDList[i].getArtist().equals(artist) && CDList[i].getTitle().equals(title))
{
System.out.println("Found CD: " + CDList[j].getArtist() + " " + CDList[j].getTitle());
System.out.println("Would you like to delete it? Y/1 N/0 ");
if(input.nextInt() == 1)
{
CDList[i] = null;
// do not do numOfCDs-- here
}
}
}
There are a number of problems here.
The immediate cause of your NPE is that the inner loop "removes" a CD from the list by assigning it to null, and then the outer loop tries to test the CD at the position you just removed. Since it is null, you then attempt to call null.getArtist() which NPEs.
The first thing to note is that you only need one loop. The loop body should test that the CD you are looking at has the same title AND artist ...
The next thing to note is that getting rid of the extra loop is not enough. If the delete() method is called more than once, the second call is likely to encounter a null entry that was produced by the first call ... and you will get an NPE as before. The tests should check for a null before they try to get the title / artist information; e.g.
CD cd = cdList[i];
if (cd != null &&
cd.getArtist().equals(artist) &&
cd.getTitle().equals(title)) {
// ...
}
At this point a design problem becomes apparent. These null values in the array are a bad idea. There are three fixes:
You could remove the CDs by creating a new array one element smaller ... and copy across all CDs apart from the one you are deleting.
You could add a cdListSize field, and arrange that it gives you the number of valid entries in the list. Then (and this is the important bit), when you delete an entry from the list, move the current last entry to the place where the deleted entry was and decrement the cdListSize. If you do that consistently, the null entries will all be at the end, and you can iterate from zero to cdListSize - 1 to get the non-null entries.
Best of all, use a List rather than an array to represent the CD list. The List API provides a method for removing the entry at a given position. The method really removes it ... it doesn't just set it to null.
Finally, you may need to take a step back and look at the larger application. Is the CD list supposed to be persisted; e.g. so that it is still available when your application restarts? Is it likely to be large; e.g. too large to fit into memory? Are you likely to want to do complicated queries on the CD list? All of these things would suggest that you should use a database rather than an in-memory data structure.
(However, with the extra code you've just added, it is clear that would be beyond the scope of your assignment.)
Found it! Thank ya'll for your comments, I did make some changes that ya'll recommended. The issue was with the CDList[i] being null. Just implemented a if(CDList[i] == null) then continue; Thank ya'll for your input. –
I have a list of strings and with each string I want to check it's characters against every other string to see if all it's characters are identical except for one.
For instance a check that would return true would be checking
rock against lock
clock and flock have one character that is different, no more no less.
rock against dent will obviously return false.
I have been thinking about first looping through the list and then having a secondary loop within that one to check the first string against the second.
And then using split(""); to create two arrays containing the characters of each string and then checking the array elements against each other (i.e. comparing each string with the same position in the other array 1-1 2-2 etc...) and so long as only one character comparison fails then the check for those two strings is true.
Anyway I have a lot of strings (4029) and considering what I am thinking of implementing at the moment would contain 3 loops each within the other that would result in a cubic loop(?) which would take a long long time with that many elements wouldn't it?
Is there an easier way to do this? Or will this method actually work okay? Or -hopefully not- but is there some sort of potential logical flaw in the solution I have proposed?
Thanks a lot!
Why not do it the naive way?
bool matchesAlmost(String str1, String str2) {
if (str1.length != str2.length)
return false;
int same = 0;
for (int i = 0; i < str1.length; ++i) {
if (str1.charAt(i) == str2.charAt(i))
same++;
}
return same == str1.length - 1;
}
Now you can just use a quadratic algorithm to check every string against every other.
Assuming the length of two strings are equal
String str1 = "rock";
String str2 = "lick";
if( str1.length() != str2.length() )
System.out.println( "failed");
else{
if( str2.contains( str1.substring( 0, str1.length()-1)) || str2.contains( str1.substring(1, str1.length() )) ){
System.out.println( "Success ");
}
else{
System.out.println( "Failed");
}
}
Not sure if this is the best approach but this one works even when two strings are not of same length. For example : cat & cattp They differ by one character p and t is repeated. Looks like O(n) time solution using additional space for hashmap & character arrays.
/**
* Returns true if two strings differ by one character
* #param s1 input string1
* #param s2 input string2
* #return true if strings differ by one character
*/
boolean checkIfTwoStringDifferByOne(String s1, String s2) {
char[] c1, c2;
if(s1.length() < s2.length()){
c1 = s1.toCharArray();
c2 = s2.toCharArray();
}else{
c1 = s2.toCharArray();
c2 = s1.toCharArray();
}
HashSet<Character> hs = new HashSet<Character>();
for (int i = 0; i < c1.length; i++) {
hs.add(c1[i]);
}
int count = 0;
for (int j = 0; j < c2.length; j++) {
if (! hs.contains(c2[j])) {
count = count +1;
}
}
if(count == 1)
return true;
return false;
}
Assuming that all the strings have the same length, I think this would help:
public boolean differByOne(String source, String destination)
{
int difference = 0;
for(int i=0;i<source.length();i++)
{
if(source.charAt(i)!=destination.charAt(i))
{
difference++;
if(difference>1)
{
return false;
}
}
}
return difference == 1;
}
Best way is to concatenate strings together one forward and other one in reverse order. Then check in single loop for both ends matching chars and also start from middle towards ends matching char. If more than 2 chars mismatch break.
If one mismatch stop and wait for the next one to complete if it reaches the same position then it matches otherwise just return false.
public static void main(String[] args) {
New1 x = new New1();
x.setFunc();
}
static void setFunc() {
Set s = new HashSet < Character > ();
String input = " aecd";
String input2 = "abcd";
String input3 = new StringBuilder(input2).reverse().toString();
String input4 = input.concat(input3);
int length = input4.length();
System.out.println(input4);
int flag = 0;
for (int i = 1, j = length - 1; j > i - 1; i++, j--) {
if (input4.charAt(i) != input4.charAt(j)) {
System.out.println(input4.charAt(i) + " doesnt match with " + input4.charAt(j));
if (input4.charAt(i + 1) != input4.charAt(j)) {
System.out.println(input4.charAt(i + 1) + " doesnt match with " + input4.charAt(j));
flag = 1;
continue;
} else if (input4.charAt(i) != input4.charAt(j - 1)) {
System.out.println(input4.charAt(i) + " doesnt match with " + input4.charAt(j - 1));
flag = 1;
break;
} else if (input4.charAt(i + 1) != input4.charAt(j - 1) && i + 1 <= j - 1) {
System.out.println(input4.charAt(i + 1) + " doesnt match with xxx " + input4.charAt(j - 1));
flag = 1;
break;
}
} else {
continue;
}
}
if (flag == 0) {
System.out.println("Strings differ by one place");
} else {
System.out.println("Strings does not match");
}
}