simpest way to get the longest sequence of sorted elements from a given unsorted integer vector in c++ - c++

I have an unsorted array and need to extract the longest sequence of sorted elements.
For instance
A = 2,4,1,7,4,5,0,8,65,4,2,34
here 0,8,65 is my target sequence
I need to keep track of the index where this sequence starts

You can do it in linear time O(N) with this algorithm: construct vector len of the same size N as the original vector, such that len[i] contains the length of the longest consecutive ascending run to which element seq[i] belongs.
The value of len[i] can be calculated as follows:
len[0] = 1;
for (int i = 1 ; i != N ; i++) {
len[i] = seq[i-1] >= seq[i] ? 1 : len[i-1]+1;
}
With len in hand, find the index of max(len) element. This is the last element of your run. Track back to len[j] == 1 to find the initial element of the run.
seq len
--- ---
2 1
4 2
1 1
7 2
4 1
5 2
0 1
8 2
65 3 << MAX
4 1
2 1
34 2
Note that at each step of the algorithm you need only the element len[i-1] to calculate len, so you can optimize for constant space by dropping vector representation of len and keeping the prior one, the max_len, and max_len_index.
Here is this algorithm optimized for constant space. Variable len represents len[i-1] from the linear-space algorithm.
int len = 1, pos = 0, maxlen = 1, current_start = 0;
for (int i = 1 ; i < seq.size() ; i++) {
if (seq[i] > seq[i-1]) {
len++;
if (len > maxlen) {
maxlen = len;
pos = current_start;
}
} else {
len = 1;
current_start = i;
}
}
Here is a link to this program on ideone.

You need 4 indexes (begin, end, tmp_begin, tmp_end). Iterate through the original array using tmp_begin, tmp_end as the work indexes and each time you find a longer sorted sequence update begin and end indices.
To check that a subsequence is sorted, you have to check that element at i is greater than element at i-- for each pair of consecutive items in the subsequence.
In the end: print all the elements in the original array starting at begin and ending at end.

for(int i=0;i<size_of_array;i++)
{
iterate++;
after=array[iterate];
if(after>before) {current_counter++;} else {current_counter=0;}
if(max_counter<current_counter) max_counter=current_counter;
before=array[iterate];
}
printf(" maximum length=%i ",max_counter);

Related

Tell me the Input in which this code will give incorrect Output

There's a problem, which I've to solve in c++. I've written the whole code and it's working in the given test cases but when I'm submitting it, It's saying wrong answer. I can't understand that why is it showing wrong answer.
I request you to tell me an input for the given code, which will give incorrect output so I can modify my code further.
Shrink The Array
You are given an array of positive integers A[] of length L. If A[i] and A[i+1] both are equal replace them by one element with value A[i]+1. Find out the minimum possible length of the array after performing such operation any number of times.
Note:
After each such operation, the length of the array will decrease by one and elements are renumerated accordingly.
Input format:
The first line contains a single integer L, denoting the initial length of the array A.
The second line contains L space integers A[i] − elements of array A[].
Output format:
Print an integer - the minimum possible length you can get after performing the operation described above any number of times.
Example:
Input
7
3 3 4 4 4 3 3
Output
2
Sample test case explanation
3 3 4 4 4 3 3 -> 4 4 4 4 3 3 -> 4 4 4 4 4 -> 5 4 4 4 -> 5 5 4 -> 6 4.
Thus the length of the array is 2.
My code:
#include <bits/stdc++.h>
using namespace std;
int main()
{
bool end = false;
int l;
cin >> l;
int arr[l];
for(int i = 0; i < l; i++){
cin >> arr[i];
}
int len = l, i = 0;
while(i < len - 1){
if(arr[i] == arr[i + 1]){
arr[i] = arr[i] + 1;
if((i + 1) <= (len - 1)){
for(int j = i + 1; j < len - 1; j++){
arr[j] = arr[j + 1];
}
}
len--;
i = 0;
}
else{
i++;
}
}
cout << len;
return 0;
}
THANK YOU
As noted in the comments: Just picking the first two neighbours that have the same value and combining those will lead to suboptimal results.
You will need to investigate which two neighbours you should combine somehow. When you have combined two neighbours you then need to investigate which neighbours to combine on the next level. The number of combinations may become plentiful.
One way to solve this is through recursion.
If you've followed the advice in the comments, you now have all your input data in std::vector<unsigned> A(L).
You can now do std::cout << solve(A) << '\n'; where solve has the signature size_t solve(const std::vector<unsigned>& A) and is described below:
Find the indices of all neighbour pairs in A that has the same values and put the indices in a std::vector<size_t> neighbours. Example: If A contains 2 2 2 3, put 0 and 1 in neighbours.
If no neighbours are found (neighbours.empty() == true), return A.size().
Define a minimum variable and initialize it with A.size() - 1 which is the worst result you know you can get at this point. So, size_t minimum = A.size() - 1;
Loop over all indices stored in neighbours (for(size_t idx : neighbours))
Copy A into a new std::vector<unsigned>. Let's call it cpy.
Increase cpy[idx] by one and remove cpy[idx+1].
Call size_t result = solve(cpy). This is where recursion comes in.
Is result less than minimum? If so assign result to minimum.
Return minimum.
I don't think I ruined the programming exercise by providing one algorithm for solving this. It should still have plenty of things to deal with. Recursion won't be possible with big data etc.

