Remove duplicate characters from a string without using additional buffer - java

I am working on an interview question where I need to remove duplicate characters from the String without using additional buffer.
Below is the code I have but it's not giving right output for this string "aabbab". Is there anything wrong in below code?
private static void removeDuplicates(char[] str) {
if (str == null)
return;
int len = str.length;
if (len < 2)
return;
int tail = 1;
for (int i = 1; i < len; ++i) {
int j;
for (j = 0; j < tail; ++j) {
if (str[i] == str[j])
break;
}
if (j == tail) {
str[tail] = str[i];
++tail;
}
}
str[tail] = 0;
}
I am not able to figure out what is wrong in the above code after debugging.

It needs to do like this
if (str == null)
return;
int len = str.length;
if (len < 2)
return;
for(int i = 0; i <len; i++) {
for(int j = i+1; j<len; j++) {
if(str[i] == str[j]) {
str[j] = 0;
}
}
}
But the result will look like this a[space]b[space][space][space] because we just set the character to 0.

This question's time complexity is O(n^2).
But if your input char array has some restrict, such as char array is between 'a' and 'z'. It has O(n) method to solve.
The idea of that is use bits of one variable to save charactor appeared.
void removeDuplicate(char s[])
{
int len = strlen(s);
if(len < 2) return;
int check = 0, p = 0;
for(int i=0; i < len; ++i)
{
int v = (int)(s[i]-'a');
if((check & (1 << v))==0)
{
s[p++] = s[i];
check |= (1 << v);
}
}
s[p] = '\0';
}
ps. This code is from other website.

So basically we will mark the duplicates first with some special characters and then we need to remove those special characters. Time complexity would be O(n^2).
char[] str = "aabbabcdcd".toCharArray();
int len = str.length;
if (len < 2)
return;
Step-1, Mark the positions with some special characters like 0 or $
for (int i = 0; i < len-1; ++i) {
for(int j=i+1;j<len;j++)
{
if(str[i]==str[j])
{
str[j]=0; //<---mark the positions
}
}
}
Output: a b cd
Step-2, We need to remove those inner black space
int j;
for(int i=1;i<len-1;i++)
{
if(str[i]==0)
{
for(j=i+1;j<len;j++)
{
if(str[j]!=0)
{
break;
}
}
if(j!=len) //<-----replace with blank
{
str[i] = str[j];
str[j]=0;
}
}
}
Output: abcd

Related

How to check if a char is upper/lowercase?

