Levenshtein algorithm in Java - java

I am trying to implement Levenshtein's algorithm in Java, inspired from this Wikipedia article
public static int indicator(char a, char b) {
return (a == b) ? 0 : 1;
}
public static int levenshtein(String token1, String token2) {
int[] levi = new int[token2.length() + 1];
int[] levi_1 = new int[token2.length() + 1];
// initialize column i=0
for (int j = 0; j <= token2.length(); j++)
levi_1[j] = j;
// columns i=1 -> i=len(token1)
for (int i = 1; i <= token1.length(); i++) {
// lev_a,b(i,0) = i
levi[0] = i;
// update rest of column i
for (int j = 1; j <= token2.length(); j++) {
levi[j] = Math.min(Math.min(levi_1[j] + 1, levi[j - 1] + 1),
levi_1[j - 1] + indicator(token1.charAt(i - 1), token2.charAt(j - 1)));
}
// save column i to update column i+1
levi_1 = levi;
}
return levi[token2.length()];
}
But testing this on string "Maus" and "Haus" gives me an incorrect answer of 4. Can you help me with what I am doing wrong?

The problem comes from this line:
levi_1 = levi;
This line doesn't change every value from the levi_1 array, it only changes its reference; the values are still the same when you call levi_1[0], levi_1[1], etc.
I would suggest you to write those lines instead:
for (int k = 0; k < levi.length; k++)
levi_1[k] = levi[k];

Related

Keeping indexes of an elements in the array after sorting in Java

I want that sorting array without actually changing its data. So I want only keep its indexes in another array. For this I use Bubble Sort algorithm, and at every swapping step I change elements of new array which keeps indexes of actual array. That's my code, but it doesn't work correctly
int[] bSort(int[] arrivalTimes) {
int[] sequence = new int[arrivalTimes.length];
for (int i = 0; i < sequence.length; i++) {
sequence[i] = i;
}
for (int i = 0; i < arrivalTimes.length - 1; i++) {
for (int j = i + 1; j < arrivalTimes.length; j++) {
if (arrivalTimes[i] > arrivalTimes[j]) {
int temp = sequence[i];
sequence[i] = sequence[j];
sequence[j] = temp;
}
}
}
return sequence;
}
So if input array is [2, 5, 1, 0, 4]
Then sequence array should be [3, 2, 0, 4, 1] (indexes of actual array)
You're forgetting to sort the actual array also. If the arrivalTimes array isn't sorted, your condition will not act the way you expect.
int[] bSort(int[] arrivalTimes) {
int[] sequence = new int[arrivalTimes.length];
for (int i = 0; i < sequence.length; i++) {
sequence[i] = i;
}
for (int i = 0; i < arrivalTimes.length - 1; i++) {
for (int j = i + 1; j < arrivalTimes.length; j++) {
if (arrivalTimes[i] > arrivalTimes[j]) {
int temp = sequence[i];
sequence[i] = sequence[j];
sequence[j] = temp;
int temp2 = arrivalTimes[i];
arrivalTimes[i] = arrivalTimes[j];
arrivalTimes[j] = temp2;
}
}
}
return sequence;
}
This is an inefficient solution though. I suspect this is part of some algorithms assignment so I'll leave the optimisations up to you.

Characters in array are being removed when sorting a string