Array-Sum Operation

I have written this code using vector. Some case has been passed but others show timeout termination error.
The problem statement is:-
You have an identity permutation of N integers as an array initially. An identity permutation of N integers is [1,2,3,...N-1,N]. In this task, you have to perform M operations on the array and report the sum of the elements of the array after each operation.
The ith operation consists of an integer opi.
If the array contains opi, swap the first and last elements in the array.
Else, remove the last element of the array and push opi to the end of the array.
Input Format
The first line contains two space-separated integers N and M.
Then, M lines follow denoting the operations opi.
Constraints :
2<=N,M <= 10^5
1 <= op <= 5*10^5
Output Format
Print M lines, each containing a single integer denoting the answer to each of the M operations.
Sample Input 0
3 2
4
2
Sample Output 0
7
7
Explanation 0
Initially, the array is [1,2,3].
After the 1st operation, the array becomes[1,2,4] as opi = 4, as 4 is not present in the current array, we remove 3 and push 4 to the end of the array and hence, sum=7 .
After 2nd operation the array becomes [4,2,1] as opi = 2, as 2 is present in the current array, we swap 1 and 4 and hence, sum=7.
Here is my code:
#include <bits/stdc++.h>
using namespace std;
int main()
{
long int N,M,op,i,t=0;
vector<long int > g1;
cin>>N>>M;
if(N>=2 && M>=2) {
g1.reserve(N);
for(i = 1;i<=N;i++) {
g1.push_back(i);
}
while(M--) {
cin>>op;
auto it = find(g1.begin(), g1.end(), op);
if(it != (g1.end())) {
t = g1.front();
g1.front() = g1.back();
g1.back() = t;
cout<<accumulate(g1.begin(), g1.end(), 0);
cout<<endl;
}
else {
g1.back() = op;
cout<<accumulate(g1.begin(), g1.end(), 0);
cout<<endl;
}
}
}
return 0;
}
Please Suggest changes.
Looking carefully in question you will find that the operation are made only on the first and last element. So there is no need to involve a whole vector in it much less calculating the sum. we can calculate the whole sum of the elements except first and last by (n+1)(n-2)/2 and then we can manipulate the first and last element in the question. We can also shorten the search by using (1<op<n or op==first element or op == last element).
p.s. I am not sure it will work completely but it certainly is faster
my guess, let take N = 3, op = [4, 2]
N= [1,2,3]
sum = ((N-2) * (N+1)) / 2, it leave first and last element, give the sum of numbers between them.
we need to play with the first and last elements. it's big o(n).
function performOperations(N, op) {
let out = [];
let first = 1, last = N;
let sum = Math.ceil( ((N-2) * (N+1)) / 2);
for(let i =0;i<op.length;i++){
let not_between = !(op[i] >= 2 && op[i] <= N-1);
if( first!= op[i] && last != op[i] && not_between) {
last = op[i];
}else {
let t = first;
first = last;
last = t;
}
out.push(sum + first +last)
}
return out;
}

To make array identical by swapping elements

