The idea of the project is to maintain the data of the dictionary in such a way that searching the word
becomes easy and efficient. Dictionary Dataset will be maintained in a text file. User will load the file
and create a linked list in such a way that all words with arranged in a sorted order just like a dictionary.
Nodes A,B,C to Z will be created while reading the file according to words. Suppose if there is no word
with letter F then node F will not be created
Here is and example Click here
My approach:
read all words from text file
sort all words in alphabetical order
create list
I have defined the maximum length of a word as 5, of course you have to adapt this to your needs. It depends on how the words are stored in the text file, for example if each line contains one word the length of the array is logically the number of lines in the text file.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define size_of_array 8
typedef struct word{
char w[5];
struct word* next;
} word;
typedef struct node{
char c;//contains the character with which the words begin
struct node* next;
struct word* firstWord;
} node;
node *anchor = NULL; //points to first node of the list
node *getNodeByChar(char c){
node *ptr = anchor;
while(ptr != NULL && ptr->c != c){
ptr = ptr->next;
}
return ptr;
}
void addWordToNode(char c, char *w){
word *newWord = (word *)malloc(sizeof(word));
strcpy(newWord->w,w);
newWord->next = NULL;
node *n = getNodeByChar(c);
word *wrd = n->firstWord;
if(wrd == NULL){ //if newWord is the first word of the node
//set firstword to newWord
n->firstWord = newWord;
}else{
//append newWord to wordlist of node
while(wrd->next != NULL){
wrd = wrd->next;
}
wrd->next = newWord;
}
}
void addNode(char c){
node *newNode = (node *)malloc(sizeof(node));
newNode->c = c;
newNode->next = NULL;
newNode->firstWord = NULL;
if(anchor == NULL){
//newNode is first Node set anchor to newNode
anchor = newNode;
}else{
//append node to list
node *ptr = anchor;
while(ptr->next != NULL){
ptr = ptr->next;
}
ptr->next = newNode;
}
}
void createList(char array[][5]){
char currentStartChar;
currentStartChar = array[0][0];
addNode(currentStartChar);//add first node
for(int i = 0; i < size_of_array; i++){
if(array[i][0] != currentStartChar){//if beginning char changes add new Node
currentStartChar = array[i][0];
addNode(currentStartChar);
}
addWordToNode(currentStartChar,array[i]);//add word to Node
}
}
void printList(){ //printing the list
node *ptr = anchor;
word *wPtr = NULL;
while(ptr != NULL){//iterate through al nodes
printf("%c: ",ptr->c);
if(ptr->firstWord != NULL){
wPtr = ptr->firstWord;
while(wPtr != NULL){ //iterate through all words of node 'ptr'
//with char 'ptr->c'
printf("%s, ",wPtr->w);
wPtr = wPtr->next;//next word
}
}
printf("\n");
ptr = ptr->next;//next node
}
}
//function to display array
void display(char array[][5]){
for(int i=0; i<size_of_array; i++){
printf("%s ", array[i]);
}
printf("\n");
}
int main()
{
//Words out of text file
char array[size_of_array][5] = {
"Ape",
"Boy",
"Ant",
"Too",
"Dog",
"Dad",
"Abc",
"TTL"
};
//display the original array
printf("Original array: ");
display(array);
char temp[5];
//Sort array using the Bubble Sort algorithm
for(int i=0; i<size_of_array; i++){
for(int j=0; j<size_of_array-1-i; j++){
if(strcmp(array[j], array[j+1]) > 0){
//swap array[j] and array[j+1]
strcpy(temp, array[j]);
strcpy(array[j], array[j+1]);
strcpy(array[j+1], temp);
}
}
}
//display the sorted array
printf("Sorted Array: ");
display(array);
createList(array);
printf("\n\n");
printList();
return 0;
}
Output:
Original array: Ape Boy Ant Too Dog Dad Abc TTL
Sorted Array: Abc Ant Ape Boy Dad Dog TTL Too
A: Abc, Ant, Ape,
B: Boy,
D: Dad, Dog,
T: TTL, Too,
I want to pass an array from one object, store reference and then work with this array inside my function, but...
I have a terrible misunderstanding of passing an array process: In the class TreeType.
I’m facing with an error and I have tried to resolve that for 3 days, but I couldn’t.
Function:
void AddElements(TreeType& tree, int info[], int fromIndex, int toIndex)
{
int midIndex;
if (fromIndex <= toIndex)
{
midIndex = (fromIndex + toIndex) / 2;
tree.PutItem(info[midIndex]);
AddElements(tree, info, fromIndex, midIndex - 1);
// Complete the left subtree.
AddElements(tree, info, midIndex+1, toIndex);
// Complete the right subtree.
}
}
void MakeTree(TreeType& tree, int info[], int length)
// Creates a binary tree from a sorted array.
{
tree.MakeEmpty();
int arrayb[length];
for(int i = 0; i < length; i++)
{
cout << "Enter Value to make tree:" << endl;
cin >> arrayb[i];
}
AddElements(tree, info, 0, length-1);
}
And invoked in main.cpp.
else if (command == "MakeTree")
{
int length=25;
//int arrayb[length];
int arrayb[]={-1000,-967,-923,-844,-669,-567,-455,-267,-209,-183,-59,-23,68,132,159,170,222,228,233,241,389,479,824,939,985};
tree.MakeTree(tree,arrayb,length);
Error capture
I have a file that contains English words in a txt file, each word in a new line.
I'm a beginner in C. I'm using a load and unload functions to store all the words into a hashtable (separate chaining) and unload them from memory, but has ran into some problems.
The functions (the code in main.c is correct):
load:
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include "dictionary.h"
#define SIZE 26
typedef struct node
{
char word[LENGTH+1];
struct node *next;
}node;
unsigned int hash_num = 0;
node *hashtable[SIZE]; //26 letters in alphabet
node *head = NULL;
// hashfunction
unsigned int hash(char const *key)
{
unsigned int hash= tolower(key[0]) - 'a';
return hash % SIZE;
}
/**
* Loads dictionary into memory. Returns true if successful else false.
*/
bool load(const char* dictionary)
{
unsigned int hash_index=0;
FILE *fp = fopen(dictionary, "r");
if(fp == NULL)
{
fprintf(stderr, "Couldn't open %s",dictionary);
return false;
}
//dictionary
while(!feof(fp))
{
node *temp = malloc(sizeof(node));
if (temp == NULL)
{
unload();
fclose(fp);
return false;
}
if(fscanf(fp , "%s", temp->word) == 1) //storing word of dictionary in my new_node -> word
{
hash_index = hash(temp->word);
head= hashtable[hash_index]; //head always points to first element of linked list (containting word of dictionary)
temp->next = head;
head = temp;
hash_num++;
}
else //if fscanf couldn't store the word (return 0)
{
free(temp); //free last temp
break;
}
}
fclose(fp);
return true;
}
unload:
bool unload(void)
{
for(int i=0; i<SIZE; i++)
{
if(hashtable[i] != NULL) //if hashtable isn't NULL (has nodes)
{
node *cursor = hashtable[i]; //cursor points at head of individual linked list
while(cursor != NULL) //free them
{
node *temp = cursor;
cursor = cursor->next;
free(temp);
}
}
}
return true;
}
Can anyone tell me if the logic is correct? Whenever I run valgrind it tells me that all my nodes were allocated but just 3 free'd.
total heap usage: 143,094 allocs, 3 frees, 8,014,288 bytes allocated
LEAK SUMMARY:
==15903== definitely lost: 8,013,040 bytes in 143,090 blocks
==15903== indirectly lost: 0 bytes in 0 blocks
==15903== possibly lost: 0 bytes in 0 blocks
When checking the provided source code (missing "dictionary.h"), the main problem is locating in the load() function.
Problem 1 (Main) - the hashtable[] is never updated when adding a new word/node (after computing hash_index = hash(temp->word);).
To store the updated linked-list (managed as reversed), it is
necessary to update the hashtable[hash_index] with the new node
pointer (the allocated temp node).
temp->next = head;
head = temp;
hashtable[hash_index] = head; // update the hashtable[] pointer
hash_num++;
Alternate solution without global variable head.
temp->next = hashtable[hash_index]; //head always points to first element...
hashtable[hash_index] = temp; // update the hashtable[] pointer
hash_num++;
Instead of
temp->next = head;
head = temp;
hash_num++;
Problem 2 (Small) - the hashtable[SIZE] is never initialized.
In the unload() function, in the for-loop, the if-condition
if(hashtable[i] != NULL) assumes that each item of the array is
initialized to NULL.
Add at the beginning the load() function or before calling it, a for-loop to initialize each pointer.
for(int i=0; i<SIZE; i++)
{
hashtable[i] = NULL;
}
Problem 3 (Potential Bug Source) - as suggest by reviewer, the use of head, declared as a global variable node *head = NULL; could be a potential source of bug.
In the load() function, the variable head is used as a temporary
storage but could store value during software run. If a read operation
is performed without a well-known write operation before, the result
could be an unexpected error even if the compilation doesn't detect
error or warning.
The best way is to reduce the number of global variable as much as
possible.
Enhancement (Reverse the linked-list) - because the managed linked-list is adding new items in the front, here is a solution to add new items in the end.
node *first = hashtable[hash_index];
if (first == NULL) {
hashtable[hash_index] = temp;
}
else {
temp->next = NULL; // ending the list
while (first->next!=NULL) {
first = first->next; // loop until last node
}
first->next = temp; // linking to the last node
}
hash_num++;
Instead of
head= hashtable[hash_index]; //head always points to first element ...
temp->next = head;
head = temp;
hash_num++;
Given a string, find the first non-repeating character in it. For
example, if the input string is “GeeksforGeeks”, then output should be
‘f’.
We can use string characters as index and build a count array.
Following is the algorithm.
Scan the string from left to right and construct the count array or
HashMap.
Again, scan the string from left to right and check for
count of each character, if you find an element who's count is 1,
return it.
Above problem and algorithm is from GeeksForGeeks
But it requires two scan of an array. I want to find first non-repeating character in only one scan.
I implemented above algorithm Please check it also on Ideone:
import java.util.HashMap;
import java.util.Scanner;
/**
*
* #author Neelabh
*/
public class FirstNonRepeatedCharacter {
public static void main(String [] args){
Scanner scan=new Scanner(System.in);
String string=scan.next();
int len=string.length();
HashMap<Character, Integer> hashMap=new HashMap<Character, Integer>();
//First Scan
for(int i = 0; i <len;i++){
char currentCharacter=string.charAt(i);
if(!hashMap.containsKey(currentCharacter)){
hashMap.put(currentCharacter, 1);
}
else{
hashMap.put(currentCharacter, hashMap.get(currentCharacter)+1);
}
}
// Second Scan
boolean flag=false;
char firstNonRepeatingChar = 0;
for(int i=0;i<len;i++){
char c=string.charAt(i);
if(hashMap.get(c)==1){
flag=true;
firstNonRepeatingChar=c;
break;
}
}
if(flag==true)
System.out.println("firstNonRepeatingChar is "+firstNonRepeatingChar);
else
System.out.println("There is no such type of character");
}
}
GeeksforGeeks also suggest efficient method but I think it is also two scan. Following solution is from GeeksForGeeks
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#define NO_OF_CHARS 256
// Structure to store count of a character and index of the first
// occurrence in the input string
struct countIndex {
int count;
int index;
};
/* Returns an array of above structure type. The size of
array is NO_OF_CHARS */
struct countIndex *getCharCountArray(char *str)
{
struct countIndex *count =
(struct countIndex *)calloc(sizeof(countIndex), NO_OF_CHARS);
int i;
// This is First Scan
for (i = 0; *(str+i); i++)
{
(count[*(str+i)].count)++;
// If it's first occurrence, then store the index
if (count[*(str+i)].count == 1)
count[*(str+i)].index = i;
}
return count;
}
/* The function returns index of the first non-repeating
character in a string. If all characters are repeating
then reurns INT_MAX */
int firstNonRepeating(char *str)
{
struct countIndex *count = getCharCountArray(str);
int result = INT_MAX, i;
//Second Scan
for (i = 0; i < NO_OF_CHARS; i++)
{
// If this character occurs only once and appears
// before the current result, then update the result
if (count[i].count == 1 && result > count[i].index)
result = count[i].index;
}
free(count); // To avoid memory leak
return result;
}
/* Driver program to test above function */
int main()
{
char str[] = "geeksforgeeks";
int index = firstNonRepeating(str);
if (index == INT_MAX)
printf("Either all characters are repeating or string is empty");
else
printf("First non-repeating character is %c", str[index]);
getchar();
return 0;
}
You can store 2 arrays: count of each character and the first occurrence(and fill both of them during the first scan). Then the second scan will be unnecessary.
Use String functions of java then you find the solution in only one for loop
The Example is show below
import java.util.Scanner;
public class firstoccurance {
public static void main(String args[]){
char [] a ={'h','h','l','l','o'};
//Scanner sc=new Scanner(System.in);
String s=new String(a);//sc.next();
char c;
int i;
int length=s.length();
for(i=0;i<length;i++)
{
c=s.charAt(i);
if(s.indexOf(c)==s.lastIndexOf(c))
{
System.out.println("first non repeating char in a string "+c);
break;
}
else if(i==length-1)
{
System.out.println("no single char");
}
}
}
}
In following solution I declare one class CharCountAndPosition which stores firstIndex and frequencyOfchar. During the reading string characterwise, firstIndex stores the first encounter of character and frequencyOfchar stores the total occurrence of characters.
We will make array of CharCountAndPosition step:1 and Initialize it step2.
During scanning the string, Initialize the firstIndex and frequencyOfchar for every character step3.
Now In the step4 check the array of CharCountAndPosition, find the character with frequency==1 and minimum firstIndex
Over all time complexity is O(n+256), where n is size of string. O(n+256) is equivalent to O(n) Because 256 is constant. Please find solution of this on ideone
public class FirstNonRepeatedCharacterEfficient {
public static void main(String [] args){
// step1: make array of CharCountAndPosition.
CharCountAndPosition [] array=new CharCountAndPosition[256];
// step2: Initialize array with object of CharCountAndPosition.
for(int i=0;i<256;i++)
{
array[i]=new CharCountAndPosition();
}
Scanner scan=new Scanner(System.in);
String str=scan.next();
int len=str.length();
// step 3
for(int i=0;i<len;i++){
char c=str.charAt(i);
int index=c-'a';
int frequency=array[index].frequencyOfchar;
if(frequency==0)
array[index].firstIndex=i;
array[index].frequencyOfchar=frequency+1;
//System.out.println(c+" "+array[index].frequencyOfchar);
}
boolean flag=false;
int firstPosition=Integer.MAX_VALUE;
for(int i=0;i<256;i++){
// Step4
if(array[i].frequencyOfchar==1){
//System.out.println("character="+(char)(i+(int)'a'));
if(firstPosition> array[i].firstIndex){
firstPosition=array[i].firstIndex;
flag=true;
}
}
}
if(flag==true)
System.out.println(str.charAt(firstPosition));
else
System.out.println("There is no such type of character");
}
}
class CharCountAndPosition{
int firstIndex;
int frequencyOfchar;
}
A solution in javascript with a lookup table:
var sample="It requires two scan of an array I want to find first non repeating character in only one scan";
var sampleArray=sample.split("");
var table=Object.create(null);
sampleArray.forEach(function(char,idx){
char=char.toLowerCase();
var pos=table[char];
if(typeof(pos)=="number"){
table[char]=sampleArray.length; //a duplicate found; we'll assign some invalid index value to this entry and discard these characters later
return;
}
table[char]=idx; //index of first occurance of this character
});
var uniques=Object.keys(table).filter(function(k){
return table[k]<sampleArray.length;
}).map(function(k){
return {key:k,pos:table[k]};
});
uniques.sort(function(a,b){
return a.pos-b.pos;
});
uniques.toSource(); //[{key:"q", pos:5}, {key:"u", pos:6}, {key:"d", pos:46}, {key:"p", pos:60}, {key:"g", pos:66}, {key:"h", pos:69}, {key:"l", pos:83}]
(uniques.shift()||{}).key; //q
Following C prog, add char specific value to 'count' if char didn't occurred before, removes char specific value from 'count' if char had occurred before. At the end I get a 'count' that has char specific value which indicate what was that char!
//TO DO:
//If multiple unique char occurs, which one is occurred before?
//Is is possible to get required values (1,2,4,8,..) till _Z_ and _z_?
#include <stdio.h>
#define _A_ 1
#define _B_ 2
#define _C_ 4
#define _D_ 8
//And so on till _Z
//Same for '_a' to '_z'
#define ADDIFNONREP(C) if(count & C) count = count & ~C; else count = count | C; break;
char getNonRepChar(char *str)
{
int i = 0, count = 0;
for(i = 0; str[i] != '\0'; i++)
{
switch(str[i])
{
case 'A':
ADDIFNONREP(_A_);
case 'B':
ADDIFNONREP(_B_);
case 'C':
ADDIFNONREP(_C_);
case 'D':
ADDIFNONREP(_D_);
//And so on
//Same for 'a' to 'z'
}
}
switch(count)
{
case _A_:
return 'A';
case _B_:
return 'B';
case _C_:
return 'C';
case _D_:
return 'D';
//And so on
//Same for 'a' to 'z'
}
}
int main()
{
char str[] = "ABCDABC";
char c = getNonRepChar(str);
printf("%c\n", c); //Prints D
return 0;
}
You can maintain a queue of keys as they are added to the hash map (you add your key to the queue if you add a new key to the hash map). After string scan, you use the queue to obtain the order of the keys as they were added to the map. This functionality is exactly what Java standard library class OrderedHashMap does.
Here is my take on the problem.
Iterate through string. Check if hashset contains the character. If so delete it from array. If not present just add it to the array and hashset.
NSMutableSet *repeated = [[NSMutableSet alloc] init]; //Hashset
NSMutableArray *nonRepeated = [[NSMutableArray alloc] init]; //Array
for (int i=0; i<[test length]; i++) {
NSString *currentObj = [NSString stringWithFormat:#"%c", [test characterAtIndex:i]]; //No support for primitive data types.
if ([repeated containsObject:currentObj]) {
[nonRepeated removeObject:currentObj];// in obj-c nothing happens even if nonrepeted in nil
continue;
}
[repeated addObject:currentObj];
[nonRepeated addObject:currentObj];
}
NSLog(#"This is the character %#", [nonRepeated objectAtIndex:0]);
If you can restrict yourself to strings of ASCII characters, I would recommend a lookup table instead of a hash table. This lookup table would have only 128 entries.
A possible approach would be as follows.
We start with an empty queue Q (may be implemented using linked lists) and a lookup table T. For a character ch, T[ch] stores a pointer to a queue node containing the character ch and the index of the first occurrence of ch in the string. Initially, all entries of T are NULL.
Each queue node stores the character and the first occurrence index as specified earlier, and also has a special boolean flag named removed which indicates that the node has been removed from the queue.
Read the string character by character. If the ith character is ch, check if T[ch] = NULL. If so, this is the first occurrence of ch in the string. Then add a node for ch containing the index i to the queue.
If T[ch] is not NULL, this is a repeating character. If the node pointed to by T[ch] has already been removed (i.e. the removed flag of the node is set), then nothing needs to be done. Otherwise, remove the node from the queue by manipulating the pointers of the previous and next nodes. Also set the removed flag of the node to indicate that the node is now removed. Note that we do not free/delete the node at this stage, nor do we set T[ch] back to NULL.
If we proceed in this way, the nodes for all the repeating characters will be removed from the queue. The removed flag is used to ensure that no node is removed twice from the queue if the character occurs more than two times.
After the string has been completely processed, the first node of the linked list will contain the character code as well as the index of the first non-repeating character. Then, the memory can be freed by iterating over the entries of lookup table T and freeing any non-NULL entries.
Here is a C implementation. Here, instead of the removed flag, I set the prev and next pointers of the current node to NULL when it is removed, and check for that to see if a node has already been removed.
#include <stdio.h>
#include <stdlib.h>
struct queue_node {
int ch;
int index;
struct queue_node *prev;
struct queue_node *next;
};
void print_queue (struct queue_node *head);
int main (void)
{
int i;
struct queue_node *lookup_entry[128];
struct queue_node *head;
struct queue_node *last;
struct queue_node *cur_node, *prev_node, *next_node;
char str [] = "GeeksforGeeks";
head = malloc (sizeof (struct queue_node));
last = head;
last->prev = last->next = NULL;
for (i = 0; i < 128; i++) {
lookup_entry[i] = NULL;
}
for (i = 0; str[i] != '\0'; i++) {
cur_node = lookup_entry[str[i]];
if (cur_node != NULL) {
/* it is a repeating character */
if (cur_node->prev != NULL) {
/* Entry has not been removed. Remove it from the queue. */
prev_node = cur_node->prev;
next_node = cur_node->next;
prev_node->next = next_node;
if (next_node != NULL) {
next_node->prev = prev_node;
} else {
/* Last node was removed */
last = prev_node;
}
cur_node->prev = NULL;
cur_node->next = NULL;
/* We will not free the node now. Instead, free
* all nodes in a single pass afterwards.
*/
}
} else {
/* This is the first occurence - add an entry to the queue */
struct queue_node *newnode = malloc (sizeof(struct queue_node));
newnode->ch = str[i];
newnode->index = i;
newnode->prev = last;
newnode->next = NULL;
last->next = newnode;
last = newnode;
lookup_entry[str[i]] = newnode;
}
print_queue (head);
}
last = head->next;
while (last != NULL) {
printf ("Non-repeating char: %c at index %d.\n", last->ch, last->index);
last = last->next;
}
/* Free the queue memory */
for (i = 0; i < 128; i++) {
if (lookup_entry[i] != NULL) {
free (lookup_entry[i]);
lookup_entry[i] = NULL;
}
}
free (head);
return (0);
}
void print_queue (struct queue_node *head) {
struct queue_node *tmp = head->next;
printf ("Queue: ");
while (tmp != NULL) {
printf ("%c:%d ", tmp->ch, tmp->index);
tmp = tmp->next;
}
printf ("\n");
}
Instead of making things more and more complex, I can use three for loops to tackle this.
class test{
public static void main(String args[]){
String s="STRESST";//Your input can be given here.
char a[]=new char[s.length()];
for(int i=0;i<s.length();i++){
a[i]=s.charAt(i);
}
for(int i=0;i<s.length();i++){
int flag=0;
for(int j=0;j<s.length();j++){
if(a[i]==a[j]){
flag++;
}
}
if(flag==1){
System.out.println(a[i]+" is not repeated");
break;
}
}
}
}
I guess it will be helpful for people who are just gonna look at the logic part without any complex methods used in the program.
This can be done in one Scan using the substring method. Do it like this:
String str="your String";<br>
String s[]= str.split("");<br>
int n=str.length();<br>
int i=0;<br><br>
for(String ss:s){
if(!str.substring(i+1,n).contains(ss)){
System.out.println(ss);
}
}
This will have the lowest complexity and will search for it even without completing one full scan.
Add each character to a HashSet and check whether hashset.add() returns true, if it returns false ,then remove the character from hashset.
Then getting the first value of the hashset will give you the first non repeated character.
Algorithm:
for(i=0;i<str.length;i++)
{
HashSet hashSet=new HashSet<>()
if(!hashSet.add(str[i))
hashSet.remove(str[i])
}
hashset.get(0) will give the non repeated character.
i have this program which is more simple,
this is not using any data structures
public static char findFirstNonRepChar(String input){
char currentChar = '\0';
int len = input.length();
for(int i=0;i<len;i++){
currentChar = input.charAt(i);
if((i!=0) && (currentChar!=input.charAt(i-1)) && (i==input.lastIndexOf(currentChar))){
return currentChar;
}
}
return currentChar;
}
A simple (non hashed) version...
public static String firstNRC(String s) {
String c = "";
while(s.length() > 0) {
c = "" + s.charAt(0);
if(! s.substring(1).contains(c)) return c;
s = s.replace(c, "");
}
return "";
}
or
public static char firstNRC(String s) {
s += " ";
for(int i = 0; i < s.length() - 1; i++)
if( s.split("" + s.charAt(i)).length == 2 ) return s.charAt(i);
return ' ';
}
//This is the simple logic for finding first non-repeated character....
public static void main(String[] args) {
String s = "GeeksforGeeks";
for (int i = 0; i < s.length(); i++) {
char begin = s.charAt(i);
String begin1 = String.valueOf(begin);
String end = s.substring(0, i) + s.substring(i + 1);
if (end.contains(begin1));
else {
i = s.length() + 1;
System.out.println(begin1);
}
}
}
#Test
public void testNonRepeadLetter() {
assertEquals('f', firstNonRepeatLetter("GeeksforGeeks"));
assertEquals('I', firstNonRepeatLetter("teststestsI"));
assertEquals('1', firstNonRepeatLetter("123aloalo"));
assertEquals('o', firstNonRepeatLetter("o"));
}
private char firstNonRepeatLetter(String s) {
if (s == null || s.isEmpty()) {
throw new IllegalArgumentException(s);
}
Set<Character> set = new LinkedHashSet<>();
for (int i = 0; i < s.length(); i++) {
char charAt = s.charAt(i);
if (set.contains(charAt)) {
set.remove(charAt);
} else {
set.add(charAt);
}
}
return set.iterator().next();
}
here is a tested code in java. note that it is possible that no non repeated character is found, and for that we return a '0'
// find first non repeated character in a string
static char firstNR( String str){
int i, j, l;
char letter;
int[] k = new int[100];
j = str.length();
if ( j > 100) return '0';
for (i=0; i< j; i++){
k[i] = 0;
}
for (i=0; i<j; i++){
for (l=0; l<j; l++){
if (str.charAt(i) == str.charAt(l))
k[i]++;
}
}
for (i=0; i<j; i++){
if (k[i] == 1)
return str.charAt(i);
}
return '0';
Here is the logic to find the first non-repeatable letter in a String.
String name = "TestRepeat";
Set <Character> set = new LinkedHashSet<Character>();
List<Character> list = new ArrayList<Character>();
char[] ch = name.toCharArray();
for (char c :ch) {
set.add(c);
list.add(c);
}
Iterator<Character> itr1 = set.iterator();
Iterator<Character> itr2= list.iterator();
while(itr1.hasNext()){
int flag =0;
Character setNext= itr1.next();
for(int i=0; i<list.size(); i++){
Character listNext= list.get(i);
if(listNext.compareTo(setNext)== 0){
flag ++;
}
}
if(flag==1){
System.out.println("Character: "+setNext);
break;
}
}
it is very easy....you can do it without collection in java..
public class FirstNonRepeatedString{
public static void main(String args[]) {
String input ="GeeksforGeeks";
char process[] = input.toCharArray();
boolean status = false;
int index = 0;
for (int i = 0; i < process.length; i++) {
for (int j = 0; j < process.length; j++) {
if (i == j) {
continue;
} else {
if (process[i] == process[j]) {
status = false;
break;
} else {
status = true;
index = i;
}
}
}
if (status) {
System.out.println("First non-repeated string is : " + process[index]);
break;
}
}
}
}
We can create LinkedHashMap having each character from the string and it's respective count. And then traverse through the map when you come across char with count as 1 return that character. Below is the function for the same.
private static char findFirstNonRepeatedChar(String string) {
LinkedHashMap<Character, Integer> map = new LinkedHashMap<>();
for(int i=0;i< string.length();i++){
if(map.containsKey(string.charAt(i)))
map.put(string.charAt(i),map.get(string.charAt(i))+1);
else
map.put(string.charAt(i),1);
}
for(Entry<Character,Integer> entry : map.entrySet()){
if(entry.getValue() == 1){
return entry.getKey();
}
}
return ' ';
}
One Pass Solution.
I have used linked Hashmap here to maintain the insertion order. So I go through all the characters of a string and store it values in Linked HashMap. After that I traverse through the Linked Hash map and whichever first key will have its value equal to 1, I will print that key and exit the program.
import java.util.*;
class demo
{
public static void main(String args[])
{
String str="GeekGsQuizk";
HashMap <Character,Integer>hm=new LinkedHashMap<Character,Integer>();
for(int i=0;i<str.length();i++)
{
if(!hm.containsKey(str.charAt(i)))
hm.put(str.charAt(i),1);
else
hm.put(str.charAt(i),hm.get(str.charAt(i))+1);
}
for (Character key : hm.keySet())
{
if(hm.get(key)==1)
{
System.out.println(key);
System.exit(0) ;
}
}
}
}
I know this comes one year late, but I think if you use LinkedHashMap in your solution instead of using a HashMap, you will have the order guaranteed in the resulting map and you can directly return the key with the corresponding value as 1.
Not sure if this is what you wanted though as you will have to iterate over the map (not the string) after you are done populating it - but just my 2 cents.
Regards,
-Vini
Finding first non-repeated character in one pass O(n ) , without using indexOf and lastIndexOf methods
package nee.com;
public class FirstNonRepeatedCharacterinOnePass {
public static void printFirstNonRepeatedCharacter(String str){
String strToCaps=str.toUpperCase();
char ch[]=strToCaps.toCharArray();
StringBuilder sb=new StringBuilder();
// ASCII range for A-Z ( 91-65 =26)
boolean b[]=new boolean[26];
for(int i=0;i<ch.length;i++){
if(b[ch[i]-65]==false){
b[ch[i]-65]=true;
}
else{
//add repeated char to StringBuilder
sb.append(ch[i]+"");
}
}
for(int i=0;i<ch.length;i++){
// if char is not there in StringBuilder means it is non repeated
if(sb.indexOf(ch[i]+"")==-1){
System.out.println(" first non repeated in lower case ...."+Character.toLowerCase((ch[i])));
break;
}
}
}
public static void main(String g[]){
String str="abczdabddcn";
printFirstNonRepeatedCharacter(str);
}
}
I did the same using LinkedHashSet. Following is the code snippet:
System.out.print("Please enter the string :");
str=sc.nextLine();
if(null==str || str.equals("")) {
break;
}else {
chArr=str.toLowerCase().toCharArray();
set=new LinkedHashSet<Character>();
dupSet=new LinkedHashSet<Character>();
for(char chVal:chArr) {
if(set.contains(chVal)) {
dupSet.add(chVal);
}else {
set.add(chVal);
}
}
set.removeAll(dupSet);
System.out.println("First unique :"+set.toArray()[0]);
}
You can find this question here
For code of the below algorithm refer this link (My implementation with test cases)
Using linkedlist in combination with hashMap
I have a solution which solves it in O(n) time One array pass and O(1) space
Inreality -> O(1) space is O(26) space
Algorithm
1) every time you visit a character for the first time
Create a node for the linkedList(storing that character).Append it at the end of the lnkedList.Add an entry in the hashMap storing for recently appended charater the address of the node in the linked list that was before that character.If character is appended to an empty linked list store null for vale in hash map.
2) Now if you encounter the same charactter again
Remove that element from the linkedlist using the address stored in the hash map and now you have to update for the element that was after the deleted element ,the previous element for it. Make it equal to the previous element of the deleted element.
Complexity Analysis
LinkedlIst add element -> O(1)
LinkedlIst delete element -> O(1)
HashMap -> O(1)
space O(1)
pass -> one in O(n)
#include<bits/stdc++.h>
using namespace std;
typedef struct node
{
char ch;
node *next;
}node;
char firstNotRepeatingCharacter(string &s)
{
char ans = '_';
map<char,node*> mp;//hash map atmost may consume O(26) space
node *head = NULL;//linkedlist atmost may consume O(26) space
node *last;// to append at last in O(1)
node *temp1 = NULL;
node *temp2 = new node[1];
temp2->ch = '$';
temp2->next = NULL;
//This is my one pass of array//
for(int i = 0;i < s.size();++i)
{
//first occurence of character//
if(mp.find(s[i]) == mp.end())
{
node *temp = new node[1];
temp->ch = s[i];
temp->next = NULL;
if(head == NULL)
{
head = temp;
last = temp;
mp.insert(make_pair(s[i],temp1));
}
else
{
last->next = temp;
mp.insert(make_pair(s[i],last));
last = temp;
}
}
//Repeated occurence//
else
{
node *temp = mp[s[i]];
if(mp[s[i]] != temp2)
{
if(temp == temp1)
{
head = head->next;
if((head)!=NULL){mp[head->ch] = temp1;}
else last = head;
mp[s[i]] = temp2;
}
else if((temp->next) != NULL)
{
temp->next = temp->next->next;
if((temp->next) != NULL){mp[temp->next->ch] = temp;}
else last = temp;
mp[s[i]] = temp2;
}
else
{
;
}
}
}
if(head == NULL){;}
else {ans = head->ch;}
return ans;
}
int main()
{
int T;
cin >> T;
while(T--)
{
string str;
cin >> str;
cout << str << " -> " << firstNotRepeatingCharacter(str)<< endl;
}
return 0;
}
Requires one scan only.
Uses a deque (saves char) and a hashmap (saves char->node). On repeating char, get char's node in deque using hashmap and remove it from deque (in O(1) time) but keep the char in hashmap with null node value. peek() gives the 1st unique character.
[pseudocode]
char? findFirstUniqueChar(s):
if s == null:
throw
deque<char>() dq = new
hashmap<char, node<char>> chToNodeMap = new
for i = 0, i < s.length(), i++:
ch = s[i]
if !chToNodeMap.hasKey(ch):
chToNodeMap[ch] = dq.enqueue(ch)
else:
chNode = chToNodeMap[ch]
if chNode != null:
dq.removeNode(chNode)
chToNodeMap[ch] = null
if dq.isEmpty():
return null
return dq.peek()
// deque interface
deque<T>:
node<T> enqueue(T t)
bool removeNode(node<T> n)
T peek()
bool isEmpty()
The string is scanned only once; other scans happen on counts and first appearance arrays, which are generally much smaller in size. Or at least below approach is for cases when string is much larger than character set the string is made from.
Here is an example in golang:
package main
import (
"fmt"
)
func firstNotRepeatingCharacter(s string) int {
counts := make([]int, 256)
first := make([]int, 256)
// The string is parsed only once
for i := len(s) - 1; i >= 0; i-- {
counts[s[i]]++
first[s[i]] = i
}
min := 0
minValue := len(s) + 1
// Now we are parsing counts and first slices
for i := 0; i < 256; i++ {
if counts[i] == 1 && first[i] < minValue {
minValue = first[i]
min = i
}
}
return min
}
func main() {
fmt.Println(string(firstNotRepeatingCharacter("fff")))
fmt.Println(string(firstNotRepeatingCharacter("aabbc")))
fmt.Println(string(firstNotRepeatingCharacter("cbbc")))
fmt.Println(string(firstNotRepeatingCharacter("cbabc")))
}
go playground
Question : Find First Non Repeating Character or First Unique Character:
The code itself is understandable.
public class uniqueCharacter1 {
public static void main(String[] args) {
String a = "GiniGinaProtijayi";
firstUniqCharindex(a);
}
public static void firstUniqCharindex(String a) {
int count[] = new int[256];
for (char ch : a.toCharArray()) {
count[ch]++;
} // for
for (int i = 0; i < a.length(); i++) {
char ch = a.charAt(i);
if (count[ch] == 1) {
System.out.println(i);// 8
System.out.println(a.charAt(i));// p
break;
}
}
}// end1
}
In Python:
def firstUniqChar(a):
count = [0] * 256
for i in a: count[ord(i)] += 1
element = ""
for items in a:
if(count[ord(items) ] == 1):
element = items ;
break
return element
a = "GiniGinaProtijayi";
print(firstUniqChar(a)) # output is P
GeeksforGeeks also suggest efficient method but I think it is also two
scan.
Note that in the second scan, it does not scan the input string, but the array of wihch the length is NO_OF_CHARS. So the time complexity is O(n+m), which is better than 2*O(n), when the n is quite large(for a long intput string)
But it requires two scan of an array. I want to find first
non-repeating character in only one scan.
IMHO, it is possible if a priority queue is used. In that queue we compare each char with its occurrence count and its first occur index, and finally, we simply get the first element in the queue. See #hlpPy 's answer.
I just test the function on one of the struct which is name but it won't reach them.
This is the full code so far:
update:
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstddef>
using namespace std;
struct Node{
string name;
string address;
int phoneNum;
struct Node* next;
};
Node insertInOrder(Node p, string theName);
void push(struct Node*& head, string theName);
int main(){
cout<<"\tEnter S or s to show the list contents \n"
<<"\tEnter A or a to add a node to the list \n"
<<"\tEnter D or d to delete a node from the list \n"
<<"\tEnter Q or q to quiet the program \n"
<<"Make your selection: "<<endl;
struct Node* newNode = new Node;
push(newNode, "yeah");
cout<<newNode;
return 0;
}
void push(struct Node*& head, string theName){
struct Node* newNode = new Node;
newNode->name = theName;
newNode->next = head;
head = newNode;
}
Node insertInOrder(Node p, string theName){
if(p == NULL || p.name >= theName){
return new Node(p, theName);
}
else{
p.next = insertInOrder(p.next, theName);
return p;
}
}
I get an error that says: invalid application of ‘sizeof’ to incomplete type ‘Node’ for this code:
void push(struct Node*& head, string theName){
struct Node* newNode = malloc(sizeof(struct Node));
newNode->name = theName;
newNode->next = head;
head = newNode;
}
I'm trying to translate this code into my code but I got an error:
Node insertInOrder( int k, Node p ) {
if( p == " " || p.item >= k )
return new Node( k, p );
else {
p.next = insertInOrder( k, p.next );
return p;
}
}
This is how I translated it:
Node insertInOrder(Node p, string theName){
if(p == " " || p.name >= theName){
return new Node(p, theName);
}
else{
p.next = insertInOrder(p.next, theName);
return p;
}
}
here is the error for this code:
if(p == " " || p.name >= theName){
return new Node(p, theName);
Errors:
- comparison with string literal results in unspecified behaviour [-Waddress]
- request for member ‘name’ in ‘p’, which is of pointer type ‘Node*’ (maybe you meant to use ‘-
>’ ?)
- comparison between distinct pointer types ‘Node*’ and ‘const char*’ lacks a cast [-
fpermissive]
p.next = insertInOrder(p.next, theName);
return p;
errors:
Invalid arguments ' Candidates are: Node insertInOrder(Node, std::basic_string<char,std::char_traits<char>,std::allocator<char>>) '
- could not convert ‘p.Node::next’ from ‘Node*’ to ‘Node’
Some points:
forget malloc since you are working with C++ and use new and delete
you don't need to specify that node is a struct again whenever you use it so sizeof(Node) is enough, but you won't directly use malloc
your function Node insertInOrder(Node p, string theName) accepts a concrete Node and return a concrete Node but the field next inside your struct is a pointer to a Node, I guess you shoul be consistent in what you are using and since you are working with a linked list using pointers is more suitable
you can't use a comparison operator directly between a value and a string literal (p == " "), you should check name field only