Graphs and depth-first search using vectors in C++ [closed] - c++

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 9 years ago.
Improve this question
I saw the following code for making a graph and doing depth-first search on it. Can you explain me the use of vector g here. In the second function, how it is written as a 2-dimensional thing. Please explain the whole process clearly, on using vectors for this purpose. Problem is following:--- A Company is connected to n cities numbered from 1 to n. Currently the Headquarter of company is situated at index hq1. Each pair of connected cities are connected both ways. The connection is such that there is exactly one connection from the Headquarter to each city. The map of the connected cities is kept in the following way: for each city i, different from the Headquarter, there is kept number ci — index of the last city on the way from the Headquarter to i.
The company decided to move the Headquarter from city hq1 to city hq2. So, after this change the old representation of the map as described above became incorrect. Please, help the company to find out a new map in the way described above.
Input
The first line contains the number of test cases(0 < T <= 10 ). The next line contains three space-separated integers n, hq1, hq2 (2 ≤ n ≤ 2*10^4, 1 ≤ hq1 ≠ hq2 ≤ n) — number of connected cities, index of the old Headquarter and index of the new Headquarter, respectively.
The following line contains n - 1 space-separated integers — the old representation of the map. For each city, other than hq1, there is given integer ci — index of the last city on the way from the Headquarter to city i. All the cities are described in order of increasing indexes.
Output
Output n - 1 numbers — new representation of the map in the same format. The solution is given below.
vector < int >g[10005];
void make_graph()
{
int k = 1;
for (int i = 1; i <= n; i++)
{
if (i == h1)
continue;
int x;
cin >> x;
g[x].push_back (i);
g[i].push_back (x);
}
}
int visited[20004], parent[20004];
void dfs(int x)
{
visited[x] = 1;
for (int i = 0; i < g[x].size (); i++)
{
int j = g[x][i];
if (j == parent[x])
continue;
parent[j] = x;
dfs (j);
}
return;
}
int
main ()
{
int t;
cin >> t;
while (t--)
{
cin >> n >> h1 >> h2;
make_graph ();
dfs (h2);
for (int i = 1; i < n; i++)
{
if (i == h2)
continue;
cout << parent[i] << " ";
}
if (n != h2)
cout << parent[n] << endl;
else
cout << endl;
memset (parent, 0, sizeof (parent));
memset (visited, 0, sizeof (parent));
for (int i = 1; i <= n; i++)
g[i].clear ();
}
return 0;
}

