Given two strings s1 and s2. Your task is to identify the characters that appear in either string but not in both (i.e., characters that are unique to one of the strings). Return the result as a sorted string.
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] Two Nested Loops - O(n * m) Time and O(MAX_CHAR) Space
The idea is to use nested loops to check whether each character of s1 is present in s2, and each character of s2 is present in s1. Use a check[] array of size MAX_CHAR to handle duplicate characters and store each uncommon character only once.
- For each character, check its presence in the other string and add it to res if it is not found and has not been added before.
- Finally, sort res in ascending order and return it.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
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 res = "";
// 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;
res.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;
res.push_back(s2[i]);
}
}
// Sort the result string
sort(res.begin(), res.end());
return res;
}
int main()
{
string s1 = "characters";
string s2 = "alphabets";
cout << "\"" << uncommonChars(s1, s2) << "\"";
return 0;
}
import java.util.Arrays;
public 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)
{
// To store the answer
String res = "";
// To handle the case of duplicates, we use an array
// 'check' to track visited characters
boolean[] check = new boolean[MAX_CHAR];
// Check for characters in s1
for (int i = 0; i < s1.length(); i++) {
// Keeping a flag variable
boolean found = false;
// Check if the character in s1 is present in s2
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 the answer
if (!found && !check[s1.charAt(i) - 'a']) {
check[s1.charAt(i) - 'a'] = true;
res += s1.charAt(i);
}
}
// Now check for characters in s2
for (int i = 0; i < s2.length(); i++) {
// Keeping a flag variable
boolean found = false;
// Check if the character in s2 is present in s1
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 the answer
if (!found && !check[s2.charAt(i) - 'a']) {
check[s2.charAt(i) - 'a'] = true;
res += s2.charAt(i);
}
}
// Sort the result string
char[] resArray = res.toCharArray();
Arrays.sort(resArray);
return new String(resArray);
}
public static void main(String[] args)
{
String s1 = "characters";
String s2 = "alphabets";
System.out.println("\"" + uncommonChars(s1, s2)
+ "\"");
}
}
def uncommonChars(s1, s2):
# To store the answer
res = ""
# To handle the case of duplicates, we use an array
# 'check' to track visited characters
check = [False] * 26
# Check for characters in s1
for i in range(len(s1)):
# Keeping a flag variable
found = False
# Check if the character in s1 is present in s2
for j in range(len(s2)):
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 not found and not check[ord(s1[i]) - ord('a')]:
check[ord(s1[i]) - ord('a')] = True
res += s1[i]
# Now check for characters in s2
for i in range(len(s2)):
# Keeping a flag variable
found = False
# Check if the character in s2 is present in s1
for j in range(len(s1)):
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 not found and not check[ord(s2[i]) - ord('a')]:
check[ord(s2[i]) - ord('a')] = True
res += s2[i]
# Sort the result string
res = ''.join(sorted(res))
return res
if __name__ == '__main__':
s1 = "characters"
s2 = "alphabets"
print("\"" + uncommonChars(s1, s2) + "\"")
using System;
using System.Collections.Generic;
using System.Linq;
class GFG {
const int MAX_CHAR = 26;
// Function to find the uncommon characters of the two
// strings
static string uncommonChars(string s1, string s2)
{
// To store the answer
string res = "";
// To handle the case of duplicates, we use an array
// 'check' to track visited characters
bool[] check = new bool[MAX_CHAR];
// Check for characters in s1
for (int i = 0; i < s1.Length; i++) {
// Keeping a flag variable
bool found = false;
// Check if the character in s1 is present in s2
for (int j = 0; j < s2.Length; 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;
res += s1[i];
}
}
// Now check for characters in s2
for (int i = 0; i < s2.Length; i++) {
// Keeping a flag variable
bool found = false;
// Check if the character in s2 is present in s1
for (int j = 0; j < s1.Length; 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;
res += s2[i];
}
}
// Sort the result string
char[] resArray = res.ToCharArray();
Array.Sort(resArray);
res = new string(resArray);
return res;
}
static void Main(string[] args)
{
string s1 = "characters";
string s2 = "alphabets";
Console.WriteLine("\"" + uncommonChars(s1, s2)
+ "\"");
}
}
// Function to find the uncommon characters of the two
// strings
function uncommonChars(s1, s2)
{
const MAX_CHAR = 26;
// To store the answer
let res = "";
// To handle the case of duplicates, we use an array
// 'check' to track visited characters
let check = Array(MAX_CHAR).fill(false);
// Check for characters in s1
for (let i = 0; i < s1.length; i++) {
// Keeping a flag variable
let found = false;
// Check if the character in s1 is present in s2
for (let j = 0; j < s2.length; 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].charCodeAt(0)
- "a".charCodeAt(0)]) {
check[s1[i].charCodeAt(0) - "a".charCodeAt(0)]
= true;
res += s1[i];
}
}
// Now check for characters in s2
for (let i = 0; i < s2.length; i++) {
// Keeping a flag variable
let found = false;
// Check if the character in s2 is present in s1
for (let j = 0; j < s1.length; 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].charCodeAt(0)
- "a".charCodeAt(0)]) {
check[s2[i].charCodeAt(0) - "a".charCodeAt(0)]
= true;
res += s2[i];
}
}
// Sort the result string
res = res.split("").sort().join("");
return res;
}
// Driver Code
let s1 = "characters";
let s2 = "alphabets";
console.log(`\"${uncommonChars(s1, s2)}\"`);
Output
"bclpr"
[Expected Approach] Array Indexing - O(n + m) Time and O(MAX_CHAR) Space
The idea is to use an array present[] of size MAX_CHAR to store the status of each character. Mark characters of s1 as 1, then update the status while traversing s2 to identify characters present in both or only in s2.
- Mark characters of s1 as 1; while traversing s2, mark common characters as -1 and new characters as 2.
- Finally, traverse present[] and add characters with value 1 or 2 to res. Since the array is traversed from a to z, the result is already sorted.
Let us understand with an example:
Input: s1 = "characters", s2 = "alphabets"
- First, traverse s1 and mark its characters as 1 in present[]: a, c, e, h, r, s, t.
- Traverse s2. Common characters a, e, h, s, t are marked as -1, while new characters b, l, p are marked as 2.
- Finally, traverse present[] and add characters having value 1 or 2 to res.
- The uncommon characters are b, c, l, p, r.
Output: "bclpr".
#include <iostream>
#include <string>
#include <vector>
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 res = "";
// 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)
res.push_back(char(i + 'a'));
return res;
}
int main()
{
string s1 = "characters";
string s2 = "alphabets";
cout << "\"" << uncommonChars(s1, s2) << "\"";
return 0;
}
import java.util.Arrays;
public 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)
{
// mark presence of each character as 0
// in the hash table 'present[]'
int[] present = new int[MAX_CHAR];
// string to store the answer.
StringBuilder res = new StringBuilder("");
// for each character of s1, mark its
// presence as 1 in 'present[]'
for (int i = 0; i < s1.length(); i++)
present[s1.charAt(i) - 'a'] = 1;
// for each character of s2
for (int 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.charAt(i) - 'a'] == 1
|| present[s2.charAt(i) - 'a'] == -1)
present[s2.charAt(i) - 'a'] = -1;
// else mark its presence as 2
else
present[s2.charAt(i) - 'a'] = 2;
}
// store all the uncommon characters
for (int i = 0; i < 26; i++)
if (present[i] == 1 || present[i] == 2)
res.append((char)(i + 'a'));
return res.toString();
}
public static void main(String[] args)
{
String s1 = "characters";
String s2 = "alphabets";
System.out.println("\"" + uncommonChars(s1, s2)
+ "\"");
}
}
# function to find the uncommon characters
# of the two strings
def uncommonChars(s1, s2):
MAX_CHAR = 26
# mark presence of each character as 0
# in the hash table 'present[]'
present = [0] * MAX_CHAR
# string to store the answer.
res = ""
# for each character of s1, mark its
# presence as 1 in 'present[]'
for char in s1:
present[ord(char) - ord('a')] = 1
# for each character of s2
for char in s2:
# if a character of s2 is also present
# in s1, then mark its presence as -1
if present[ord(char) - ord('a')] == 1 or present[ord(char) - ord('a')] == -1:
present[ord(char) - ord('a')] = -1
# else mark its presence as 2
else:
present[ord(char) - ord('a')] = 2
# store all the uncommon characters
for i in range(MAX_CHAR):
if present[i] == 1 or present[i] == 2:
res += chr(i + ord('a'))
return res
if __name__ == '__main__':
s1 = "characters"
s2 = "alphabets"
print("\"" + uncommonChars(s1, s2) + "\"")
using System;
class GFG {
const int MAX_CHAR = 26;
// function to find the uncommon characters
// of the two strings
static string uncommonChars(string s1, string s2)
{
// mark presence of each character as 0
// in the hash table 'present[]'
int[] present = new int[MAX_CHAR];
// string to store the answer.
string res = "";
// for each character of s1, mark its
// presence as 1 in 'present[]'
for (int i = 0; i < s1.Length; i++)
present[s1[i] - 'a'] = 1;
// for each character of s2
for (int 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[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)
res += (char)(i + 'a');
return res;
}
static void Main()
{
string s1 = "characters";
string s2 = "alphabets";
Console.WriteLine("\"" + uncommonChars(s1, s2)
+ "\"");
}
}
// function to find the uncommon characters
// of the two strings
function uncommonChars(s1, s2)
{
const MAX_CHAR = 26;
// mark presence of each character as 0
// in the hash table 'present[]'
const present = new Array(MAX_CHAR).fill(0);
// string to store the answer.
let res = "";
// 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)
res += String.fromCharCode(i
+ "a".charCodeAt(0));
return res;
}
// Driver Code
const s1 = "characters";
const s2 = "alphabets";
console.log("\"" + uncommonChars(s1, s2) + "\"");
Output
"bclpr"
Note: MAX_CHAR represents the size of the character set. Since the input contains only lowercase English letters, MAX_CHAR is 26. If the input contains all ASCII characters, MAX_CHAR would be 256.
[Alternate Approach] Bit Manipulation - O(n + m) Time and O(1) Space
The idea is to use two variables that store the bitwise OR of the left shift of 1 with each character's ASCII code - 97, i.e. 0 for 'a', 1 for 'b', and so on.
For both strings, we get an integer after performing these bitwise operations. The bitwise XOR of these two integers gives the bit as 1 only at positions that denote uncommon characters because XOR of opposite bits is 1.
- Traverse both strings and set the bit corresponding to each character.
- Print the character values for the positions where the resulting bit is 1.
Let us understand with an example:
Input: s1 = "characters", s2 = "alphabets"
- For s1 = "characters", the bits corresponding to a, c, e, h, r, s, t are set in a1.
- For s2 = "alphabets", the bits corresponding to a, b, e, h, l, p, s, t are set in a2.
- res = a1 ^ a2 keeps only the bits of characters that occur in one string but not both, giving b, c, l, p, r.
- Traverse the 26 bits from a to z and add the characters whose bits are set.
Output: "bclpr".
#include <iostream>
#include <string>
using namespace std;
// Function to find the uncommon characters
// of the two strings
string uncommonChars(string &s1, string &s2)
{
// Store characters of s1 and s2 using bits
int a1 = 0, a2 = 0;
// Set the bit corresponding to each character of s1
for (int i = 0; i < s1.length(); i++)
{
int ch = s1[i] - 'a';
a1 = a1 | (1 << ch);
}
// Set the bit corresponding to each character of s2
for (int i = 0; i < s2.length(); i++)
{
int ch = s2[i] - 'a';
a2 = a2 | (1 << ch);
}
// XOR leaves only uncommon characters
int res = a1 ^ a2;
// To store the result
string ans = "";
// Check each of the 26 bits
for (int i = 0; i < 26; i++)
{
if (res % 2 == 1)
ans.push_back(char('a' + i));
res = res / 2;
}
return ans;
}
int main()
{
string s1 = "characters";
string s2 = "alphabets";
cout << "\"" << uncommonChars(s1, s2) << "\"";
return 0;
}
import java.util.Scanner;
// Function to find the uncommon characters
// of the two strings
public class GFG {
public static String uncommonChars(String s1, String s2)
{
// Store characters of s1 and s2 using bits
int a1 = 0, a2 = 0;
// Set the bit corresponding to each character of s1
for (int i = 0; i < s1.length(); i++) {
int ch = s1.charAt(i) - 'a';
a1 = a1 | (1 << ch);
}
// Set the bit corresponding to each character of s2
for (int i = 0; i < s2.length(); i++) {
int ch = s2.charAt(i) - 'a';
a2 = a2 | (1 << ch);
}
// XOR leaves only uncommon characters
int res = a1 ^ a2;
// To store the result
String ans = "";
// Check each of the 26 bits
for (int i = 0; i < 26; i++) {
if (res % 2 == 1)
ans += (char)('a' + i);
res = res / 2;
}
return ans;
}
public static void main(String[] args)
{
String s1 = "characters";
String s2 = "alphabets";
System.out.println("\"" + uncommonChars(s1, s2)
+ "\"");
}
}
# Function to find the uncommon characters
# of the two strings
def uncommonChars(s1, s2):
# Store characters of s1 and s2 using bits
a1 = 0
a2 = 0
# Set the bit corresponding to each character of s1
for i in range(len(s1)):
ch = ord(s1[i]) - ord('a')
a1 = a1 | (1 << ch)
# Set the bit corresponding to each character of s2
for i in range(len(s2)):
ch = ord(s2[i]) - ord('a')
a2 = a2 | (1 << ch)
# XOR leaves only uncommon characters
res = a1 ^ a2
# To store the result
ans = ''
# Check each of the 26 bits
for i in range(26):
if res % 2 == 1:
ans += chr(ord('a') + i)
res = res // 2
return ans
if __name__ == "__main__":
s1 = 'characters'
s2 = 'alphabets'
print(f'"{uncommonChars(s1, s2)}"')
using System;
using System.Text;
class GFG {
// Function to find the uncommon characters
// of the two strings
static string uncommonChars(string s1, string s2)
{
// Store characters of s1 and s2 using bits
int a1 = 0, a2 = 0;
// Set the bit corresponding to each character of s1
for (int i = 0; i < s1.Length; i++) {
int ch = s1[i] - 'a';
a1 = a1 | (1 << ch);
}
// Set the bit corresponding to each character of s2
for (int i = 0; i < s2.Length; i++) {
int ch = s2[i] - 'a';
a2 = a2 | (1 << ch);
}
// XOR leaves only uncommon characters
int res = a1 ^ a2;
// To store the result
string ans = "";
// Check each of the 26 bits
for (int i = 0; i < 26; i++) {
if ((res & 1) == 1)
ans += (char)('a' + i);
res = res >> 1;
}
return ans;
}
static void Main()
{
string s1 = "characters";
string s2 = "alphabets";
Console.WriteLine("\"" + uncommonChars(s1, s2)
+ "\"");
}
}
function uncommonChars(s1, s2)
{
// Store characters of s1 and s2 using bits
let a1 = 0, a2 = 0;
// Set the bit corresponding to each character of s1
for (let i = 0; i < s1.length; i++) {
let ch = s1.charCodeAt(i) - "a".charCodeAt(0);
a1 = a1 | (1 << ch);
}
// Set the bit corresponding to each character of s2
for (let i = 0; i < s2.length; i++) {
let ch = s2.charCodeAt(i) - "a".charCodeAt(0);
a2 = a2 | (1 << ch);
}
// XOR leaves only uncommon characters
let res = a1 ^ a2;
// To store the result
let ans = "";
// Check each of the 26 bits
for (let i = 0; i < 26; i++) {
if ((res & 1) === 1)
ans += String.fromCharCode("a".charCodeAt(0)
+ i);
res = res >> 1;
}
return ans;
}
// Driver Code
let s1 = "characters";
let s2 = "alphabets";
console.log("\"" + uncommonChars(s1, s2) + "\"");
Output
"bclpr"