There are 2 i/p array's. They are identical when they have exactly same numbers in it. To make them identical, we can swap their elements. Swapping will have cost. If we are swapping a and b elements then cost = min(a, b).
While making array's identical, cost should be minimum.
If it is not possible to make array identical then print -1.
i/p:
3 6 6 2
2 7 7 3
o/p :
4
Here I have swapped (2,7) and (2,6). So min Cost = 2 + 2 = 4.
Logic :
Make 2 maps which will store frequency of i/p array's elements.
if element "a" in aMap is also present in bMap, then we have to consider number of swapping for a = abs(freq(a) in aMap - freq(a) in bMap)
if frequency of elements is "odd", then not possible to make them identical.
else , add total swaps from both maps and find cost using
cost = smallest element * total swaps
Here is the code
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
int main()
{
int t;
cin >> t;
while(t--)
{
int size;
long long int cost = 0;
cin >> size;
bool flag = false;
map<long long int, int> aMap;
map<long long int, int> bMap;
// storing frequency of elements of 1st input array in map
for( int i = 0 ; i < size; i++)
{
long long int no;
cin >> no;
aMap[no]++;
}
// storing frequency of elements of 2nd input array in map
for(int i = 0 ; i < size; i++)
{
long long int no;
cin >> no;
bMap[no]++;
}
// fetching smallest element (i.e. 1st element) from both map
long long int firstNo = aMap.begin()->first;
long long int secondNo = bMap.begin()->first;
long long int smallestNo;
// finding smallest element from both maps
if(firstNo < secondNo)
smallestNo = firstNo;
else
smallestNo = secondNo;
map<long long int, int> :: iterator itr;
// trying to find out total number of swaps we have to perform
int totalSwapsFromA = 0;
int totalSwapsFromB = 0;
// trversing a map
for(itr = aMap.begin(); itr != aMap.end(); itr++)
{
// if element "a" in aMap is also present in bMap, then we have to consider
// number of swapping = abs(freq(a) in aMap - freq(a) in bMap)
auto newItr = bMap.find(itr->first);
if(newItr != bMap.end())
{
if(itr->second >= newItr->second)
{
itr->second -= newItr->second;
newItr->second = 0;
}
else
{
newItr->second -= itr->second;
itr->second = 0;
}
}
// if freq is "odd" then, this input is invalid as it can not be swapped
if(itr->second & 1 )
{
flag = true;
break;
}
else
{
// if freq is even, then we need to swap only for freq(a)/ 2 times
itr->second /= 2;
// if swapping element is smallest element then we required 1 less swap
if(itr->first == smallestNo && itr->second != 0)
totalSwapsFromA += itr->second -1;
else
totalSwapsFromA += itr->second;
}
}
// traversing bMap to check whether there any number is present which is
// not in aMap.
if(!flag)
{
for(itr = bMap.begin(); itr != bMap.end(); itr++)
{
auto newItr = aMap.find(itr->first);
if( newItr == aMap.end())
{
// if frew is odd , then i/p is invalid
if(itr->second & 1)
{
flag = true;
break;
}
else
{
itr->second /= 2;
// if swapping element is smallest element then we required 1 less swap
if(itr->first == smallestNo && itr->second != 0)
totalSwapsFromB += itr->second -1;
else
totalSwapsFromB += itr->second;
}
}
}
}
if( !flag )
{
cost = smallestNo * (totalSwapsFromB + totalSwapsFromA);
cout<<"cost "<<cost <<endl;
}
else
cout<<"-1"<<endl;
}
return 0;
}
No error in the above code but giving wrong answer and not getting accepted.
Can anyone improve this code / logic ?
Suppose you have 2 arrays:
A: 1 5 5
B: 1 4 4
We know that we want to move a 5 down and a 4 up, so we have to options: swapping 4 by 5 (with cost min(4, 5) = 4) or using the minimum element to do achive the same result, making 2 swaps:
A: 1 5 5 swap 1 by 4 (cost 1)
B: 1 4 4
________
A: 4 5 5 swap 1 by 5 (cost 1)
B: 1 1 4
________
A: 4 1 5 total cost: 2
B: 5 1 4
So the question we do at every swap is this. Is it better to swap directly or swapping twice using the minimum element as pivot?
In a nutshell, let m be the minimum element in both arrays and you want to swap i for j. The cost of the swap will be
min( min(i,j), 2 * m )
So just find out all the swaps you need to do, apply this formula and sum the results to get your answer.
#user1745866 You can simplify your task of determining the answer -1 by using only variable:
let we have int x=0 and we will just do XOR of all the i/p integers like this:
int x = 0;
for(int i=0;i<n;i++){
cin>>a[i];
x = x^a[i];
}
for(int i=0;i<n;i++){
cin>>b[i];
x = x^b[i];
}
if(x!=0)
cout<<-1;
else{
...do code for remain 2 condition...
}
Now the point is how it will work because , as all the numbers of both array should occurs only even number of times and when we do XOR operation of any number which occured even number of times we will get 0.... otherwise they can't be identical arrays.
Now for 2nd condition(which gives answer 0) you should use multimap so you would be able to directly compare both arrays in O(n) time complexity as if all elements of both arrays are same you can output:0
(Notice: i am suggesting multimap because 1:You would have both array sorted and all elements would be there means also duplicates.
2: because they are sorted, if they consist of same element at same position we can output:0 otherwise you have to proceed further for your 3rd condition or have to swap the elements.)
For reducing the swap cost see Daniel's answer. For finding if the swap is actually possible, please do the following, the swaps are actually only possible if you have an even number of elements in total, so that you can split them out evenly, so if you have 2, 4 or 6 5's you are good, but if you have 1, 3, or 5 5's return -1. It is impossible if your number of duplicates of a number is odd. For actually solving the problem, there is a very simple solution I can think of, through it is a little bit expensive, you just need to make sure that there are the same number of elements on each side so the simple way to do that would be to declare a new array:
int temp[size of original arrays];
//Go through both arrays and store them in temp
Take half of each element, so something like:
int count[max element in array - min element in array];
for(int i = 0; i < temp.size(); i++){
count[temp[i]]++;
}
Take half of each element from temp. When you see an element that matches a element on your count array so whenever you see a 1 decrement the index on the count array by 1, so something like count[1]--; Assuming count starts at 0. If the index is at zero and the element is that one, that means a swap needs to be done, in this case find the next min in the other array and swap them. Albeit a little bit expensive, but it is the simplest way I can think of. So for example in your case:
i/p:
3 6 6 2
2 7 7 3
o/p :
4
We would need to store the min index as 2. Cause that is the smallest one. So we would have an array that looks like the following:
1 1 0 0 1 1
//one two one three zero four zero five 1 six and 1 seven
You would go through the first array, when you see the second six, your array index at 6 would be zero, so you know you need to swap it, you would find the min in the other array, which is 2 and then swap 6 with 2, after wards you can go through the array smoothly. Finally you go through the second array, afterwards when you see the last 7 it will look for the min on the other side swap them...., which is two, note that if you had 3 twos on one side and one two on the other, chances are the three twos will go to the other side, and 2 of them will come back, because we are always swapping the min, so there will always be an even number of ways we can rearrange the elements.
Problem link https://www.codechef.com/JULY20B/problems/CHFNSWPS
here for calculating minimum number of swap.we will having 2 cases
let say an example
l1=[1,2,2]
l2=[1,5,5]
case 1. swap each pair wrt to min(l1,l2)=1
step 1 swapping single 2 of a pair of 2 from l1-> [1,1,2]
[2,5,5] cost is 1
step 2 swapping single 5 of a pair of 5 from l1-> [1,5,2]
[2,1,5] cost is 1
total cost is 2
case 2. swap min of l1 with max of l2(repeat until both list end)
try to think if we sort 1st list in increasing order and other as decreasing order then we can minimize cost.
l1=[1,2,2]
l2=[5,5,1]
Trick is that we only need to store min(l1,l2) in variable say mn. Then remove all common element from both list.
now list became l1=[2,2]
l2=[5,5]
then swap each element from index 0 to len(l1)-1 with jump of 2 like 0,2,4,6..... because each odd neighbour wiil be same as previous number.
after perform swapping cost will be 2 and
l1=[5,2]
l2=[2,5] cost is 2
total cost is 2
Let say an other example
l1=[2,2,5,5]
l2=[3,3,4,4]
after solving wrt to min(l1,l2) total cost will be 2+2+2=6
but cost after sorting list will be swap of ((2,4) and (5,3)) is 2+3=5
so minimum swap to make list identical is min(5,6)=5
//code
l1.sort()
l2.sort(reverse=True)
sums=0
for i in range(len(l1)):
sums+=min(min(l1[i],l2[i]),2*minimum))
print(sums)
#print -1 if u get odd count of a key in total (means sums of count of key in both list)

