Given an array of words sentence[] and another array of words dictionary[] denoting the correct order of words, the task is to find the number of pairs of words that are not in the correct order.
Examples:
Input: sentence[]= {“red”, “apple”, “is”, “the”}, dictionary[]= {“the”, “apple”, “is”, “red”} Output: 5 Explanation: In the comparison of the positions of each word in the two sentences, there are 5 pairs that are not in correct order. These are: (“red”, “apple”), (“red”, “is”), (“red”, “the”), (“apple”, “the”), and (“is”, “the”).
Input: sentence[] = {“sun”, “the”, “shining”, “is”, “bright”, “today”}, dictionary[]= {“the”, “sun”, “is”, “shining”, “bright”, “today”} Output: 2 Explanation: In the comparison of the positions of each word in the sentences, there are 2 pairs that are not in correct order. These are: (“sun”, “the”) and (“shining”, “is”).
We recommend you to refer Fenwick Tree or Binary Indexed Tree (BIT) before further reading this post.
Background on BIT:
BIT basically supports two operations for an array arr[] of size n:
- Sum or query of elements till arr[i] in O(log n) time.
- Update an array element in O(log n) time.
BIT is implemented using an array and works in form of trees. Note that there are two ways of looking at BIT as a tree.
- The sum or query operation where parent of index x is “x – (x & -x)”.
- The update operation where parent of index x is “x + (x & -x)”.
Approach: To solve the problem, follow the below idea:
Store the ‘dictionary‘ order in the map and convert the ‘sentence‘ order to integers using the map and store it in an array. Traverse through the array from right and for every index find the number of smaller elements on the right side of the array. This can be done using BIT. Sum up the counts for all indexes in the array and print the sum which is the number of pairs which are not in order.
Step-by-step algorithm:
- Create a map, BIT and an array.
- Store the dictionary order in the map.
- Convert the sentence order to integers using the map and store it in an array.
- Traverse through the array from right to left.
- For every index get count of elements smaller than arr[i] and add it to variable ‘ans’.
- To get the count of smaller elements, query() of BIT is used.
- After that we add the current element to the BIT[] by using update() of BIT that updates the count of the current element from 0 to 1, and therefore updates ancestors of the current element in BIT.
- Return the sum as ans.
Below is the implementation of the algorithm:
C++14
#include <bits/stdc++.h>
using namespace std;
void update( int bit[], int x, int val, int n)
{
while (x <= n) {
bit[x] += val;
x += x & -x;
}
}
int query( int bit[], int x)
{
int sum = 0;
while (x > 0) {
sum += bit[x];
x -= x & -x;
}
return sum;
}
long long getDisorderLevel(string sentence[],
string normal[], int n)
{
int MAX = n + 1;
map<string, int > m;
int bit[MAX] = { 0 }, a[MAX];
for ( int i = 0; i < n; i++) {
m[normal[i]] = i + 1;
}
for ( int i = 0; i < n; i++) {
a[i] = m[sentence[i]];
}
long long disorderLevel = 0;
for ( int i = n - 1; i >= 0; i--) {
disorderLevel += query(bit, a[i] - 1);
update(bit, a[i], 1, n);
}
return disorderLevel;
}
int main()
{
string sentence1[] = { "red", "apple", "is", "the" };
string normal1[] = { "the", "apple", "is", "red" };
int n1 = sizeof (sentence1) / sizeof (sentence1[0]);
cout << getDisorderLevel(sentence1, normal1, n1)
<< endl;
string sentence2[] = { "sun", "the", "shining",
"is", "bright", "today" };
string normal2[] = { "the", "sun", "is",
"shining", "bright", "today" };
int n2 = sizeof (sentence2) / sizeof (sentence2[0]);
cout << getDisorderLevel(sentence2, normal2, n2)
<< endl;
return 0;
}
|
Java
import java.util.*;
import java.util.HashMap;
import java.util.Map;
public class Main {
static void update( int [] bit, int x, int val, int n)
{
while (x <= n) {
bit[x] += val;
x += x & -x;
}
}
static int query( int [] bit, int x)
{
int sum = 0 ;
while (x > 0 ) {
sum += bit[x];
x -= x & -x;
}
return sum;
}
static long getDisorderLevel(String[] sentence,
String[] normal, int n)
{
int MAX = n + 1 ;
Map<String, Integer> m = new HashMap<>();
int [] bit = new int [MAX];
int [] a = new int [MAX];
for ( int i = 0 ; i < n; i++) {
m.put(normal[i], i + 1 );
}
for ( int i = 0 ; i < n; i++) {
a[i] = m.get(sentence[i]);
}
long disorderLevel = 0 ;
for ( int i = n - 1 ; i >= 0 ; i--) {
disorderLevel += query(bit, a[i] - 1 );
update(bit, a[i], 1 , n);
}
return disorderLevel;
}
public static void main(String[] args)
{
String[] sentence1
= { "red", "apple", "is", "the" };
String[] normal1 = { "the", "apple", "is", "red" };
int n1 = sentence1.length;
System.out.println(
getDisorderLevel(sentence1, normal1, n1));
String[] sentence2 = { "sun", "the", "shining",
"is", "bright", "today" };
String[] normal2 = { "the", "sun", "is",
"shining", "bright", "today" };
int n2 = sentence2.length;
System.out.println(
getDisorderLevel(sentence2, normal2, n2));
}
}
|
Python3
def update(bit, x, val, n):
while x < = n:
bit[x] + = val
x + = x & - x
def query(bit, x):
sum_val = 0
while x > 0 :
sum_val + = bit[x]
x - = x & - x
return sum_val
def get_disorder_level(sentence, normal, n):
MAX = n + 1
m = {}
bit = [ 0 ] * MAX
a = [ 0 ] * MAX
for i in range (n):
m[normal[i]] = i + 1
for i in range (n):
a[i] = m[sentence[i]]
disorder_level = 0
for i in range (n - 1 , - 1 , - 1 ):
disorder_level + = query(bit, a[i] - 1 )
update(bit, a[i], 1 , n)
return disorder_level
sentence1 = ["red", "apple", " is ", "the"]
normal1 = ["the", "apple", " is ", "red"]
n1 = len (sentence1)
print (get_disorder_level(sentence1, normal1, n1))
sentence2 = ["sun", "the", "shining", " is ", "bright", "today"]
normal2 = ["the", "sun", " is ", "shining", "bright", "today"]
n2 = len (sentence2)
print (get_disorder_level(sentence2, normal2, n2))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static void Update( int [] bit, int x, int val, int n)
{
while (x <= n)
{
bit[x] += val;
x += x & -x;
}
}
static int Query( int [] bit, int x)
{
int sum = 0;
while (x > 0)
{
sum += bit[x];
x -= x & -x;
}
return sum;
}
static long GetDisorderLevel( string [] sentence, string [] normal, int n)
{
int MAX = n + 1;
Dictionary< string , int > m = new Dictionary< string , int >();
int [] bit = new int [MAX];
int [] a = new int [MAX];
for ( int i = 0; i < n; i++)
{
m[normal[i]] = i + 1;
}
for ( int i = 0; i < n; i++)
{
a[i] = m[sentence[i]];
}
long disorderLevel = 0;
for ( int i = n - 1; i >= 0; i--)
{
disorderLevel += Query(bit, a[i] - 1);
Update(bit, a[i], 1, n);
}
return disorderLevel;
}
static void Main()
{
string [] sentence1 = { "red" , "apple" , "is" , "the" };
string [] normal1 = { "the" , "apple" , "is" , "red" };
int n1 = sentence1.Length;
Console.WriteLine(GetDisorderLevel(sentence1, normal1, n1));
string [] sentence2 = { "sun" , "the" , "shining" , "is" , "bright" , "today" };
string [] normal2 = { "the" , "sun" , "is" , "shining" , "bright" , "today" };
int n2 = sentence2.Length;
Console.WriteLine(GetDisorderLevel(sentence2, normal2, n2));
}
}
|
Javascript
function update(bit, x, val, n) {
while (x <= n) {
bit[x] += val;
x += x & -x;
}
}
function query(bit, x) {
let sum = 0;
while (x > 0) {
sum += bit[x];
x -= x & -x;
}
return sum;
}
function getDisorderLevel(sentence, normal, n) {
const MAX = n + 1;
const m = new Map();
const bit = new Array(MAX).fill(0);
const a = [];
for (let i = 0; i < n; i++) {
m.set(normal[i], i + 1);
}
for (let i = 0; i < n; i++) {
a[i] = m.get(sentence[i]);
}
let disorderLevel = 0;
for (let i = n - 1; i >= 0; i--) {
disorderLevel += query(bit, a[i] - 1);
update(bit, a[i], 1, n);
}
return disorderLevel;
}
const sentence1 = [ "red" , "apple" , "is" , "the" ];
const normal1 = [ "the" , "apple" , "is" , "red" ];
console.log(getDisorderLevel(sentence1, normal1, sentence1.length));
const sentence2 = [ "sun" , "the" , "shining" , "is" , "bright" , "today" ];
const normal2 = [ "the" , "sun" , "is" , "shining" , "bright" , "today" ];
console.log(getDisorderLevel(sentence2, normal2, sentence2.length));
|
Time complexity: O(N * log(N)), where N is the number of words in the input. Auxiliary Space: O(N)
|