DFS search time complexity analysis - c++

In finding the cycle in the dfs if we pass & to the boolean vector the code correctely submitted but when I I don't use it give time complexity erroe
bool dfs(vector<int>adj[],int V,vector<bool>&b,int i,vector<bool>&d){
b[i]=true;
d[i]=true;
vector<int>::iterator it;
for(it=adj[i].begin();it!=adj[i].end();++it){
if(b[*it]!=true){
if(dfs(adj,V,b,*it,d)){
return true;
}
}
else if(d[*it]==true){
return true;
}
}
d[i]=false;
return false;
}

Related

Fastest solution to Testdome excercise about repeating playlist

I tried to an exercise on TestDome about discovering if a playlist has repetitions ( TestDome C++ Playlist )
I tried to solve in this way:
bool isRepeatingPlaylist()
{
std::map<std::string, int> songs;
Song* pSong = this;
while (pSong != nullptr) {
if (songs[pSong->name] > 0)
return true;
songs[pSong->name]++;
pSong = pSong->nextSong;
}
return false;
}
The feedback is that I passed 3 out of 4 test cases. The test case I'm not passing is the one about performances. Can you help me improving?
The 4th test is "Performance test on a large playlist"
when it comes to efficiency and you don't need ordered data you should use unordered_set<> or unordered_map<>.
map<> search complexity is O(log n) but it's average O(1) to O(n) in the worst case for unordered_set<> or unordered_map<>.
below code passed all 4 tests of TestDome C++ Playlist
bool isRepeatingPlaylist()
{
std::unordered_set<std::string> playedSongs;
Song *pSong = this;
while (pSong != nullptr)
{
if (playedSongs.find(pSong->name) == playedSongs.end())
playedSongs.insert(pSong->name);
else
return true;
pSong = pSong->nextSong;
}
return false;
}
to use it just add #include<unordered_set>

I am getting a TLE error while performing cycle detection