How can I find the occurence number of each suffix in a string?

I want to find how many times each suffix of a string occurs in the original string in O(nlogn) or O(n) time.
For example, for string aba, suffix a appears twice, ba appears once, aba appears once.
Suffix Array Solution
Construct suffix tree of the string S along with LCP array. This will help in counting all the occurrences of each suffix.
without learning what suffix array and LCP are, its difficult to understand.
suffix array
LCP
kasai’s Algorithm for Construction of LCP array from Suffix Array
Let us take an example string and create its suffix array. Consider the string S = "ABABBAABB".
suffix positions(pos) Suffixes of S LCP array of S
5 AABB 1
0 ABABBAABB 2
6 ABB 3
2 ABBAABB 0
8 B 1
4 BAABB 2
1 BABBAABB 1
3 BBAABB 2
7 BB not Defined
First column(pos array) is the original starting points of sorted suffixes in Suffix Array. Let call second column as SuffixArray (we do not need to compute it, its just for visualization).
Now, as we know LCP[i]= the length of longest common prefix between SuffixArray[i] and SuffixArray[i+1]. e.g. LCP1=lcp("ABABBAABB","ABB")=2.
Let Count[i] = number of occurrences of suffix starting at position i.
for (int i = 0; i < n; )
{
int j=i;
while(LCP[j]==n-pos[j]){ // loop if SuffixArray[j] is a prefix of SuffixArray[j+1]
j++;
}
int incr=1;
for (int k = j-1; k>= i ; --k)
{
count[ pos[k] ] = incr;
incr++;
}
i=j+1;
}
This is highly optimized solution and if you look closely towards all steps, Complexity is O(n log n).
Hope it helps. Please go through everything again if you do not understand in the first try.
EDIT: There is tiny bug in this computation of count array. Basically my problem is to find the immediate next index in the LCP array which is smaller than current value. I am providing the correct implementation .
stack< int > stack;
count[ pos[n-1] ] = 1;
for(int i=n-2;i>=0;i--){
while(!stack.empty() and LCP[stack.top()]>=LCS[i]){
stack.pop();
}
if( LCP[i] == n-pos[i] ){
if (stack.empty())
{
count[ pos[i] ] = n-i ;
}else{
count[ pos[i] ] = stack.top()-i ;
}
}else{
count[ pos[i] ] = 1;
}
stack.push(i);
}
next smaller element in array

