How Does This String Permutation Works - algorithm

Need help understanding the correctness of the second swap call.
/* 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 i, int n)
{
int j;
if (i == n)
printf("%s\n", a);
else
{
for (j = i; j <= n; j++)
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j)); // how does this work here?
}
}
}
It seems like the second swap is to undo the first swap. But I don't see a proof why the in-between permute call would preserve that the original *(a+i) would remain at a+j.
Notes:
[1] Code was found at http://www.geeksforgeeks.org/write-a-c-program-to-print-all-permutations-of-a-given-string/

Proposition: For all a of length > n (so that n is a valid index) and 0 <= i <= n, when
permute(a, i, n)
returns, a is the same as when permute was called.
Proof: (Induction start) If i == n, then permute(a, n, n); only prints the string and doesn't change it, hence the proposition holds in that case.
(Induction hypothesis) Let 0 <= k < n, and the enoncé of the proposition hold for all k < i <= n.
Then in the loop
for (j = i; j <= n; j++)
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j)); // how does this work here?
}
for each j, the recursive call to permute doesn't change the contents [more precisely, it undoes all changes intermediately done] per the hypothesis. Therefore, before the second swap, the contents of a[i] and a[j] are exactly what they were after the first swap, hence at the end of the loop body, the contents of a are exactly what they were when the loop body was entered.

Related

Is this sorting right? Or is it missing anything

This algorithm seems to work after a few tries but I'm not sure if it's right. Can anyone help?
n is the size of the array
i goes from the first case to the case number (n-1)
j goes from i+1 to n
#include <stdio.h>
#include <stdlib.h>
void main() {
int t[50];
int i;
int j;
int n;
int aux;
scanf("%d", &n);
for (i = 1; i <= n; i++) {
scanf("%d", &t[i]);
}
for (i = 1; i <= n - 1; i++) {
for (j = i + 1; j <= n; j++) {
if (t[i] > t[j]) {
aux = t[i];
t[i] = t[j];
t[j] = aux;
}
}
}
for (i = 1; i <= n; i++) {
printf("|| %d", t[i]);
}
}
Looks like in pseudocode, your algorithm is the following:
Sort(A, N):
for (i = 1 to N-1):
for (j = i+1 to N):
if (A[i] > A[j]):
swap(A, i, j)
where A is the array of numbers and N is the array size.
It's been a while since I tried proving the correctness of anything, but it seems that if the outer loop can guarantee that at the end of each iteration, the smallest number will be at A[i], it will be correct. So the question is whether or not the inner loop puts the smallest element in A[i].
Since it swaps A[i] with A[j] every time A[i] is larger than A[j], we can guarantee that A[k-1] is always larger than A[i] at any k-th iteration of the inner loop, and therefore A[i] will be the smallest element for the subarray A[i:N] by the time the inner loop finishes executing (when k = N+1). Therefore, this algorithm is correct.
I am not too familiar with C programming so I can't tell you if your code exactly follows this, but if it does, then your code sample is also correct.

Find the Xor value between two integers who value is 2

Given an array consisting of N integers. Is it possible to find the number
of (a[i],a[j]) pairs such that 1 <= i < j< = N and the bitwise Xor value is exactly 2 with a time complexity less than O(n^2) or is there any mathematical formula to find the number of pairs like a[i] ^ a[j] == 2.
Constraints
1≤N≤10^5
1≤Ai≤10^6
An efficient solution of this problem can be of O(n) time complexity. The idea is based on the fact that arr[i] ^ arr[j] is equal to 2 if and only if arr[i] ^ 2 is equal to arr[j].
1) Initialize result as 0.
2) Create an empty hash set "s".
3) Do following for each element arr[i] in arr[]
(a) If 2 ^ arr[i] is in "s", then increment result by 1.
(b) Insert arr[i] into the hash set "s".
3) return result.
Here is C++ implementation:
int xorPairCount(vector<int>& arr) {
int n= (int)arr.size();
int result = 0;
unordered_set<int> s;
for (int i = 0; i < n ; i++) {
// If there exist an element in set s
// with XOR equals to 2^arr[i], that means
// there exist an element such that the
// XOR of element with arr[i] is equal to
// 2, then increment count.
if (s.find(2^arr[i]) != s.end())
result++;
// Make element visited
s.insert(arr[i]);
}
return result;
}
Note that, for this solution, I assumed there is no duplicate in the array. If duplicate allowed, then the solution will be a bit different. Let me know.
Update
If there are duplicates in the array, use an hashmap instead of hashset to count the frequency of each number, because for each occurrence, there will be one count. Here is the update of the above code:
int xorPairCount(vector<int>& arr) {
int n= (int)arr.size();
int result = 0;
unordered_map<int, int> m;
for (int i = 0; i < n ; i++) {
int curr_xor = 2^arr[i];
if (m.find(curr_xor) != m.end())
result += m[curr_xor];
m[arr[i]]++;
}
return result;
}

Run time Complexity

I believe that the following code is big theta of n^3, is this correct?
for (int i = 0; i < n; i ++)
{ // A is an array of integers
if (A[i] == 0) {
for (int j = 0; j <= i; j++) {
if (A[i] == 0) {
for (int k = 0; k <= j; k++) {
A[i] = 1;
}
}
}
}
}
And that the following is big theta of nlog(n)
for (int i = 1; i < n; i *= 2)
{
func(i);
}
void func(int x) {
if (x <= 1) return;
func(x-1);
}
because the for loop would run log(n) times, and func runs at most n recursive calls.
Thanks for the help!
Your intuition looks correct. Note that for the first bit if the input contains non-zero elements the time complexity drops down to big-theta(n). If you remove the checks it would definitely be big-theta(n^3).
You are correct about the second snippet, however the first is not Big-Theta(n^3). It is not even O(n^3)! The key observation is: for each i, the innermost loop will execute at most once.
Obviously, the worst-case is when the array contains only zeros. However, A[i] will be set to 1 in the first pass of the inner-most loop, and all subsequent checks of if (A[i] == 0) for the same i will be evaluated to false and the innermost loop will not be executed anymore until i increments. Therefore, there are total of 1 + 2 + 3 + .. + n = n * (n + 1) / 2 iterations, so the time complexity of the first snippet is O(n^2).
Hope this helps!

Sort a given array whose elements range from 1 to n , in which one element is missing and one is repeated

I have to sort this array in O(n) time and O(1) space.
I know how to sort an array in O(n) but that doesn't work with missing and repeated numbers. If I find the repeated and missing numbers first (It can be done in O(n)) and then sort , that seems costly.
static void sort(int[] arr)
{
for(int i=0;i<arr.length;i++)
{
if(i>=arr.length)
break;
if(arr[i]-1 == i)
continue;
else
{
while(arr[i]-1 != i)
{
int temp = arr[arr[i]-1];
arr[arr[i]-1] = arr[i];
arr[i] = temp;
}
}
}
}
First, you need to find missing and repeated numbers. You do this by solving following system of equations:
Left sums are computed simultaneously by making one pass over array. Right sums are even simpler -- you may use formulas for arithmetic progression to avoid looping. So, now you have system of two equations with two unknowns: missing number m and repeated number r. Solve it.
Next, you "sort" array by filling it with numbers 1 to n left to right, omitting m and duplicating r. Thus, overall algorithm requires only two passes over array.
void sort() {
for (int i = 1; i <= N; ++i) {
while (a[i] != a[a[i]]) {
std::swap(a[i], a[a[i]]);
}
}
for (int i = 1; i <= N; ++i) {
if (a[i] == i) continue;
for (int j = a[i] - 1; j >= i; --j) a[j] = j + 1;
for (int j = a[i] + 1; j <= i; ++j) a[j] = j - 1;
break;
}
}
Explanation:
Let's denote m the missing number and d the duplicated number
Please note in the while loop, the break condition is a[i] != a[a[i]] which covers both a[i] == i and a[i] is a duplicate.
After the first for, every non-duplicate number i is encountered 1-2 time and moved into the i-th position of the array at most 1 time.
The first-found number d is moved to d-th position, at most 1 time
The second d is moved around at most N-1 times and ends up in m-th position because every other i-th slot is occupied by number i
The second outer for locate the first i where a[i] != i. The only i satisfies that is i = m
The 2 inner fors handle 2 cases where m < d and m > d respectively
Full implementation at http://ideone.com/VDuLka
After
int temp = arr[arr[i]-1];
add a check for duplicate in the loop:
if((temp-1) == i){ // found duplicate
...
} else {
arr[arr[i]-1] = arr[i];
arr[i] = temp;
}
See if you can figure out the rest of the code.

Efficient Mergesort Confusion

I have been reading a mergesort example (the efficient one) since yesterday and I still can't understand how it works despite looking at the code:
private static void sort(int[] list) {
a = list;
int n = a.length;
// according to variant either/or:
b = new int[n];
b = new int[(n + 1) / 2];
mergesort(0, n - 1);
}
private static void mergesort(int first, int last) {
if (first < last) {
int mid = (first + last) / 2;
mergesort(first, mid);
mergesort(mid + 1, last);
merge(first, mid, last);
}
}
No problem understanding the algorithm up until this point but the confusion is in the following method:
private static void merge(int first, int mid, int last) {
int i, j, k;
i = 0;
j = first;
while (j <= mid)
b[i++] = a[j++]; // *j's value is now mid*
i = 0; // *i is reset to 0, nothing's been done to j*
k = first;
// *before entering the following while loop, j still carries mid's value*
while (k < j && j <= last)
if (b[i] <= a[j])
a[k++] = b[i++];
else
a[k++] = a[j++];
// copy back remaining elements of first half (if any)
while (k < j)
a[k++] = b[i++];
}
Entering the second while loop while (k < j && j <= last) is where I don't understand how this sorting works. From what I understood, the first half of the array a is already copied to the auxiliary array b, and now we want to arrange the entire array by comparing a[j++] (the second half) to the auxiliary array b[i++] so that we can get the smaller array element and place it in array a to sort the array in ascending order.
But why while (k < j && j <= last)? k < j sounds logical enough because we need to get all the values back from the auxiliary array but why j <= last? And why can't we just do while (k <= last) ?
And also, could somebody please affirm that my understanding of j's value in the above code is correct?
k < j denotes that auxillary array b still contains elements
j <= last denotes that the second part of a still contains elements
We cannot use k <= last here, because we may access array a indexes beyond the border, when j becomes last+1
Too long for comments, added here:
This variant is useful when available memory is limited (large dataset). It is mentioned in some tutorials (I've met it in J.Bucknall book about algorithms in Delphi). It is stable ( if (b[i] <= a[j]) holds stability. It is usually not faster, because it is better not to copy data at all , but, for example, 'trigger' source and destination array (pointers) at every stage

Resources