Different results on LeetCode by Submit Solution and Run Code - java

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

Related

Levenshtein algorithm in 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];

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.

Trie Data Structure in Finding an Optimal Solution

This Question is part of ongoing Competition , I have solved the 75% of this Question Data Set but the 25% is giving me TLE. I am asking why it's is giving TLE an i am sure my complexity is O(n*n)Question:
String S consisting of N lowercase English alphabets. We has prepared a list L consisting of all non empty substrings of the string S.
Now he asks you Q questions. To ith question, you need to count the number of ways to choose exactly Ki equal strings from the list L
For Example:
String = ababa
L = {"a", "b", "a", "b", "a", "ab", "ba", "ab", "ba", "aba", "bab", "aba", "abab", "baba", "ababa"}.
k1 = 2: There are seven ways to choose two equal strings ("a", "a"), ("a", "a"), ("a", "a"), ("b", "b"), ("ab", "ab"), ("ba", "ba"), ("aba", "aba").
k2 = 1: We can choose any string from L (15 ways).
k3 = 3: There is one way to choose three equal strings - ("a", "a", "a").
k4 = 4: There are no four equal strings in L .
Question LINK
My approach
I am making a TRIE of IT and Calculating The and Array F[i] where F[i] represent the number of times i equal String Occur.
My TRIE:
static class Batman{
int value;
Batman[] next = new Batman[26];
public Batman(int value){
this.value = value;
}
}
MY Insert Function
public static void Insert(String S,int[] F , int start){
Batman temp = Root;
for(int i=start;i<S.length();i++){
int index = S.charAt(i)-'a';
if(temp.next[index]==null){
temp.next[index] = new Batman(1);
F[1]+=1;
}else{
temp.next[index].value+=1;
int xx = temp.next[index].value;
F[xx-1]-=1;
F[xx]+=1;
// Calculating The Frequency of I equal Strings
}
temp = temp.next[index];
}
}
MY MAIN FUNCTION
public static void main(String args[] ) throws java.lang.Exception {
Root = new Batman(0);
int n = in.nextInt();
int Q = in.nextInt();
String S = in.next();
int[] F = new int[n+1];
for(int i=0;i<n;i++)
Insert(S,F,i);
long[] ans = new long[n+1];
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
ans[i]+= F[j]*C[j][i]; // C[n][k] is the Binomial Coffecient
ans[i]%=mod;
}
}
while(Q>0){
Q--;
int cc = in.nextInt();
long o =0;
if(cc<=n) o=ans[cc];
System.out.println(o+" "+S.length());
}
}
Why My appraoch is giving TLE as time Complexity is O(N*N) ans the length of String is N<=5000. Please Help me Working CODE
One reason this program get TLE (keep in mind that time constraint is 1 sec):
Each time you create a Batman object, it will create an array with length [26], and it is equivalence to adding a loop with n = 26.
So, you time complexity is 26*5000*5000 = 650000000 = 6.5*10^8 operations, theoretically, it can still fit into time limit if CPU speed is 10^9 operations per sec, but also keep in mind that there are some heavy calculation stuffs after this, so, this should be the reason.
To solve this problem, I used Z-algorithm and get accepted: Link
The actual code is quite complex, so the idea is, you have a table count[i][j], which is the number of substring that matched substring (i, j). Using Z-algorithm, you can have a time complexity of O(n^2).
For each string s:
int n = in.nextInt();
int q = in.nextInt();
String s = in.next();
int[][] cur = new int[n][];
int[][] count = new int[n][n];
int[] length = new int[n];
for (int i = 0; i < n; i++) {
cur[i] = Z(s.substring(i).toCharArray());//Applying Z algorithm
for (int j = 1; j < cur[i].length; j++) {
if (cur[i][j] > length[j + i]) {
for (int k = i + length[j + i]; k < i + cur[i][j]; k++) {
count[i][k]++;
}
length[j + i] = cur[i][j];
}
}
}
int[] F = new int[n + 1];
for(int i = 0; i < n; i++){
for(int j = i; j < n; j++){
int v = count[i][j] + (length[i] < (j - i + 1) ? 1 : 0);
F[v]++;
}
}
Z-algorithm method:
public static int[] Z(char[] s) {
int[] z = new int[s.length];
int n = s.length;
int L = 0, R = 0;
for (int i = 1; i < n; i++) {
if (i > R) {
L = R = i;
while (R < n && s[R - L] == s[R])
R++;
z[i] = R - L;
R--;
} else {
int k = i - L;
if (z[k] < R - i + 1) {
z[i] = z[k];
} else {
L = i;
while (R < n && s[R - L] == s[R])
R++;
z[i] = R - L;
R--;
}
}
}
return z;
}
Actual code: http://ideone.com/5GYWeS
Explanation:
First, we have an array length, with length[i] is the longest substring that matched with the string start from index i
For each index i, after calculate the Z function, we see that, if cur[i][j] > length[j + i], which means, there exists one substring longer than previous substring matched at index j + i, and we havent counted them in our result, so we need to count them.
So, even there are 3 nested for loop, but each substring is only counted once, which make this whole time complexity is O(n ^2)
for (int j = 1; j < cur[i].length; j++) {
if (cur[i][j] > length[j + i]) {
for (int k = i + length[j + i]; k < i + cur[i][j]; k++) {
count[i][k]++;
}
length[j + i] = cur[i][j];
}
}
For below loop, we notice that, if there is a matched for substring (i,j), length[i] >= length of substring (i,j), but if there is no matched, we need to add 1 to count substring (i,j), as this substring is unique.
for(int j = i; j < n; j++){
int v = count[i][j] + (length[i] < (j - i + 1) ? 1 : 0);
F[v]++;
}

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.

