Middle node of Singly linked List [closed] - c++

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
I found this code to print the middle node of a list in C++ but I don't understand the code...Someone can explain me this?
Type& findMiddleNode()
{
int check = 0;
nodeType *current;
nodeType *mid;
current = first;
mid = first;
while (current != NULL)
{
current = current->link;
check = (check + 1) % 2;
if (check == 0)
mid = mid->link;
}
return mid->info;
}
PD: This code works perfect, but I dont understand! Someone help me to understand this. Thanks!

The basic idea is to move two pointers B and A through the list, but with B moving at only half the speed of A.
The statement
check = (check + 1) % 2;
… gives check the values 0, 1, 0, 1 and so on, which is used to move B only every second time A is moved.
The same idea is one possible (and expected) answer to a question about checking whether a singly linked list contains a loop. In this case the fast moving pointer will catch up with the slow one after both have entered the loop.
A simpler way to do the same, with just about the same work expended by the program, is to (1) count the number of nodes n, and (2) starting at the start again, go to node number n/2.
Step (1) moves a pointer n times, like A above, and step (2) moves a pointer n/2 times, like B above.

Related

Is iterating inside a vector slower than accessing indices with a for loop? [closed]

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 17 days ago.
Improve this question
Is iterating through a vector of integers slower than accessing the indices using a loop? Here's what I mean:
std::vector<int> nums = {1, 2, 3, 4, 5};
for (int num : nums) {
std::cout << num;
}
for (int i = 0; i < nums; i++) {
std::cout << nums[i] << "\n";
}
Which one would be faster, which one uses more memory?
I'm just wondering which one is better performance-wise.
There is ultimately no way to know for sure apart from trying it and measuring it. There are always unexpected things that can happen that can affect the performance, so performance predictions on this level of detail are not always useful. But I would expect that your compiler is smart enough to produce the same code.
There is a chance the first one is slightly faster because it doesn't call nums.size() on every iteration. If the compiler can't be sure that nums.size() doesn't change, it might actually check the size again, on every iteration. The : syntax calculates the start and end of the vector before it runs the loop.
I suppose you meant i < nums.size() in the second one.

Issue with leet code problem 3 Longest substring [closed]

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 3 months ago.
Improve this question
Essentially we are asked to find, given a string, the longest substring with no repeating characters, below I am using the sliding window approach.
Examples:
Input: s = "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.
Input: s = "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.
Input: s = "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3.
Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.
My attempt:
class Solution {
public:
int lengthOfLongestSubstring(std::string s){
int count{0};
std::map<char,int> char_map;
std::vector<char> char_vec;
auto left{char_vec.begin()};
auto right{char_vec.begin()};
for(int i = 0; i < s.length(); i++){
char_vec.push_back(s[i]);
if(char_map.find(s[i]) != char_map.end()){
char_map[s[i]]++;
}
else{
char_map.insert(std::pair<char,int>{s[i],1});
}
while(++right != char_vec.end() && char_map[*(right)] > 1){
char_map[*(left++)]--;
}
count = (count < std::distance(left,right)) ? std::distance(left,right) : count;
}
return count;
}
};
However, there is an issue in the while loop near the end of the code block that is causing
compiler error and am very confused about how to solve it.
So your code is suffering from iterator invalidation. Here you have a vector
std::vector<char> char_vec;
and here you create two iterators to that vector
auto left{char_vec.begin()};
auto right{char_vec.begin()};
and then here you add an item to that vector
char_vec.push_back(s[i]);
When you add an item to a vector you may invalidate any iterators to that vector, and any use of such iterators causes your program to have undefined behaviour.
Instead of using iterators you could try using offsets (i.e. integer variables which you use to index the vector). These have the advantage that they are not invalidated as the vector grows.
For more information on iterator invalidation see the table on this page. Different containers have different behaviour wrt iterator invalidation.

How to optimise this code of sorting,this is not exeuting within the time limits.This question is from hackerrank [closed]

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 2 years ago.
Improve this question
How to reduce the time compexity of this code,this is not exeuting within the time
exact ques from hackerrank--
Complete the circularArrayRotation function in the editor below. It should return an array of integers representing the values at the specified indices.
circularArrayRotation has the following parameter(s):
a: an array of integers to rotate
k: an integer, the rotation count
queries: an array of integers, the indices to report
vector<int> circularArrayRotation(vector<int> a, int k, vector<int> queries) {
int i,temp;
vector<int> ans;
//to perform number of queries k
while(k--)
{ //shift last element to first pos and then move rest of elements to 1 postion forward
temp=a[a.size()-1]; //last element
for(i=a.size()-1;i>0;i--)
{
a[i]=a[i-1];
}
a[0]=temp;
}
for(i=0;i<queries.size();i++)
{
ans.push_back(a[queries[i]]);
}
return ans;
}
The vector a is being rotated by k in the while loop. The whole loop can be removed by adding k and using modulo when accessing elements in a:
ans.push_back(a[(queries[i]+k)%a.size()]);
Note: you might need handling of negative values of k.
Note: Maybe it should be minus instead of plus.
An alternative could be to use std::rotate.
Furthermore, the ans vector should be pre-allocated to reduce the number of allocations to one:
ans.reserve(queries.size());