The following code is supposed to convert letters to numbers and give the sum, but ignore any letters that are uppercase.
Example:
The input abcde should return 15. The input abCde should return 12.
Any help is appreciated.
static int strScore(String str[], String s, int n) {
int score = 0, index=0;
for (int i = 0; i < n; i++) {
if (str[i] == s) {
for (int j = 0; j < s.length(); j++)
score += s.charAt(j) - 'a' + 1;
index = i + 1;
break;
}
}
score = score * index;
return score;
}
public static void main(String[] args) {
String str[] = { "abcde" };
String s = "abcde";
int n = str.length;
int score = strScore(str, s, n);
System.out.println( score);
}
Use Character.isLowerCase(...).
So this is what your strScore method should look like:
static int strScore(String str[], String s, int n) {
int score = 0, index = 0;
for (int i = 0; i < n; i++) {
if (str[i].equals(s)) {
for (int j = 0; j < s.length(); j++) {
char c = s.charAt(j);
if(Character.isLowerCase(c)) // <-- This is the important part
score += c - 'a' + 1;
}
index = i + 1;
break;
}
}
score = score * index;
return score;
}
As pointed out in the comments, there is no need for the str and therfore neither the n parameter. This is a better version:
static int strScore(String s) {
int score = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if(Character.isLowerCase(c))
score += c - 'a' + 1;
}
return score;
}
There are two things to address:
You have used == to compare strings. You need to use .equals
You need to put a check like if(s.charAt(j)>= 'a' && s.charAt(j)<'z')
for (int i = 0; i < n; i++) {
if (str[i].equals(s)) {
for (int j = 0; j < s.length(); j++)
if(s.charAt(j)>= 'a' && s.charAt(j)<'z') {
score += s.charAt(j) - 'a' + 1;
You can avoid passing String str[] = { "abcde" }; which has one element which equals s
to The method. You can also avoid passing n which is an simply str.length():
static int strScore(String s) {
int score = 0, index = 0;
for (int i = 0; i < s.length(); i++) {
for (char c : s.toCharArray()) {
if(c >= 'a' && c <'z') { //alternatively if(Character.isLowerCase(c))
score += c - 'a' + 1;
}
}
index = i + 1;
break;
}
score = score * index;
return score;
}

Integer variable does not update when if condition is true

public class test
{
static Scanner store = new Scanner(System.in);
public static void main(String[] args)
{
String str1 = args[0];
String str2 = args[1];
System.out.printf("%nThere are %d dissimilar characters in the two strings.%n", CountNotSim(str1, str2));
}
public static int CountNotSim(String str1, String str2)
{
String s1 = str1.toLowerCase();
String s2 = str2.toLowerCase();
char[] a1 = new char[s1.length()];
char[] a2 = new char[s2.length()];
for (int g = 0; g < s1.length(); g++)
a1[g] = s1.charAt(g);
for (int h = 0; h < s2.length(); h++)
a2[h] = s2.charAt(h);
int check = 0, stored;
char[] array = new char[26];
int ctr = s1.length() + s2.length();
for (int i = 0; i < a1.length; i++)
{
check = 0;
stored = 0;
for (int j = 0; j < a2.length; j++)
{
if (a1[i] == a2[j])
{
check++;
for (int k = 0; k < 26; k++)
{
if (array[k] == ' ')
if (stored == 0)
array[k] = a1[i];
if (a1[i] == array[k])
{
stored = 1;
break;
}
}
System.out.print(stored + "/ ");
}
}
if (check > 0)
{
if (stored == 0)
ctr -= (check + 1);
else if (stored == 1)
ctr--;
}
System.out.print(ctr + " "); //checker
}
System.out.println();
return ctr;
}
}
The program checks for dissimilar letters in two strings inputted from the command line. Variable "stored" is supposed to change to 1 whenever there's a match to avoid extra deductions to variable "ctr". However, for some reason, not only does "stored's" value not change, the array "array" also doesn't update its elements whenever there's a match. I'm at a loss on how to fix it--nothing looks incorrect.
You wrote this:
char[] array = new char[26];
...
for (int k = 0; k < 26; k++)
{
if (array[k] == ' ') {
...
But you simply set the length of array not its content.
As a char array, it's filled with the default char value, which is not the character space but the value 0 (not the character 0, but the numeric value 0)
So array[k] == ' ' will never be true.
Try with that:
for (int k = 0; k < 26; k++)
{
if (array[k] == 0) {
...

Where did I make a mistake in the Mergesort algorithm

I'm learning some algorithm and at the moment I try to implement Mergesort into Java. This is my code:
public class Mergesort {
/**
* #param args
*/
public static void main(String[] args) {
int []a = {12,34,6543,3,6,45,23,677,56,67,3,4,54,5};
sort(a);
for(int i:a)
{
System.out.println(i);
}
}
private static void merge(int[]a,int[]b,int[]c)
{
int i = 0, j = 0, k = 0;
while((i < b.length) && (j < c.length))
{
if(b[i] < c[j])
{
a[k++] = b[i++];
}
else
{
a[k++] = c[j++];
}
while( i < b.length)
{
a[k++] = b[i++];
}
while( j < c.length)
{
a[k++] = c[j++];
}
}
}
public static void sort (int[]a)
{
if(a.length > 1)
{
int m = a.length / 2;
int[]b = new int[m];
int[]c = new int[a.length-m];
for(int i = 0; i < m; i++)
{
b[i] = a[i];
}
for(int i = m; i <a.length; i++ )
{
c[i-m] = a[i];
}
sort(b);
sort(c);
merge(a,b,c);
}
}
}
This is the output:
6543
6
23
45
56
677
67
4
5
54
I copy this from a tutorial but I dont know where the mistake is. My second question is:
What does this mean: a[k++] == b[i++];
I know that we are changing the value of a[k] ( k = position in a) to b[i] but why the ++?
I thought this mean that you are increasing the value by 1?
Thank you for reading.
What does this mean:
a[k++] == b[i++];
++ is the increment operator. See Unary Operators under Assignment, Arithmetic, and Unary Operators
This is equivalent to
a = a + 1
So
a[k++] == b[i++];
is same as
a[k] == b[i];
k = k + 1;
i = i + 1;
Wny is my code not working is offtopic. Please debug and ask any specific questions
Your merge routine is wrong. The second and third while loops should not be inside the first while loop. They should be outside it.
The first while loop compares items of the two arrays until there are no more elements left in one of them.
Only after it is done, the second and third loops should come into play.
The second and third loops (only one of them actually does any work in any invocation of merge) handle the remainder of the array that contains the highest values.
Therefore it should look like this :
private static void merge(int[]a,int[]b,int[]c)
{
int i = 0, j = 0, k = 0;
while((i < b.length) && (j < c.length))
{
if(b[i] < c[j])
{
a[k++] = b[i++];
}
else
{
a[k++] = c[j++];
}
}
while( i < b.length)
{
a[k++] = b[i++];
}
while( j < c.length)
{
a[k++] = c[j++];
}
}

How to check array for possible divisors?

Creating the array, I am letting the user choose the length:
StartNum = scan.nextInt();
int[] NumBox = new int[StartNum];
for (int i = 1; i < NumBox.length+1; i++)
{NumBox[i - 1] = i;}
NumBox[0]=0;
Assuming there are other methods that can change cells in NumBox to 0, how would I use a for loop to check each cells in the array for any divisor? If there are no divisors for the cell in the array, it will then become a 0. For example, if the array is [0,2,0,4,0,6,7,8,9] 9,2 and 7 would become a 0.
The code below is what I tired but didn't get far.
boolean NoDiv=false;
for (int a=1; a < NumBox.length+1; a++)
{
a++
for (int check=1; a < NumBox.length+1; check++)
{
if (NumBox[a-1]% check == 0 && NumBox[a-1] !=0)
{
NumBox[a-1] = 0;
}
}
}
for (int i = 0; i < NumBox.length; i++) {
if (NumBox[i] == 0) continue;
boolean hasDivisor = false;
for (int j = 0; j < i; j++) {
if (NumBox[j] == 0) continue;
if (NumBox[i] % NumBox[j] == 0) {
hasDivisor = true;
break;
}
}
if (!hasDivisor) NumBox[i] = 0;
}

how to delete null values/elements from an array

need help again. sorry. how can i remove the null values from my array? here is what i got so far.
int unikCount = 0;
String c = " ";
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length; j++) {
if (tempAry[i].equals(tempAry[j])) {
unikCount++;
}
if (unikCount > 1) {
tempAry[j] = c;
unikCount = 1;
}
}
unikCount = 0;
}
for (i = 0; i < a.length; i++) {
if (tempAry[i] != c) {
unikCount++;
}
}
System.out.println(unikCount);
for (int i = 0; i < a.length; i++) {
for (int j = 1; j < a.length; j++) {
if (tempAry[i].equals(tempAry[j])) {
if (tempAry[i] == c) {
count++;
if (tempAry[j] != c) {
count++;
tempAry[j] = tempAry[i];
}
}
}
}
}
count = 0;
for (int i = 0; i < a.length; i++) {
System.out.println(tempAry[i]);
}
*the remove part is after the "System.out.println(unikCount)". thanks for the upcoming help. by the way, cant use hash and arraylist.
You can check for null like this:
if ( null == someObject )
{
// do things
}
There is no way to remove an element from an array and have it shrink automatically. You'll have to use a temporary array to hold values, create an array of a new size and transfer all those items.
A more effective way would be to use a List.
Look at your logic (with proper indentation):
if(tempAry[i].equals(tempAry[j])) {
if(tempAry[i] == c) {
count++;
if(tempAry[j] != c) {
count++;
tempAry[j] = tempAry[i];
}
}
}
It does not make any sense. Why would you check for tempAry[j] != c inside if(tempAry[i] == c) ???
Did you mean to use if...else instead?
int j = 0;
Object[] temp = new Object[a.length];
for (int i = 0; i < a.length; i++) {
if (a[i] != null) {
temp[j++] = a[i];
}
}
Object[] newA = new Object[j];
System.arraycopy(temp, 0, newA, 0, j);
If the array is an array of, eg, String, you'd of course change "Object" to "String". And if by "null" one means an empty String, then the if test would be changed appropriately.

Categories