Shortest string to try all 3 digit lock - algorithm

I was asked this question in one of my recent interviews. A three digit lock can have its key value between range "000" - "999". So basically 1000 combinations have to be tried to open the lock. So I had to generate the shortest string such that all possible combinations (i.e between "000"-"999") would be checked. So for example if we had string "01234" then it would check the combinations "012", "123" and "234". So I had to generate a string which would check all combination. I tried to use a hashset to implement this, where I started with "000" and then took the last two character in string i.e "00" and then appended a new number from 0 to 9 and checked if it existed in hashset. If not I appended that number to output string and repeated the process. Is there any other efficient and clean way to solve this problem.

The procedure you described is based on the assumption that the shortest string has every code exactly once. It turns out that this assumption is correct.
Here's a simple backtracking implementation (C++):
#include <stdio.h>
bool used[1000];
int digits[33333];
bool backtrack(int index, int total)
{
if (total == 1000)
{
printf("%d\n", index);
for (int i = 0; i < index; ++i) {
printf("%d", digits[i]);
}
printf("\n");
return true;
}
for (int d = 0; d < 10; ++d)
{
int prev = 100*digits[index-2]+10*digits[index-1]+d;
if (!used[prev]) {
digits[index] = d;
used[prev] = true;
if (backtrack(index+1, total+1))
return true;
used[prev] = false;
}
}
}
int main(void) {
digits[0] = 0;
backtrack(2, 0);
return 0;
}
Output:
1002
00010020030040050060070080090110120130140150160170\
18019021022023024025026027028029031032033034035036\
03703803904104204304404504604704804905105205305405\
50560570580590610620630640650660670680690710720730\
74075076077078079081082083084085086087088089091092\
09309409509609709809911121131141151161171181191221\
23124125126127128129132133134135136137138139142143\
14414514614714814915215315415515615715815916216316\
41651661671681691721731741751761771781791821831841\
85186187188189192193194195196197198199222322422522\
62272282292332342352362372382392432442452462472482\
49253254255256257258259263264265266267268269273274\
27527627727827928328428528628728828929329429529629\
72982993334335336337338339344345346347348349354355\
35635735835936436536636736836937437537637737837938\
43853863873883893943953963973983994445446447448449\
45545645745845946546646746846947547647747847948548\
64874884894954964974984995556557558559566567568569\
57657757857958658758858959659759859966676686696776\
78679687688689697698699777877978878979879988898999\
00
The procedure is efficient.

Related

Make unique array with minimal sum

