I find recursion, apart from very straight forward ones like factorial, very difficult to understand. The following snippet prints all permutations of a string. Can anyone help me understand it. What is the way to go about to understand recursion properly.
void permute(char a[], int i, int n)
{
int j;
if (i == n)
cout << a << endl;
else
{
for (j = i; j <= n; j++)
{
swap(a[i], a[j]);
permute(a, i+1, n);
swap(a[i], a[j]);
}
}
}
int main()
{
char a[] = "ABCD";
permute(a, 0, 3);
getchar();
return 0;
}
PaulR has the right suggestion. You have to run through the code by "hand" (using whatever tools you want - debuggers, paper, logging function calls and variables at certain points) until you understand it. For an explanation of the code I'll refer you to quasiverse's excellent answer.
Perhaps this visualization of the call graph with a slightly smaller string makes it more obvious how it works:
The graph was made with graphviz.
// x.dot
// dot x.dot -Tpng -o x.png
digraph x {
rankdir=LR
size="16,10"
node [label="permute(\"ABC\", 0, 2)"] n0;
node [label="permute(\"ABC\", 1, 2)"] n1;
node [label="permute(\"ABC\", 2, 2)"] n2;
node [label="permute(\"ACB\", 2, 2)"] n3;
node [label="permute(\"BAC\", 1, 2)"] n4;
node [label="permute(\"BAC\", 2, 2)"] n5;
node [label="permute(\"BCA\", 2, 2)"] n6;
node [label="permute(\"CBA\", 1, 2)"] n7;
node [label="permute(\"CBA\", 2, 2)"] n8;
node [label="permute(\"CAB\", 2, 2)"] n9;
n0 -> n1 [label="swap(0, 0)"];
n0 -> n4 [label="swap(0, 1)"];
n0 -> n7 [label="swap(0, 2)"];
n1 -> n2 [label="swap(1, 1)"];
n1 -> n3 [label="swap(1, 2)"];
n4 -> n5 [label="swap(1, 1)"];
n4 -> n6 [label="swap(1, 2)"];
n7 -> n8 [label="swap(1, 1)"];
n7 -> n9 [label="swap(1, 2)"];
}
To use recursion effectively in design, you solve the problem by assuming you've already solved it.
The mental springboard for the current problem is "if I could calculate the permutations of n-1 characters, then I could calculate the permutations of n characters by choosing each one in turn and appending the permutations of the remaining n-1 characters, which I'm pretending I already know how to do".
Then you need a way to do what's called "bottoming out" the recursion. Since each new sub-problem is smaller than the last, perhaps you'll eventually get to a sub-sub-problem that you REALLY know how to solve.
In this case, you already know all the permutations of ONE character - it's just the character. So you know how to solve it for n=1 and for every number that's one more than a number you can solve it for, and you're done. This is very closely related to something called mathematical induction.
It chooses each character from all the possible characters left:
void permute(char a[], int i, int n)
{
int j;
if (i == n) // If we've chosen all the characters then:
cout << a << endl; // we're done, so output it
else
{
for (j = i; j <= n; j++) // Otherwise, we've chosen characters a[0] to a[j-1]
{ // so let's try all possible characters for a[j]
swap(a[i], a[j]); // Choose which one out of a[j] to a[n] you will choose
permute(a, i+1, n); // Choose the remaining letters
swap(a[i], a[j]); // Undo the previous swap so we can choose the next possibility for a[j]
}
}
}
This code and reference might help you to understand it.
// C program to print all permutations with duplicates allowed
#include <stdio.h>
#include <string.h>
/* Function to swap values at two pointers */
void swap(char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
/* Function to print permutations of string
This function takes three parameters:
1. String
2. Starting index of the string
3. Ending index of the string. */
void permute(char *a, int l, int r)
{
int i;
if (l == r)
printf("%s\n", a);
else
{
for (i = l; i <= r; i++)
{
swap((a+l), (a+i));
permute(a, l+1, r);
swap((a+l), (a+i)); //backtrack
}
}
}
/* Driver program to test above functions */
int main()
{
char str[] = "ABC";
int n = strlen(str);
permute(str, 0, n-1);
return 0;
}
Reference: Geeksforgeeks.org
Though it is little old question and already answered thought of adding my inputs to help new visitors. Also planning to explain the running time without focusing on Recursive Reconciliation.
I have written the sample in C# but easy to understand for most of the programmers.
static int noOfFunctionCalls = 0;
static int noOfCharDisplayCalls = 0;
static int noOfBaseCaseCalls = 0;
static int noOfRecursiveCaseCalls = 0;
static int noOfSwapCalls = 0;
static int noOfForLoopCalls = 0;
static string Permute(char[] elementsList, int currentIndex)
{
++noOfFunctionCalls;
if (currentIndex == elementsList.Length)
{
++noOfBaseCaseCalls;
foreach (char element in elementsList)
{
++noOfCharDisplayCalls;
strBldr.Append(" " + element);
}
strBldr.AppendLine("");
}
else
{
++noOfRecursiveCaseCalls;
for (int lpIndex = currentIndex; lpIndex < elementsList.Length; lpIndex++)
{
++noOfForLoopCalls;
if (lpIndex != currentIndex)
{
++noOfSwapCalls;
Swap(ref elementsList[currentIndex], ref elementsList[lpIndex]);
}
Permute(elementsList, (currentIndex + 1));
if (lpIndex != currentIndex)
{
Swap(ref elementsList[currentIndex], ref elementsList[lpIndex]);
}
}
}
return strBldr.ToString();
}
static void Swap(ref char Char1, ref char Char2)
{
char tempElement = Char1;
Char1 = Char2;
Char2 = tempElement;
}
public static void StringPermutationsTest()
{
strBldr = new StringBuilder();
Debug.Flush();
noOfFunctionCalls = 0;
noOfCharDisplayCalls = 0;
noOfBaseCaseCalls = 0;
noOfRecursiveCaseCalls = 0;
noOfSwapCalls = 0;
noOfForLoopCalls = 0;
//string resultString = Permute("A".ToCharArray(), 0);
//string resultString = Permute("AB".ToCharArray(), 0);
string resultString = Permute("ABC".ToCharArray(), 0);
//string resultString = Permute("ABCD".ToCharArray(), 0);
//string resultString = Permute("ABCDE".ToCharArray(), 0);
resultString += "\nNo of Function Calls : " + noOfFunctionCalls;
resultString += "\nNo of Base Case Calls : " + noOfBaseCaseCalls;
resultString += "\nNo of General Case Calls : " + noOfRecursiveCaseCalls;
resultString += "\nNo of For Loop Calls : " + noOfForLoopCalls;
resultString += "\nNo of Char Display Calls : " + noOfCharDisplayCalls;
resultString += "\nNo of Swap Calls : " + noOfSwapCalls;
Debug.WriteLine(resultString);
MessageBox.Show(resultString);
}
Steps:
For e.g. when we pass input as "ABC".
Permutations method called from Main for first time. So calling with Index 0 and that is first call.
In the else part in for loop we are repeating from 0 to 2 making 1 call each time.
Under each loop we are recursively calling with LpCnt + 1.
4.1 When index is 1 then 2 recursive calls.
4.2 When index is 2 then 1 recursive calls.
So from point 2 to 4.2 total calls are 5 for each loop and total is 15 calls + main entry call = 16.
Each time loopCnt is 3 then if condition gets executed.
From the diagram we can see loop count becoming 3 total 6 times i.e. Factorial value of 3 i.e. Input "ABC" length.
If statement's for loop repeats 'n' times to display chars from the example "ABC" i.e. 3.
Total 6 times (Factorial times) we enter into if to display the permutations.
So the total running time = n X n!.
I have given some static CallCnt variables and the table to understand each line execution in detail.
Experts, feel free to edit my answer or comment if any of my details are not clear or incorrect, I am happy correct them.
Download the sample code and other samples from here
Think about the recursion as simply a number of levels. At each level, you are running a piece of code, here you are running a for loop n-i times at each level. this window gets decreasing at each level. n-i times, n-(i+1) times, n-(i+2) times,..2,1,0 times.
With respect to string manipulation and permutation, think of the string as simply a 'set' of chars. "abcd" as {'a', 'b', 'c', 'd'}. Permutation is rearranging these 4 items in all possible ways. Or as choosing 4 items out of these 4 items in different ways. In permutations the order does matter. abcd is different from acbd. we have to generate both.
The recursive code provided by you exactly does that. In my string above "abcd", your recursive code runs 4 iterations (levels). In the first iteration you have 4 elements to choose from. second iteration, you have 3 elements to choose from, third 2 elements, and so on. so your code runs 4! calculations. This is explained below
First iteration:
choose a char from {a,b,c,d}
Second Iteration:
choose a char from subtracted set {{a,b,c,d} - {x}} where x is the char chosen from first iteration. i.e. if 'a' has been choose in first iteration, this iteration has {b,c,d} to choose from.
Third Iteration:
choose a char from subtracted set {{a,b,c,d} - {x,y}} where x and y are chosen chars from previous iterations. i.e. if 'a' is chosen at first iteration, and 'c' is chosen from 2nd, we have {b,d} to play with here.
This repeats until we choose 4 chars overall. Once we choose 4 possible char, we print the chars. Then backtrack and choose a different char from the possible set. i.e. when backtrack to Third iteration, we choose next from possible set {b,d}. This way we are generating all possible permutations of the given string.
We are doing this set manipulations so that we are not selecting the same chars twice. i.e. abcc, abbc, abbd,bbbb are invalid.
The swap statement in your code does this set construction. It splits the string into two sets free set to choose from used set that are already used. All chars on left side of i+1 is used set and right are free set. In first iteration, you are choosing among {a,b,c,d} and then passing {a}:{b,c,d} to next iteration. The next iteration chooses one of {b,c,d} and passes {a,b}:{c,d} to next iteration, and so on. When the control backtracks back to this iteration, you will then choose c and construct {a,c}, {b,d} using swapping.
That's the concept. Otherwise, the recursion is simple here running n deep and each level running a loop for n, n-1, n-2, n-3...2,1 times.
Related
Two integers x and y form a magical pair, if the result of their Bitwise And equals 0.
Given an array of integers, find for every array element whether it forms a magical pair with some other array element or not.
Input
First line of the input contains a single integer T denoting the number of test cases.
The first line of each test case has an integer N denoting the number of elements in the given array.
The second line contains N single space-separated integers a1,a2,...an denoting the elements of the given array.
Output
For each test case ,print N space separated integers in a line.
If ai forms a magical pair with any other element of the given array , then ans'i should be equal to 1. Otherwise ans'i is 0.
Constraints
1<=N,Ai<=10^6
I tried brute force. For each element I checked if the bitwise AND of this number is zero or not with any other element present in the array. Obviously, it had a time complexity of O(N^2) and most of my test cases timed out
This problem is here: https://www.hackerearth.com/challenges/test/netapp-codenet-2017/algorithm/d2d1f6a92c6740278682e88ed42068a4/
Can anyone suggest me a better approach or algorithm so it passes the time limit?
Brute force code:
int n;
cin >> n;
int a[n];
for (int i = 0; i < n; i++)
cin >> a[i];
int ans[n];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (a[i] & a[j] == 0)
ans[i] = 1;
for (int i = 0; i < n; i++)
cout << ans[i] << " ";
One way to do it would be to create a binary tree for all the numbers like a Trie.
For example, if you have array 3 6 2 9 10, binary array would look like
arr = 11, 110, 10, 1001, 1010, and the tree would like
root
/ \
0 1
\ / \
1 0 1
/ \ /
0 1 0
\ \
1 1
If we iterate through each element in binary array, the number(answer) matching the condition should have 0 for every set bit in the element and either 0 or 1 for unset bit in the element.
Now, we only need to traverse these bits into the tree. And if we are able to do it, then there exists at least one number satisfying the condition.
Time complexity O(N).
Reason:- There are n numbers. Each number is of 32 bit binary length. New node creation will take O(1). Therefore, O(32N) => O(N). Same time for inv_arr.
Note: Try converting the numbers into 32 bit binary numbers as it will cover all the numbers specified in the range. Otherwise it will result in a problem. Here 6 and 9 forms a magical pair, but 0110 in the inv_arr cannot be traversed and will result in no magical pair present as traversal of leftmost 0 cannot be done. If all numbers will be represented with same length binary, tree traversal will give correct answer.
Code
public class BinaryNode {
char c;
public BinaryNode left;
public BinaryNode right;
public BinaryNode(char c) {
this.c = c;
}
}
public class BinaryTree {
public BinaryNode root;
public BinaryTree(char c) {
root = new BinaryNode(c);
}
public void addToTree(String s) {
BinaryNode node = this.root;
int length = s.length();
for (int i = s.length()-1; i >= 0; i--) {
BinaryNode newNode;
if (s.charAt(i) == '0') {
newNode = addCharToTree(node.left, s.charAt(i));
node.left = newNode;
} else {
newNode = addCharToTree(node.right, s.charAt(i));
node.right = newNode;
}
node = newNode;
}
}
private BinaryNode addCharToTree(BinaryNode node, char c) {
if (node == null)
return new BinaryNode(c);
return node;
}
}
public class Solution {
private static void findMagicalPairs(List<Integer> list) {
// for creating 32 char long binary string list
List<String> binaryNumberList = list.stream()
.map(num -> Long.toBinaryString( Integer.toUnsignedLong(num) | 0x100000000L ).substring(1))
.collect(Collectors.toList());
// dummy character as root
BinaryTree binaryTree = new BinaryTree('c');
binaryNumberList.forEach(binaryTree::addToTree);
List<Boolean> booleanList = binaryNumberList.stream()
.map(s -> hasMagicalPair(s, binaryTree.root))
.collect(Collectors.toList());
}
private static boolean hasMagicalPair(String s, BinaryNode node) {
if (s == null || s.length() == 0)
return true;
if (node == null)
return false;
String substring = s.substring(0, s.length() - 1);
if (s.charAt(s.length()-1) == '1')
return hasMagicalPair(substring, node.left) ;
return hasMagicalPair(substring, node.left) || hasMagicalPair(substring, node.right);
}
}
First of all, sorry for the long answer :)
Problem: I think the problem with your brute force is that you are performing each checking twice (in both directions). Moreover, a lot of checkings are unnecessary.You can easily reduce the number of iterations by doing every checking only once (and only the necessary ones).
Key idea: You should not start the inner loop from 0.
Note: The first of the following sections only introduce the second, but the second section is the one that answers your question.
The whole code provided here is only meant to illustrate the stated ideas, nothing more.
1 - Find all possible magical pairs
Here we are trying to find all possible magical pairs in the given vector avoiding to check multiple times the same pair.
A solution could be:
std::vector<std::pair<int, int>> magical_pairs(const std::vector<int> & data)
{
std::vector<std::pair<int, int>> result;
for(size_t i = 0; i < data.size()-1; ++i) // Stop at second to last
{
for(size_t j = i+1; j < data.size(); ++j) // Start from i+1 and not 0
{
if((data[i] & data[j]) == 0)
result.push_back(std::make_pair(data[i], data[j]));
}
}
return result;
}
This way, you check all possible pairs only once.
According to me, if you want to get all possible magical pairs, you cannot reduce the complexity less than what it takes to check all possible pairs only once.But if someone has a better solution, I will be very interested to hear it (read it).
You can run an example this way:
std::vector<int> input_array {3, 12, -6, 27, 8, 18, -66, 47, 11}; // input example
for(const std::pair<int, int> & mp : magical_pairs(input_array))
std::cout << mp.first << " : " << mp.second << std::endl;
The results for this example:
3 : 12
3 : 8
12 : 18
8 : 18
2 - Check whether a number has a magical pair or not
Now that we know how to avoid to check already checked pairs, we will reuse the same principle to realize the function you want.
You want to check for every number in the array whether they have a magical pair in the array or not.In this case, we don't want to check all possible magical pairs, only one match is sufficient to determine if a number has a pair. Moreover, when we find a match, we can set two results at a time (one for each number of the pair).You can see that this way, we will be able to significantly reduce the number of iterations.
It leads us to proceed as follows:
Check every pair only once
Stop evaluation of a number at first match
Determine two results per match --> don't perform the search if already set
Knowing this, a solution could be:
std::vector<bool> has_magical_pair(const std::vector<int> & data)
{
std::vector<bool> result(data.size(), false);
for(size_t i = 0; i < data.size()-1; ++i) // From 0 to second to last
{
if(!result[i]) // search for a magical pair only if not already found
{
for(size_t j = i+1; j < data.size(); ++j) // From i+1 to last
{
if((data[i] & data[j]) == 0)
{
// Set two results at a time
result[i] = true;
result[j] = true;
break; // Exit the inner loop at first match
}
}
}
}
return result;
}
This way, you will be much more efficient than the brute force method.
You can run an example this way:
std::vector<int> input_array {3, 12, -6, 27, 8, 18, -66, 47, 11};
for(bool hmp : has_magical_pair(input_array))
std::cout << hmp << ", ";
std::cout << std::endl;
The results for this example:
1, 1, 0, 0, 1, 1, 0, 0, 0,
I think you will be able to adapt the code of this example to your use case quite easily.
I hope it can help you.
You have to save the operations you do first.
In the example you have 3 6 2 9 10
When you do it by brute force you first do
3 & 6
And after doing all the
3 & y
you repeat
6 & 3
. If you find how to avoid repeating this, you'll solve the problem.
I am currently struggling with a homework problem for my Algorithms Class. A summary of the instruction:
The user enters an integer 'n' to determine the number of test cases.
The user individually enters another integer 'num' to determine the # of elements in each test case.
The user enters the elements of the individual array.
The algorithm has to process the array and determine whether it can be partitioned into two subsequences, each of which is in strictly increasing order. If the result is positive, the program prints "Yes", otherwise it prints "No".
I have 24 hours to complete this assignment but am struggling with the primary problem - I cannot properly process the user input. (come up with an algorithm to split the two subsequences)
update: I got to this solution. It passes 4/5 tests but fails the time constraint in the last test.
#include<iostream>
#include<string>
using namespace std;
bool run(){
int numbers;
int *arr;
cin >> numbers;
arr = new int[numbers];
for (int i = 0; i < numbers; i++)
cin >> arr[i];
long long int MAX = 0;
long long int MAX2 = 0;
string stra = "";
string strb = "";
string result = "";
string total = "";
long long int sum = 0;
for (int i = 0; i < numbers; i++){
if (arr[i] >= MAX && arr[i] != arr[i - 1]){
stra += to_string(arr[i]);
MAX = arr[i];
}
else
if (arr[i] >= MAX2 && MAX2 != MAX){
strb += to_string(arr[i]);
MAX2 = arr[i];
}
}
for (int i = 0; i < numbers; i++){
result = to_string(arr[i]);
total += result;
}
long long int len1 = stra.length();
long long int len2 = strb.length();
sum += len1 + len2;
delete[] arr;
if (sum != total.length())
return false;
else
return true;
}
int main()
{
int test;
cin >> test;
while (test > 0)
{
if (run())
cout << "Yes\n";
else
cout << "No\n";
test--;
}
system("pause");
}
Example input:
2
5
3 1 5 2 4
5
4 8 1 5 3
Example output:
Yes
No
Explanation: For the array 3 1 5 2 4, the two strictly increasing subsequences are: 3 5 and 1 2 4.
It seems that the existence of any equal or decreasing subsequence of at least three elements means the array cannot be partitioned into two subsequences, each with strictly increasing order, since once we've placed the first element in one part and the second element in the other part, we have no place to place the third.
This seems to indicate that finding the longest decreasing or equal subsequence is a sure solution. Since we only need one of length 3, we can record in O(n) for each element if it has a greater or equal element to the left. Then perform the reverse. If any element has both a greater or equal partner on the left and a smaller or equal partner on the right, the answer is "no."
We can visualise the O(n) time, O(1) space method by plotting along value and position:
A choosing list B here
A x would be wrong
x
value B z
^ B x
| x
| A
| x
|
| B
| x
- - - - - - - -> position
We notice that as soon as a second list is established (with the first decrease), any element higher than the absolute max so far must be assigned to the list that contains it, and any element lower than it can, in any case, only be placed in the second list if at all.
If we were to assign an element higher than the absolute max so far to the second list (that does not contain it), we could arbitrarily construct a false negative by making the next element lower than both the element we just inserted into the second list and the previous absolute max, but greater than the previous max of the second list (z in the diagram). If we had correctly inserted the element higher than the previous absolute max into that first list, we'd still have room to insert the new, arbitrary element into the second list.
(The JavaScript code below technically uses O(n) space in order to show the partition but notice that we only rely on the last element of each part.)
function f(A){
let partA = [A[0]];
let partB = [];
for (let i=1; i<A.length; i++){
if (A[i] > partA[partA.length-1])
partA.push(A[i]);
else if (partB.length && A[i] <= partB[partB.length-1])
return false;
else
partB.push(A[i]);
}
return [partA, partB];
}
let str = '';
let examples = [
[30, 10, 50, 25, 26],
[3, 1, 5, 2, 4],
[4, 8, 1, 5, 3],
[3, 1, 1, 2, 4],
[3, 4, 5, 1, 2],
[3, 4, 1],
[4, 1, 2, 7, 3]
];
for (e of examples)
str += JSON.stringify(e) + '\n' + JSON.stringify(f(e)) + '\n\n';
console.log(str);
I would go over the entire array once and check two maximal values. If the actual array value is smaller than both maxima, it is not possible, otherwise the proper maximum is increased.
The algorithm does not have to traverse the whole array, if the split condition is violated before.
Here is my code
#include <algorithm>
#include <iostream>
#include <vector>
bool isAddable(const int item, int &max1, int &max2) {
if (max2 > item) {
return false;
}
else {
if (max1 > item) {
max2 = item;
}
else {
max1 = item;
}
return true;
}
}
void setStartValue(int &max1, int &max2, const std::vector<int> &vec) {
max1 = *std::min_element(vec.begin(), vec.begin() + 3);
max2 = *std::max_element(vec.begin(), vec.begin() + 3);
}
bool isDiviableIntoTwoIncreasingArrays(const std::vector<int> &vec) {
if (vec.size() < 3) {
return true;
}
int max1, max2;
setStartValue(max1, max2, vec);
for (int i = 2; i < vec.size(); ++i) {
if (max1 > max2) {
if (!isAddable(vec[i], max1, max2)) {
return false;
}
}
else {
if (!isAddable(vec[i], max2, max1)) {
return false;
}
}
}
return true;
}
int main() {
std::vector<int> userVec;
int tmp1;
while (std::cin >> tmp1) {
userVec.emplace_back(tmp1);
}
const std::vector<int> v1{3, 1, 5, 2, 4};
const std::vector<int> v2{4, 8, 1, 5, 3};
const std::vector<int> v3{3, 4, 1};
for (const std::vector<int> &vec : {userVec, v1, v2, v3}) {
if (isDiviableIntoTwoIncreasingArrays(vec)) {
std::cout << "Yes\n";
}
else {
std::cout << "No\n";
}
}
}
I think you could resort to using a brute force solution. Notice here I use vectors(I think you should as well) to store the data and I use recursion to exhaust out all possible combinations. Keep the problem in mind, solve it and then focus on trivial tasks like parsing the input and matching the way your coursework expects you to enter data. I have added inline comments to make this understandable.
bool canPartition(vector<int>& nums) {
if(nums.empty()) return false;
vector<int> part1 = {}, part2 = {}; // two partitions
auto ans = canPart(nums, part1, part2, 0); // pass this to our recursive function
return ans;
}
bool canPart(vector<int>& nums, vector<int>& part1, vector<int>& part2, int i)
{
if(i >= nums.size()) // we are at the end of the array is this a solution?
{
if(!part1.empty() && !part2.empty()) // only if the partitions are not empty
{
//if you want you could print part1 and part2 here
//to see what the partition looks like
return true;
}
return false;
}
bool resp1empty = false, resp2empty = false, resp1 = false, resp2 = false;
if(part1.empty()) // first partition is empty? lets add something
{
part1.push_back(nums[i]);
resp1empty = canPart(nums, part1, part2, i + 1);
part1.pop_back(); // well we need to remove this element and try another one
}
else if(nums[i] > part1.back()) // first partition is not empty lets check if the sequence is increasing
{
part1.push_back(nums[i]);
resp1 = canPart(nums, part1, part2, i + 1);
part1.pop_back();
}
if(part2.empty()) // is partition two empty? lets add something
{
part2.push_back(nums[i]);
resp2empty = canPart(nums, part1, part2, i + 1);
part2.pop_back();
}
else if(nums[i] > part2.back()) // check if sequence is increasing
{
part2.push_back(nums[i]);
resp2 = canPart(nums, part1, part2, i + 1);
part2.pop_back();
}
//if any of the recursive paths returns a true we have an answer
return resp1empty || resp2empty || resp1 || resp2;
}
You can now try this out with a main function:
vector<int> v = {3,1,5,2,4};
cout << canPartition(v);
The key take away is make a small test case, add a few more non trivial test cases, solve the problem and then look into parsing inputs for other test cases
I think this comes down to whether you have an option for a number to appear in the first list or second list or not.
So, we will keep adding numbers to list 1 and if we can't add any element, we will make it as the start of the new list.
Let's say, we have both the lists going. If we come across an element to whom we can't add to any of the lists, we return false.
There does arise a situation where we could add an element to any of the 2 lists. In this scenario, we adopt a greedy approach as to add to which list.
We prepare an array of minimum values from the right. For example, for [30,10,50,25,26], we will have an array of minimums as [10,25,25,26,(empty here since last)].
Now, let's trace how we could divide them into 2 lists properly.
30 => List A.
10 => List B. (since you can't add it first list, so make a new one from here)
50 => List A.
Here, 50 applies to come after either 30 or 10. If we choose 10, then we won't be able to accommodate the next 25 in either of the 2 lists and our program would fail here itself, since our lists would look like [30] and [10,50]. However, we could continue further if we add 50 to 30 by checking for the minimum stored for it in our minimums array, which is 25.
25 => List B.
26 => List B.
So, our final lists are [30,50] and [10,25,26].
Time complexity: O(n), Space complexity: O(n) and you can print the 2 lists as well.
If we come across a sorted array which is strictly increasing, we return true for them anyway.
I recently came across the KMP algorithm, and I have spent a lot of time trying to understand why it works. While I do understand the basic functionality now, I simply fail to understand the runtime computations.
I have taken the below code from the geeksForGeeks site: https://www.geeksforgeeks.org/kmp-algorithm-for-pattern-searching/
This site claims that if the text size is O(n) and pattern size is O(m), then KMP computes a match in max O(n) time. It also states that the LPS array can be computed in O(m) time.
// C++ program for implementation of KMP pattern searching
// algorithm
#include <bits/stdc++.h>
void computeLPSArray(char* pat, int M, int* lps);
// Prints occurrences of txt[] in pat[]
void KMPSearch(char* pat, char* txt)
{
int M = strlen(pat);
int N = strlen(txt);
// create lps[] that will hold the longest prefix suffix
// values for pattern
int lps[M];
// Preprocess the pattern (calculate lps[] array)
computeLPSArray(pat, M, lps);
int i = 0; // index for txt[]
int j = 0; // index for pat[]
while (i < N) {
if (pat[j] == txt[i]) {
j++;
i++;
}
if (j == M) {
printf("Found pattern at index %d ", i - j);
j = lps[j - 1];
}
// mismatch after j matches
else if (i < N && pat[j] != txt[i]) {
// Do not match lps[0..lps[j-1]] characters,
// they will match anyway
if (j != 0)
j = lps[j - 1];
else
i = i + 1;
}
}
}
// Fills lps[] for given patttern pat[0..M-1]
void computeLPSArray(char* pat, int M, int* lps)
{
// length of the previous longest prefix suffix
int len = 0;
lps[0] = 0; // lps[0] is always 0
// the loop calculates lps[i] for i = 1 to M-1
int i = 1;
while (i < M) {
if (pat[i] == pat[len]) {
len++;
lps[i] = len;
i++;
}
else // (pat[i] != pat[len])
{
// This is tricky. Consider the example.
// AAACAAAA and i = 7. The idea is similar
// to search step.
if (len != 0) {
len = lps[len - 1];
// Also, note that we do not increment
// i here
}
else // if (len == 0)
{
lps[i] = 0;
i++;
}
}
}
}
// Driver program to test above function
int main()
{
char txt[] = "ABABDABACDABABCABAB";
char pat[] = "ABABCABAB";
KMPSearch(pat, txt);
return 0;
}
I am really confused why that is the case.
For LPS computation, consider: aaaaacaaac
In this case, when we try to compute LPS for the first c, we would keep going back until we hit LPS[0], which is 0 and stop. So, essentially, we would travel back atleast the length of the pattern until that point. If this happens multiple times, how will time complexity be O(m)?
I have similar confusion on runtime of KMP to be O(n).
I have read other threads in stack overflow before posting, and also various other sites on the topic. I am still very confused. I would really appreciate if someone can help me understand the best and worse case scenarios for these algorithms and how their runtime is computed using some examples. Again, please don't suggest I google this, I have done it, spent a whole week trying to gain any insight, and failed.
One way to establish an upper bound on the runtime for construction of the LPS array is to consider a pathological case - how can we maximize the number of times we have to execute len = lps[len - 1]? Consider the following string, ignoring spaces: x1 x2 x1x3 x1x2x1x4 x1x2x1x3x1x2x1x5 ...
The second term needs to be compared to the first term as if it ended in 1 instead of 2, it would match the first term. Similarly the third term needs to be compared to the first two terms as if it ended in 1 or 2 instead of 3, it would match those partial terms. And so forth.
In the example string, it is clear that only every 1/2^n characters can match n times, so the total runtime will be m+m/2+m/4+..=2m=O(m), the length of the pattern string. I suspect it's impossible to construct a string with worse runtime than the example string and this can probably be formally proven.
So, I have a cycle that goes over an array and should reverse the sequence of consecutive positive numbers, but it seems to count excess negative number as a part of a sequence, thus changing its position. I can't figure the error myself, and will be happy to hear any tips!
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
int Arr[100];
int Arr2[100];
int main()
{
srand(time(NULL));
int n, x;
bool seq = false;
int ib = 0;
printf("Starting array\n");
for (n = 0; n < 100; Arr[n++] = (rand() % 101) - 50);
for (n = 0; n < 100; printf("%3d ", Arr[n++]));
putchar('\n');
for (n = 0; n < 100; n++) //sorting
{
if (Arr[n] > 0) //check if the number is positive
{
if (seq == false) //if it isn't the part of a sequence
{
seq = true; ib = n; //declare it now is, and remember index of sequence's beginning
}
else
seq = true; //do nothing if it isn't first
}
else //if the number is negative
{
if (seq==true) //if sequence isn't null
for (x = n; ib <= n; ib++, x--) //new variable so that n will stay unchanged,
number of iterations = length of sequence
{
Arr2[x] = Arr[ib]; //assigning array's value to a new one,
reversing it in the process
}
seq = false; //declaring sequence's end
Arr2[n + 1] = Arr[n + 1]; //assigning negative numbers at the same place of a new array
}
}
printf("Modified array\n");
for (n = 0; n < 100; printf("%3d ", Arr2[n++]));
putchar('\n');
system('pause');
return 0;
}
following what we discussed in comments, i listed couple of rules here to shape my answer around it.
Rules :
the sequence of elements can be varied. so if there are 5 positive numbers in a row within an array, we would be reversing the 5 elements. for example
array[5] = {1,2,3,4,5} would become array[5]{5,4,3,2,1}
if single positive number neighboured by negatives, no reverse can happen
array[4] = {-1,0,-2,1} would result the same array
no processing happens when a negative number is discovered.
based on these rules.
here is what I think going wrong in your code.
Problems :
1- consider thisarray = {1,2,-1}. notice that the last value is negative. because of this. the following code would run when the 3rd index of the array is processed;
` Arr2[n + 1] = Arr[n + 1]; //assigning negative numbers at the same place of a new array`
this is a no-no. since you are already at the end of the Arr2 n+1 would indicate that there is a 4th element in the array. (in your case 101h element of the array) this would cause an undefined behaviour.
2 - consider the same array mentioned above. when that array is looped, the outcome would be array = {-1,2,1} . the -1 and 1 are swapped instead of 1 and 2.
3 - you are assigning ib = n whenever a negative number is found. because whenever a negative value is hit, seq=false is forced. But the ib, never been put into use until a next negative number is found. here is an example;
array = {...2, 6}
in such scenario, 2 and 6 would never get reversed because there is no negative value is following this positive sequence.
4 - consider this scenario arr = {-10,-1,....} this would result in arr = {0,-1,....}. This happens because of the same code causing the undefined behaviour problem mentioned above.
`Arr2[n + 1] = Arr[n + 1];`
Suggestion
Most of the problems mentioned above is happening because you are trying to figure out the sequence of the positive numbers when a negative number is found.
else //if the number is negative
{
if (seq==true) //if sequence isn't null
for (x = n; ib <= n; ib++, x--) //new variable so that n will stay unchanged,
number of iterations = length of sequence
{
Arr2[x] = Arr[ib]; //assigning array's value to a new one,
reversing it in the process
}
you should completely get rid of that and completely ignore the negative numbers unless you forgot to mention in your question some key details. instead just focus on the positive numbers. I'm not going to send you the entire code but here is how I approached the problem. feel free to let me know if you need help and I would be more then happy to go through in detail.
start your for loop as usual.
for (n = 0; n < 100; n++) //sorting
{
don't try to do anything when an element in an array is a negative value.
if (Arr[n] > 0) //check if the number is positive
if the number is positive. create recording the sequence indices. for one, we know the sequence will start at n once the `if (Arr[n] > 0) true. so we can do something like this;
int sequenceStart = n;
we also need to know when the positive number sequence ends.
int sequenceEnd = sequenceStart;
the reason for int sequenceEnd = sequenceStart; is because we going to start using the same n value to start with. we can now loop through the array and increment the sequenceEnd until we reach to a negative number or to the end of the array.
while (currentElement > 0)
{
n++;//increment n
if(n < arraySiz) //make sure we still in the range
{
currentElement = Arr[n]; // get the new elemnet
if (currentElement > 0)
{
sequenceEnd++;
}
}
else
break; // we hit to a negative value so stop the while loop.
}
notice the n++;//increment n this would increment the n++ until we reach to the negative number. which is great because at the end of the sequence the for loop will continue from the updated n
after the while loop, you can create an array that has the same size as the number of sequences you iterated through. you can then store the elements from starting arr[sequenceStart] and arr[sequenceEnd] this will make the reversing the sequence in the array easier.
My Input is:
W[10] = {1, 3, 5, 7, 9, 12, 19, 22, 36, 63}
X[10] = {0};
M = 79;
I called the function by:
findSolution(0,0,177); <br>
Note: 177 is sum of all the elements inside W array.
void findSolution(int s, int k, int r) {
cout << "fn(" << s << " , " << k << ", " << r << " )" << endl;
X[k] = 1;
if (s + W[k] == M){
printArr(X);
}
else if (s + W[k] + W[k + 1] <= M) {
return findSolution(s + W[k], k + 1, r - W[k]);
}
if ((s + r - W[k] >= M) && (s + W[k + 1]) <= M){
X[k] = 0;
return findSolution(s, k + 1, r - W[k]);
}
}
Output:
fn(0 , 0, 177 )
fn(1 , 1, 176 )
fn(4 , 2, 173 )
fn(9 , 3, 168 )
fn(16 , 4, 161 )
fn(25 , 5, 152 )
fn(37 , 6, 140 )
fn(56 , 7, 121 )
The output given above is to track the function calls. The output ends here and doesn't go forward. What is wrong with my code. I am trying to print a subset which gives a desired sum = 79. The recursive call doesn't return back.
The problem with your solution is that it uses a greedy strategy (i.e. it does not "backtrack" after finding a suitable candidate).
Your algorithm checks for three conditions:
You found a solution,
A solution is possible if you add k-th element to the subset, or
A solution is possible if you replace k-1-st element with k-th.
This strategy does not exhaust all possibilities: for instance, it may not be possible to replace k-th element with k+1-st, but it may be possible to replace several elements ahead of k-th with k+1-st and obtain a solution. Your strategy is greedy, because when it discovers that an element could be added to a set (i.e. s + W[k] + W[k + 1] <= M) it takes that path, and never looks back (i.e. returns from that branch).
You can fix this by restructuring your code as follows:
Make your function return true when a solution is found, and false otherwise.
Keep your base case if (s + W[k] == M), and add a return true when a solution is found.
Check if it is possible to add k-th element to the set. If it is possible, add it, and try for the partial sum of s + W[k]
Check the return of the recursive invocation. If it is true, return true.
Otherwise, remove k-th element from the set, and make a second recursive invocation without the k-th element in the mix. Use the same partial sum of s.
Return the value of the last recursive invocation to the caller.
Now your algorithm is exhaustive, because for each element the algorithm tries to find a partial sum both when the element is part of the solution, and when the element is not part of the solution (i.e. O(2n) checks in all).
The recursive call is returning back; it is just doing so before you found a solution. This can happen if the last if is reached but fails. (Note that what looks like your base case, when you call printArr, does not necessarily stop the recursion.)
//code in c++ for return subset sum to k using recursion
int subsetSumToK(int input[], int n, int output[][50], int k) {
//as we are decreasing the value of k in int count1 recursive call, at a time value of k will be zero ,positive value and negative value also, so we will return only those subsets where the value of k is zero when the size of input array will become zero else we just return 0. In recursive calls we use two recursive calls, in first we are including the element, so as we including the element so now we have to find the value k - input[0](that included element) and store that element in o1 output array and in second recursive call as we are not including the element so just directily pass the call by input+1 and size-1 with o2 output array and the same value k.
if(n == 0){ //base case
if(k==0){
output[0][0] = 0;
return 1;
}else{
return 0;
}
}
int o1[1000][50]; //to store the output individually of two recusive calls
int o2[1000][50];
int count1 = subsetSumToK(input+1,n-1,o1,k-input[0]); //recursive calls
int count2 = subsetSumToK(input+1,n-1,o2,k);
for(int i=0;i<count1;i++){ //small calulations
for(int j=1;j<=o1[i][0];j++){
output[i][j+1] = o1[i][j];
}
output[i][0] = o1[i][0] +1;
output[i][1] = input[0];
}
for(int i=0 ; i<count2 ; i++){
for(int j=0 ; j<=o2[i][0] ; j++){
output[i + count1][j] = o2[i][j];
}
}
return count1 + count2;
}