I have written a code to the leetcode problem(courseSchedule) which basically asks whether a given set of courses can be done given dependencies. my approach is to create a graph and then check for a cycle, however, it's giving a TLE error. Can you help me as to why is the TLE happening or if there's a better approach that I can use ?
bool cycle( vector<vector<int>> &adj,int i,vector<bool> vis){
if(vis[i])
return true;
vis[i]=true;
for(int k=0;k<adj[i].size();k++)
if(cycle(adj,adj[i][k],vis))
return true;
return false;
}
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<vector<int>> adj(numCourses);
for(int i=0;i<prerequisites.size();i++)
adj[prerequisites[i][1]].push_back(prerequisites[i][0]);
vector<bool> vis(numCourses,false);
for(int i=0;i<numCourses;i++)
if(cycle(adj,i,vis))
return false;
return true;
}
};
Actually, your function is correct but so inefficient.
This is because in the cycle function performs so many redundant operations i.e check for the same node multiple times.
Your Code:
bool cycle( vector<vector<int>> &adj,int i,vector<bool> vis){
if(vis[i])
return true;
vis[i] = true;
for(int k = 0; k < adj[i].size(); k++)
if(cycle(adj, adj[i][k], vis))
return true;
return false;
}
Ex:
0 ---> 1 ---> 2 ......... (some more edges)
0 ---> 3 ---> 2 ---> 4 ........ (some more edges)
So, for this graph, for the start vertex 0 (with your code) for the bool function:
iteration - 1: you perform the DFS and check for 1 and 2 and
......
iteration - 2: you perform the DFS and check for 3 and again 2 .....
So, like this, you will be recomputing the same sub-problems. To avoid this you need to put another array just check if a node is already computed.
So I have introduced another vector var (initialized to false) which basically sets to true if node is visited and got approved as non-cycle node (which doesn't involve in a cycle) .
Improved Code:
bool cycle( vector<vector<int>> &adj,int i,vector<bool> vis, vector<bool>& var){
// if i involves in cycle and visited in the current sequence
if(!var[i] and vis[i])
return true;
vis[i] = true;
for(int k=0;k<adj[i].size();k++) {
// if adj[i][k] is true i.e doesn't involve in cycle, so no need to check it. If it is false we should check it.
if(!var[adj[i][k]] and cycle(adj,adj[i][k],vis, var))
return true;
else
var[adj[i][k]] = true; // else setting true to tell it doesn't involve in cycle
}
// setting true to tell it doesn't involve in cycle
var[i] = true;
return false;
}
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<vector<int>> adj(numCourses);
for(int i=0;i<prerequisites.size();i++)
adj[prerequisites[i][1]].push_back(prerequisites[i][0]);
vector<bool> vis(numCourses,false);
vector<bool> var(numCourses,false);
for(int i=0;i<numCourses;i++)
if(cycle(adj,i,vis, var))
return false;
return true;
}
};
Note:
I just made small changes to make your code overcome TLE without changing the basic logic. But this is still inefficient as your logic needs to pass the vector by value. I suggest you think another way :)
I also think vis is not passed by reference would be the problem for large size test cases.
This is a similar depth first search graph method, that'd pass through:
#include <cstdint>
#include <utility>
#include <vector>
const static struct Solution {
static bool canFinish(
const int num_courses,
const std::vector<std::vector<int>>& prerequisites
) {
GraphType graph = buildCourseGraph(prerequisites, num_courses);
std::vector<bool> to_take(num_courses, false);
std::vector<bool> taken(num_courses, false);
for (SizeType course = 0; course < num_courses; ++course) {
if (!taken[course] && !validateAcyclic(graph, course, to_take, taken)) {
return false;
}
}
return true;
}
private:
using GraphType = std::vector<std::vector<int>>;
using SizeType = std::uint_fast16_t;
static GraphType buildCourseGraph(
const std::vector<std::vector<int>>& prerequisites,
const SizeType num_courses
) {
GraphType graph(num_courses);
for (const auto& prerequisite : prerequisites) {
graph[prerequisite[1]].emplace_back(prerequisite[0]);
}
return graph;
}
static bool validateAcyclic(
const GraphType& graph,
const SizeType& course,
std::vector<bool>& to_take,
std::vector<bool>& taken
) {
if (to_take[course]) {
return false;
}
if (taken[course]) {
return true;
}
to_take[course] = taken[course] = true;
for (const auto& adj_course : graph[course]) {
if (!validateAcyclic(graph, adj_course, to_take, taken)) {
return false;
}
}
to_take[course] = false;
return true;
}
};
and here is LeetCode's depth first search solution in Java (with comments):
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
// course -> list of next courses
HashMap<Integer, List<Integer>> courseDict = new HashMap<>();
// build the graph first
for (int[] relation : prerequisites) {
// relation[0] depends on relation[1]
if (courseDict.containsKey(relation[1])) {
courseDict.get(relation[1]).add(relation[0]);
} else {
List<Integer> nextCourses = new LinkedList<>();
nextCourses.add(relation[0]);
courseDict.put(relation[1], nextCourses);
}
}
boolean[] checked = new boolean[numCourses];
boolean[] path = new boolean[numCourses];
for (int currCourse = 0; currCourse < numCourses; ++currCourse) {
if (this.isCyclic(currCourse, courseDict, checked, path))
return false;
}
return true;
}
/*
* postorder DFS check that no cycle would be formed starting from currCourse
*/
protected boolean isCyclic(
Integer currCourse, HashMap<Integer, List<Integer>> courseDict,
boolean[] checked, boolean[] path) {
// bottom cases
if (checked[currCourse])
// this node has been checked, no cycle would be formed with this node.
return false;
if (path[currCourse])
// come across a previously visited node, i.e. detect the cycle
return true;
// no following courses, no loop.
if (!courseDict.containsKey(currCourse))
return false;
// before backtracking, mark the node in the path
path[currCourse] = true;
boolean ret = false;
// postorder DFS, to visit all its children first.
for (Integer child : courseDict.get(currCourse)) {
ret = this.isCyclic(child, courseDict, checked, path);
if (ret)
break;
}
// after the visits of children, we come back to process the node itself
// remove the node from the path
path[currCourse] = false;
// Now that we've visited the nodes in the downstream,
// we complete the check of this node.
checked[currCourse] = true;
return ret;
}
}
References
For additional details, please see the Discussion Board which you can find plenty of well-explained accepted solutions in there, with a variety of languages including efficient algorithms and asymptotic time/space complexity analysis1, 2.

Iterating over vector of custom object with two conditions