Array in the reverse order [duplicate]

This question already has answers here:
How do I reverse an int array in Java?
(47 answers)
Closed 8 years ago.
I have an array of n elements and these methods:
last() return the last int of the array
first() return the first int of the array
size() return the length of the array
replaceFirst(num) that add the int at the beginning and returns its position
remove(pos) that delete the int at the pos
I have to create a new method that gives me the array at the reverse order.
I need to use those method. Now, I can't understand why my method doesn't work.
so
for (int i = 1; i
The remove will remove the element at the position i, and return the number that it is in that position, and then with replaceFirst will move the number (returned by remove) of the array.
I made a try with a simple array with {2,4,6,8,10,12}
My output is: 12 12 12 8 6 10
so if I have an array with 1,2,3,4,5
for i = 1; I'm gonna have : 2,1,3,4,5
for i=2 >3,2,1,4,5
etc
But it doesn't seem to work.
Well, I'll give you hints. There are multiple ways to reverse an array.
The simplest and the most obvious way would be to loop through the array in the reverse order and assign the values to another array in the right order.
The previous method would require you to use an extra array, and if you do not want to do that, you could have two indices in a for loop, one from the first and next from the last and start swapping the values at those indices.
Your method also works, but since you insert the values into the front of the array, its going to be a bit more complex.
There is also a Collections.reverse method in the Collections class to reverse arrays of objects. You can read about it in this post
Here is an code that was put up on Stackoverflow by #unholysampler. You might want to start there: Java array order reversing
public static void reverse(int[] a)
{
int l = a.length;
for (int j = 0; j < l / 2; j++)
{
int temp = a[j]
a[j] = a[l - j - 1];
a[l - j - 1] = temp;
}
}
int[] reverse(int[] a) {
int len = a.length;
int[] result = new int[len];
for (int i = len; i > 0 ; i--)
result[len-i] = a[i-1];
return result;
}
for(int i = array.length; i >= 0; i--){
System.out.printf("%d\n",array[i]);
}
Try this.
If it is a Java array and not a complex type, the easiest and safest way is to use a library, e.g. Apache commons: ArrayUtils.reverse(array);
In Java for a random Array:
public static void reverse(){
int[] a = new int[4];
a[0] = 3;
a[1] = 2;
a[2] = 5;
a[3] = 1;
LinkedList<Integer> b = new LinkedList<Integer>();
for(int i = a.length-1; i >= 0; i--){
b.add(a[i]);
}
for(int i=0; i<b.size(); i++){
a[i] = b.get(i);
System.out.print(a[i] + ",");
}
}
Hope this helps.
Reversing an array is a relatively simple process. Let's start with thinking how you print an array normally.
int[] numbers = {1,2,3,4,5,6};
for(int x = 0; x < numbers.length; x++)
{
System.out.println(numbers[x]);
}
What does this do? Well it increments x while it is less than numbers.length, so what is actually happening is..
First run : X = 0
System.out.println(numbers[x]);
// Which is equivalent to..
System.out.println(numbers[0]);
// Which resolves to..
System.out.println(1);
Second Run : X = 1
System.out.println(numbers[x]);
// Which is equivalent to..
System.out.println(numbers[1]);
// Which resolves to..
System.out.println(2);
What you need to do is start with numbers.length - 1, and go back down to 0. To do this, you need to restructure your for loop, to match the following pseudocode..
for(x := numbers.length to 0) {
print numbers[x]
}
Now you've worked out how to print, it's time to move onto reversing the array. Using your for loop, you can cycle through each value in the array from start to finish. You'll also be needing a new array.
int[] revNumbers = new int[numbers.length];
for(int x = numbers.length - 1 to 0) {
revNumbers[(numbers.length - 1) - x] = numbers[x];
}
int[] noArray = {1,2,3,4,5,6};
int lenght = noArray.length - 1;
for(int x = lenght ; x >= 0; x--)
{
System.out.println(noArray[x]);
}
}
int[] numbers = {1,2,3,4,5};
int[] ReverseNumbers = new int[numbers.Length];
for(int a=0; a<numbers.Length; a++)
{
ReverseNumbers[a] = numbers.Length - a;
}
for(int a=0; a<ReverseNumbers.Length; a++)
Console.Write(" " + ReverseNumbers[a]);
int[] numbers = { 1, 2, 3, 4, 5, 6 };
reverse(numbers, 1); >2,1,3,4,5
reverse(numbers, 2); >3,2,1,4,5
public int[] reverse(int[] numbers, int value) {
int index = 0;
for (int i = 0; i < numbers.length; i++) {
int j = numbers[i];
if (j == value) {
index = i;
break;
}
}
int i = 0;
int[] result = new int[numbers.length];
int forIndex = index + 1;
for (int x = index + 2; x > 0; x--) {
result[i] = numbers[forIndex--];
++i;
}
for (int x = index + 2; x < numbers.length; x++) {
result[i] = numbers[x];
++i;
}
return result;
}

Categories

Resources