Leetcode question to finding the longest univalue path [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 3 years ago.
Improve this question
Question:
Given a binary tree, find the length of the longest path where each node in the path has the same value. This path may or may not pass through the root.
The length of path between two nodes is represented by the number of edges between them.
source
A solution to this is:
class Solution
{
public:
int max_len = INT_MIN;
int longestUnivaluePath(TreeNode* root)
{
if(!root)
return 0;
helper(root, root->val);
return max_len;
}
int helper(TreeNode* root, int prev_value)
{
if(!root)
return 0;
int left = helper(root->left, root->val);
int right = helper(root->right, root->val);
max_len = std::max(left + right, max_len); // Why do we do this? I have no idea
if(root->val == prev_value)
return std::max(left, right) + 1;
return 0;
}
};
Why do we do this: max_len = std::max(left + right, max_len); This part does not make sense to me. If anyone can actually explain it simply I would greatly appreciate the insight.
The longest path doesn't have to be strictly descending, right? For example, the length of the longest univalue path in the following tree is 2:
3
/ \
3 3
In their algorithm,
left is the length of the longest descending univalue path down the left branch of node.
right is the length of the longest descending univalue path down the right branch of node.
Combined, left + right is the length of the longest univalue path going through the node node, which is the new candidate path.
So the line in question actually means
max_len = std::max(candidate_len, max_len);
which is a canonical running max algorithm: it processes the candidate values sequentially, one by one, and keeps the maximum value seen thus far in max_len. Eventually, max_len will end up with the maximum value of all candidates.

Group duplicate items in vector - c++ [closed]

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 5 years ago.
Improve this question
INPUT : [3,3,3,2,2,2,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0]
OUTPUT : [[3,3,3],[2,2,2],[1,1,1,1,1],[0,0,0,0,0,0,0,0,0,0]]
The Input is a vector of int while the Output is a vector of vectors of ints. The aim is to do this in the most efficient possible way in terms of time-taken.
The solution I am currently using is this :
vector<vector<int> results;
vector<int> result;
for(int i = 0 ; i < list.size() - 1 ; i++ ){
result.push_back(list[i]);
if ( list[i] != list[i+1]){
results.push_back(result);
result.clear();
}
}
result.push_back(list[list.size()-1]);
results.push_back(result);
credit to : #kabanus
You should use the standard algorithm library as much as possible
This is a possible implementation:
template <class T>
auto make_clusters(std::vector<T>& v) -> std::vector<std::vector<T>>
{
std::vector<std::vector<T>> clusters;
auto cluster_begin = v.begin();
while (cluster_begin != v.end())
{
auto elem = *cluster_begin;
auto cluster_end = std::find_if(cluster_begin, v.end(),
[&](int e) { return e != elem; });
clusters.emplace_back(std::distance(cluster_begin, cluster_end), elem);
cluster_begin = cluster_end;
}
return clusters;
}
You're close. You already figured out your bounds problem, but consider what happens at the interface of clusters:
..2,2,3,3...
^ ^
i i+1
You are going to enter the else (else if is unnecessary if the condition is the exact opposite of the original if) and forget to add that last 2. If there are no duplicates in the vector, such as
`{1,2,3,4}`
You are not going to add anything but empty clusters! So, you always want to add the number, rather you're in a cluster or ending it. If you're ending a cluster you also want to add it and clear.
for(int i = 0 ; i < sorted.size()-1 ; i++ ){
cluster.push_back(sorted[i]);
if ( sorted[i] != sorted[i+1]){
clusters.push_back(cluster);
cluster.clear();
}
}
Finally, as #tobi303 mentioned the last element is missing. This is especially obvious with a list with a single element ({3}). Note the last cluster is not added in any case, whether if it's a new single element at the end or just a final cluster.
So, once we exit the for we need one more check (not really) - if the cluster is empty that means the last element is not a part of it, and is a new one. Otherwise, the last cluster wasn't added yet and you need to append the last element to it, and then add the cluster. I'm leaving this one up to you.