I am trying to implement radix sort for integers, including negative integers. For non-negative ints, I was planning to create a queue of 10 queues correspondingly for the digits 0-9 and implement the LSD algorithm. But I was kind of confused with negative integers. What I am thinking now, is to go ahead and create another queue of 10 queues for them and separately sort them and then at the end, I will gave 2 lists, one containing negative ints sorted and the other containing non-negative ints. And finally I would merge them.
What do you think about this? Is there more efficient way to handle with negative integers?
You can treat the sign as a special kind of digit. You sort the pile on the units, then the tens, etc. and finally on the sign. This does produce a reversed order for the negatives, you then simply reverse the contents of that bucket. It's how old mechanical card sorters worked.
One more solution is to separate negative integers from the array, make them positive, sort as positive values using radix, then reverse it and append with sorted non-negative array.
Note that the sign bit is the uppermost bit in a signed integer, but all numbers are treated by radix sort as unsigned integers by default. So you need to tell the algorithm that negative numbers are smaller than positive ones. In case of 32-bit signed integers, you can sort three lower bytes first, then sort the fourth (upper) byte with the sign bit inverted so that 0 will be used for negative numbers instead of 1, and consequently they will go first.
I strongly advise to sort numbers byte-by-byte rather than by decimal digits, because it's far easier for the machine to pick up bytes than extract digits.
The accepted answer requires one more pass than necessary.
Just flip the sign bit.
This assumes you are working with a two's-complement representation, which is true for 99% of us.
The following table demonstrates that simply flipping the sign bit will cause two's-complement integers to sort correctly when sorted lexicographically.
The first column gives a 4-bit binary value, the second column gives the interpretation of those bits as signed integers, and the third column gives the interpretation of those bits with the high bit flipped.
Binary | 2s-comp | Flip sign
----------+----------+----------
0000 | 00 | -8
0001 | +1 | -7
0010 | +2 | -6
0011 | +3 | -5
0100 | +4 | -4
0101 | +5 | -3
0110 | +6 | -2
0111 | +7 | -1
1000 | -8 | 00
1001 | -7 | +1
1010 | -6 | +2
1011 | -5 | +3
1100 | -4 | +4
1101 | -3 | +5
1110 | -2 | +6
1111 | -1 | +7
The answer given by punpcklbw recommends only flipping the bit when you are looking at the highest byte, but it would be faster to simply flip the sign bit every time. That's because a single xor to flip the bit will be faster than the branch to decide if you should flip or not.
[An important detail to mention, which some textbooks fail to address properly, is that a real implementation should use radix of 256 instead of radix 10. That allows you to read bytes instead of decimal digits.]
Your radix sort wont be faster than the famous comparison sorts if you dont use "bitshift" and "bitwise AND" for radix calculation.
Computers use 2's complement to represent signed numbers, here the sign-bit lies at the leftmost end of a binary digit, in memory representation
eg
436163157 (as 32 bit number) = 00011001 11111111 01010010 01010101 -436163157 (as 32 bit number) = 11100110 00000000 10101101 10101011
1 (as 32 bit number) = 00000000 00000000 00000000 00000001
-1 (as 32 bit number) = 11111111 1111111 1111111 11111111
0 is represented as = 00000000 00000000 00000000 00000000
Highest negative value as = 10000000 00000000 00000000 00000000
So you see, the more negative a number becomes, it looses that many 1's, a small negative number has many 1's, if you set only the sign-bit to 0, it becomes a very large positive number. Vice versa a small positive number becomes a large negative number.
In radix sort the key to sorting negative numbers is how you handle the last 8 bits, for negative numbers at least the last bit has to be 1, in 32-bit scheme it has to be from 10000000 00000000 00000000 00000000 which is the most negative value farthest from zero to 11111111 11111111 11111111 11111111 which is -1. If you look at the leftmost 8 bits, the magnitude ranges from 10000000 to 11111111, i.e. from 128 to 255.
These values can be obtained by this code piece
V = ( A[i] >> 24 ) & 255
For negative numbers V will always lie from 128 upto 255. For positive numbers it will be from 0 to 127. As said earlier, the value of M will be 255 for -1 and 128 for highest negative number in 32-bit scheme. Build up your histogram as usual. Then from index 128 to 255 do the cumulative sum, then add frequency of 255 to 0, and proceed the cumulative sum from 0 till index 127. Perform the Sort as usual. This technique is both optimal, fast, elegant and neat both in theory and in practice. No need of any kind of separate lists nor order reversal after sorting nor converting all inputs to positive which make the sort slow and messy.
For the code see Radix Sort Optimization A 64-bit version can be built using same concepts
Further read:
http://codercorner.com/RadixSortRevisited.htm
http://stereopsis.com/radix.html
Absolutely! Of course you do have to take care of splitting up the negatives from the positives but luckily this is easy. At the beginning of your sorting algorithm all you have to do is partition your array around the value 0. After that, radix sort below and above the partition.
Here is the algorithm in practice. I derived this from Kevin Wayne and Bob Sedgewick's MSD radix sort: http://algs4.cs.princeton.edu/51radix/MSD.java.html
private static final int CUTOFF = 15;
private static final int BITS_PER_INT = 32;
private static final int BITS_PER_BYTE = 8;
private static final int R = 256;
public void sort(int[] a){
int firstPositiveIndex = partition(0, a, 0, a.length-1);
int[] aux =new int[a.length];
if(firstPositiveIndex>0){
recSort(a, firstPositiveIndex, a.length-1, 0,aux);
recSort(a, 0, firstPositiveIndex-1, 0,aux);
}else{//all positive
recSort(a, 0, a.length-1, 0, aux);
}
}
private void recSort(int[] a, int lo, int hi, int d, int[] aux){
if(d>4)return;
if(hi-lo<CUTOFF){
insertionSort(a,lo, hi);
return;
}
int[] count = new int[R+1];
//compute counts
int bitsToShift = BITS_PER_INT-BITS_PER_BYTE*d-BITS_PER_BYTE;
int mask = 0b1111_1111;
for(int i = lo; i<=hi; i++){
int c = (a[i]>>bitsToShift) & mask;
count[c+1]++;
}
//compute indices
for(int i = 0; i<R; i++){
count[i+1]=count[i]+count[i+1];
}
//distribute
for(int i = lo; i<=hi; i++){
int c = (a[i]>>bitsToShift) & mask;
aux[count[c]+lo] = a[i];
count[c]++;
}
//copy back
for(int i = lo; i<=hi; i++){
a[i]=aux[i];
}
if(count[0]>0)
recSort(a, lo, lo+count[0]-1, d+1, aux);
for(int i = 1; i<R; i++){
if(count[i]>0)
recSort(a, lo+count[i-1], lo+count[i]-1, d+1, aux);
}
}
// insertion sort a[lo..hi], starting at dth character
private void insertionSort(int[] a, int lo, int hi) {
for (int i = lo; i <= hi; i++)
for (int j = i; j > lo && a[j] < a[j-1]; j--)
swap(a, j, j-1);
}
//returns the index of the partition or to the right of where it should be if the pivot is not in the array
public int partition(int pivot, int[] a, int lo, int hi){
int curLo = lo;
int curHi = hi;
while(curLo<curHi){
while(a[curLo]<pivot){
if((curLo+1)>hi)return hi+1;
curLo++;
}
while(a[curHi]>pivot){
if((curHi-1)<lo)return lo-1;
curHi--;
}
if(curLo<curHi){
swap(a, curLo, curHi);
if(a[curLo]!=pivot)curLo++;
if(a[curHi]!=pivot)curHi--;
}
}
return curLo;
}
private void swap(int[] a, int i1, int i2){
int t = a[i1];
a[i1]=a[i2];
a[i2]=t;
}
Probably the easiest way to handle signed values is to offset the starting position for the accumulation (i.e., generation of positional offsets) when operating on the most significant digit. Transforming the input so all digits may be treated as unsigned is also an option, but requires applying an operation over the value array at least twice (once to prepare input and again to restore output).
This uses the first technique as well as byte-sized digits (byte access is generally more efficient):
void lsdradixsort(int* a, size_t n)
{
// isolate integer byte by index.
auto bmask = [](int x, size_t i)
{
return (static_cast<unsigned int>(x) >> i*8) & 0xFF;
};
// allocate temporary buffer.
auto m = std::make_unique<int[]>(n);
int* b = m.get();
// for each byte in integer (assuming 4-byte int).
for ( size_t i, j = 0; j < 4; j++ ) {
// initialize counter to zero;
size_t h[256] = {}, start;
// histogram.
// count each occurrence of indexed-byte value.
for ( i = 0; i < n; i++ )
h[bmask(a[i], j)]++;
// accumulate.
// generate positional offsets. adjust starting point
// if most significant digit.
start = (j != 3) ? 0 : 128;
for ( i = 1+start; i < 256+start; i++ )
h[i % 256] += h[(i-1) % 256];
// distribute.
// stable reordering of elements. backward to avoid shifting
// the counter array.
for ( i = n; i > 0; i-- )
b[--h[bmask(a[i-1], j)]] = a[i-1];
std::swap(a, b);
}
}
This can be done without requiring partitioning or having to practically invert the MSB. Here's a working solution in Java:
public class RadixSortsInterviewQuestions {
private static final int MSB = 64;
static Map.Entry<Integer, Integer> twoSum(long[] a, long sum) {
int n = a.length - 1;
sort(a, MSB, 0, n);
for (int i = 0, j = n; i < j; ) {
long t = a[i] + a[j];
if (t == sum) {
return new SimpleImmutableEntry<>(i, j);
} else if (t < sum) {
i++;
} else {
j--;
}
}
return null;
}
// Binary MSD radix sort: https://en.wikipedia.org/wiki/Radix_sort#In-place_MSD_radix_sort_implementations
private static void sort(long[] a, int d, int lo, int hi) {
if (hi < lo || d < 1) return;
int left = lo - 1;
int right = hi + 1;
for (int i = left + 1; i < right; ) {
if (isBitSet(a[i], d)) {
swap(a, i, --right);
} else {
left++;
i++;
}
}
sort(a, d - 1, lo, left);
sort(a, d - 1, right, hi);
}
private static boolean isBitSet(long x, int k) {
boolean set = (x & 1L << (k - 1)) != 0;
// invert signed bit so that all positive integers come after negative ones
return (k == MSB) != set;
}
private static void swap(long[] a, int i, int j) {
long tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
All proposed solutions here imply performance penalty:
flip highest bit via (a[i] XOR 0x8000000000000000) on grouping stage;
treat sign bit as radix and use extra pass, sorting by it;
separate negative numbers from array;
use special bitmasks, etc.
You don't need them all. Use regular radix sort. On the last iteration you'll have array items splitted into 0..255 groups. Example items:
1 50 200 -500 -300 -2 -1
The only thing to tweak is how we copy those groups back into original array. We should start copy signed 128..255 groups (-128..-1 actually) and then 0..127.
Result:
-500 -300 -2 -1 1 50 200
Tested in PHP 7.4. Regular radix sort implementation is 2-2.5x faster, than QuickSort.
Adding extra xor operation slows down the result to 1.7-1.8x. Using the above mention approach has no performance penalty at all.
The code:
function sortRadix (array &$arr) {
static $groups;
isset($groups) or $groups = [];
$numRadix = 8;
$arrSize = count($arr);
$shift = 0;
for ($i = 0; $i < $numRadix; $i++) {
// Cleaning groups
for ($j = 0; $j < 256; $j++) {
$groups[$j] = [];
}
// Splitting items into radix groups
for ($j = 0; $j < $arrSize; $j++) {
$currItem = $arr[$j];
$groups[(($currItem >> $shift) & 0xFF)][] = $currItem;
}
// Copying sorted by radix items back into original array
$arrPos = 0;
// Treat the last radix with sign bit specially
// Output signed groups (128..256 = -128..-1) first
// Other groups afterwards. No performance penalty, as compared to flipping sign bit
// via (($currItem ^ 0x8000000000000000) >> $shift) & 0xFF)
if ($i === 7) {
for ($j = 128; $j < 256; $j++) {
foreach ($groups[$j] as $item) {
$arr[$arrPos++] = $item;
}
}
for ($j = 0; $j < 128; $j++) {
foreach ($groups[$j] as $item) {
$arr[$arrPos++] = $item;
}
}
} else {
foreach ($groups as $group) {
foreach ($group as $item) {
$arr[$arrPos++] = $item;
}
}
}
// Change shift value for next iterations
$shift += 8;
} // .for
} // .function sortRadix
You can also interpret the histogram (count[]) differently for the most significant byte (which contains the signed bit). Here is a solution in C:
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
static void sortbno(const int32_t* tab, // table of entries
int tabsz, // #entries in tab
int bno, // byte number in T
int* inidx, // current sorted index before this byte
int* outidx) // indices after sorting this byte
{
int count[256];
memset(count, 0, sizeof(count));
// count occurrences of each byte value
for (int i = 0; i < tabsz; i++) {
int32_t x = tab[i];
int v = (x >> (8 * bno)) & 0xff;
count[v]++;
}
// change count[i] so it now reflects the actual
// position of this byte value in outidx
if (bno == sizeof(tab[0]) - 1) {
/* account for signed bit for most-significant-byte */
for (int i = 129; i < 256; i++) {
count[i] += count[i - 1];
}
count[0] += count[255];
for (int i = 1; i < 128; i++) {
count[i] += count[i - 1];
}
} else {
for (int i = 1; i < 256; i++) {
count[i] += count[i - 1];
}
}
// fill outidx[]
for (int i = tabsz - 1; i >= 0; i--) {
int in = inidx[i];
int32_t x = tab[in];
int v = (x >> (8 * bno)) & 0xff;
outidx[--count[v]] = in;
}
}
/**
* Sort tab[].
* Return the indices into tab[] in ascending order.
*/
int* rsort(const int32_t* tab, int tabsz)
{
int* r[2];
r[0] = malloc(tabsz * sizeof(*r[0]));
r[1] = malloc(tabsz * sizeof(*r[1]));
if (! (r[0] && r[1]))
goto bail;
// Artificially assign indices to items
for (int i = 0; i < tabsz; i++) {
r[0][i] = i;
}
// Sort byte by byte. byte #0 is x & 0xff.
int bin = 0;
for (int i = 0; i < (int)sizeof(tab[0]); i++) {
sortbno(tab, tabsz, i, r[bin], r[1-bin]);
bin = !bin;
}
free(r[1-bin]);
return r[bin];
bail:
if (r[0]) free(r[0]);
if (r[1]) free(r[1]);
return 0;
}
You can see below Radix sort implementation for both positive and negative integers in JS.
const getDigit = (num, place) => {
return Math.floor(Math.abs(num) / Math.pow(10, place)) % 10;
}
const maxDigitNumber = arr => {
const digitCount = (num) => {
return Math.abs(num).toString().length;
}
let maxDigit = digitCount(arr[0]);
for(let num of arr) {
const digits = digitCount(num);
if(maxDigit < digits) maxDigit = digits;
}
return maxDigit;
}
const radixSort = arr => {
const maxDigit = maxDigitNumber(arr);
digitIteration:
for(let d = 0; d < maxDigit; d++) {
const bucket = {};
arrIteration:
for(let i = 0; i < arr.length; i++) {
const number = arr[i];
const digitValue = getDigit(number, d);
if(!bucket[digitValue]) bucket[digitValue] = [];
if(number > 0) bucket[digitValue].push(number);
else bucket[digitValue].unshift(number);
};
const newArr = [];
for(let obj in bucket) {
bucket[obj].map(el => {
if(el < 0) newArr.unshift(el);
else newArr.push(el);
});
}
arr = newArr;
}
return arr;
}
Related
This question already has answers here:
Finding an element in an array that isn't repeated a multiple of three times?
(4 answers)
Closed 7 years ago.
I have been asked this question in an interview.
Given that, there are 3n+1 numbers. n of those numbers occur in triplets, only 1 occurs single time. How do we find the unique number in linear time i.e., O(n) ? The numbers are not sorted.
Note that, if there were 2n+1 numbers, n of which occur in pairs, we could just XOR all the numbers to find the unique one. The interviewer told me that it can be done by bit manipulation.
Count the number of times that each bit occurs in the set of 3n+1 numbers.
Reduce each bit count modulo 3.
What is left is the bit pattern of the single number.
Oh, dreamzor (above) has beaten me to it.
You can invent a 3nary XOR (call it XOR3) operation which operates in base 3 instead of base 2 and simply takes each 3nary digit modulo 3 (when usual XOR takes 2nary digit modulo 2).
Then, if you XOR3 all the numbers (converting them to 3nary first) this way, you will be left with the unique number (in base 3 so you will need to convert it back).
The complexity is not exactly linear, though, because the conversions from/to base 3 require additional logarithmic time. However, if the range of numbers is constant then the conversion time is also constant.
Code on C++ (intentionally verbose):
vector<int> to_base3(int num) {
vector<int> base3;
for (; num > 0; num /= 3) {
base3.push_back(num % 3);
}
return base3;
}
int from_base3(const vector<int> &base3) {
int num = 0;
for (int i = 0, three = 1; i < base3.size(); ++i, three *= 3) {
num += base3[i] * three;
}
return num;
}
int find_unique(const vector<int> &a) {
vector<int> unique_base3(20, 0); // up to 3^20
for (int num : a) {
vector<int> num_base3 = to_base3(num);
for (int i = 0; i < num_base3.size(); ++i) {
unique_base3[i] = (unique_base3[i] + num_base3[i]) % 3;
}
}
int unique_num = from_base3(unique_base3);
return unique_num;
}
int main() {
vector<int> rands { 1287318, 172381, 5144, 566546, 7123 };
vector<int> a;
for (int r : rands) {
for (int i = 0; i < 3; ++i) {
a.push_back(r);
}
}
a.push_back(13371337); // unique number
random_shuffle(a.begin(), a.end());
int unique_num = find_unique(a);
cout << unique_num << endl;
}
byte [] oneCount = new byte [32];
int [] test = {1,2,3,1,5,2,9,9,3,1,2,3,9};
for (int n: test) {
for (int bit = 0; bit < 32; bit++) {
if (((n >> bit) & 1) == 1) {
oneCount[bit]++;
oneCount[bit] = (byte)(oneCount[bit] % 3);
}
}
}
int result = 0;
int x = 1;
for (int bit = 0; bit < 32; bit++) {
result += oneCount[bit] * x;
x = x << 1;
}
System.out.print(result);
Looks like while I was coding, others gave the main idea
I am trying to solve this problem but I can't find a solution:
A board consisting of squares arranged into N rows and M columns is given. A tiling of this board is a pattern of tiles that covers it. A tiling is interesting if:
only tiles of size 1x1 and/or 2x2 are used;
each tile of size 1x1 covers exactly one whole square;
each tile of size 2x2 covers exactly four whole squares;
each square of the board is covered by exactly one tile.
For example, the following images show a few interesting tilings of a board of size 4 rows and 3 columns:
http://dabi.altervista.org/images/task.img.4x3_tilings_example.gif
Two interesting tilings of a board are different if there exists at least one square on the board that is covered with a tile of size 1x1 in one tiling and with a tile of size 2x2 in the other. For example, all tilings shown in the images above are different.
Write a function
int count_tilings(int N, int M);
that, given two integers N and M, returns the remainder modulo 10,000,007 of the number of different interesting tilings of a board of size N rows and M columns.
Assume that:
N is an integer within the range [1..1,000,000];
M is an integer within the range [1..7].
For example, given N = 4 and M = 3, the function should return 11, because there are 11 different interesting tilings of a board of size 4 rows and 3 columns:
http://dabi.altervista.org/images/task.img.4x3_tilings_all.gif
for (4,3) the result is 11, for (6,5) the result is 1213.
I tried the following but it doesn't work:
static public int count_tilings ( int N,int M ) {
int result=1;
if ((N==1)||(M==1)) return 1;
result=result+(N-1)*(M-1);
int max_tiling= (int) ((int)(Math.ceil(N/2))*(Math.ceil(M/2)));
System.out.println(max_tiling);
for (int i=2; i<=(max_tiling);i++){
if (N>=2*i){
int n=i+(N-i);
int k=i;
//System.out.println("M-1->"+(M-1) +"i->"+i);
System.out.println("(M-1)^i)->"+(Math.pow((M-1),i)));
System.out.println( "n="+n+ " k="+k);
System.out.println(combinations(n, k));
if (N-i*2>0){
result+= Math.pow((M-1),i)*combinations(n, k);
}else{
result+= Math.pow((M-1),i);
}
}
if (M>=2*i){
int n=i+(M-i);
int k=i;
System.out.println("(N-1)^i)->"+(Math.pow((N-1),i)));
System.out.println( "n="+n+ " k="+k);
System.out.println(combinations(n, k));
if (M-i*2>0){
result+= Math.pow((N-1),i)*combinations(n, k);
}else{
result+= Math.pow((N-1),i);
}
}
}
return result;
}
static long combinations(int n, int k) {
/*binomial coefficient*/
long coeff = 1;
for (int i = n - k + 1; i <= n; i++) {
coeff *= i;
}
for (int i = 1; i <= k; i++) {
coeff /= i;
}
return coeff;
}
Since this is homework I won't give a full solution, but I'll give you some hints.
First here's a recursive solution:
class Program
{
// Important note:
// The value of masks given here is hard-coded for m == 5.
// In a complete solution, you need to calculate the masks for the
// actual value of m given. See explanation in answer for more details.
int[] masks = { 0, 3, 6, 12, 15, 24, 27, 30 };
int CountTilings(int n, int m, int s = 0)
{
if (n == 1) { return 1; }
int result = 0;
foreach (int mask in masks)
{
if ((mask & s) == 0)
{
result += CountTilings(n - 1, m, mask);
}
}
return result;
}
public static void Main()
{
Program p = new Program();
int result = p.CountTilings(6, 5);
Console.WriteLine(result);
}
}
See it working online: ideone
Note that I've added an extra parameter s. This stores the contents of the first column. If the first column is empty, s = 0. If the first column contains some filled squares the corresponding bits in s are set. Initially s = 0, but when a 2 x 2 tile is placed, this fills up some squares in the next column, and that will mean that s will be non-zero in the recursive call.
The masks variable is hard-coded but in a complete solution it needs to be calculated based on the actual value of m. The values stored in masks make more sense if you look at their binary representations:
00000
00011
00110
01100
01111
11000
11011
11110
In other words, it's all the ways of setting pairs of bits in a binary number with m bits. You can write some code to generate all these possiblities. Or since there are only 7 possible values of m, you could also just hard-code all seven possibilities for masks.
There are however two serious problems with the recursive solution.
It will overflow the stack for large values of N.
It requires exponential time to calculate. It is incredibly slow even for small values of N
Both these problems can be solved by rewriting the algorithm to be iterative. Keep m constant and initalize the result for n = 1 for all possible values of s to be 1. This is because if you only have one column you must use only 1x1 tiles, and there is only one way to do this.
Now you can calculate n = 2 for all possible values of s by using the results from n = 1. This can be repeated until you reach n = N. This algorithm completes in linear time with respect to N, and requires constant space.
Here is a recursive solution:
// time used : 27 min
#include <set>
#include <vector>
#include <iostream>
using namespace std;
void placement(int n, set< vector <int> > & p){
for (int i = 0; i < n -1 ; i ++){
for (set<vector<int> > :: iterator j = p.begin(); j != p.end(); j ++){
vector <int> temp = *j;
if (temp[i] == 1 || temp[i+1] == 1) continue;
temp[i] = 1; temp[i+1] = 1;
p.insert(temp);
}
}
}
vector<vector<int> > placement( int n){
if (n > 7) throw "error";
set <vector <int> > p;
vector <int> temp (n,0);
p.insert (temp);
for (int i = 0; i < 3; i ++) placement(n, p);
vector <vector <int> > s;
s.assign (p.begin(), p.end());
return s;
}
bool tryput(vector <vector <int> > &board, int current, vector<int> & comb){
for (int i = 0; i < comb.size(); i ++){
if ((board[current][i] == 1 || board[current+1][i]) && comb[i] == 1) return false;
}
return true;
}
void put(vector <vector <int> > &board, int current, vector<int> & comb){
for (int i = 0; i < comb.size(); i ++){
if (comb[i] == 1){
board[current][i] = 1;
board[current+1][i] = 1;
}
}
return;
}
void undo(vector <vector <int> > &board, int current, vector<int> & comb){
for (int i = 0; i < comb.size(); i ++){
if (comb[i] == 1){
board[current][i] = 0;
board[current+1][i] = 0;
}
}
return;
}
int place (vector <vector <int> > &board, int current, vector < vector <int> > & all_comb){
int m = board.size();
if (current >= m) throw "error";
if (current == m - 1) return 1;
int count = 0;
for (int i = 0; i < all_comb.size(); i ++){
if (tryput(board, current, all_comb[i])){
put(board, current, all_comb[i]);
count += place(board, current+1, all_comb) % 10000007;
undo(board, current, all_comb[i]);
}
}
return count;
}
int place (int m, int n){
if (m == 0) return 0;
if (m == 1) return 1;
vector < vector <int> > all_comb = placement(n);
vector <vector <int> > board(m, vector<int>(n, 0));
return place (board, 0, all_comb);
}
int main(){
cout << place(3, 4) << endl;
return 0;
}
time complexity O(n^3 * exp(m))
to reduce the space usage try bit vector.
to reduce the time complexity to O(m*(n^3)), try dynamic programming.
to reduce the time complexity to O(log(m) * n^3) try divide and conquer + dynamic programming.
good luck
for starters, I did have a look at these questions:
Given an array of integers where some numbers repeat 1 time, some numbers repeat 2 times and only one number repeats 3 times, how do you find the number that repeat 3 times
Algorithm to find two repeated numbers in an array, without sorting
this one different:
given an unsorted array of integers with one unique number and the rest numbers repeat 3 times,
i.e.:
{4,5,3, 5,3,4, 1, 4,3,5 }
we need to find this unique number in O(n) time and O(1) space
NOTE: this is not a homework, just I an nice question I came across
What about this one:
Idea: do bitwise addition mod 3
#include <stdio.h>
int main() {
int a[] = { 1, 9, 9, 556, 556, 9, 556, 87878, 87878, 87878 };
int n = sizeof(a) / sizeof(int);
int low = 0, up = 0;
for(int i = 0; i < n; i++) {
int x = ~(up & a[i]);
up &= x;
x &= a[i];
up |= (x & low);
low ^= x;
}
printf("single no: %d\n", low);
}
This solution works for all inputs.
The idea is to extract the bits of an integer from array and add to respective 32bit
bitmap 'b' (implemented as 32byte array to represent 32bit no.)
unsigned int a[7] = {5,5,4,10,4,9,9};
unsigned int b[32] = {0}; //Start with zeros for a 32bit no.
main1() {
int i, j;
unsigned int bit, sum =0 ;
for (i=0;i<7; i++) {
for (j=0; j<32; j++) { //This loop can be optimized!!!!
bit = ((a[i] & (0x01<<j))>>j); //extract the bit and move to right place
b[j] += bit; //add to the bitmap array
}
}
for (j=0; j<32; j++) {
b[j] %= 2; //No. repeating exactly 2 times.
if (b[j] == 1) {
sum += (unsigned int) pow(2, j); //sum all the digits left as 1 to get no
//printf("no. is %d", sum);
}
}
printf("no. is %d", sum);
}
I'm looking for an algorithm to generate all permutations with repetition of 4 elements in list(length 2-1000).
Java implementation
The problem is that the algorithm from the link above alocates too much memory for calculation. It creates an array with length of all possible combination. E.g 4^1000 for my example. So i got heap space exception.
Thank you
Generalized algorithm for lazily-evaluated generation of all permutations (with repetition) of length X for a set of choices Y:
for I = 0 to (Y^X - 1):
list_of_digits = calculate the digits of I in base Y
a_set_of_choices = possible_choices[D] for each digit D in list_of_digits
yield a_set_of_choices
If there is not length limit for repetition of your 4 symbols there is a very simple algorithm that will give you what you want. Just encode your string as a binary number where all 2 bits pattern encode one of the four symbol. To get all possible permutations with repetitions you just have to enumerate "count" all possible numbers. That can be quite long (more than the age of the universe) as a 1000 symbols will be 2000 bits long. Is it really what you want to do ? The heap overflow may not be the only limit...
Below is a trivial C implementation that enumerates all repetitions of length exactly n (n limited to 16000 with 32 bits unsigned) without allocating memory. I leave to the reader the exercice of enumerating all repetitions of at most length n.
#include <stdio.h>
typedef unsigned char cell;
cell a[1000];
int npack = sizeof(cell)*4;
void decode(cell * a, int nbsym)
{
unsigned i;
for (i=0; i < nbsym; i++){
printf("%c", "GATC"[a[i/npack]>>((i%npack)*2)&3]);
}
printf("\n");
}
void enumerate(cell * a, int nbsym)
{
unsigned i, j;
for (i = 0; i < 1000; i++){
a[i] = 0;
}
while (j <= (nbsym / npack)){
j = 0;
decode(a, nbsym);
while (!++a[j]){
j++;
}
if ((j == (nbsym / npack))
&& ((a[j] >> ((nbsym-1)%npack)*2)&4)){
break;
}
}
}
int main(){
enumerate(a, 5);
}
You know how to count: add 1 to the ones spot, if you go over 9 jump back to 0 and add 1 to the tens, etc..
So, if you have a list of length N with K items in each spot:
int[] permutations = new int[N];
boolean addOne() { // Returns true when it advances, false _once_ when finished
int i = 0;
permutations[i]++;
while (permutations[i] >= K) {
permutations[i] = 0;
i += 1;
if (i>=N) return false;
permutations[i]++;
}
return true;
}
First of all this is not homework!
My question is from the book: Algorithms in C++ third edition by Robert Sedgewick.
There is given an array of size n by 2^n (two dimensional) and we should fill it with binary numbers of bits size exactly n. For example for n=5 the result will be:
00001
00010
00011
00100
00101
00110
00111
And so on. We should put this sequence of bits into arrays.
This is a very rudimentary problem, and I will demonstrate with this Java snippet:
public class Bin { // prints:
static String zero(int L) { // 0000
return (L <= 0 ? "" : String.format("%0" + L + "d", 0)); // 0001
} // 0010
static String zeroPad(String s, int L) { // 0011
return zero(L - s.length()) + s; // 0100
} // 0101
public static void main(String[] args) { // 0110
final int N = 4; // 0111
for (int i = 0; i < (1 << N); i++) { // 1000
System.out.println(zeroPad(Integer.toBinaryString(i), N)); // 1001
} // 1010
} // 1011
} // 1100
// 1101
// 1110
// 1111
I will leave it to you to figure out how to implement toBinaryString and how to populate int[][] with the bits.
I do not know much C/C++, but a naïve, language-agnostic approach would be to simply find a formula for A[i, j], where i \in [0, 2^n - 1] and j \in [0, n-1].
In words, A[i, j] contains the jth binary digit of i, counting from the most significant bit.
In formulae, A[i, j] = (i AND 2^(n-1-j) ) SHR (n-1-j)
where AND is the binary bitwise and operator, and SHR is the binary "shift bits right" operator. a^b means (of course) "a raised to the power of b".
Ugly Proof-Of-Concept Delphi Code:
var
i: Integer;
twoton: integer;
j: Integer;
begin
twoton := round(IntPower(2, n));
SetLength(A, twoton, n);
for i := 0 to twoton - 1 do
for j := 0 to n - 1 do
A[i, j] := (i and round(IntPower(2, n-1-j))) shr (n-1-j);
This works perfectly, but I am quite sure there are faster ways... At least one could store the powers of 2 in an array and use POWEROF2[k] rather than round(IntPower(2, k)), but - of course - this depends on your language. After all, IntPower is a Delphi function.
How this works
Say that we have the number 23, or, in binary 10111. Now we want the third binary digit. Then we want to AND the number 10111 with the number 00100, to obtain 00100 if the sought digit is one, and 00000 otherwise. Notice that 00100, the number we AND with, is simply 2^3 in decimal; hence all powers-of-2. Now we have the number 00N00, where N is the sought digit, in this example 1: 00100. We now shift the bits of this number 3 steps to the right (the SHR operation), to obtain 00001 = 1, and - voilà! - we have gotten our digit!
A Smarter Approach
I do not know how C stores arrays, but you could simply create a 2^N-dimensional vector A of unsigned integers (8-bit, 16-bit, or 32-bit, preferably), namely the numbers 0, 1, 2, ..., 2^N - 1, and then argue that this actually is a two-dimensional matrix. Indeed, if we introduce the notation UNSINGED_INTEGER[k] as the kth bit of UNSIGNED_INTEGER, then A[i][k] is more or less the matrix you wanted...
Each number is one more than the last in the binary number system.
To increment (add one) in binary
start at the right end of the number
turn all trailing ones, if any, into zeroes
turn the last 0 into a 1
if there isn't a 0 in the string, you've gone too far.
Note that the << operator multiplies the left operand by two to the power of the right operand. The number 1l is simply 1 expressed as a long, which is 64 bits on a 64-bit system.
template< size_t n > // template detects size of array. Strictly optional.
void ascending_binary_fill( bool (&arr)[ 1l << n ][ n ] ) {
std::fill( arr[0], arr[0] + n, 0 ); // first # is 0
for ( size_t pred = 0; pred < 1l << n; ++ pred ) {
int bit = n; // pred = index of preceding number; bit = bit index
while ( arr[ pred ][ -- bit ] ) { // trailing 1's in preceding #
arr[ pred+1 ][ bit ] = 0; // ... are trailing 0's in current #
}
arr[ pred+1 ][ bit ] = 1;
std::copy( arr[ pred ], arr[ pred ] + bit, arr[ pred+1 ] );
}
}
Quite simple!
here is a solution in pseudocode
assert(bits <= 32)
int array[pow(2, bits)]
for (uint i= 0; i < length(array); i++)
array[i]= i;
The result is an array filled with the pattern you gave as an example
public static uint[][] FillUpCode(uint qValue, uint kValue)
{
var size = (ulong)Math.Pow(qValue, kValue);
var array = new uint[size][];
var workArray = new uint[kValue];
long position = kValue - 1;
ulong n = 0;
while (position > 0)
{
while (workArray[position] < qValue)
{
var tempArray = new uint[kValue];
Array.Copy(workArray, tempArray, kValue);
array[n++] = tempArray;
workArray[position]++;
}
while (position > 0)
{
workArray[position] = 0;
if (workArray[position - 1] < (qValue - 1))
{
workArray[position - 1]++;
position = kValue - 1;
break;
}
position--;
}
}
return array;
}
qValue - number base, kValue - line length :) Code may be useful when you need to generate array in different number basis.
So basically, you need an array that starts at zero, and goes up to 2^n?
Psuedo-C:
bool[][] Fill(int n) {
max = Pow(2, n);
array = new bool[max, n];
for i from 0 to max - 1
for j from 0 to n - 1
array[i][n - j - 1] = ((i >> j) & 1) == 1;
return array;
}
The only problem I can see with that is that it capped at n = 32, but that will already take enormous amounts of memory so that really is a non-issue.
Note that you could as well make it a one dimensional number and fill it with numbers from 0 to 2^n, and the A[i][j]th element will actually be retrieved using (A[i]>>j) & 1.
// My solution is based on that of Potatoswatter.
// use cols value where rows = 2^cols
// start here after setting cols
rows = pow(2.0, double(cols));
// memory allocation
bool **array = new bool*[rows];
for (int i = 0; i < rows; i++) {
array[i] = new bool[cols];
}
std::fill( array[0], array[0] + cols, 0 ); // maybe not needed
for (int i = 1; i < rows; i++) { // first row is zero, start at second
// starting at right ...
int j = lits - 1;
// turn the last zero into a one
if (array[i][j] == false) {
array[i][j] = true;
}
else {
// turn all trailing ones into zeros (prior to first zero)
while (array[i][j] == true) {
array[i][j] = false;
j--;
}
array[i][j] = true;
}
// copy this row to next row
if (i < (rows - 1)) {
std::copy(array[i], array[i] + lits, array[i+1]);
}
}