Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
How do you find the longest row of different(!) elements in an array?
We have a matrix
Our task is to find a row in this matrix where is the longest row of different elements
For example
0 1 2 3 4 1 2 3
Should count 0 1 2 3 4 = 5 elements
Try to use Kadane's algorithm described here: Maximum Subarray Problem
Just replace sum operation with adding-to-set and find-in-set operations. So, you is able to create a O(n) algo.
This is my try:
#include <iostream>
#include <unordered_set>
using namespace std;
int main() {
int mas[] = {1,2,3,1,2,3,4,1,2};
size_t count = sizeof(mas)/sizeof(mas[0]);
size_t best = 0;
int best_index = 0;
unordered_set<int> unique;
for (int i = 0; i < count; i++) {
while (unique.find(mas[i]) != unique.end()) {
unique.erase(mas[i - unique.size()]);
}
unique.insert(mas[i]);
if (unique.size() > best) {
best = unique.size();
best_index = i - best + 1;
}
}
cout << "Index = " << best_index << " Length = " << best << endl;
}
Gives output:
Index = 3 Length = 4
Suppose you use two data structures:
a std::list of integers
a std::unordered_map mapping integers into iterators of the list
Now operate as follows. When you encounter the next integer, check if it is in the unordered map.
If it is, find the corresponding iterator in the list, and remove it and all items left of it (from both list and unordered map)
If it is not, add it to the list, and set the unordered map to point at it
Furthermore, at each step, track both the step index, and the size of the unordered map (or the list). Output the index of the largest size, at the end.
This algorithm is amortized expected linear time: although there might be a step that removes more than a single list item (from each of the data structures), each item enters and leaves them at most once.
Example
Here is an example of the two data structures at some step. The grey map references items in the blue linked list.
The distinct length is now 4. If 2 is now encountered, however, then it and the link(s) left of it (in this case 3) will be purged before it is added, and the length will be reduced to 3.
You can do this in O(n) using a caterpillar algorithm.
Head and Tail pointers begin in the same spot. You move the head along and add to a hash set if it isn't already there.
If the head can't move, move the tail. Remove the corresponding number from the hash set.
As you're going along, see if there's a new max length.
The head and tail are each at each location once, so it's O(n)
Try something like this:
const int len = 4;
int arr[len][len] = {{1, 2, 2, 2}, {3, 2, 3, 5}, {2, 4, 3, 6}, {1, 1, 1, 1}};
int max = -1, current = 1;
for (int i = 0; i < len; i++) {
for (int j = 1; j < len; j++) {
if (arr[i][j] != arr[i][j - 1]) {
current++;
} else {
if (current > max) {
max = current;
}
current = 1;
}
}
if (current > max) {
max = current;
}
current = 1;
}
// output max
It is not very elegant solution, but it works
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 months ago.
Improve this question
An array of length L is given. Elements are '–ve' and +ve integers. Make a function that figure out all positive numbers in the array that have their opposites in it as well.
Input : 4,5,8,3,2,-5,-8,-4,-2,-3,-5,8,-8
Output : 2,-2,3,-3,4,-4,5,-5,8,-8
I copied this code from the web but couldn't understand it, is there some other easier way.
#include <bits/stdc++.h>
using namespace std;
void printPairs(int arr[], int n)
{
vector<int> v;
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
// If absolute values are equal print pair.
if (abs(arr[i]) == abs(arr[j]))
v.push_back(abs(arr[i]));
if (v.size() == 0)
return;
for (int i = 0; i < v.size(); i++)
cout << -v[i] << " " << v[i] << " ";
}
int main()
{
int arr[] = { 4, 8, 9, -4, 1, -1, -8, -9 };
int n = sizeof(arr) / sizeof(arr[0]);
printPairs(arr, n);
return 0;
}
Using standard algorithms does not always immediately make code easier, but standard algorithms are well documented. If you do not understand application of a standard algorithm you can find plenty of documentation. That isnt the case for self-written algorithms.
Know your algorithms! I will use a simpler example: 2,1,-2,2, and I will use a std::vector.
std::sort can be used to sort the vector to 1,2,2,-2 by using a custom comparator that compares the elements absolute values and places positive elements before negative ones ( to achive that you can compare std::pairs of {abs(element),element<0}).
std::unique can be used to move adjacent duplciates to the end of the vector, resulting in 1,2,-2,2. The returned iterator refers to the 2 because thats the end of the vector that has only the unique elements. (Here it is not actually needed to erase the duplicates from the vector)
std::adjacent_find can be used to find pairs of adjacent elements for which abs(a) == abs(b).
Thats all you need.
#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
int main() {
std::vector<int> x{4,5,8,3,2,-5,-8,-4,-2,-3,-5,8,-8};
std::sort(x.begin(),x.end(),[](auto a,auto b){ return std::make_pair(std::abs(a),a<0) < std::make_pair(std::abs(b),b<0);});
auto last = std::unique(x.begin(), x.end());
//x.erase(last, x.end()); // no need to actually erase
auto it = x.begin();
while (it != last) {
it = std::adjacent_find(it,last,[](auto a,auto b){ return std::abs(a) == std::abs(b);});
if (it != last) {
std::cout << *it << " " << *std::next(it) << "\n";
it += 2;
}
}
}
I am not expecting that you find this code much simpler to read compared to the original, but if you just spend some time on the documentation of the used algorithms it should become clear how it works.
I think the algorithm is not correct, just looking at absolute values.
Also it is quadratic O(n²), 1,000 items would need 500,000 steps.
Sort the array. -8, -5, -4, 2, 4, 8, 9
Now you can have two iterators, from the beginning (-8) for negative numbers and from the end (9) for positive numbers.
As long the iterators are in the negative resp. positive range, you can advance to absolutely identical numbers. Mind repeats ..., 13, 13, 13, ....
The coding I leave to you. Would not like to spoil it.
I'm trying to implement Priority queue with custom operator. The algorithm tries to find the minimum increments to be done so that no two adjacent elements in array have absolute difference > 1.
For this, I get the maximum element "x" in the array and modify its neighbours to x-1, then repeat the same for other elements
Here's the code:
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
int arr[100], visited[100];
int sizeOfArray;
struct comp
{
public:
bool operator() (int x1, int x2) {
return arr[x1] < arr[x2];
}
};
int main(){
cin>>sizeOfArray;
priority_queue<int, vector<int>, comp> priorityQue;
for(int i = 0; i < sizeOfArray; i++) {
cin>>arr[i];
priorityQue.push(i);
visited[i]=0;
}
while(!priorityQue.empty()) {
int index = priorityQue.top();
priorityQue.pop();
if(visited[index])
continue;
visited[index]=1;
cout<<"Currently at index: "<<index<<endl;
int currentElement = arr[index];
int dx[] = {-1, 1}; // left and right neighbours
for(int k = 0; k < 2; k++) {
int nextIndex = index + dx[k];
if( nextIndex >= 0 && nextIndex < sizeOfArray &&
(currentElement - arr[nextIndex]) > 1 )
{
arr[nextIndex] = currentElement - 1;
cout<<"Modifying index :"<<nextIndex<<endl;
cout<<"New Array is: ";
// print array
for(int z=0;z<sizeOfArray;z++)
cout<<arr[z]<<" ";
cout<<endl;
priorityQue.push(nextIndex);
cout<<"Pushing index "<<nextIndex<<" to queue"<<endl;
}
}
}
return 0;
}
For the input:
4 4 1 1 0
The Output is:
Currently at index: 0
Modifying index :1
New Array is: 4 3 1 0
Pushing index 1 to queue
Currently at index: 2
Currently at index: 1
Modifying index :2
New Array is: 4 3 2 0
Pushing index 2 to queue
Currently at index: 3
I found that priority queue is not extracting the maximum element as per the comparator as it should be. After visiting index 0, array becomes 4 3 1 0 hence index 1 should come next but in this case index 2 is picked up.
What am I missing??
You are modifying the item after it was put into the queue and still is part of that queue. This is not supported by the priority queue and yields unspecified results. C++ STL does not offer updatable priority queue.
But, seeing your use case I suspect this is competitive algorithmic programming. There are decent alternetives for this use case. I wouldn't recommend them for production code (at least not without proper abstractions.
The first, "proper" alternative is to use std::set<std::pair<...>> instead. Your code will stay very similar, but there are some important differences:
You won't need custom comparator, instead relying on pair comparison (you will need to use std::greater as comparator to have largest items "on top",
You will put {a[index], index} as elements of this set,
You will use .begin() instead of .top(),
You will need to .erase() items before updating their values, and insert them again with new values.
I believe above has same complexities as the standard implementation of priority queue. Even though updates seem slow, we are doing just two O(log n) operations - which is same complexity as an actual update in a heap structure.
You could implement it with an indirect comparator as in your example. In general it would work, but you still need the erase and insert flow around update. Additionally you would need to compare indices in your comparator as well, in order to make items with same priority different, so that the correct item is removed.
Moreover, there is another trick we can do in many common cases, like Dijkstra or Prim's algorithms. In these cases we only update priority to higher (lower values). In such case we can ignore erasing items, and instead just add duplicates. This works because time complexity of a single query/update becomes O(log n^2) = O(2 log n) = O(log n). Memory complexity increases, but this often is not a problem.
In this last case you can use other containers to fit your preferences, both std::priority_queue<std::pair<...>> or std::multimap<...> will work nicely. But in all of them you need to keep priority as part of item you insert, and not use it via indirect comparator.
As an appendix, this is your code with changes to work as intended:
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
int arr[100], visited[100];
int sizeOfArray;
int main(){
cin>>sizeOfArray;
priority_queue<std::pair<int, int>> priorityQue;
for(int i = 0; i < sizeOfArray; i++) {
cin>>arr[i];
priorityQue.push({arr[i], i});
visited[i]=0;
}
while(!priorityQue.empty()) {
int index = priorityQue.top().second;
priorityQue.pop();
if(visited[index])
continue;
visited[index]=1;
cout<<"Currently at index: "<<index<<endl;
int currentElement = arr[index];
int dx[] = {-1, 1}; // left and right neighbours
for(int k = 0; k < 2; k++) {
int nextIndex = index + dx[k];
if( nextIndex >= 0 && nextIndex < sizeOfArray &&
(currentElement - arr[nextIndex]) > 1 )
{
arr[nextIndex] = currentElement - 1;
cout<<"Modifying index :"<<nextIndex<<endl;
cout<<"New Array is: ";
// print array
for(int z=0;z<sizeOfArray;z++)
cout<<arr[z]<<" ";
cout<<endl;
priorityQue.push({arr[nextIndex], nextIndex});
cout<<"Pushing index "<<nextIndex<<" to queue"<<endl;
}
}
}
return 0;
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Here is the link for the program: http://gpe.acm-icpc.tw/domjudge2/pct/showproblemtab.php?probid=10527&cid=5.
Here is the work I have done so far :
First, I created a function that will sort the array which is ord(a, j) in the code below.
The variable j is the size of the array that will increment every time the user input a number.
To compute the median, I have two cases.
1) if the size of the array is even, then I subtract the size of the array by 1 and divide it by 2, then the result will be the index of the sorted array plus the next element of the sorted array divided by 2 to find the median.
For example : an array of {1,3,6,2,7,8} elements. I will sort the array first which will give : {1,2,3,6,7,8} then the median will be (3+6)/2 = 4.
2) if the size of the array is odd, then I subtract the size of the sorted array by 1 and divide it by 2, the result is the index of the median.
For example : an array of {1,3,7,2,5} elements. I will sort the array first which will give : {1,2,3,5,7} then the median is 3.
int* ord(int A[], int n) // function to sort the array
{
for(int i = 0; i < n; i++)
{
for(int v = 0; v < n -1; v++)
{
if(A[v] > A[v+1])
{
swap(A[v], A[v+1]);
}
}
}
return A;
}
int main()
{
int a[N], x, j = 0, c;
while(cin >> x)
{
j++; // This is the size of the array
a[j-1]=x;
// Below is the algorithm for finding the median
if (j == 1) // if the array contains only one value, I just output the value
{
cout << a[0] << endl;
}
else // if it contains more than one value then I compute the median
{
ord(a, j); //sorted array
if (j % 2 == 0) // first case is when the size of the array is even
{
// First I subtract the size of the array by 1 and divide it by 2, then c will be the index of the sorted array plus the next element of the sorted array divided by 2 to find the median
c = (j-1) / 2;
cout << (a[c] + a[c+1]) / 2 << endl;
}
else // second case when the size of the array is odd
{
// First I subtract the size of the array by 1 and divide it by 2, c will be the index of the median
c = j-1;
cout << a[c / 2] << endl;
}
}
}
}
Use a std::vector to hold your ints. Then use std::sort on it. If you have to write your own sort, try to implement a quicksort or a mergsort.
This is a fast sort via a vector and std::sort.
int array_size = 8;
int myints[] = {32,71,12,45,26,80,53,33};
std::vector<int> myvector (myints, myints+array_size);
std::sort (myvector.begin(), myvector.end());
If you need to read up about faster sort algorithms:
https://en.wikipedia.org/wiki/Quicksort
https://en.wikipedia.org/wiki/Merge_sort
The general idea is to do some kind of presorting for parts of the array and then sort everything. This make the runtime log(n)n instead of nn. This is a major speed up, even more the bigger the numbers rise. Example:
log(1024)*1024 = 10*1024 = 10.240 Operations.
1024*1024 ~ 1.000.000 Operations <- 100 times slower
log(1.000.000)*1.000.000 = 20*1.000.000 = 20.000.000 Operations.
1.000.000*1.000.000 = 1.000.000.000.000 Operations <- 50.000 times slower
I think you are doing it wrong.
first of all you should not call the sorting function inside loop, it does the same work every time, and increasing time. It will be enough to call it once after the end of the while loop. This will drastically speed up your program.
Also inside while loop you have first incremented the value of j then you have assigned
a[j-1] = x;
you should first assign
a[j] = x;
and then j++;
because
a[j-1] = x; // here j-1 will take some fraction of milliseconds to calc [j-1].
Hope your program will speed up.
Let's say i have an array of 5 elements. My program knows it's always 5 elements and when sorted it's always 1,2,3,4,5 only.
As per permutations formula i.e n!/(n-r)! we can order it in 120 ways.
In C++ using std::next_permutation I can generate all those 120 orders.
Now, my program/routine accepts an input argument as a number in the range of 1 to 120 and gives the specific order of an array as output.
This works fine for small array sizes as i can repeat std::next_permutation until that matches input parameter.
The real problem is, How can i do it in less time if my array has 25 elements or more? For 25 elements, the number of possible orders are : 15511210043330985984000000.
Is there a technique that I can easily find the order of numbers using a given number as input?
Thanks in advance :)
This is an example c++ implementation of the algorithm mentioned in this link:
#include <vector>
#define ull unsigned long long
ull factorial(int n) {
ull fac = 1;
for (int i = 2; i <= n; i++)
fac *= i;
return fac;
}
std::vector<int> findPermutation(int len, long idx) {
std::vector<int> original = std::vector<int>(len);
std::vector<int> permutation = std::vector<int>();
for (int i = 0; i < len; i++) {
original[i] = i;
}
ull currIdx = idx;
ull fac = factorial(len);
while (original.size() > 0) {
fac /= original.size();
int next = (currIdx - 1) / fac;
permutation.push_back(original[next]);
original.erase(original.begin() + next);
currIdx -= fac * next;
}
return permutation;
}
The findPermutation function accepts the length of the original string and the index of the required permutation, and returns an array that represents that permutation. For example, [0, 1, 2, 3, 4] is the first permutation of any string with length 5, and [4, 3, 2, 1, 0] is the last (120th) permutation.
I have had a similar problem where I was storing lots of row in a Gtk TreeView and did not want to go over all of them every time I want to access a row by its position and not by its reference.
So, I created a map of the positions of the row so I could easily identify them by the parameter I needed.
So, my suggestion to this is you go over all permutations once and map every std::permutation in an array (I used a std::vector), so you can access it by myVector[permutation_id].
Here is my way I have done the mapping:
vector<int> FILECHOOSER_MAP;
void updateFileChooserMap() {
vector<int> map;
TreeModel::Children children = getInterface().getFileChooserModel()->children();
int i = 0;
for(TreeModel::Children::iterator iter = children.begin(); iter != children.end(); iter++) {
i++;
TreeModel::Row row = *iter;
int id = row[getInterface().getFileChooserColumns().id];
if( id >= map.size()) {
for(int x = map.size(); x <= id; x++) {
map.push_back(-1);
}
}
map[id] = i;
}
FILECHOOSER_MAP = map;
}
So in your case you would just iterate over the permutations like this and you can map them in a way that allows you accesing them by their id.
I hope this helps you :D
regards, tagelicht
I'm trying to make a function to get the 3 biggest numbers in a vector. For example:
Numbers: 1 6 2 5 3 7 4
Result: 5 6 7
I figured I could sort them DESC, get the 3 numbers at the beggining, and after that resort them ASC, but that would be a waste of memory allocation and execution time. I know there is a simpler solution, but I can't figure it out. And another problem is, what if I have only two numbers...
BTW: I use as compiler BorlandC++ 3.1 (I know, very old, but that's what I'll use at the exam..)
Thanks guys.
LE: If anyone wants to know more about what I'm trying to accomplish, you can check the code:
#include<fstream.h>
#include<conio.h>
int v[1000], n;
ifstream f("bac.in");
void citire();
void afisare_a();
int ultima_cifra(int nr);
void sortare(int asc);
void main() {
clrscr();
citire();
sortare(2);
afisare_a();
getch();
}
void citire() {
f>>n;
for(int i = 0; i < n; i++)
f>>v[i];
f.close();
}
void afisare_a() {
for(int i = 0;i < n; i++)
if(ultima_cifra(v[i]) == 5)
cout<<v[i]<<" ";
}
int ultima_cifra(int nr) {
return nr - 10 * ( nr / 10 );
}
void sortare(int asc) {
int aux, s;
if(asc == 1)
do {
s = 0;
for(int i = 0; i < n-1; i++)
if(v[i] > v[i+1]) {
aux = v[i];
v[i] = v[i+1];
v[i+1] = aux;
s = 1;
}
} while( s == 1);
else
do {
s = 0;
for(int i = 0; i < n-1; i++)
if(v[i] < v[i+1]) {
aux = v[i];
v[i] = v[i+1];
v[i+1] = v[i];
s = 1;
}
} while(s == 1);
}
Citire = Read
Afisare = Display
Ultima Cifra = Last digit of number
Sortare = Bubble Sort
If you were using a modern compiler, you could use std::nth_element to find the top three. As is, you'll have to scan through the array keeping track of the three largest elements seen so far at any given time, and when you get to the end, those will be your answer.
For three elements that's a trivial thing to manage. If you had to do the N largest (or smallest) elements when N might be considerably larger, then you'd almost certainly want to use Hoare's select algorithm, just like std::nth_element does.
You could do this without needing to sort at all, it's doable in O(n) time with linear search and 3 variables keeping your 3 largest numbers (or indexes of your largest numbers if this vector won't change).
Why not just step through it once and keep track of the 3 highest digits encountered?
EDIT: The range for the input is important in how you want to keep track of the 3 highest digits.
Use std::partial_sort to descending sort the first c elements that you care about. It will run in linear time for a given number of desired elements (n log c) time.
If you can't use std::nth_element write your own selection function.
You can read about them here: http://en.wikipedia.org/wiki/Selection_algorithm#Selecting_k_smallest_or_largest_elements
Sort them normally and then iterate from the back using rbegin(), for as many as you wish to extract (no further than rend() of course).
sort will happen in place whether ASC or DESC by the way, so memory is not an issue since your container element is an int, thus has no encapsulated memory of its own to manage.
Yes sorting is good. A especially for long or variable length lists.
Why are you sorting it twice, though? The second sort might actually be very inefficient (depends on the algorithm in use). A reverse would be quicker, but why even do that? If you want them in ascending order at the end, then sort them into ascending order first ( and fetch the numbers from the end)
I think you have the choice between scanning the vector for the three largest elements or sorting it (either using sort in a vector or by copying it into an implicitly sorted container like a set).
If you can control the array filling maybe you could add the numbers ordered and then choose the first 3 (ie), otherwise you can use a binary tree to perform the search or just use a linear search as birryree says...
Thank #nevets1219 for pointing out that the code below only deals with positive numbers.
I haven't tested this code enough, but it's a start:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> nums;
nums.push_back(1);
nums.push_back(6);
nums.push_back(2);
nums.push_back(5);
nums.push_back(3);
nums.push_back(7);
nums.push_back(4);
int first = 0;
int second = 0;
int third = 0;
for (int i = 0; i < nums.size(); i++)
{
if (nums.at(i) > first)
{
third = second;
second = first;
first = nums.at(i);
}
else if (nums.at(i) > second)
{
third = second;
second = nums.at(i);
}
else if (nums.at(i) > third)
{
third = nums.at(i);
}
std::cout << "1st: " << first << " 2nd: " << second << " 3rd: " << third << std::endl;
}
return 0;
}
The following solution finds the three largest numbers in O(n) and preserves their relative order:
std::vector<int>::iterator p = std::max_element(vec.begin(), vec.end());
int x = *p;
*p = std::numeric_limits<int>::min();
std::vector<int>::iterator q = std::max_element(vec.begin(), vec.end());
int y = *q;
*q = std::numeric_limits<int>::min();
int z = *std::max_element(vec.begin(), vec.end());
*q = y; // restore original value
*p = x; // restore original value
A general solution for the top N elements of a vector:
Create an array or vector topElements of length N for your top N elements.
Initialise each element of topElements to the value of your first element in your vector.
Select the next element in the vector, or finish if no elements are left.
If the selected element is greater than topElements[0], replace topElements[0] with the value of the element. Otherwise, go to 3.
Starting with i = 0, swap topElements[i] with topElements[i + 1] if topElements[i] is greater than topElements[i + 1].
While i is less than N, increment i and go to 5.
Go to 3.
This should result in topElements containing your top N elements in reverse order of value - that is, the largest value is in topElements[N - 1].