In the draft section 7.2.1.3 of The art of computer programming, generating all combinations, Knuth introduced Algorithm C for generating Chase's sequence.
He also mentioned a similar algorithm (based on the following equation) working with index-list without source code (exercise 45 of the draft).
I finally worked out a c++ version which I think is quite ugly. To generate all C_n^m combination, the memory complexity is about 3 (m+1) and the time complexity is bounded by O(m n^m)
class chase_generator_t{
public:
using size_type = ptrdiff_t;
enum class GET : char{ VALUE, INDEX };
chase_generator_t(size_type _n) : n(_n){}
void choose(size_type _m){
m = _m;
++_m;
index.resize(_m);
threshold.resize(_m + 1);
tag.resize(_m);
for (size_type i = 0, j = n - m; i != _m; ++i){
index[i] = j + i;
tag[i] = tag_t::DECREASE;
using std::max;
threshold[i] = max(i - 1, (index[i] - 3) | 1);
}
threshold[_m] = n;
}
bool get(size_type &x, size_type &y, GET const which){
if (which == GET::VALUE) return __get<false>(x, y);
return __get<true>(x, y);
}
size_type get_n() const{
return n;
}
size_type get_m() const{
return m;
}
size_type operator[](size_t const i) const{
return index[i];
}
private:
enum class tag_t : char{ DECREASE, INCREASE };
size_type n, m;
std::vector<size_type> index, threshold;
std::vector<tag_t> tag;
template<bool GetIndex>
bool __get(size_type &x, size_type &y){
using std::max;
size_type p = 0, i, q;
find:
q = p + 1;
if (index[p] == threshold[q]){
if (q >= m) return false;
p = q;
goto find;
}
x = GetIndex ? p : index[p];
if (tag[p] == tag_t::INCREASE){
using std::min;
increase:
index[p] = min(index[p] + 2, threshold[q]);
threshold[p] = index[p] - 1;
}
else if (index[p] && (i = (index[p] - 1) & ~1) >= p){
index[p] = i;
threshold[p] = max(p - 1, (index[p] - 3) | 1);
}
else{
tag[p] = tag_t::INCREASE;
i = p | 1;
if (index[p] == i) goto increase;
index[p] = i;
threshold[p] = index[p] - 1;
}
y = index[p];
for (q = 0; q != p; ++q){
tag[q] = tag_t::DECREASE;
threshold[q] = max(q - 1, (index[q] - 3) | 1);
}
return true;
}
};
Does any one has a better implementation, i.e. run faster with the same memory or use less memory with the same speed?
I think that the C code below is closer to what Knuth had in mind. Undoubtedly there are ways to make it more elegant (in particular, I'm leaving some scaffolding in case it helps with experimentation), though I'm skeptical that the array w can be disposed of. If storage is really important for some reason, then steal the sign bit from the a array.
#include <stdbool.h>
#include <stdio.h>
enum {
N = 10,
T = 5
};
static void next(int a[], bool w[], int *r) {
bool found_r = false;
int j;
for (j = *r; !w[j]; j++) {
int b = a[j] + 1;
int n = a[j + 1];
if (b < (w[j + 1] ? n - (2 - (n & 1)) : n)) {
if ((b & 1) == 0 && b + 1 < n) b++;
a[j] = b;
if (!found_r) *r = j > 1 ? j - 1 : 0;
return;
}
w[j] = a[j] - 1 >= j;
if (w[j] && !found_r) {
*r = j;
found_r = true;
}
}
int b = a[j] - 1;
if ((b & 1) != 0 && b - 1 >= j) b--;
a[j] = b;
w[j] = b - 1 >= j;
if (!found_r) *r = j;
}
int main(void) {
typedef char t_less_than_n[T < N ? 1 : -1];
int a[T + 1];
bool w[T + 1];
for (int j = 0; j < T + 1; j++) {
a[j] = N - (T - j);
w[j] = true;
}
int r = 0;
do {
for (int j = T - 1; j > -1; j--) printf("%x", a[j]);
putchar('\n');
if (false) {
for (int j = T - 1; j > -1; j--) printf("%d", w[j]);
putchar('\n');
}
next(a, w, &r);
} while (a[T] == N);
}
Related
Given an array and some value X, find the number of pairs such that i < j , a[i] = a[j] and (i * j) % X == 0
Array size <= 10^5
I am thinking of this problem for a while but only could come up with the brute force solution(by checking all pairs) which will obviously time-out [O(N^2) time complexity]
Any better approach?
First of all, store separate search structures for each distinct A[i] as we iterate.
i * j = k * X
i = k * X / j
Let X / j be some fraction. Since i is an integer, k would be of the form m * least_common_multiple(X, j) / X, where m is natural.
Example 1: j = 20, X = 60:
lcm(60, 20) = 60
matching `i`s would be of the form:
(m * 60 / 60) * 60 / 20
=> m * q, where q = 3
Example 2: j = 6, X = 2:
lcm(2, 6) = 6
matching `i`s would be of the form:
(m * 6 / 2) * 2 / 6
=> m * q, where q = 1
Next, I would consider how to efficiently query the number of multiples of a number in a sorted list of arbitrary naturals. One way is to hash the frequency of divisors of each i we add to the search structure of A[i]. But first consider i as j and add to the result the count of divisors q that already exist in the hash map.
JavaScript code with brute force testing at the end:
function gcd(a, b){
return b ? gcd(b, a % b) : a;
}
function getQ(X, j){
return X / gcd(X, j);
}
function addDivisors(n, map){
let m = 1;
while (m*m <= n){
if (n % m == 0){
map[m] = -~map[m];
const l = n / m;
if (l != m)
map[l] = -~map[l];
}
m += 1;
}
}
function f(A, X){
const Ais = {};
let result = 0;
for (let j=1; j<A.length; j++){
if (A[j] == A[0])
result += 1;
// Search
if (Ais.hasOwnProperty(A[j])){
const q = getQ(X, j);
result += Ais[A[j]][q] || 0;
// Initialise this value's
// search structure
} else {
Ais[A[j]] = {};
}
// Add divisors for j
addDivisors(j, Ais[A[j]]);
}
return result;
}
function bruteForce(A, X){
let result = 0;
for (let j=1; j<A.length; j++){
for (let i=0; i<j; i++){
if (A[i] == A[j] && (i*j % X) == 0)
result += 1;
}
}
return result;
}
var numTests = 1000;
var n = 100;
var m = 50;
var x = 100;
for (let i=0; i<numTests; i++){
const A = [];
for (let j=0; j<n; j++)
A.push(Math.ceil(Math.random() * m));
const X = Math.ceil(Math.random() * x);
const _brute = bruteForce(A, X);
const _f = f(A, X);
if (_brute != _f){
console.log("Mismatch!");
console.log(X, JSON.stringify(A));
console.log(_brute, _f);
break;
}
}
console.log("Done testing.")
Just in case If someone needed the java version of this answer - https://stackoverflow.com/a/69690416/19325755 explanation has been provided in that answer.
I spent lot of time in understanding the javascript code so I thought the people who are comfortable with java can refer this for better understanding.
import java.util.HashMap;
public class ThisProblem {
public static void main(String[] args) {
int t = 1000;
int n = 100;
int m = 50;
int x = 100;
for(int i = 0; i<t; i++) {
int[] A = new int[n];
for(int j = 0; j<n; j++) {
A[j] = ((int)Math.random()*m)+1;
}
int X = ((int)Math.random()*x)+1;
int optR = createMaps(A, X);
int brute = bruteForce(A, X);
if(optR != brute) {
System.out.println("Wrong Answer");
break;
}
}
System.out.println("Test Completed");
}
public static int bruteForce(int[] A, int X) {
int result = 0;
int n = A.length;
for(int i = 1; i<n; i++) {
for(int j = 0; j<i; j++) {
if(A[i] == A[j] && (i*j)%X == 0)
result++;
}
}
return result;
}
public static int gcd(int a, int b) {
return b==0 ? a : gcd(b, a%b);
}
public static int getQ(int X, int j) {
return X/gcd(X, j);
}
public static void addDivisors(int n, HashMap<Integer, Integer> map) {
int m = 1;
while(m*m <= n) {
if(n%m == 0) {
map.put(m, map.getOrDefault(m, 0)+1);
int l = n/m;
if(l != m) {
map.put(l, map.getOrDefault(l, 0)+1);
}
}
m++;
}
}
public static int createMaps(int[] A, int X) {
int result = 0;
HashMap<Integer, HashMap<Integer, Integer>> contentsOfA = new HashMap<>();
int n = A.length;
for(int i = 1; i<n; i++) {
if(A[i] == A[0])
result++;
if(contentsOfA.containsKey(A[i])) {
int q = getQ(X, i);
result += contentsOfA.get(A[i]).getOrDefault(q, 0);
} else {
contentsOfA.put(A[i], new HashMap<>());
}
addDivisors(i, contentsOfA.get(A[i]));
}
return result;
}
}
This is a very simple program where the user inputs (x,y) coordinates and distance 'd' and the program has to find out the number of unrepeated coordinates from (x,y) to (x+d,y).
For eg: if input for one test case is: 4,9,2 then the unrepeated coordinates are (4,9),(5,9) and (6,9)(x=4,y=9,d=2). I have used a sorting algorithm as mentioned in the question (to keep track of multiple occurrences) however the program shows runtime error for test cases beyond 30. Is there any mistake in the code or is it an issue with my compiler?
For a detailed explanation of question: https://www.hackerearth.com/practice/algorithms/sorting/merge-sort/practice-problems/algorithm/missing-soldiers-december-easy-easy/
#include <stdio.h>
#include <stdlib.h>
int partition(int *arr, int p, int r) {
int x;
x = arr[r];
int tmp;
int i = p - 1;
for (int j = p; j <= r - 1; ++j) {
if (arr[j] <= x) {
i = i + 1;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
tmp = arr[i + 1];
arr[i + 1] = arr[r];
arr[r] = tmp;
return (i + 1);
}
void quicksort(int *arr, int p, int r) {
int q;
if (p < r) {
q = partition(arr, p, r);
quicksort(arr, p, q - 1);
quicksort(arr, q + 1, r);
}
}
int count(int A[],int ct) {
int cnt = 0;
for (int i = 0; i < ct; ++i) {
if (A[i] != A[i + 1]) {
cnt++;
}
}
return cnt;
}
int main() {
int t;
scanf("%d", &t);
long int tmp, y, d;
int ct = 0;
int i = 0;
int x[1000];
int j = 0;
for (int l = 0; l < t; ++l) {
scanf("%d%d%d", &tmp, &y, &d);
ct = ct + d + 1; //this counts the total no of coordinates for each (x,y,d)
for (int i = 0; i <= d; ++i) {
x[j] = tmp + i; //storing all possible the x and x+d coordinates
j++;
}
}
int cnt;
int p = ct - 1;
quicksort(x, 0, p); //quicksort sorting
for (int l = 0; l < ct; ++l) {
printf("%d ", x[l]); //prints sorted array not necessary to question
}
cnt = count(x, ct); //counts the number of non-repeated vertices
printf("%d\n", cnt);
}
The problem was the bounds of the array int x[1000] is not enough for the data given below.
what is the time complexity of below-written code-
i think the complexity should be O(rcn)
where n= maximum size island
but on gfg they had written the complexity is O(V+E)
void bfs(int r, int c, vector < vector < char >> & grid) {
queue < pair < int, int >> q;
int row[4] = {-1,0,1,0};
int col[4] = {0,1,0,-1};
q.push(make_pair(r, c));
while (!q.empty()) {
pair < int, int > p = q.front();
int x = p.first;
int y = p.second;
q.pop();
for (int i = 0; i < 4; i++) {
if (x + row[i] < grid.size() && y + col[i] < grid[0].size() && x + row[i] >= 0 && y + col[i] >= 0 && grid[x + row[i]][y + col[i]] == '1') {
q.push(make_pair(x + row[i], y + col[i]));
grid[x + row[i]][y + col[i]] = '0';
}
}
}
}
int numIslands(vector < vector < char >> & grid) {
int count = 0;
int r = grid.size();
if (r == 0)
return count;
int c = grid[0].size();
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (grid[i][j] == '1') {
bfs(i, j, grid);
count++;
}
}
}
return count;
}
I found a very interesting paper about bit-reversal algorithm suitable for in-place FFT: "A simple algorithm for the bit-reversal permutation" by
Urszula Rutkowska from 1990 (doi.org/10.1016/0165-1684(91)90008-7).
However, her algorithm G1 does not appear to work as the very first iteration results in out-of-bounds error for that N1 = L << 1 and swap(a + 1, a + N1);. I assume L means the length of input vector.
Please, does anyone know if there was any errata for the paper or how to fix the algorithm?
The paper's pseudocode:
G1(L)
{int i,j,L1
N1,N2,a,b;
unsigned k;
j=0; L1=L-1;
N1=L<<1;N2=N1+1;
for(i=0;i<L1;i++)
{if(i<j)
{ a=i<<1;
b=j<<1;
swap(a,b);
swap(a+N2,b+N2);
swap(a+1,b+N1);
swap(b+1,a+N1);
}
else
if(i==j)
{ a=i<<1;
swap(a+1,a+N1);
}
k=L>>1;
while(k<=j){ j=j-k;
k=k>>1;
}
j+=k;
}
i<<=1;
swap(i+1,i+N1);
}
Screenshot of the paper:
It was pretty garbled, frankly. I had to read the paper for the idea (run Gold's algorithm (G) for L/4 and then derive the swaps for L) and then sort of massage the code into the right form. Here's my final result.
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
static bool is_power_of_two(int L) { return L > 0 && (L & (L - 1)) == 0; }
static void swap(int i, int j) { printf("swap %d,%d\n", i, j); }
static void G(int L) {
assert(is_power_of_two(L));
int j = 0;
for (int i = 0; i < L - 1; i++) {
if (i < j) {
swap(i, j);
}
int k = L >> 1;
while (j >= k) {
j -= k;
k >>= 1;
}
j += k;
}
}
static void G1(int L) {
assert(is_power_of_two(L));
if (L < 4) {
return;
}
int j = 0;
int N1 = L >> 1;
int N2 = N1 + 1;
int L2 = L >> 2;
for (int i = 0; i < L2 - 1; i++) {
if (i < j) {
int a = i << 1;
int b = j << 1;
swap(a, b);
swap(a + N2, b + N2);
swap(a + 1, b + N1);
swap(b + 1, a + N1);
} else if (i == j) {
int a = i << 1;
swap(a + 1, a + N1);
}
int k = L2 >> 1;
while (j >= k) {
j -= k;
k >>= 1;
}
j += k;
}
int a = (L2 - 1) << 1;
swap(a + 1, a + N1);
}
int main(int argc, char *argv[]) {
assert(1 < argc);
int L = atoi(argv[1]);
G(L);
putchar('\n');
G1(L);
}
Given`en an array of integers. We have to find the length of the longest subsequence of integers such that gcd of any two consecutive elements in the sequence is greater than 1.
for ex: if array = [12, 8, 2, 3, 6, 9]
then one such subsequence can be = {12, 8, 2, 6, 9}
other one can be= {12, 3, 6, 9}
I tried to solve this problem by dynamic programming. Assume that maxCount is the array such that maxCount[i] will have the length of such longest subsequence
ending at index i.
`maxCount[0]=1 ;
for(i=1; i<N; i++)
{
max = 1 ;
for(j=i-1; j>=0; j--)
{
if(gcd(arr[i], arr[j]) > 1)
{
temp = maxCount[j] + 1 ;
if(temp > max)
max = temp ;
}
}
maxCount[i]=max;
}``
max = 0;
for(i=0; i<N; i++)
{
if(maxCount[i] > max)
max = maxCount[i] ;
}
cout<<max<<endl ;
`
But, this approach is getting timeout. As its time complexity is O(N^2). Can we improve the time complexity?
The condition "gcd is greater than 1" means that numbers have at least one common divisor. So, let dp[i] equals to the length of longest sequence finishing on a number divisible by i.
int n;
cin >> n;
const int MAX_NUM = 100 * 1000;
static int dp[MAX_NUM];
for(int i = 0; i < n; ++i)
{
int x;
cin >> x;
int cur = 1;
vector<int> d;
for(int i = 2; i * i <= x; ++i)
{
if(x % i == 0)
{
cur = max(cur, dp[i] + 1);
cur = max(cur, dp[x / i] + 1);
d.push_back(i);
d.push_back(x / i);
}
}
if(x > 1)
{
cur = max(cur, dp[x] + 1);
d.push_back(x);
}
for(int j : d)
{
dp[j] = cur;
}
}
cout << *max_element(dp, dp + MAX_NUM) << endl;
This solution has O(N * sqrt(MAX_NUM)) complexity. Actually you can calculate dp values only for prime numbers. To implement this you should be able to get prime factorization in less than O(N^0.5) time (this method, for example). That optimization should cast complexity to O(N * factorization + Nlog(N)). As memory optimization, you can replace dp array with map or unordered_map.
GCD takes log m time, where m is the maximum number in the array. Therefore, using a Segment Tree and binary search, one can reduce the time complexity to O(n log (m² * n)) (with O(n log m) preprocessing). This list details other data structures that can be used for RMQ-type queries and to reduce the complexity further.
Here is one possible implementation of this:
#include <bits/stdc++.h>
using namespace std;
struct SegTree {
using ftype = function<int(int, int)>;
vector<int> vec;
int l, og, dummy;
ftype f;
template<typename T> SegTree(const vector<T> &v, const T &x, const ftype &func) : og(v.size()), f(func), l(1), dummy(x) {
assert(og >= 1);
while (l < og) l *= 2;
vec = vector<int>(l*2);
for (int i = l; i < l+og; i++) vec[i] = v[i-l];
for (int i = l+og; i < 2*l; i++) vec[i] = dummy;
for (int i = l-1; i >= 1; i--) {
if (vec[2*i] == dummy && vec[2*i+1] == dummy) vec[i] = dummy;
else if (vec[2*i] == dummy) vec[i] = vec[2*i+1];
else if (vec[2*i+1] == dummy) vec[i] = vec[2*i];
else vec[i] = f(vec[2*i], vec[2*i+1]);
}
}
SegTree() {}
void valid(int x) {assert(x >= 0 && x < og);}
int get(int a, int b) {
valid(a); valid(b); assert(b >= a);
a += l; b += l;
int s = vec[a];
a++;
while (a <= b) {
if (a % 2 == 1) {
if (vec[a] != dummy) s = f(s, vec[a]);
a++;
}
if (b % 2 == 0) {
if (vec[b] != dummy) s = f(s, vec[b]);
b--;
}
a /= 2; b /= 2;
}
return s;
}
void add(int x, int c) {
valid(x);
x += l;
vec[x] += c;
for (x /= 2; x >= 1; x /= 2) {
if (vec[2*x] == dummy && vec[2*x+1] == dummy) vec[x] = dummy;
else if (vec[2*x] == dummy) vec[x] = vec[2*x+1];
else if (vec[2*x+1] == dummy) vec[x] = vec[2*x];
else vec[x] = f(vec[2*x], vec[2*x+1]);
}
}
void update(int x, int c) {add(x, c-vec[x+l]);}
};
// Constructor (where val is something that an element in the array is
// guaranteed to never reach):
// SegTree st(vec, val, func);
// finds longest subsequence where GCD is greater than 1
int longest(const vector<int> &vec) {
int l = vec.size();
SegTree st(vec, -1, [](int a, int b){return __gcd(a, b);});
// checks if a certain length is valid in O(n log (m² * n)) time
auto valid = [&](int n) -> bool {
for (int i = 0; i <= l-n; i++) {
if (st.get(i, i+n-1) != 1) {
return true;
}
}
return false;
};
int length = 0;
// do a "binary search" on the best possible length
for (int i = l; i >= 1; i /= 2) {
while (length+i <= l && valid(length+i)) {
length += i;
}
}
return length;
}