Using C++11, I'd like to iterate over a vector and return a type that indicates that the index was not found.
I am use to the traditional for(;;) loop and specifying the index manually, as my code shows below.
inline std::size_t ItemList::FindItem(Items& Item)
{
for (std::size_t i = 0; i < ItemVector.size(); i++)
{
if (ItemVector[i]->GetId() == Item.GetId() && !ItemVector[i]->GetName().compare(Item.GetName()))
{
return i + 1;
}
}
return 0;
}
I'm also having to increment the index +1 in order to return a value of 0 (to accommodate unsigned size_t) to indicate the calling method that the index was not found (I understand this is asinine). I am assuming it would be more suitable to return something more like std::end()?
Would using a C++11 iterator approach be more efficient? The vector will populate to a large number and the find needs to be quick.
You could use std::find_if and work with iterators:
auto it = std::find_if(ItemVector.begin(), ItemVector.end(),
[&Item](Items *value) {
return value->GetId() == Item.GetId() && !value->GetName().compare(Item.GetName());
}
);
Then you can simply test if it != ItemVector.end() to know if you found something.
There will likely be no (or very small) difference between this and your version in term of speed, but it is a cleaner way to check if something was found or not.
Yes, an iterator would be the way to do this, you're actually writing your own version of find_if You could instead do:
find_if(cbegin(ItemVector), cend(ItemVector), [&](const auto& i){ return i.GetId() == Item.GetId() && i.GetName() != Item.GetName(); })
You can test whether the result of this function was found by testing for equality with cend(ItemVector).
Additionally if you need to find the index of the item you can pass this result after cbegin(ItemVector) to: distance
Live Example
My solution for double search condition that Lambda has multiple parameters in find_if
bool check_second_loop(FullFrame *image_track, guint64 object_id, bool *deletion)
{
auto itr= std::find_if(image_track->track_ids.begin(),
image_track->track_ids.end(),
[object_id](const guint64& a)
{
return a == object_id;
});
if (itr != image_track->track_ids.end())
{
image_track->track_ids.erase(itr);
if(image_track->track_ids.size()==0)
{
*deletion = true;
}
return true;
}
else
return false;
}
bool check_first_loop(guint64 object_id, gint source_id)
{
bool deletion = false;
auto it = find_if(full_frame_list.begin(), full_frame_list.end(),
[object_id, &deletion, source_id](FullFrame &x)
{
return check_second_loop(&x, object_id, &deletion)
&& x.camera_number == source_id;
});
if (it != full_frame_list.end())
{
// Found
return true;
}
else
return false;
}

Recursive function building a vector, what will be returned?