Vectors can be accessed via [] as normal arrays. g is an array of vectors of ints, so can be accessed as 2D array. It contains info about edges in graph of cities, as an adjacency list
In make_graph() on list (vector) of x'th vertex, i'th one is pushed and vice versa, because the connection is in both ways.
In dfs() function for each adjacent vertex j on x'th list, x is marked as j's parent, because DFS starts from root (new HQ) and x is connected with j.
Line if (j == parent[x]) prevents from DFS-ing parent nodes (which still are on their children's lists).

Related

Selection sort program not sorting correctly [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
#include <iostream>
using namespace std;
int main()
{
int n, arr[10], i, j, temp, minin;
cin >> n;
for (i = 0; i < n; i++)
{
cin >> arr[i];
}
for (i = 0; i < n - 1; i++)
{
minin = i;
for (j = i + 1; j < n; j++)
{
if (arr[j] < arr[minin])
minin = j;
temp = arr[minin];
arr[minin] = arr[i];
arr[i] = temp;
}
}
for (i = 0; i < n; i++)
{
cout << arr[i];
}
return 0;
}
There are no compile-time errors. But my code does not sort properly.
This is what I get:
INPUT :
4 //size of the array to be sorted
5 3 2 8 //actual array to be sorted
OUTPUT :
3528
The expected output is the sorted array in ascending order.
Off the top of my head (no testing at all) you need to move the swap code out of the inner loop
Not your code
for(j=i+1;j<n;j++)
{
if(arr[j]<arr[minin])
minin=j;
temp=arr[minin];
arr[minin]=arr[i];
arr[i]=temp;
}
but instead
// calculate the index of the minimum element in the rest of the array
for(j=i+1;j<n;j++)
{
if(arr[j]<arr[minin])
minin=j;
}
// swap the minimum element with the current element
temp=arr[minin];
arr[minin]=arr[i];
arr[i]=temp;
That is what you should do is calculate the minimum index first, and then swap the minimum index with i. These tasks should be separate, your code mixed them up.

Climbing the leaderboard- hacker rank [closed]

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 2 years ago.
Improve this question
I was solving this problem in Hackerrank.
This question will give us an array of scores. We have to rank those sores as per the dense leader board ranking. It means the highest score gets the first rank, if the next score is equal to the highest rank, we give them the same rank. If it is less than that, we give it the next immediate rank.
ex- the scores 100, 80, 80, 60 will get ranks 1, 2,2 3.
ALso we are given an array of alice's score and we have to find out what rank Alice will get with each of her score.
Note that the scores are given in descending order. And Alice's scores are given in ascending order.
WHat I do is first create an array whoose ith element will denote the rank of ith score in the score vector.
Then I take the smallest score of ALice and do a search of the smallest score >= Alice's score. Then I gave ALice's score the rank accordingly. AFter that I pick the second smallest alice score and this time start searching for the smallest score >= Alice's score from where I left off.
This is the code that I wrote-
#include <vector>
#include <iostream>
using namespace std;
//function for the question.
vector<int> climbingLeaderboard(vector<int> scores, vector<int> alice)
{
vector<int> rank; //another array that will store the rank of all people already on the leaderboard
vector<int> result; //vector that will store the return value of alice's rank.
int val = scores[0]; //stores the current score that we are pointing on.
int len = 1, k, n = 0; //len is the current rank we are on. it changes if value(score) changes.
for (int i = 0; i < scores.size(); i++) {
if (scores[i] == val) { //if the scores are equal...
rank.push_back(len); //it stores the value of len that is the rank. This command ensures that the same scores have the same rank.
}
else if (scores[i] < val) { //if the score is less than val....
len++; //increments len by 1.
rank.push_back(len); //gives the current len as rank to the next person.
val = scores[i]; //sets the new value to the current score
}
}
//now I have stored ranks. Now for giving alice ranks...
k = scores.size() - 1; //points to the current score that we are comparing for Alice.
for (int j = 0; j < alice.size(); j++) { //does the loop for every score of Alice given.
k = n; //sets k=n so that we begin our search with the same index we left on for the next time.
while (k >= 0) {
if (scores[k] < alice[j]) { //if score is less, sub 1 from k
k--;
}
else if (scores[k] == alice[j]) {
result[j] = rank[k]; //if scores are equal, we set the rank of alice same as that of the rank that this score got.
n = k; //we store the value of k for which the scores are equal.
k = -1; //to end the while loop
}
else if (scores[k] > alice[j]) {
result[j] = rank[k] - 1;
n = k; //we do the same if the scores are one less, but give one less rank
k = -1;
}
}
}
return result; //return the vector.
}
// main function just takes in all the values and prints the vector that we get
int main()
{
int n, value, m;
cin >> n;
vector<int> scores;
vector<int> alice;
for (int i = 0; i < n; i++) {
cin >> value;
scores.push_back(value);
}
cin >> m;
for (int i = 0; i < m; i++) {
cin >> value;
alice.push_back(value);
}
vector<int> result;
result = climbingLeaderboard(scores, alice);
for (int k = 0; k < m; k++) {
cout << result[k];
cout << endl;
}
return 0;
}
It is showing a runtime error. Pls look at the code and tell me whats wrong. Also I would suggest to look at the link once bcoz it will explain the question much better than I evr will.
It also contains the sample inputs and sample outputs. The input format is a bit strange.
Looking at the debug output it's clear that you have an out of bounds access on one of your vectors.
Looking at the code I can see at least one such problem (there may be more)
vector<int> result;
...
result[j]=rank[k];
...
result[j]=rank[k]-1;
result is a vector with size 0, at no point do you resize it. So result[j]=... is an out of bounds vector access.

Is this the correct implementation of Insertion Sort? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
OUTPUT
#include <iostream>
using namespace std;
int main()
{
//declaring the size of array and taking input from the user
int n = 0;
cout<<"Enter the Number of elements you want in the Array : ";
cin>>n;
//checking the user input
if(n <= 0)
{
cout<<"Not Possible\n";
return 1;
}
//declaring array of size 'n' and taking input from user
int list[n];
cout<<"Enter the Elements of the array of size "<<n<<" : ";
for(int i = 0; i < n; i++)
cin>>list[i];
//Insertion Sort
int swap = 0; //number of swaps
int comp = 0; //number of comparison
int temp; //temporary variable
for(int i = 0; i < n-1; i++)
{
for(int j = i+1; j > 0; j--)
{
if(list[j] < list[j-1])
{
//swapping equivalent to shifting
temp = list[j-1];
list[j-1] = list[j];
list[j] = temp;
comp++;
swap++;
}
else
{
comp++;
break;
}
}
//printing the iteration
cout<<"Iteration "<<(i+1)<<" : ";
for(int k = 0; k < n; k++)
cout<<list[k]<<" ";
cout<<"\n";
}
cout<<"\nSwap : "<<swap<<"\n";
cout<<"Comparison : "<<comp<<"\n";
cout<<"Sorted Array : ";
for (int i = 0; i < n; i++)
{
cout<<list[i]<<" ";
}
return 0;
}
Is this implementation of insertion sort correct because I have seen many implementation online using while loop and other things?
If not can you point out what is wrong?
Thanks in advance
link - https://github.com/ish-u/DiscreteStructures/blob/master/InsertionSort.cpp
No, this is a different type of sort, known as bubble sort. It still sorts, but insertion sort works in a different way, by keeping the array sorted at all times (moving elements if a new insertion would break the ordering).
So instead of just tagging new elements to the end of the array where you read them from cin, you should place each element directly in the right spot in the array. This will likely involve moving existing elements in order to keep the array sorted.
Note that your line
int list [n];
is wrong; you cannot allocate memory this way (and I'm surprised it even compiles). A better choice would be to use std::vector.

How to compare structs faster (who met the most people problem)

I will start by saying that I'm not a native speaker so please excuse me my grammatical errors.
I'm an university student and my task is the following: I have an input that tells me the number of people, and then every line contains the time of arrival and the time of exit, both natural numbers separated by a space.
I have to find the (index of the) person who met the most people and then output the number of meetings that person had.
Example input and output:
If person A has datestamps of 3 and 6 and person B has 6 and 7, it is still considered a meeting.
I already solved this problem with a fixed size array of structs that compares every person to everybody else to find out the number of meetings and then searched for the person with the most meetings.
My problem is that this code is very slow and I must hadle inputs consisting of maximum 200000 people and timestamps ranging from 1 to 1000000.
This - compare everyone with everyone else - solution works for small sample sizes, but there is no way it can work for 200000 structs.
Also, this code has to successfully run under 0.2 sec.
What is a faster way to solve this?
#include <iostream>
using namespace std;
const int maxN = 20000;
struct Data {
int arrival;
int departure;
int meetings = -1;
};
int main()
{
Data x[maxN];
int N;
///input
cin >> N;
for (int i = 0; i < N; i++) {
cin >> x[i].arrival;
cin >> x[i].departure;
}
for(int i = 0; i < N; i++) {
for(int j = 0; j < N; j++){
if ( ((x[i].arrival >= x[j].arrival && x[i].arrival <= x[j].departure) || (x[i].departure >= x[j].arrival && x[i].departure <= x[j].departure)) || ((x[j].arrival >= x[i].arrival && x[j].arrival <= x[i].departure) || (x[j].departure >= x[i].arrival && x[j].departure <= x[i].departure)) ) {
x[i].meetings++;
}
}
}
int maxInd = 0;
int maximum = 0;
for(int i = 0; i < N; i++) {
if (x[i].meetings > maximum){
maxInd = i;
maximum = x[i].meetings;
}
}
///output
cout << maxInd+1 << endl;
cout << maximum << endl;
return 0;
}
I will only give you a starting point...
If I had to solve it, i would start by defining the following structure:
struct come_or_go {
size_t person_index;
int time;
bool arrival; // true for arrival, false for leaving
};
Next I would read the input into a vector<come_or_go> with two entries for each person. One when it arrives and one when it leaves. Next I'd sort that vector with respect to the elements time member. Finally I'd try to come up with a clever idea that requires to traverse this vector only once.
So far thats all I can provide, maybe I will update when I can give more hints. Hope this helps to push you into a differernt direction, because your brute force simply looses by complexity. Instead of trying to get details of it "faster" you need to change your overall approach.
I managed to do it by creating a vector and storing the 100.000 points of time in it.
I added 1 to each index where a person came in, stayed, and left.
Working with 100.000 long vectors, I managed to solve this problem with only one for loop se it ran reasonably fast.

Count number of triples whose product is x [closed]

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 4 years ago.
Improve this question
Given an array of integers and an integer x, I need to find the number of unordered triples in the array whose product is x. I have a brute-force O(n3) solution:
int solve(int a[], int n, int x) {
int ans = 0;
for (int i = 0; i < n; ++i)
for (int j = i+1; j < n; ++j)
for (int k = j+1; k < n; ++k)
if(a[i]*a[j]*a[k] == x)
ans++;
return ans;
}
Is there a faster way to do this, say in O(n log n) time?
You could
put all elements in a into a hashtable -- O(n)
Factorize x -- O(sqrt(x))
Build all possible triplets of divisors of x -- O(3^log(x))
Search for these triplets in your Hashtable -- O(1)
If a triplet exists, increase your counter -- O(1)
The runtime will now be dependent on the number of prime factors pf(x) of x, specifically O(3^pf(x)). Since the number of prime factors of x can be bounded by log(x) this yields O(3^log(x)) which could actually simplify further dependent on the exact base.
Code is in java but as you know, the idea remains the same.
Time complexity is O(n^1.5). I checked this with 10^5 elements and it works ok.
The idea is-
Put all elements of the list with their count in a map.
Now, if a[i]*a[j]*a[k] == x to be true, all these 3 have to be factors of x. Hence, if x%a[i] == 0, I hunt for checking all factors(pairs) that multiply to x/a[i] in sqrt(x/a[i]) time.
Since, we do it for every element in the list, complexity goes like this-
O(n) for adding elements to map.
O(n * n^0.5) for checking triplets.
So, total complexity = O(n) + O(n * n^0.5) = O(n^1.5) asymptotically.
ASSUMPTION - I am considering tuples as triplets having different indices in the array.
UPDATE - Current code considers different permutations of the same indices i,j,k as different tuples. You can fix it by having an additional map storing triplet indices as a string by joining them | (pipe) separated.
import java.util.*;
import java.io.*;
class Solution{
public static void main(String args[]) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
String[] s = br.readLine().split("\\s");
int[] a = new int[n];
for(int i=0;i<n;++i){
a[i] = Integer.parseInt(s[i]);
}
int x = Integer.parseInt(br.readLine());
System.out.println(solve(a,n,x));
}
private static long solve(int a[], int n, int x) {
long tuples = 0;
Map<Integer,Integer> elements = new HashMap<>();
for(int i=0;i<a.length;++i){
elements.put(a[i],elements.getOrDefault(a[i],0) + 1);
}
for(int i=0;i<a.length;++i){
if(x%a[i] == 0){
tuples += factorPairs(x/a[i],elements,a[i]);
}
}
return tuples;
}
private static long factorPairs(int x,Map<Integer,Integer> elements,int factor1){
long pairs = 0;
for(int i=1;i*i<=x;++i){
int second = i;
int third = x/i;
if(second*third == x && elements.containsKey(second) && elements.containsKey(third)){
long second_cnt = elements.get(second) - (second == factor1 ? 1 : 0);
long third_cnt = elements.get(third) - (third == factor1 ? 1 : 0);
pairs += second_cnt * third_cnt;
}
}
return pairs;
}
}