Loop Explanation in Counting Sort

Could somebody please explain to me the purpose of the second loop in this implementation of counting sort?:
short c[RADIX_MAX] = {0};
int i;
for (i = 0; i < LEN_MAX; i++) {
if (i == len)
break;
int ind = a.getElem(i);
c[ind]++;
}
for (i = 1; i < RADIX_MAX; i++) {
if (i == radix)
break;
c[i] += c[i - 1];
}
for (i = LEN_MAX - 1; i >= 0; i--) {
int j = i - LEN_MAX + len;
if (j < 0)
break;
int ind = a.getElem(j);
short t = ind;
ind = --c[ind];
b.setElem(ind, t);
}
Counting sort works by calculating the target index of each element to be sorted from the value of the element itself. There are three passes involved:
In the first loop, each element is counted: for example our array has six "A"s and two "B"s, five "C"s and so on.
In the second loop, the index where each element goes is calculated. If there are six "A"s, then the first "B" needs to go at index 6 (in 0-based indexing). What the counting sort does is a bit more complicated in order to make the code simpler and the sort stable. In the third loop it will traverse the original array in reverse order, so in the second loop it calculates the index not of the first instance of a given value, but of the last. In our example above, the last "A" needs to appear at index 5, but the last "B" needs to go at index 6 ("A"s) + 2 ("B"s) - 1 (zero based) = index 7. So for each value it calculates the ending index of that value. It walks the count array forward, adding the previosely calculated count to the current count. So in our count array, the value for "A" remains at 6 (no previous element), the value for "B" is 6+2=8 (six "A" + two "B"s), the value for C is now 6+2+5=13 (six "A"s + two "B"s + five "C"s), and so on
In the last loop, the values are inserted in their position, decrementing the indexes as we go along. So the last of the "B"s is inserted at index 7, the one before that at index 6, and so on. This preserves the original order of equal elements, making the sort stable which is essential for Radix sort.
For each digit we count index where it starts from in sorted array.
Example:
array: 0 0 0 0 2 2 3 3 3 9 9
index: 0 1 2 3 4 5 6 7 8 9 10
Then c[0] = 0, c[1] = 4, c[2] = 4, c [3] = 6, c[4] = 9, ... c[9] = 9.
Index in sorted array where digit appears depends on index of previous digit and number of previous digit. Second loop counts this.