I am writing a class to print the given string to lexicographical order but in the final method 'reverseOrder()' the array is automatically deleting values from it (I suppose). The method reverseOrder is deleting some characters for selected string such as "dkhc". Thanks
Debugging shows the values are correctly added to the array.
public class LexicalOrder {
static String biggerIsGreater(String w) {
String finalString = "";
char[] charArr = w.toCharArray();
int largestX = -1;
// Find the largest x such that P[x]<P[x+1].
// (If there is no such x, P is the last permutation.)
for (int i = 0; i < charArr.length - 1; i++) {
if (charArr[i] < charArr[i + 1]) {
largestX = i;
}
}
if (largestX == -1) {
finalString = "no answer";
}
int largestY = -1;
if (largestX != -1) {
for (int j = 0; j < charArr.length; j++) {
if (charArr[largestX] < charArr[j]) {
largestY = j;
}
}
charArr = swap(charArr, largestX, largestY);
charArr = reverseOrder(charArr, largestX + 1);
finalString = new String(charArr);
}
return finalString;
}
// Method to swap characters in index largestX and largestY
public static char[] swap(char[] a, int largestX, int largestY) {
char temp = a[largestY];
a[largestY] = a[largestX];
a[largestX] = temp;
return a;
}
// Method to reverse the order of the array from the index
// largestX + 1 to n (n being last element of array)
public static char[] reverseOrder(char[] a, int index) {
int step = 0;
char[] newArr = new char[a.length];
for (int j = 0; j < index; j++) {
System.out.println(j);
newArr[j] = a[j]; // adding elements to new arr till index=largestX
System.out.println(newArr[j] = a[j]);
}
for (int i = index; i < a.length; i++) {
System.out.println(i);
newArr[index] = a[a.length - step - 1]; // adding remaining values but with reversing order
System.out.println(newArr[index] = a[a.length - step - 1]);
step++;
}
for (char c : newArr)
System.out.println(c);
return newArr;
}
public static void main(String[] args) {
System.out.println(biggerIsGreater("dkhc"));
}
}
What is expected is = hcdk.
But what I get is = hk
I ran the method to check and it clearly adds those elements to the "newArr" array in method 'reverseOrder()' as shown below.
0
h
1
c
2
d
3
k
Output - hk (and two spaces)
The two characters are replaced by two spaces for some reason.
P.S : I am following the steps mentioned here link
Note: It works for some words such as "lmno,dcba,etc"
What you have missed is index++. In reverseOrder method increment index++ will give you hcdk expected output.
public static char[] reverseOrder(char[] a, int index) {
int step = 0;
char[] newArr = new char[a.length];
for (int j = 0; j < index; j++) {
System.out.println(j);
newArr[j] = a[j]; // adding elements to new arr till index=largestX
System.out.println(newArr[j] = a[j]);
}
for (int i = index; i < a.length; i++) {
System.out.println(i);
newArr[index] = a[a.length - step - 1]; // adding remaining values
// but with reversing order
System.out.println(newArr[index] = a[a.length - step - 1]);
step++;index++;
}
for (char c : newArr)
System.out.println(c);
return newArr;
}
In your case index value is not getting incremented due to which 2 and 3 item in an array are blank.

Different results on LeetCode by Submit Solution and Run Code