It is a interview question. Given an array, e.g., [3,2,1,2,7], we want to make all elements in this array unique by incrementing duplicate elements and we require the sum of the refined array is minimal. For example the answer for [3,2,1,2,7] is [3,2,1,4,7] and its sum is 17. Any ideas?
It's not quite as simple as my earlier comment suggested, but it's not terrifically complicated.
First, sort the input array. If it matters to be able to recover the original order of the elements then record the permutation used for the sort.
Second, scan the sorted array from left to right (ie from low to high). If an element is less than or equal to the element to its left, set it to be one greater than that element.
Pseudocode
sar = sort(input_array)
for index = 2:size(sar) ! I count from 1
if sar(index)<=sar(index-1) sar(index) = sar(index-1)+1
forend
Is the sum of the result minimal ? I've convinced myself that it is through some head-scratching and trials but I haven't got a formal proof.
If you only need to find ONE of the best solution, here's the algorythm with some explainations.
The idea of this problem is to find an optimal solution, which can be found only by testing all existing solutions (well, they're infinite, let's stick with the reasonable ones).
I wrote a program in C, because I'm familiar with it, but you can port it to any language you want.
The program does this: it tries to increment one value to the max possible (I'll explain how to find it in the comments under the code sections), than if the solution is not found, decreases this value and goes on with the next one and so on.
It's an exponential algorythm, so it will be very slow on large values of duplicated data (yet, it assures you the best solution is found).
I tested this code with your example, and it worked; not sure if there's any bug left, but the code (in C) is this.
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef int BOOL; //just to ease meanings of values
#define TRUE 1
#define FALSE 0
Just to ease comprehension, I did some typedefs. Don't worry.
typedef struct duplicate { //used to fasten the algorythm; it uses some more memory just to assure it's ok
int value;
BOOL duplicate;
} duplicate_t;
int maxInArrayExcept(int *array, int arraySize, int index); //find the max value in array except the value at the index given
//the result is the max value in the array, not counting th index
int *findDuplicateSum(int *array, int arraySize);
BOOL findDuplicateSum_R(duplicate_t *array, int arraySize, int *tempSolution, int *solution, int *totalSum, int currentSum); //resursive function used to find solution
BOOL check(int *array, int arraySize); //checks if there's any repeated value in the solution
These are all the functions we'll need. All split up for comprehension purpose.
First, we have a struct. This struct is used to avoid checking, for every iteration, if the value on a given index was originally duplicated. We don't want to modify any value not duplicated originally.
Then, we have a couple functions: first, we need to see the worst case scenario: every value after the duplicated ones is already occupied: then we need to increment the duplicated value up to the maximum value reached + 1.
Then, there are the main Function we'll discute later about.
The check Function only checks if there's any duplicated value in a temporary solution.
int main() { //testing purpose
int i;
int testArray[] = { 3,2,1,2,7 }; //test array
int nTestArraySize = 5; //test array size
int *solutionArray; //needed if you want to use the solution later
solutionArray = findDuplicateSum(testArray, nTestArraySize);
for (i = 0; i < nTestArraySize; ++i) {
printf("%d ", solutionArray[i]);
}
return 0;
}
This is the main Function: I used it to test everything.
int * findDuplicateSum(int * array, int arraySize)
{
int *solution = malloc(sizeof(int) * arraySize);
int *tempSolution = malloc(sizeof(int) * arraySize);
duplicate_t *duplicate = calloc(arraySize, sizeof(duplicate_t));
int i, j, currentSum = 0, totalSum = INT_MAX;
for (i = 0; i < arraySize; ++i) {
tempSolution[i] = solution[i] = duplicate[i].value = array[i];
currentSum += array[i];
for (j = 0; j < i; ++j) { //to find ALL the best solutions, we should also put the first found value as true; it's just a line more
//yet, it saves the algorythm half of the duplicated numbers (best/this case scenario)
if (array[j] == duplicate[i].value) {
duplicate[i].duplicate = TRUE;
}
}
}
if (findDuplicateSum_R(duplicate, arraySize, tempSolution, solution, &totalSum, currentSum));
else {
printf("No solution found\n");
}
free(tempSolution);
free(duplicate);
return solution;
}
This Function does a lot of things: first, it sets up the solution array, then it initializes both the solution values and the duplicate array, that is the one used to check for duplicated values at startup. Then, we find the current sum and we set the maximum available sum to the maximum integer possible.
Then, the recursive Function is called; this one gives us the info about having found the solution (that should be Always), then we return the solution as an array.
int findDuplicateSum_R(duplicate_t * array, int arraySize, int * tempSolution, int * solution, int * totalSum, int currentSum)
{
int i;
if (check(tempSolution, arraySize)) {
if (currentSum < *totalSum) { //optimal solution checking
for (i = 0; i < arraySize; ++i) {
solution[i] = tempSolution[i];
}
*totalSum = currentSum;
}
return TRUE; //just to ensure a solution is found
}
for (i = 0; i < arraySize; ++i) {
if (array[i].duplicate == TRUE) {
if (array[i].duplicate <= maxInArrayExcept(solution, arraySize, i)) { //worst case scenario, you need it to stop the recursion on that value
tempSolution[i]++;
return findDuplicateSum_R(array, arraySize, tempSolution, solution, totalSum, currentSum + 1);
tempSolution[i]--; //backtracking
}
}
}
return FALSE; //just in case the solution is not found, but we won't need it
}
This is the recursive Function. It first checks if the solution is ok and if it is the best one found until now. Then, if everything is correct, it updates the actual solution with the temporary values, and updates the optimal condition.
Then, we iterate on every repeated value (the if excludes other indexes) and we progress in the recursion until (if unlucky) we reach the worst case scenario: the check condition not satisfied above the maximum value.
Then we have to backtrack and continue with the iteration, that will go on with other values.
PS: an optimization is possible here, if we move the optimal condition from the check into the for: if the solution is already not optimal, we can't expect to find a better one just adding things.
The hard code has ended, and there are the supporting functions:
int maxInArrayExcept(int *array, int arraySize, int index) {
int i, max = 0;
for (i = 0; i < arraySize; ++i) {
if (i != index) {
if (array[i] > max) {
max = array[i];
}
}
}
return max;
}
BOOL check(int *array, int arraySize) {
int i, j;
for (i = 0; i < arraySize; ++i) {
for (j = 0; j < i; ++j) {
if (array[i] == array[j]) return FALSE;
}
}
return TRUE;
}
I hope this was useful.
Write if anything is unclear.
Well, I got the same question in one of my interviews.
Not sure if you still need it. But here's how I did it. And it worked well.
num_list1 = [2,8,3,6,3,5,3,5,9,4]
def UniqueMinSumArray(num_list):
max=min(num_list)
for i,V in enumerate(num_list):
while (num_list.count(num_list[i])>1):
if (max > num_list[i]+1) :
num_list[i] = max + 1
else:
num_list[i]+=1
max = num_list[i]
i+=1
return num_list
print (sum(UniqueMinSumArray(num_list1)))
You can try with your list of numbers and I am sure it will give you the correct unique minimum sum.
I got the same interview question too. But my answer is in JS in case anyone is interested.
For sure it can be improved to get rid of for loop.
function getMinimumUniqueSum(arr) {
// [1,1,2] => [1,2,3] = 6
// [1,2,2,3,3] = [1,2,3,4,5] = 15
if (arr.length > 1) {
var sortedArr = [...arr].sort((a, b) => a - b);
var current = sortedArr[0];
var res = [current];
for (var i = 1; i + 1 <= arr.length; i++) {
// check current equals to the rest array starting from index 1.
if (sortedArr[i] > current) {
res.push(sortedArr[i]);
current = sortedArr[i];
} else if (sortedArr[i] == current) {
current = sortedArr[i] + 1;
// sortedArr[i]++;
res.push(current);
} else {
current++;
res.push(current);
}
}
return res.reduce((a,b) => a + b, 0);
} else {
return 0;
}
}

Find word in string buffer/paragraph/text

This was asked in Amazon telephonic interview - "Can you write a program (in your preferred language C/C++/etc.) to find a given word in a string buffer of big size ? i.e. number of occurrences "
I am still looking for perfect answer which I should have given to the interviewer.. I tried to write a linear search (char by char comparison) and obviously I was rejected.
Given a 40-45 min time for a telephonic interview, what was the perfect algorithm he/she was looking for ???
The KMP Algorithm is a popular string matching algorithm.
KMP Algorithm
Checking char by char is inefficient. If the string has 1000 characters and the keyword has 100 characters, you don't want to perform unnecessary comparisons. The KMP Algorithm handles many cases which can occur, but I imagine the interviewer was looking for the case where: When you begin (pass 1), the first 99 characters match, but the 100th character doesn't match. Now, for pass 2, instead of performing the entire comparison from character 2, you have enough information to deduce where the next possible match can begin.
// C program for implementation of KMP pattern searching
// algorithm
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void computeLPSArray(char *pat, int M, int *lps);
void KMPSearch(char *pat, char *txt)
{
int M = strlen(pat);
int N = strlen(txt);
// create lps[] that will hold the longest prefix suffix
// values for pattern
int *lps = (int *)malloc(sizeof(int)*M);
int j = 0; // index for pat[]
// Preprocess the pattern (calculate lps[] array)
computeLPSArray(pat, M, lps);
int i = 0; // index for txt[]
while (i < N)
{
if (pat[j] == txt[i])
{
j++;
i++;
}
if (j == M)
{
printf("Found pattern at index %d \n", i-j);
j = lps[j-1];
}
// mismatch after j matches
else if (i < N && pat[j] != txt[i])
{
// Do not match lps[0..lps[j-1]] characters,
// they will match anyway
if (j != 0)
j = lps[j-1];
else
i = i+1;
}
}
free(lps); // to avoid memory leak
}
void computeLPSArray(char *pat, int M, int *lps)
{
int len = 0; // length of the previous longest prefix suffix
int i;
lps[0] = 0; // lps[0] is always 0
i = 1;
// the loop calculates lps[i] for i = 1 to M-1
while (i < M)
{
if (pat[i] == pat[len])
{
len++;
lps[i] = len;
i++;
}
else // (pat[i] != pat[len])
{
if (len != 0)
{
// This is tricky. Consider the example
// AAACAAAA and i = 7.
len = lps[len-1];
// Also, note that we do not increment i here
}
else // if (len == 0)
{
lps[i] = 0;
i++;
}
}
}
}
// Driver program to test above function
int main()
{
char *txt = "ABABDABACDABABCABAB";
char *pat = "ABABCABAB";
KMPSearch(pat, txt);
return 0;
}
This code is taken from a really good site that teaches algorithms:
Geeks for Geeks KMP
Amazon and companies alike expect knowledge of Boyer–Moore string search or / and Knuth–Morris–Pratt algorithms.
Those are good if you want to show perfect knowledge. Otherwise, try to be creative and write something relatively elegant and efficient.
Did you ask about delimiters before you wrote anything? It could be that they may simplify your task to provide some extra information about a string buffer.
Even code below could be ok (it's really not) if you provide enough information in advance, properly explain runtime, space requirements, choice of data containers.
int find( std::string & the_word, std::string & text )
{
std::stringstream ss( text ); // !!! could be really bad idea if 'text' is really big
std::string word;
std::unordered_map< std::string, int > umap;
while( ss >> text ) ++umap[text]; // you have to assume that each word separated by white-spaces.
return umap[the_word];
}

Check if binary string can be partitioned such that each partition is a power of 5

I recently came across this question - Given a binary string, check if we can partition/split the string into 0..n parts such that each part is a power of 5. Return the minimum number of splits, if it can be done.
Examples would be:
input = "101101" - returns 1, as the string can be split once to form "101" and "101",as 101= 5^1.
input = "1111101" - returns 0, as the string itself is 5^3.
input = "100"- returns -1, as it can't be split into power(s) of 5.
I came up with this recursive algorithm:
Check if the string itself is a power of 5. if yes, return 0
Else, iterate over the string character by character, checking at every point if the number seen so far is a power of 5. If yes, add 1 to split count and check the rest of the string recursively for powers of 5 starting from step 1.
return the minimum number of splits seen so far.
I implemented the above algo in Java. I believe it works alright, but it's a straightforward recursive solution. Can this be solved using dynamic programming to improve the run time?
The code is below:
public int partition(String inp){
if(inp==null || inp.length()==0)
return 0;
return partition(inp,inp.length(),0);
}
public int partition(String inp,int len,int index){
if(len==index)
return 0;
if(isPowerOfFive(inp,index))
return 0;
long sub=0;
int count = Integer.MAX_VALUE;
for(int i=index;i<len;++i){
sub = sub*2 +(inp.charAt(i)-'0');
if(isPowerOfFive(sub))
count = Math.min(count,1+partition(inp,len,i+1));
}
return count;
}
Helper functions:
public boolean isPowerOfFive(String inp,int index){
long sub = 0;
for(int i=index;i<inp.length();++i){
sub = sub*2 +(inp.charAt(i)-'0');
}
return isPowerOfFive(sub);
}
public boolean isPowerOfFive(long val){
if(val==0)
return true;
if(val==1)
return false;
while(val>1){
if(val%5 != 0)
return false;
val = val/5;
}
return true;
}
Here is simple improvements that can be done:
Calculate all powers of 5 before start, so you could do checks faster.
Stop split input string if the number of splits is already greater than in the best split you've already done.
Here is my solution using these ideas:
public static List<String> powers = new ArrayList<String>();
public static int bestSplit = Integer.MAX_VALUE;
public static void main(String[] args) throws Exception {
// input string (5^5, 5^1, 5^10)
String inp = "110000110101101100101010000001011111001";
// calc all powers of 5 that fits in given string
for (int pow = 1; ; ++pow) {
String powStr = Long.toBinaryString((long) Math.pow(5, pow));
if (powStr.length() <= inp.length()) { // can be fit in input string
powers.add(powStr);
} else {
break;
}
}
Collections.reverse(powers); // simple heuristics, sort powers in decreasing order
// do simple recursive split
split(inp, 0, -1);
// print result
if (bestSplit == Integer.MAX_VALUE) {
System.out.println(-1);
} else {
System.out.println(bestSplit);
}
}
public static void split(String inp, int start, int depth) {
if (depth >= bestSplit) {
return; // can't do better split
}
if (start == inp.length()) { // perfect split
bestSplit = depth;
return;
}
for (String pow : powers) {
if (inp.startsWith(pow, start)) {
split(inp, start + pow.length(), depth + 1);
}
}
}
EDIT:
I also found another approach which looks like very fast one.
Calculate all powers of 5 whose string representation is shorter than input string. Save those strings in powers array.
For every string power from powers array: if power is substring of input then save its start and end indexes into the edges array (array of tuples).
Now we just need to find shortest path from index 0 to index input.length() by edges from the edges array. Every edge has the same weight, so the shortest path can be found very fast with BFS.
The number of edges in the shortest path found is exactly what you need -- minimum number of splits of the input string.
Instead of calculating all possible substrings, you can check the binary representation of the powers of 5 in search of a common pattern. Using something like:
bc <<< "obase=2; for(i = 1; i < 40; i++) 5^i"
You get:
51 = 1012
52 = 110012
53 = 11111012
54 = 10011100012
55 = 1100001101012
56 = 111101000010012
57 = 100110001001011012
58 = 10111110101111000012
59 = 1110111001101011001012
510 = 1001010100000010111110012
511 = 101110100100001110110111012
512 = 11101000110101001010010100012
513 = 10010001100001001110011100101012
514 = 1011010111100110001000001111010012
515 = 111000110101111110101001001100011012
516 = 100011100001101111001001101111110000012
517 = 10110001101000101011110000101110110001012
518 = 1101111000001011011010110011101001110110012
...
529 = 101000011000111100000111110101110011011010111001000010111110010101012
As you can see, odd powers of 5 always ends with 101 and even powers of 5 ends with the pattern 10+1 (where + means one or more occurrences).
You could put your input string in a trie and then iterate over it identifying the 10+1 pattern, once you have a match, evaluate it to check if is not a false positive.
You just have to save the value for a given string in a map. For example having if you have a string ending like this: (each letter may be a string of arbitrary size)
ABCD
You find that part A mod 5 is ok, so you try again for BCD, but find that B mod 5 is also ok, same for C and D as well as CD together. Now you should have the following results cached:
C -> 0
D -> 0
CD -> 0
BCD -> 1 # split B/CD is the best
But you're not finished with ABCD - you find that AB mod 5 is ok, so you check the resulting CD - it's already in the cache and you don't have to process it from the beginning.
In practice you just need to cache answers from partition() - either for the actual string or for the (string, start, length) tuple. Which one is better depends on how many repeating sequences you have and whether it's faster to compare the contents, or just indexes.
Given below is a solution in C++. Using dynamic programming I am considering all the possible splits and saving the best results.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int isPowerOfFive(ll n)
{
if(n == 0) return 0;
ll temp = (ll)(log(n)/log(5));
ll t = round(pow(5,temp));
if(t == n)
{
return 1;
}
else
{
return 0;
}
}
ll solve(string s)
{
vector<ll> dp(s.length()+1);
for(int i = 1; i <= s.length(); i++)
{
dp[i] = INT_MAX;
for(int j = 1; j <= i; j++)
{
if( s[j-1] == '0')
{
continue;
}
ll num = stoll(s.substr(j-1, i-j+1), nullptr, 2);
if(isPowerOfFive(num))
{
dp[i] = min(dp[i], dp[j-1]+1);
}
}
}
if(dp[s.length()] == INT_MAX)
{
return -1;
}
else
{
return dp[s.length()];
}
}
int main()
{
string s;
cin>>s;
cout<<solve(s);
}

Given a string, find its first non-repeating character in only One scan

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.

All of the option to replace an unknown number of characters

I am trying to find an algorithm that for an unknown number of characters in a string, produces all of the options for replacing some characters with stars.
For example, for the string "abc", the output should be:
*bc
a*c
ab*
**c
*b*
a**
***
It is simple enough with a known number of stars, just run through all of the options with for loops, but I'm having difficulties with an all of the options.
Every star combination corresponds to binary number, so you can use simple cycle
for i = 1 to 2^n-1
where n is string length
and set stars to the positions of 1-bits of binary representations of i
for example: i=5=101b => * b *
This is basically a binary increment problem.
You can create a vector of integer variables to represent a binary array isStar and for each iteration you "add one" to the vector.
bool AddOne (int* isStar, int size) {
isStar[size - 1] += 1
for (i = size - 1; i >= 0; i++) {
if (isStar[i] > 1) {
if (i = 0) { return true; }
isStar[i] = 0;
isStar[i - 1] += 1;
}
}
return false;
}
That way you still have the original string while replacing the characters
This is a simple binary counting problem, where * corresponds to a 1 and the original letter to a 0. So you could do it with a counter, applying a bit mask to the string, but it's just as easy to do the "counting" in place.
Here's a simple implementation in C++:
(Edit: The original question seems to imply that at least one character must be replaced with a star, so the count should start at 1 instead of 0. Or, in the following, the post-test do should be replaced with a pre-test for.)
#include <iostream>
#include <string>
// A cleverer implementation would implement C++'s iterator protocol.
// But that would cloud the simple logic of the algorithm.
class StarReplacer {
public:
StarReplacer(const std::string& s): original_(s), current_(s) {}
const std::string& current() const { return current_; }
// returns true unless we're at the last possibility (all stars),
// in which case it returns false but still resets current to the
// original configuration.
bool advance() {
for (int i = current_.size()-1; i >= 0; --i) {
if (current_[i] == '*') current_[i] = original_[i];
else {
current_[i] = '*';
return true;
}
}
return false;
}
private:
std::string original_;
std::string current_;
};
int main(int argc, const char** argv) {
for (int a = 1; a < argc; ++a) {
StarReplacer r(argv[a]);
do {
std::cout << r.current() << std::endl;
} while (r.advance());
std::cout << std::endl;
}
return 0;
}

Resources