Find uncommon characters of the two strings (original) (raw)
Last Updated : 26 Dec, 2024
Given two strings **s1 and **s2, the task is to **find the **uncommon **characters in **both strings. An uncommon character means that the **character is **present in only **one string or in **another string but **not in **both. The strings contain only **lowercase characters and can have **duplicates.
**Note: Output the uncommon characters in **sorted order.
**Examples:
**Input: s1 = "geeksforgeeks", s2 = "geeksquiz"
**Output: "fioqruz"
**Explanation: The characters 'f', 'i', 'o', 'q', 'r', 'u', and 'z' are present in either s1 or s2, but not in both.**Input: s1 = "characters", s2 = "alphabets"
**Output: "bclpr"
**Explanation: The characters 'b', 'c', 'l', 'p', and 'r' are present in either s1 or s2, but not in both.**Input: s1 = "rome", s2 = "more"
**Output: ""
**Explanation: Both strings contain the same characters, so there are no unique characters. The output is an empty string.
Table of Content
- [Naive Approach] Using Two Nested Loops - O(n*m) Time and O(MAX_CHAR) Space
- [Better Approach] Using Hashing - O(n + m) Time and O(MAX_CHAR) Space
- [Expected Approach] Using Bit Manipulation O(n) Time and O(1) Space
[Naive Approach] Using Two Nested Loops - O(n*m) Time and O(MAX_CHAR) Space
The idea is to use nested loops: for each character in string s1, **check whether it is present in string s2 or not. Likewise, for each character in **string s2, **check whether it is present in string s1 or not. Create an array **check[] of **size MAX_CHAR (where MAX_CHAR is set to 26 for lowercase English letters) to flag the already used characters. Store the **uncommon characters in a character array or string. Finally, **sort the characters in ascending order and print the result.
C++ `
// C++ implementation to find the uncommon // characters of the two strings #include <bits/stdc++.h> using namespace std;
const int MAX_CHAR = 26;
// Function to find the uncommon characters of the two strings string uncommonChars(string &s1, string &s2) {
// To store the answer
string ans = "";
// To handle the case of duplicates, we use an array
// 'check' to track visited characters
vector<bool> check(MAX_CHAR, false);
// Check for characters in s1
for (int i = 0; i < s1.size(); i++) {
// Keeping a flag variable
bool found = false;
// Check if the character in s1 is present in s2
for (int j = 0; j < s2.size(); j++) {
if (s1[i] == s2[j]) {
found = true;
break;
}
}
// If character is not found in s2 and not already
// used, add it to the answer
if (!found && !check[s1[i] - 'a']) {
check[s1[i] - 'a'] = true;
ans.push_back(s1[i]);
}
}
// Now check for characters in s2
for (int i = 0; i < s2.size(); i++) {
// Keeping a flag variable
bool found = false;
// Check if the character in s2 is present in s1
for (int j = 0; j < s1.size(); j++) {
if (s2[i] == s1[j]) {
found = true;
break;
}
}
// If character is not found in s1 and not already
// used, add it to the answer
if (!found && !check[s2[i] - 'a']) {
check[s2[i] - 'a'] = true;
ans.push_back(s2[i]);
}
}
// Sort the result string
sort(ans.begin(), ans.end());
return ans;}
int main() { string s1 = "characters"; string s2 = "alphabets";
cout << uncommonChars(s1, s2);
return 0;}
Java
// Java implementation to find the uncommon // characters of the two strings import java.util.Arrays;
class GfG {
static final int MAX_CHAR = 26;
// Function to find the uncommon characters of the two
// strings
static String uncommonChars(String s1, String s2) {
StringBuilder ans = new StringBuilder();
// To handle the case of duplicates
boolean[] check = new boolean[MAX_CHAR];
// Check first for s1
for (int i = 0; i < s1.length(); i++) {
boolean found = false;
for (int j = 0; j < s2.length(); j++) {
if (s1.charAt(i) == s2.charAt(j)) {
found = true;
break;
}
}
// If character is not found in s2 and not
// already used, add it to ans
if (!found && !check[s1.charAt(i) - 'a']) {
check[s1.charAt(i) - 'a'] = true;
ans.append(s1.charAt(i));
}
}
// Now check for s2
for (int i = 0; i < s2.length(); i++) {
boolean found = false;
for (int j = 0; j < s1.length(); j++) {
if (s2.charAt(i) == s1.charAt(j)) {
found = true;
break;
}
}
// If character is not found in s1 and not
// already used, add it to ans
if (!found && !check[s2.charAt(i) - 'a']) {
check[s2.charAt(i) - 'a'] = true;
ans.append(s2.charAt(i));
}
}
// Sort the answer string
char[] ansArray = ans.toString().toCharArray();
Arrays.sort(ansArray);
return new String(ansArray);
}
public static void main(String[] args) {
String s1 = "characters";
String s2 = "alphabets";
System.out.println(uncommonChars(s1, s2));
}}
Python
Python implementation to find the uncommon
characters of the two strings
MAX_CHAR = 26
def uncommonChars(s1, s2): ans = ""
# to handle the case of duplicates
check = [False] * MAX_CHAR
# check first for s1
for i in range(len(s1)):
found = False
for j in range(len(s2)):
if s1[i] == s2[j]:
found = True
break
if not found and not check[ord(s1[i]) - ord('a')]:
check[ord(s1[i]) - ord('a')] = True
ans += s1[i]
# now check for s2
for i in range(len(s2)):
found = False
for j in range(len(s1)):
if s2[i] == s1[j]:
found = True
break
if not found and not check[ord(s2[i]) - ord('a')]:
check[ord(s2[i]) - ord('a')] = True
ans += s2[i]
# Sort the result string
ans = ''.join(sorted(ans))
return ansif name == "main": s1 = "characters" s2 = "alphabets" print(uncommonChars(s1, s2))
C#
// C# implementation to find the uncommon // characters of the two strings using System; using System.Text;
class GfG {
const int MAX_CHAR = 26;
// Function to find the uncommon characters of the two
// strings
static string uncommonChars(string s1, string s2) {
StringBuilder ans = new StringBuilder("");
// to handle the case of duplicates
bool[] check = new bool[MAX_CHAR];
// Check first for s1
for (int i = 0; i < s1.Length; i++) {
bool found = false;
for (int j = 0; j < s2.Length; j++) {
if (s1[i] == s2[j]) {
found = true;
break;
}
}
if (!found && !check[s1[i] - 'a']) {
check[s1[i] - 'a'] = true;
ans.Append(s1[i]);
}
}
// Now check for s2
for (int i = 0; i < s2.Length; i++) {
bool found = false;
for (int j = 0; j < s1.Length; j++) {
if (s2[i] == s1[j]) {
found = true;
break;
}
}
if (!found && !check[s2[i] - 'a']) {
check[s2[i] - 'a'] = true;
ans.Append(s2[i]);
}
}
// Sort the answer
char[] ansArray = ans.ToString().ToCharArray();
Array.Sort(ansArray);
return new string(ansArray);
}
static void Main(string[] args) {
string s1 = "characters";
string s2 = "alphabets";
Console.WriteLine(uncommonChars(s1, s2));
}}
JavaScript
// Javascript implementation to find the uncommon // characters of the two strings
function uncommonChars(s1, s2) { let ans = ""; const MAX_CHAR = 26;
// to handle the case of duplicates
let check = Array(MAX_CHAR).fill(false);
// check first for s1
for (let i = 0; i < s1.length; i++) {
let found = false;
for (let j = 0; j < s2.length; j++) {
if (s1[i] === s2[j]) {
found = true;
break;
}
}
if (!found && !check[s1.charCodeAt(i) - 'a'.charCodeAt(0)]) {
check[s1.charCodeAt(i) - 'a'.charCodeAt(0)] = true;
ans = ans.concat(s1[i]);
}
}
// now check for s2
for (let i = 0; i < s2.length; i++) {
let found = false;
for (let j = 0; j < s1.length; j++) {
if (s2[i] === s1[j]) {
found = true;
break;
}
}
if (!found && !check[s2.charCodeAt(i) - 'a'.charCodeAt(0)]) {
check[s2.charCodeAt(i) - 'a'.charCodeAt(0)] = true;
ans = ans.concat(s2[i]);
}
}
// sort the answer
ans = ans.split('').sort().join('');
return ans;}
//driver code let s1 = "characters"; let s2 = "alphabets"; console.log(uncommonChars(s1, s2));
`
[Better Approach] Using Hashing - O(n + m) Time and O(MAX_CHAR) Space
The idea is to use a hash table , present[], of size **MAX_CHAR (set to 26 for the lowercase English alphabet), to store the characters of each string. First, iterate through the **string s1 and mark each character in the present[] array with the value 1. Then, iterate through the string s2, and update the **present[] array: mark characters already seen in s1 with the value -1 and mark new characters in s2 with the value 2. Finally, collect all characters marked as unique (i.e., those with value 1 or 2), and return them in **sorted order.
Note the **MAX_CHAR is alphabet size of input characters which is typically a constant. If we have only lower case characters, then MAX_CHAR is 26 only. If we consider all ASCII characters, then MAX_CHAR is 256.
C++ `
// C++ implementation to find the uncommon // characters of the two strings #include <bits/stdc++.h> using namespace std;
const int MAX_CHAR = 26;
// function to find the uncommon characters // of the two strings string uncommonChars(string &s1, string &s2) {
// mark presence of each character as 0
// in the hash table 'present[]'
vector<int> present(MAX_CHAR, 0);
// string to store the answer.
string ans = "";
// for each character of s1, mark its
// presence as 1 in 'present[]'
for (int i = 0; i < s1.size(); i++)
present[s1[i] - 'a'] = 1;
// for each character of s2
for (int i = 0; i < s2.size(); i++) {
// if a character of s2 is also present
// in s1, then mark its presence as -1
if (present[s2[i] - 'a'] == 1 || present[s2[i] - 'a'] == -1)
present[s2[i] - 'a'] = -1;
// else mark its presence as 2
else
present[s2[i] - 'a'] = 2;
}
// store all the uncommon characters
for (int i = 0; i < 26; i++)
if (present[i] == 1 || present[i] == 2)
ans.push_back(char(i + 'a'));
return ans;}
int main() { string s1 = "characters"; string s2 = "alphabets"; cout << uncommonChars(s1, s2); return 0; }
Java
// Java implementation to find the uncommon // characters of the two strings import java.util.Arrays;
class GfG {
static final int MAX_CHAR = 26;
static String uncommonChars(String s1, String s2) {
StringBuilder ans = new StringBuilder();
// mark presence of each character as 0
// in the hash table 'present[]'
int[] present = new int[MAX_CHAR];
for (int i = 0; i < 26; i++) {
present[i] = 0;
}
// store each character of s1
for (int i = 0; i < s1.length(); i++) {
present[s1.charAt(i) - 'a'] = 1;
}
// check for each character of s2
for (int i = 0; i < s2.length(); i++) {
if (present[s2.charAt(i) - 'a'] == 1
|| present[s2.charAt(i) - 'a'] == -1) {
present[s2.charAt(i) - 'a'] = -1;
}
else {
present[s2.charAt(i) - 'a'] = 2;
}
}
for (int i = 0; i < 26; i++) {
if (present[i] == 1 || present[i] == 2) {
ans.append((char)(i + 'a'));
}
}
return ans.toString();
}
public static void main(String[] args) {
String s1 = "characters";
String s2 = "alphabets";
System.out.println(uncommonChars(s1, s2));
}}
Python
Python implementation to find the uncommon
characters of the two strings
MAX_CHAR = 26 def uncommonChars(s1, s2): ans = ""
# Mark presence of each character as 0 in the
# hash table 'present[]'
present = [0] * MAX_CHAR
# Store characters in s1
for char in s1:
present[ord(char) - ord('a')] = 1
# Check for each character of s2
for char in s2:
index = ord(char) - ord('a')
if present[index] == 1:
present[index] = -1
elif present[index] == 0:
present[index] = 2
# Collect the uncommon characters
for i in range(MAX_CHAR):
if present[i] == 1 or present[i] == 2:
ans += chr(i + ord('a'))
return ansif name == "main": s1 = "characters" s2 = "alphabets" print(uncommonChars(s1, s2))
C#
// C# implementation to find the uncommon // characters of the two strings using System; using System.Text;
class GfG {
static int MAX_CHAR = 26;
static string uncommonChars(string s1, string s2) {
StringBuilder ans = new StringBuilder("");
// create hashtable of size 26
// and fill elements with 0
int[] present = new int[MAX_CHAR];
for (int i = 0; i < 26; i++) {
present[i] = 0;
}
// store elements of s1
for (int i = 0; i < s1.Length; i++) {
present[s1[i] - 'a'] = 1;
}
// check for s2;
for (int i = 0; i < s2.Length; i++) {
if (present[s2[i] - 'a'] == 1 ||
present[s2[i] - 'a'] == -1) {
present[s2[i] - 'a'] = -1;
}
else {
present[s2[i] - 'a'] = 2;
}
}
// store the results.
for (int i = 0; i < 26; i++) {
if (present[i] == 1 || present[i] == 2) {
ans.Append((char)(i + 'a'));
}
}
char[] ansArray = ans.ToString().ToCharArray();
Array.Sort(ansArray);
return new string(ansArray);
}
static void Main(string[] args) {
string s1 = "characters";
string s2 = "alphabets";
Console.WriteLine(uncommonChars(s1, s2));
}}
JavaScript
// JavaScript function to find the uncommon characters // of two strings function uncommonChars(s1, s2) {
const MAX_CHAR = 26;
let present = new Array(MAX_CHAR).fill(0);
let ans = "";
// For each character of s1, mark its
// presence as 1 in 'present[]'
for (let i = 0; i < s1.length; i++) {
present[s1.charCodeAt(i) - "a".charCodeAt(0)] = 1;
}
// For each character of s2
for (let i = 0; i < s2.length; i++) {
// If a character of s2 is also present
// in s1, then mark its presence as -1
if (present[s2.charCodeAt(i) - "a".charCodeAt(0)]
=== 1
|| present[s2.charCodeAt(i) - "a".charCodeAt(0)]
=== -1) {
present[s2.charCodeAt(i) - "a".charCodeAt(0)]
= -1;
}
// Else mark its presence as 2
else {
present[s2.charCodeAt(i) - "a".charCodeAt(0)]
= 2;
}
}
// Store all the uncommon characters
for (let i = 0; i < 26; i++) {
if (present[i] === 1 || present[i] === 2) {
ans += String.fromCharCode(i
+ "a".charCodeAt(0));
}
}
return ans;}
// Driver code const s1 = "characters"; const s2 = "alphabets"; console.log(uncommonChars(s1, s2));
`
[Expected Approach] Using Bit Manipulation - O(n) Time and O(1) Space
The approach uses 2 variables that store the bit-wise OR of the **left shift of 1 with each character’s ASCII code. For both the strings, we get an integer after performing these bit-wise operations. Now the XOR of these two integers will give the binary bit as 1 at only those positions that denote uncommon characters. Print the character values for those positions. Please refer to Find uncommon characters of the two strings using Bit Manipulation for implementation.