so I'm trying to build a vector recursively, as I look at this I begin to think I'm doing it quite wrong. Will the following code return a vector with each iterations results, or am I just creating new vectors on each iteration that actually wont build on each recursive call. If I'm wrong, how do I go about building a vector recursively... Thanks in advance for your constructive help!
std::vector<ParameterClass> recursiveParser :: parseParamList()
{
std::vector<ParameterClass> paramVector;
if (lexicator->getCurrentToken()->getTokenType() == STRING) {
paramVector.push_back(ParameterClass(*lexicator->getCurrentToken()));
lexicator->advance();
parseParamList();
} else if (lexicator->getCurrentToken()->getTokenType() == ID) {
paramVector.push_back(ParameterClass(*lexicator->getCurrentToken()));
lexicator->advance();
parseParamList();
} else {
// so as to not fail in Expression, i need to check to see that there is a
// left paren indicating that there should be an expression
if (lexicator->getCurrentToken()->getTokenType() == LEFT_PAREN) {
paramVector.push_back(ParameterClass(parseExpression()));
lexicator->advance();
parseParamList();
}
}
return paramVector;
}
If you want build a list (vector etc) recursively, use the following pattern:
private:
void InternalBuild(std::vector<OutputData> & vec)
{
// Add data to vec
// Possibly call recursively InternalBuild(vec);
}
public:
std::vector<OutputData> RecursiveBuild()
{
std::vector<OutputData> vec;
InternalBuild(vec);
return vec;
}
It is worth noting, that you seem to misuse recursion here. The recursion is meant to be used on data structures, which are recursive by their nature (trees, graphs etc.). In this case you process linear data recursively - why not simply write something like:
while (!lexer.endOfExpression())
{
// Process token
lexer.Advance();
}
In your case, if you get expression long enough, you'll end up with a stack overflow exception, because your program will run out of stack memory. That won't happen if you implement this algorithm linearly.
try this, which append the result from recursive call
std::vector<ParameterClass> recursiveParser :: parseParamList()
{
std::vector<ParameterClass> paramVector;
if(lexicator->getCurrentToken()->getTokenType() == STRING)
{
paramVector.push_back(ParameterClass(*lexicator->getCurrentToken()));
lexicator->advance();
std::vector<ParameterClass> result = parseParamList();
std::copy(result.begin(), result.end(), std::back_inserter(paramVector));
}
else
if(lexicator->getCurrentToken()->getTokenType() == ID)
{
paramVector.push_back(ParameterClass(*lexicator->getCurrentToken()));
lexicator->advance();
std::vector<ParameterClass> result = parseParamList();
std::copy(result.begin(), result.end(), std::back_inserter(paramVector));
}else
{
// so as to not fail in Expression, i need to check to see that there is a left paren indicating that there should be an expression
if(lexicator->getCurrentToken()->getTokenType() == LEFT_PAREN)
{
paramVector.push_back(ParameterClass(parseExpression()));
lexicator->advance();
std::vector<ParameterClass> result = parseParamList();
std::copy(result.begin(), result.end(), std::back_inserter(paramVector));
}
}
return paramVector;
}
also please use switch instead of if-elseif-elseif and avoid repeated code
std::vector<ParameterClass> recursiveParser :: parseParamList()
{
std::vector<ParameterClass> paramVector;
switch(lexicator->getCurrentToken()->getTokenType())
{
case STRING:
paramVector.push_back(ParameterClass(*lexicator->getCurrentToken()));
break;
case ID:
paramVector.push_back(ParameterClass(*lexicator->getCurrentToken()));
break;
case LEFT_PAREN: // so as to not fail in Expression, i need to check to see that there is a left paren indicating that there should be an expression
paramVector.push_back(ParameterClass(parseExpression()));
break;
}
lexicator->advance();
std::vector<ParameterClass> result = parseParamList();
std::copy(result.begin(), result.end(), std::back_inserter(paramVector));
return paramVector;
}
but use #Spook's pattern, because it allows tail call optimization

Recursive Search Not Working

I have been building binary tree in C++. I tried to add search element functionality via recursive method.
It's not working properly.
Please see below code and guide.
bool Binarytree::SearchElement(node* SearchPtr,int key,bool found) {
if(SearchPtr->data==key)
found=true;
if(SearchPtr==NULL || found==true)
return found;
else
{
if(SearchPtr->data>key)
{ cout<<endl<<"Seaching in Left Sub tree"<<endl;
SearchElement(SearchPtr->left,key,found);
}
else
{ cout<<endl<<"Seaching in right Sub tree"<<endl;
SearchElement(SearchPtr->right,key,found);
}
}
}
The function SearchElement is called as below: (Note value 1 is not present in tree)
if(SearchElement(root,1,false))
cout<<endl<<"Element Found"<<endl;
else
cout<<endl<<"Element not Found"<<endl;
You're not returning anything. Once you've found NULL you need to return false. And if you've found the element you need to return true. Once you've known whether the element is present or not, you need to return for all the recursive calls. Check the code below.
Note: You've mentioned binary tree and searched like a binary search tree. Considering it is a binary search tree, it will be like this:
bool Binarytree::SearchElement(node* SearchPtr,int key) {
if(SearchPtr->data==key)
return true;
if(SearchPtr==NULL)
return false;
if(SearchPtr->data < key) //not greater than, but less than
{ cout<<endl<<"Seaching in Left Sub tree"<<endl;
return SearchElement(SearchPtr->left,key);
}
else
{ cout<<endl<<"Seaching in right Sub tree"<<endl;
return SearchElement(SearchPtr->right,key);
}
}
If it is binary tree, you'll have to traverse the whole tree to find whether the element is present or not. Like this:
bool Binarytree::SearchElement(node* SearchPtr,int key) {
if (SearchPtr==NULL)
return false;
if(SearchPtr->data==key)
return true;
if (SearchElement(SearchPtr->left,key))
return true;
if (SearchElement(SearchPtr->right,key))
return true;
return false;
}