I am working on the LeetCode question Longest Substring Without Repeating Characters. But I got two different results between Run Code and Submit Solution. My c++ code is
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int* a = new int[257];
int ans = 0;
int n = s.size();
for (int j = 0, i = 0; j < n; j++) {
i = i > a[s[j]] ? i : a[s[j]];
ans = ans > j - i +1 ? ans : j - i + 1;
a[s[j]] = j + 1;
}
return ans;
}
};
And two outputs are
I don't know what's wrong with my code. Besides, my c++ code is written by learning his website java answer
public class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length(), ans = 0;
int[] index = new int[128]; // current index of character
// try to extend the range [i, j]
for (int j = 0, i = 0; j < n; j++) {
i = Math.max(index[s.charAt(j)], i);
ans = Math.max(ans, j - i + 1);
index[s.charAt(j)] = j + 1;
}
return ans;
}
}
for (int j = 0, i = 0; j < n; j++) {
i = i > a[s[j]] ? i : a[s[j]];
Since a is uninitialized, a[s[j]] is undefined behavior. You want
for (int i=0;i<257;i++)
a[i]=0;
or better a vector
vector<int> a(257,0);
Unlike Java, C++ does not zero heap memory for you.
int* a = new int[257];
What is the data inside your array a?
In Java, a[0], a[1], ... a[256] are all equal to zero. But in C++, a[0], a[1], ... a[256] contains random garbage from whatever data was previously at that memory address.
You have to zero the memory first:
std::fill_n(a, 257, 0);
Or, if you prefer memset:
std::memset(a, 0, sizeof(int) * 257);
EDIT: As pointed out by #It'scominghome, value-initialization (C++11) is also possible:
int* a = new int[257](); // will zero the array

After counting sort the result array has one more element (0) than the original one

So I have a problem, this method is supposed to sort an array of integers by using counting sort. The problem is that the resulting array has one extra element, zero. If the original array had a zero element (or several) it's fine, but if the original array didn't have any zero elements the result starts from zero anyway.
e.g. int input[] = { 2, 1, 4 }; result -> Sorted Array : [0, 1, 2, 4]
Why would this be happening?
public class CauntingSort {
public static int max(int[] A)
{
int maxValue = A[0];
for(int i = 0; i < A.length; i++)
if(maxValue < A[i])
maxValue = A[i];
return maxValue;
}
public static int[] createCountersArray(int[] A)
{
int maxValue = max(A) + 1;
int[] Result = new int[A.length + 1];
int[] Count = new int[maxValue];
for (int i = 0; i < A.length; i++) {
int x = Count[A[i]];
x++;
Count[A[i]] = x;
}
for (int i = 1; i < Count.length; i++) {
Count[i] = Count[i] + Count[i - 1];
}
for (int i = A.length -1; i >= 0; i--) {
int x = Count[A[i]];
Result[x] = A[i];
x--;
Count[A[i]] = x;
}
return Result;
}
}
You are using int[] Result = new int[A.length + 1]; which makes the array one position larger. But if you avoid it, you'll have an IndexOutOfBounds exception because you're supposed to do x-- before using x to access the array, so your code should change to something like:
public static int[] createCountersArray(int[] A)
{
int maxValue = max(A) + 1;
int[] Result = new int[A.length];
int[] Count = new int[maxValue];
for (int i = 0; i < A.length; i++) {
int x = Count[A[i]];
x++;
Count[A[i]] = x;
}
for (int i = 1; i < Count.length; i++) {
Count[i] = Count[i] + Count[i - 1];
}
for (int i = A.length -1; i >= 0; i--) {
int x = Count[A[i]];
x--;
Result[x] = A[i];
Count[A[i]] = x;
}
return Result;
}
Here you go: tio.run
int maxValue = max(A) + 1;
Returns the highest value of A + 1, so your new array with new int[maxValue] will be of size = 5;
The array Result is of the lenght A.lenght + 1, that is 4 + 1 = 5;
The first 0 is a predefinied value of int if it is a ? extends Object it would be null.
The leading 0 in your result is the initial value assigned to that element when the array is instantiated. That initial value is never modified because your loop that fills the result writes only to elements that correspond to a positive number of cumulative counts.
For example, consider sorting a one-element array. The Count for that element will be 1, so you will write the element's value at index 1 of the result array, leaving index 0 untouched.
Basically, then, this is an off-by-one error. You could fix it by changing
Result[x] = A[i];
to
Result[x - 1] = A[i];
HOWEVER, part of the problem here is that the buggy part of the routine is difficult to follow or analyze (for a human). No doubt it is comparatively efficient; nevertheless, fast, broken code is not better than slow, working code. Here's an alternative that is easier to reason about:
int nextResult = 0;
for (int i = 0; i < Count.length; i++) {
for (int j = 0; j < Count[i]; j++) {
Result[nextResult] = i;
nextResult++;
}
}
Of course, you'll also want to avoid declaring the Result array larger than array A.

Inserting number into random array

I need some help inserting the number 8 into an array that gives me random values. The array must be in order. For example if I had an array of (1,5,10,15), I have to insert the number 8 between 5 and 10. I am having a problem on how I can figure our a way to find the index where 8 will be placed because the array is random, it can be anything. Here is my code so far :
public class TrickyInsert {
public static void main(String[] args) {
int[] mysteryArr = generateRandArr();
//print out starting state of mysteryArr:
System.out.print("start:\t");
for ( int a : mysteryArr ) {
System.out.print( a + ", ");
}
System.out.println();
//code starts below
// insert value '8' in the appropriate place in mysteryArr[]
int[] tmp = new int[mysteryArr.length + 1];
int b = mysteryArr.length;
for(int i = 0; i < mysteryArr.length; i++) {
tmp[i] = mysteryArr[i];
}
tmp[b] = 8;
for(int i =b ; i<mysteryArr.length; i++) {
tmp[i+1] = mysteryArr[i];
}
mysteryArr = tmp;
any tips? thanks!
Simply add the number then use Arrays.sort method,
int b = mysteryArr.length;
int[] tmp = new int[b + 1];
for(int i = 0; i < b; i++) {
tmp[i] = mysteryArr[i];
}
tmp[b] = 8;
mysteryArr = Arrays.sort(tmp);
In your example the random array is sorted. If this is the case, just insert 8 and sort again.
Simply copy the array over, add 8, and sort again.
int[] a = generateRandArr();
int[] b = Arrays.copyOf(a, a.length + 1);
b[a.length] = 8;
Arrays.sort(b);
int findPosition(int a, int[] inputArr)
{
for(int i = 0; i < inputArr.length; ++i)
if(inputArr[i] < a)
return i;
return -1;
}
int[] tmpArr = new int[mysteryArr.length + 1];
int a = 8; // or any other number
int x = findPosition(a, mysteryArr);
if(x == -1)
int i = 0;
for(; i < mysteryArr.length; ++i)
tmpArr[i] = mysteryArr[i];
tmpArr[i] = a;
else
for(int i = 0; i < mysteryArr.length + 1; ++i)
if(i < x)
tmpArr[i] = mysteryArr[i];
else if(i == x)
tmpArr = a;
else
tmpArr[i] = mysteryArr[i - 1];
I will suggest using binary search to find the appropriate index. Once you locate the index, you can use
System.arraycopy(Object src, int srcIndex, Obj dest, int destIndex, int length)
to copy the left half to your new array (with length one more than the existing one) and then the new element and finally the right half. This will stop the need to sort the whole array every time you insert an element.
Also, the following portion does not do anything.
for(int i =b ; i<mysteryArr.length; i++) {
tmp[i+1] = mysteryArr[i];
}
since int b = mysteryArr.length;, after setting int i =b ;, i<mysteryArr.length; will be false and hence the line inside this for loop will never execute.

Categories

Resources