I am trying to solve the Word Ladder problem from leetcode. In a nutshell, it asks you to write code that transforms one word into another by replacing one letter at a time, such that each intermediate string is also a word.
I know anyone can solve it easily with BFS. But I think dynamic programming (dp) technique will also work here. So I am trying to solve it with dp. For every sample test cases, it works fine. But this code fails for large input (System judges). .
Still now I am not understanding why dp won't work here?
Can anyone please give me a small input where this fails? You know it is almost impossible to test this code debugging by this large input.
Thank in advance.
class Solution {
public:
vector<int> dp;
int n;
bool isOneDiff(string str1, string str2) {
if(str1.length() != str2.length()) return false;
int len = str1.length();
int cnt = 0;
for(int i = 0; i < len; i++) {
if(str1[i] != str2[i]) cnt++;
}
return cnt == 1;
}
int solve(string cur, int ind, const string endWord, vector<string> wordList) {
if(cur == endWord) return 1;
int &ret = dp[ind];
if(ret != -1) return ret;
ret = 100000000; // Infinity
for(int i = 0; i < n; i++) {
if(isOneDiff(cur, wordList[i])) {
ret = min(ret, 1 + solve(wordList[i], i, endWord, wordList));
}
}
return ret;
}
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
n = wordList.size();
dp.clear();
dp.resize(n+2, -1);
int res = solve(beginWord, n, endWord, wordList);
if(res >= 100000000) return 0; // if res is greater than or equal to infinity then I have to return 0
return res;
}
};
It looks like you are trying to memoize a DFS. DFS will run into trouble on cycles, and also means that you have to explore a possibly large search space before you consider very short solutions.
Incidentally I would not suggest using BFS for this problem. Instead I would suggest using A* search.
Related
Been working through LeetCode things as a supplement to get ahead before taking my intro course this term at university and as a way to pick up C++. I'm very comfortable with Python, but obviously working backwards here is rather difficult. At any rate, this algorithm seems like it should work, but, per the title, it isn't.
The parameter is an arbitrarily sized vector of 1's and 0's (int's). The goal is to return the length of the longest string of 1's. For example, given [1,0,1,1,0,1,1,1], this function should return 3.
int findMaxConsecutiveOnes(vector<int>& nums) {
int len = nums.size();
int i;
int temp = 0;
int max, t2 = 0;
for(i = 0; i<len; i++){
if(nums[i] == 1){
temp++;
}
if(nums[i] == 0){
t2 = temp;
temp = 0;
if(t2 > max){
max = t2;
}
}
}
return max;
}
When I submit this though, it fails on the test case [1,0,1,1,0,1].
Rather than yielding the correct answer 2, it returns a seemingly random number far greater than 2 each time. Here are a few: 1834804276, 153863300, 928150512, ...
The only thing I can think of is issues with data types that are currently beyond my knowledge, but I'm beat. Appreciate any comments/ feedback.
int findMaxConsecutiveOnes(vector<int>& nums) {
int len = nums.size();
int i;
int temp = 0;
int max = 0;
for(i=0; i < len; i++){
if(nums[i] == 1){
temp++;
if (temp > max){
max = temp;
}
}
if(nums[i] == 0){
temp = 0;
}
}
return max;
}
In response to Sam and Quentin's comments and for some closure if someone is looking at this. C++ does require you to actually initialize everything (something that was new to me coming from Python3). Like Sam had mentioned in a comment, checking for the largest string of 1's while adding to temp is a much wider umbrella. Thus, here is my accepted solution.
I have tried to solve the problem Rerouting at hacker rank. I am posting here for help as competition is over.
https://www.hackerrank.com/contests/hack-the-interview-v-asia-pacific/challenges/rerouting
I have tried to solve problem using Strong connected components, but test cases failed. I can understand we have to remove cycles. But I stuck how to approach problem. Below is solution i have written. I am looking for guidence how to move forward so that i can apply my knowledge future based on mistakes i made here. Thanks for your time and help
int getMinConnectionChange(vector<int> connection) {
// Idea: Get number of strongly connected components.
int numberOfVertices = connection.size();
for(int idx = 0; idx < numberOfVertices; idx++) {
cout << idx+1 <<":"<< connection[idx] << endl;
}
stack<int> stkVertices;
map<int, bool> mpVertexVisited; //is vertex visited.think this as a chalk mark for nodes visited.
int numOFSCCs = 0;
int currTime = 1;
for (int vertexId = 0; vertexId < numberOfVertices; vertexId++) {
// check if node is already visited.
if (mpVertexVisited.find(vertexId+1) == mpVertexVisited.end()) {
numOFSCCs++;
mpVertexVisited.insert(make_pair(vertexId+1, true));
stkVertices.push(vertexId+1);
currTime++;
while (!stkVertices.empty()) {
int iCurrentVertex = stkVertices.top();
stkVertices.pop();
// get adjacent vertices. In this excercise we have only one neighbour. i.e., edge
int neighbourVertexId = connection[iCurrentVertex-1];
// if vertex is already visisted, don't insert in to stack.
if (mpVertexVisited.find(neighbourVertexId) != mpVertexVisited.end()) {
continue;
}
mpVertexVisited.insert(make_pair(neighbourVertexId, true));
stkVertices.push(neighbourVertexId);
} // while loop
} // if condition m_mapVrtxTimes.find(*itr) == m_mapVrtxTimes.end()
} // for loop of vertices
return numOFSCCs - 1;
}
This is a problem that I just solved and would like to share the solution.
The problem can be solved with union-find.
Two main observation:
The number of edges that has to be changed is the number of components - 1 (not necessarily strongly connected) Thus, union-find is handy here for finding the number of components
Second observation is that some component doesn't have terminating node, consider 1<->2, in other words, a cycle exist. We can detect whether there exists a terminating node if some node doesn't have an outgoing edge.
If all components have a cycle, it means that we need to change every component instead of a number of components - 1. This is to make it such that the graph will have a terminating point.
Code:
struct UF {
vector<int> p, rank, size;
int cnt;
UF(int N) {
p = rank = size = vector<int>(N, 1);
for (int i = 0; i < N; i++) p[i] = i;
cnt = N;
}
int find(int i) {
return p[i] == i ? i : p[i] = find(p[i]);
}
bool connected(int i, int j) {
return find(i) == find(j);
}
void join(int i, int j) {
if (connected(i, j)) return;
int x = find(i), y = find(j);
cnt--;
if (rank[x] > rank[y]) {
p[y] = x;
size[x] += size[y];
} else {
p[x] = y;
size[y] += size[x];
if (rank[x] == rank[y]) rank[y]++;
}
}
};
int getMinConnectionChange(vector<int> connection) {
int nonCycle = 0;
int n = connection.size();
UF uf(n);
for(int i=0;i<n;i++) {
int to = connection[i] - 1;
if(to == i) nonCycle++;
else uf.join(i, to);
}
int components = uf.cnt;
int countCycle = uf.cnt - nonCycle;
int res = components - 1;
if(countCycle == components) res++; // all components have cycle
return res;
}
TL;DR: you can view this as looking for a minimal spanning arborescence problem.
More precisely, add a node for each server, and another one called "Terminate".
Make a complete graph (each node is linked to every other one) and set as cost 0 for the edges corresponding to your input, 1 for the other ones.
You can use for example Edmond's algorithm to solve this.
I'm working with a few long strings inside a C++ program (up to 65535 letters).
What am looking for is a way to add a new line every set amount of letters with an function like this:
addNewLinesToString(std::string* string, u8 lettersBetween newline);
Which would work like this:
string test = "Testing1234567";
addNewLinesToString(&test, 7); //test == "Testing\n1234567\n"
I have yet to find such a function that only used the standard class library (C and/or C++)
If somebody has a simple solution for this would be great :)
Thanks.
You can use string::insert for this purpose.
addNewLinesToString(std::string& str, int sep)
{
for (int i = 0; i < str.size(); i += sep)
str.insert(i, "\n");
}
But this will be O(n^2) (as pointed by #stefan) , you can also
addNewLinesToString(std::string& str, int sep)
{
string ans;
int i = 0;
while (i < str.size())
{
if (i % sep == 0 && i)
ans.push_back('\n');
ans.push_back(str[i]);
i++;
}
return ans;
}
Which uses more memory but is O(n).
Take a look at examples: http://www.cplusplus.com/reference/string/string/insert/
std::string insert_newlines(const std::string &in, const size_t every_n)
{
std::string out;
out.reserve(in.size() + in.size() / every_n);
for(std::string::size_type i = 0; i < in.size(); i++) {
if (!(i % every_n) && i) {
out.push_back('\n');
}
out.push_back(in[i]);
}
return out;
}
This:
allocates memory exactly once.
doesn't make the mistake of using int where size_t or std::string::size_type is required, so you don't run into strange problems for large strings or embedded platforms.
runs in linear O(n) time.
has an functional interface (rather than modifying the string in-place), an algorithm that modifies the input string and runs in O(n) time would be much more complex.
Try this function:
void addNewLinesToString(std::string* s, int change){
if(change <= 0)
return;
for(int i = 0; i < s.size(); i += change){
s.insert(i, "\n");
i++;
}
}
Edit: I don't know why your post got voted down, I up voted.
Maybe not fastest, but working:
void addNewLinesToString (std::string* txt, int limit)
{
if(limit <= 0)
return;
limit++;
for (int i=1; i<=txt->size()/limit; i++)
txt->insert((i*limit)-1, "\n");
}
What is the fastest method to check if all elements of an array(preferable integer array) are equal. Till now I have been using the following code:
bool check(int array[], int n)
{
bool flag = 0;
for(int i = 0; i < n - 1; i++)
{
if(array[i] != array[i + 1])
flag = 1;
}
return flag;
}
int check(const int a[], int n)
{
while(--n>0 && a[n]==a[0]);
return n!=0;
}
Here is a solid solution which is valid C++11.
The advantages is that you do not need to manually play with the indexes or iterators. It is a best practice to
prefer algorithm calls to handwritten loops [Herb Sutter - C++ Coding Standards]
I think this will equally efficient as Paul R's solution.
bool check(const int a[], int n)
{
return !std::all_of(a, a+n, [a](int x){ return x==a[0]; });
}
Once you have found a mismatching element you can break out of the loop:
bool check(const int array[], int n)
{
for (int i = 0; i < n - 1; i++)
{
if (array[i] != array[i + 1])
return true;
}
return false;
}
If this is performance-critical then it can be further optimised slightly as:
bool check(const int array[], int n)
{
const int a0 = array[0];
for (int i = 1; i < n; i++)
{
if (array[i] != a0)
return true;
}
return false;
}
Recast the array to a larger data type. Eg, operate on 64bit ints, or use SSE or AVX intrinsics for 128 or 256 bit operation. For example, the SSE2 intrinsic is _mm_cmpeq_epi32, whose result you'll use with _mm_or_si128. Check the result with repeated application of _mm_srli_si128 and _mm_cvtsi128_si32. Check the result every few hundred iterations for early exit.
Make sure to operate on aligned memory, check the unaligned start and end as ints, and check the first packed element with itself.
For programmer efficiency you may try the following all in one line.
vector<int> v{1, 1, 1, 1};
all_of(v.cbegin(), v.cend(), [&r=v[0]](int value){ return value == r; }->bool);
I did not test run this code, let me know if there is syntax error.
Find a library that's available on your platform that supports threading or parallel-for loops, and split the computation out such that different cores test different ranges of the array.
Some available libraries are listed here:
http://parallel-for.sourceforge.net/parallelfor.html
Or possibly, you can make use of the parallism that many GPU's offer.
bool check(int array[],int n)
{
// here 1st element is checked with others. This decreases the number of iteration by 1.
// also it returns immediately.
// The requirement is to check if all the elements are equal.
// So if 1st element is equal to others then all elements are equal.
// Otherwise the elements are not equal.
for(int i=1;i<n;i++)
{
if(array[0]!=array[i])
return false;
}
return true;
}
We'll it's basically an O(n) operation so you can't do much better than what you have, other than dispensing with the flag and just return false; on the first failure and return true; after the iteration.
In theory, I would propose this:
bool check_single(const int a[], int n)
{
for (int i = 1; i < n; ++i) {
if (a[0] != a[n]) { return false; }
}
return true;
}
Compared to other (already proposed) versions:
a[0] will be hoisted outside the loop by the compiler, meaning a single array access within the loop
we loop from 0 to n, which is better (access-wise) than loading a[0] and then looping from a[n]
Obviously, it still checks N elements and thus is O(N).
fast hash mapping technique:
bool areSame(int a[],int n)
{
unordered_map<int,int> m; //hash map to store the frequency od every
for(int i=0;i<n;i++)
m[a[i]]++;
if(m.size()==1)
return true;
else
return false;
}
I think the following is more readable than the highest rated answer and I would wager more efficient too (but havent benchmarked)
bool check(int a[], int n)
{
if (n)
{
auto first = a[0];
for(int i = 1; i < n; i++)
{
if(array[i] != first) return false;
}
return true;
}
return true; //change to false for the OPs logic. I prefer logical true here
}
bool check_identity (int a[], int b[], const int size)
{
int i;
i = 0;
while ((i < size-1) && (a[i] == b[i])) i++;
return (a[i] == b[i]);
}
I've done a program for string comparison with one mismatch at a programming website. It gives me wrong answer. I've working on it extensively but, I couldn't find testcases where my code fails. Can somebody provide me test cases where my code fails. I've done the comparison using Boyer Moore Horspool k-mismatches algorithm as it's the fastest searching algorithm
The code is as such
int BMSearch_k(string text, string pattern, int tlen, int mlen,int pos)
{
int i, j=0,ready[256],skip2[256][mlen-1],neq;
for(i=0; i<256; ++i) ready[i] = mlen;
for(int a=0; a<256;a++) {
for(i = mlen;i>mlen-k;i--)
skip2[i][a] = mlen;
}
for(i = mlen-2;i>=1;i--) {
for(j=ready[pattern[i]]-1;j>=max(i,mlen-k);j--)
skip2[j][pattern[i]] = j-i;
ready[pattern[i]] = max(i,mlen-k);
}
j = mlen-1+pos;
//cout<<"\n--jafffa--\n"<<pos<<"+"<<mlen<<"="<<j<<endl;
while(j<tlen+k) {
//cout<<"\t--"<<j<<endl;
int h = j;
i=mlen-1;
int neq=0,shift = mlen-k;
while(i>=0&&neq<=k) {
//cout<<"\t--"<<i<<endl;
if(i>=mlen-k)
shift = min(shift,skip2[i][text[h]]);
if(text[h]!= pattern[i])
neq++;
i--;
h--;
}
if(neq<=k)
return j-1;
j += shift;
}
return -1;
}
You aren't initialising your arrays correctly,
int i, j=0,ready[256],skip2[256][mlen-1],neq;
for(i=0; i<256; ++i) ready[i] = mlen;
for(int a=0; a<256;a++) {
for(i = mlen;i>mlen-k;i--)
skip2[i][a] = mlen;
}
On the one hand, you declare skip2 as a 256×(mlen-1) array, on the other hand, you fill it as a (mlen+1)×256 array.
In the next loop,
for(i = mlen-2;i>=1;i--) {
for(j=ready[pattern[i]]-1;j>=max(i,mlen-k);j--)
skip2[j][pattern[i]] = j-i;
ready[pattern[i]] = max(i,mlen-k);
}
you use ready[pattern[i]] before it has been set. I don't know if those mistakes are what's causing the failing testcase, but it's easily imaginable that they do.
If Daniel's suggestions do not solve the problem, here are a couple more things that look odd:
return j-1; // I would expect "return j;" here
This seems odd as if you have k=0,mlen=1, then the highest value that j can take is tlen+k-1, and so the highest return value is tlen-2. In other words matching a pattern 'a' against a string 'a' will not return a match at position 0.
Another oddity is the loop:
for(i = mlen-2;i>=1;i--) // I would expect "for(i = mlen-2;i>=0;i--)" here
it seems odd that in the preprocessing you will never access the first character in your pattern (i.e. pattern[0] is not read).