I want to know a algorithm to find out the maximum xor value of three elements of an array.
I have read about the maximum xor for two elements from an array but cannot understand how to apply it on finding the maximum value of XOR taking 3 elements of an array . Can someone point out a hint ?
Required complexity : less than O(N^3) where N is the number of elements in the array.
Example:
A = [1,2,3,4]
All Possible Triplets :-
1^2^3 = 0
1^2^4 = 7
1^3^4 = 6
2^3^4 = 5
Thus, the maximum XOR value is 7.
Edit :
I have thought of a solution having complexity O(N^2 * log(MAX)) and it has solved my purpose :D .
MAX = Maximum Value in the Array
Well, I have found a solution with complexity O(N^2 * log(MAX)) where MAX is the largest value in the array .
Let there be 3 elements X,Y,Z fron the array A.
where X = A[i] , Y = A[j] , Z = A[k] and i != j != k
We want the maximum value of (X^Y^Z) .
Let us assume W = X*Y.
Then we would like to find such a Z which give maximum value for W^Z and Z != X and Z != Y
Now this has been reduced to the problem of finding "Two elements whose XOR is maximum" which can be done for a given W in O(log(MAX)) using a Trie .
Explanation for Trie :
Let us assume W = 10001 here W is in binary .
Now we know 1^0 = 1 , 0^0 = 0 , 1^1 = 0 , so the maximum value we
can get for W^Z is when Z is 01110 because
W^Z will give = 11111.
But it is not necessary to have 15 or Base2(11111) in our array so
we would take the best possible option available.
So we will create a Trie of all the elements of the array
according to their binary representation.
If A = [1,2,7] , then 1 = 001 , 2 = 010 , 7 = 111 in
binary .
Then the Trie will look like :-
Top
/ \
0 1
/ \ \
0 1 1
\ / \
1 0 1
Now to lets assume W = 7 , and we want to find Z such that
W^Z is maximum (when Z = 000 ) then we will start at the Top and look if we have branch leading to 0 since the first bit of 7 is 1
, then we will down through that branch and then again look if we have
branch leading to 0 at 2nd bit , again we find it , then for the last
time we search for branch leading to a 0 at 3rd bit but we do not find
it , so we go down through the other branch which gives us Z =
001. Thus, the maximum W^Z will be 7^1 = 6 . Now , the
complexity of finding Z will be maximum height of the Trie which
will be log(MAX).
Thus , we have N*(N-1)/2 number of W's and for each W we can find the Maximum value of W^Z and if we take the Maximum from all the values of W^Z we will have our answer.
With three nested loop:
int max2=0,max3=0;
for (int i=0;i<arr.size();i++)
for (int j=0;j<arr.size();j++)
for (int k=0;k<arr.size();k++)
{
if (arr[i]^arr[j]>max2) // for 2 elements
max2 = arr[i]^arr[j];
if (arr[i]^arr[j]^arr[k]>max3) // for 3 elements
max3 = arr[i]^arr[j]^arr[k];
}
int max = max2; // for both
if (max3>max2)
max = max3;
following will do the O(N^3), but in an more optimized approach - not testing same combination more than once, not testing element against itself,
and somewhat optimized evaluation (xoring the first two elements once for all possible third elements)
Number of Xor operations performed will be:
n(n-1)(n-2)/6 + n(n-1)/2
Complexity is still n(n-1)(n-2)/6 ===> O(N^3) though.
unsigned int maxXor3(unsigned int* element, int len)
{
unsigned int max = 0;
unsigned int xor2 = 0;
unsigned int xor3 = 0;
int j = k = 0;
for (int i = 0 ; i < len ; i++)
{
for (j = i + 1 ; j < len ; j++)
{
xor2 = element[i] ^ element[j];
for(k = j + 1; k < len; k++)
{
xor3 = xor2 ^ element[k];
if (xor3 > max)
max = xor3;
}
}
}
return max;
}
Related
This code is to move all the zeroes in the vector to the end of the vector while maintaining the order of the non zero elements.
Eg: 0 3 0 8 0 9
Output : 3 8 9 0 0 0
I wrote the following code for this
void moveZeroes(vector<int>& nums) {
vector<int> v, v1; // v has the index of all the zero elements while v1 has index of non zero elements
for(int i = 0; i < nums.size(); i++){
if(nums[i] == 0)
v.push_back(i);
else v1.push_back(i);
}
//Here i'm swapping all the zero elements with non zero elements
for(int i = 0; i < v.size(); i++){
for(int j = 0; j < v1.size(); j++){
if(v[i] < v1[j]){
swap(nums[v[i]], nums[v1[j]]);
v[i] = v1[j];
}
}
}
}
So if nums has size n and v has size x & v1 has size y where x + y = n, then time complexity is O(x*y) . But what will be the time complexity in terms of n?
Let N be the the number of elements in the vector.
In the best case the time complexity would be linear, i.e, O(N). This happens in 2 cases:
when all the elements are non-zero. The second loop in which you swap elements would not be executed (v would be empty)
when all the elements are zero. In such a case only the first part of the second loop would run (v1 would be empty).
In the other cases you incur in a quadratic time complexity O(N^2) due to the double loop.
For instance, suppose that half of the elements are zero and the other half is non-zero. This means that the number of iterations would be.
N/2*N/2 = N^2/4 = O(N^2)
So if nums has size n and v has size x & v1 has size y where x + y = n, then time complexity is O(x*y) . But what will be the time complexity in terms of n?
Could be up to O(n2) if x and y are roughly n/2, e.g: y = x = n / 2 => x * y = n^2/4.
I recommend you to do the following:
void moveZeroes(vector<int>& nums)
{
for(int i = 0, p = 0; i < (int)nums.size(); ++i)
if(nums[i])
{
if(p != i)
swap(nums[i], nums[p]);
++p;
}
}
Pointer p indicates how many non zero elements have been swapped.
This way you get an O(n) time complexity, the code is clearer and don't use an extra O(n) memory consumption.
Given an array of non-negative integers, what is the fastest and most efficient way to find the maximum no. that can be obtained by performing bitwise and (i.e, & operator) on 2 DISTINCT elements of the array?
This is my code until now :
max = 0
for(i=0; i<n; i++)
{
for(j=i+1; j<n; j++)
{
temp = a[i] & a[j];
if(temp > max)
max = temp
}
}
This, of course, is the naive method. I am looking for a more efficient solution.
Maybe something like using a trie(actually a binary tree) to find max XOR of elements of array. The description for the max XOR solution can be found at http://threads-iiith.quora.com/Tutorial-on-Trie-and-example-problems?share=1
I hope I have got the question right. Here's my solution to it:
You have an array of integers, say that they are unsigned integers since we are dealing with bitwise operations. Let's think of them as a string of zeroes and ones in their binary representation and then put them on top of each other.
We now have their corresponding bits aligned vertically. Let's draw vertical lines, starting from the leftmost column. If we ever encounter more than or equal to two 1s in a column, then rule out every row that does not have the 1s. We are to disregard the ruled out ones while drawing our further vertical lines.
You see where this is going at?
This shall go on until we have only and exactly 2 lines left that hasn't been ruled out. If we ever end up with anything else than 2, then it means something went wrong:
Less than 2 means we had less than 2 lines initially
More than 2 means that...
If there are less than what we had initially, then the ones left should all be identical
If there are exactly as many as we had initially, then it can be that all are the same, or every possible pair is bitwise distinct, meaning that every single pair produces 0
Here's the code I've written that follows the logic I've described above:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <memory.h>
#define bit(_x_) (1U << (_x_))
void randomfillarray( unsigned int * arr, size_t size ) {
srand( time( NULL ) );
for ( int i = 0; i < size; i++ )
arr[i] = rand( );
}
int main( ) {
unsigned int arr[10];
size_t size = sizeof arr / sizeof * arr;
randomfillarray( arr, size );
unsigned int * resultantcouple = malloc( sizeof arr );
memcpy( resultantcouple, arr, sizeof arr );
for ( int i = 0; i < size; i++ )
printf( i ? " %u" : "%u", arr[i] );
putchar( '\n' );
int success = 0;
for ( unsigned int thebit = bit( sizeof( int ) * 8 - 1 ); thebit; thebit >>= 1 ) {
int count = 0;
int * indices = NULL;
for ( int i = 0; i < size; i++ ) {
if ( resultantcouple[i] & thebit ) {
indices = realloc( indices, ++count * sizeof * indices );
indices[count - 1] = i;
}
}
if ( count >= 2 ) {
size = count;
for ( int i = 0; i < size; i++ )
resultantcouple[i] = resultantcouple[indices[i]];
resultantcouple = realloc( resultantcouple, size * sizeof * resultantcouple );
}
if ( size == 2 ) {
success = 1;
break;
}
free( indices );
}
if ( success )
printf( "Success! %u and %u are the ones.", resultantcouple[0], resultantcouple[1] );
else
printf( "Failure! Either all pairs are bitwise distinct, or there are less than 2 elements, or something else..." );
putchar( '\n' );
return 0;
}
Here's the same during action: http://ideone.com/hRA8tn
I'm not sure if this is the best, but it should be better than testing all out.
First look at and understand the heapsort algorithm.
Turn the array into a heap which lets you access the two largest elements. This is done in linear time, O (n).
Take the two largest elements, x = largest, y = second largest. If y = 0, the solution is 0. If the highest bit in x and the highest bit in y are the same, the solution is x & y. Otherwise, clear the highest bit in x, fix the heap, and try again. The last step takes O (log n) steps, and if you are using k bit integers, like 32 or 64, it is repeated at most k times.
No extra space needed, and linear time.
Pseudo-code:
If n ≤ 1 there is no solution.
Turn a [0] to a [n-1] into a heap with a [0] as the largest element.
Repeat
Let x = a [0].
Let y = a [1].
If n ≥ 3 and a [2] > a [1] then let y = a [2].
If y = 0 then the solution is 0.
Determine b = the highest bit of x.
If (y & b) != 0 then the solution is x & y.
Replace a [0] with x & (~ b)
Turn a [0] to a [n-1] into a heap again by moving a [0] down.
This assumes that a [i] and a [j] are considered "distinct array elements" if i ≠ j. If you require instead that a [i] ≠ a [j] then things are slightly different. You'd have to remove duplicate entries in your array, but in case the largest elements are for example 31 and 15, you don't want to clear the highest bit in 31 and then remove it as a duplicate! So the code is more difficult.
Let mask = ~0. In the following, when creating a heap compare a [i] & mask, not a [i].
Turn a [0] to a [n-1] into a heap with a [0] as the largest element.
Repeat
If n ≤ 1 then there is no solution.
Let x = a [0].
Let y = a [1].
If n ≥ 3 and a [2] & mask > y & mask then let y = a [2].
If x = y then let n = n - 1, let a [0] = a [n], restore the heap, and continue.
If (y & mask) = 0 then the solution is 0.
Determine b = the highest bit of x & mask.
If (y & b) != 0 then the solution is x & y.
Replace mask with mask & ~b.
Restore the heap and continue.
Worst case is O (n log n), for example if all elements are 1 except one that is 0.
The following worked for me for our_n uints in uint our_a[our_n], without changing the array or copying it or anything else. The essence is that in one pass down the array it identifies the next bit that can be added to the result so far. Each pass only considers values which contain all the bits of the result so far:
uint result ;
uint passes ;
uint msb ;
uint pn ;
at->start_clock = times(&at->start_tms) ;
result = 0 ;
passes = 0 ;
msb = (UINT_MAX >> 1) + 1 ;
pn = our_n ;
do
{
uint seen_once ;
uint seen_again ;
passes += 1 ;
seen_once = 0 ;
seen_again = 0 ;
for (uint i = 0 ; i < pn ; ++i)
{
uint a ;
a = our_a[i] ;
if ((a & result) == result)
{
seen_again |= (a & seen_once) ;
seen_once |= a ;
} ;
} ;
assert((seen_again & result) == result) ;
seen_again ^= result ;
while (msb > seen_again)
msb >>= 1 ;
result |= msb ;
}
while (msb > 1) ;
So, this is O(p * n), where p is the number of passes: 1..32.
If it is OK to destroy the contents of the array, then the inner loop can be changed to:
k = 0 ;
for (uint i = 0 ; i < pn ; ++i)
{
uint a ;
a = our_a[i] ;
if ((a & result) == result)
{
our_a[k++] = a ;
seen_again |= (a & seen_once) ;
seen_once |= a ;
} ;
} ;
pn = k ;
Of course, the first pass is now doing rather more work than it need to, so doing that separately saves a bit more.
This is the code that I had tried to find the consecutive zero which are in the order of 5 or more.
a=[0,0,0,0,0,0,0,0,9,8,5,6,0,0,0,0,0,0,3,4,6,8,0,0,9,8,4,0,0,7,8,9,5,0,0,0,0,0,8,9,0,5,8,7,0,0,0,0,0];
[x,y]=size(a);
for i=0:y
i+1;
k=1;
l=0;
n=i;
count=0;
while (a==0)
count+1;
break;
n+1;
end
if(count>=5)
v([]);
for l=k:l<n
v(m)=l+1;
m+1;
end
end
count=1;
i=n;
end
for i = o : i<m
i+1;
fprintf('index of continous zero more than 5 or equal=%d',v(i));
end
If you want to find the starting indices of runs of n or more zeros:
v = find(conv(double(a==0),ones(1,n),'valid')==n); %// find n zeros
v = v([true diff(v)>n]); %// remove similar indices, indicating n+1, n+2... zeros
In your example, this gives
v =
1 13 34 45
One-liner strfind approach to find the starting indices of 5 consecutive zeros -
out = strfind(['0' num2str(a==0,'%1d')],'011111')
Output -
out =
1 13 34 45
The above code could be generalised like this -
n = 5 %// number of consecutive matches
match = 0 %// match to be used
out = strfind(['0' num2str(a==match,'%1d')],['0' repmat('1',1,n)]) %// starting indices of n consecutive matches
If you are looking to find all the indices where the n consecutive matches were found, you can add this code -
outb = strfind([num2str(a==match,'%1d'),'0'],[repmat('1',1,n) '0'])+n-1
allind = find(any(bsxfun(#ge,1:numel(a),out') & bsxfun(#le,1:numel(a),outb')))
If you want to find the general case of a "run of n or more values x in vector V", you could do the following:
% your particular case:
n = 5;
x = 0;
V = [0,0,0,0,0,0,0,0,9,8,5,6,0,0,0,0, ...
0,0,3,4,6,8,0,0,9,8,4,0,0,7,8,9, ...
5,0,0,0,0,0,8,9,0,5,8,7,0,0,0,0,0];
b = (V == x); % create boolean array: ones and zeros
d = diff( [0 b 0] ); % turn the start and end of a run into +1 and -1
startRun = find( d==1 );
endRun = find( d==-1 );
runlength = endRun - startRun;
answer = find(runlength > n);
runs = runlength(answer);
disp([answer(:) runs(:)]);
This will display the start of the run, and its length, for all runs > n of value x.
Suppose I have an array of M elements, all numbers, negative or positive or zero.
Can anyone suggest an algorithm to select N elements from the array, such that the sum of these N elements is the smallest possible positive number?
Take this array for example:
-1000,-700,-400,-200,-100,-50,10,100,300,600,800,1200
Now I have to select any 5 elements such that their sum is the smallest possible positive number.
Formulation
For i = 1, ..., M:
Let a_i be the ith number in your list of candidates
Let x_i denote whether the ith number is included in your set of N chosen numbers
Then you want to solve the following integer programming problem.
minimize: sum(a_i * x_i)
with respect to: x_i
subject to:
(1) sum(a_i * x_i) >= 0
(2) sum(x_i) = N
(3) x_i in {0, 1}
You can apply an integer program solver "out of the box" to this problem to find the optimal solution or a suboptimal solution with controllable precision.
Resources
Integer programming
Explanation of branch-and-bound integer program solver
If you want to find the best possible solution, you can simply use brute force ie. try all posible combinations of fiwe numbers.
Something like this very quick and dirty algorithm:
public List<Integer> findLeastPositivSum(List<Integer> numbers) {
List<Integer> result;
Integer resultSum;
List<Integer> subresult, subresult2, subresult3, subresult4, subresult5;
for (int i = 0; i < numbers.size() - 4; i++) {
subresult = new ArrayList<Integer>();
subresult.add(numbers.get(i));
for (int j = i + 1; j < numbers.size() - 3; j++) {
subresult2 = new ArrayList<Integer>(subresult);
subresult2.add(j);
for (int k = j + 1; k < numbers.size() - 2; k++) {
subresult3 = new ArrayList<Integer>(subresult2);
subresult3.add(k);
for (int l = k + 1; l < numbers.size() - 1; l++) {
subresult4 = new ArrayList<Integer>(subresult3);
subresult4.add(k);
for (int m = l + 1; m < numbers.size(); m++) {
subresult5 = new ArrayList<Integer>(subresult4);
subresult5.add(k);
Integer subresultSum = sum(subresult5);
if (subresultSum > 0) {
if (result == null || resultSum > subresultSum) {
result = subresult;
}
}
}
}
}
}
}
return result;
}
public Integer sum(List<Integer> list) {
Integer result = 0;
for (Integer integer : list) {
result += integer;
}
return result;
}
This is really quick and dirty algorithm, it can be done more elegantly. I can provide cleaner algorithm e.g. using recursion.
It can be also further optimized. E.g. you can remove similar numbers from input list as first step.
Let initial array be shorted already, or i guess this will work even when it isnt shorted..
N -> Length of array
M -> Element req.
R[] -> Answer
TEMP[] -> For calculations
minSum -> minSum
A[] -> Initial input
All above variables are globally defined
int find(int A[],int start,int left)
{
if(left=0)
{
//sum elements in TEMP[] and save it as curSum
if(curSum<minSum)
{
minSum=curSum;
//assign elements from TEMP[] to R[] (i.e. our answer)
}
}
for(i=start;i<=(N-left);i++)
{
if(left==M)
curSum=0;
TEMP[left-1]=A[i];
find(A[],i+1,left-1);
}
}
// Made it in hurry so maybe some error would be existing..
Working solution on ideone :
http://ideone.com/YN8PeW
I suppose Kadane’s Algorithm would do the trick, although it is for the maximum sum but I have also implemented it to find the minimum sum, though can't find the code right now.
Here's something sub optimal in Haskell, which (as with many of my ideas) could probably be further and better optimized. It goes something like this:
Sort the array (I got interesting results by trying both ascending and descending)
B N = first N elements of the array
B (i), for i > N = best candidate; where (assuming integers) if they are both less than 1, the candidates are compared by the absolute value of their sums; if they are both 1 or greater, by their sums; and if only one candidate is greater than 0 then that candidate is chosen. If a candidate's sum is 1, return that candidate as the answer. The candidates are:
B (i-1), B (i-1)[2,3,4..N] ++ array [i], B (i-1)[1,3,4..N] ++ array [i]...B (i-1)[1,2..N-1] ++ array [i]
B (i-2)[2,3,4..N] ++ array [i], B (i-2)[1,3,4..N] ++ array [i]...B (i-2)[1,2..N-1] ++ array [i]
...
B (N)[2,3,4..N] ++ array [i], B (N)[1,3,4..N] ++ array [i]...B (N)[1,2..N-1] ++ array [i]
Note that for the part of the array where the numbers are negative (in the case of ascending sort) or positive (in the case of descending sort), step 3 can be done immediately without calculations.
Output:
*Main> least 5 "desc" [-1000,-700,-400,-200,-100,-50,10,100,300,600,800,1200]
(10,[-1000,600,300,100,10])
(0.02 secs, 1106836 bytes)
*Main> least 5 "asc" [-1000,-700,-400,-200,-100,-50,10,100,300,600,800,1200]
(50,[300,100,-200,-100,-50])
(0.02 secs, 1097492 bytes)
*Main> main -- 10000 random numbers ranging from -100000 to 100000
(1,[-106,4,-40,74,69])
(1.77 secs, 108964888 bytes)
Code:
import Data.Map (fromList, insert, (!))
import Data.List (minimumBy,tails,sort)
import Control.Monad.Random hiding (fromList)
array = [-1000,-700,-400,-200,-100,-50,10,100,300,600,800,1200]
least n rev arr = comb (fromList listStart) [fst (last listStart) + 1..m]
where
m = length arr
r = if rev == "asc" then False else True
sorted = (if r then reverse else id) (sort arr)
listStart = if null lStart
then [(n,(sum $ take n sorted,take n sorted))]
else lStart
lStart = zip [n..]
. takeWhile (all (if r then (>0) else (<0)) . snd)
. foldr (\a b -> let c = take n (drop a sorted) in (sum c,c) : b) []
$ [0..]
s = fromList (zip [1..] sorted)
comb list [] = list ! m
comb list (i:is)
| fst (list ! (i-1)) == 1 = list ! (i-1)
| otherwise = comb updatedMap is
where updatedMap = insert i bestCandidate list
bestCandidate = comb' (list!(i - 1)) [i - 1,i - 2..n] where
comb' best [] = best
comb' best (j:js)
| fst best == 1 = best
| otherwise =
let s' = map (\x -> (sum x,x))
. (take n . map (take (n - 1)) . tails . cycle)
$ snd (list!j)
t = s!i
candidate = minimumBy compare' (map (add t) s')
in comb' (minimumBy compare' [candidate,best]) js
add x y#(a,b) = (x + a,x:b)
compare' a#(a',_) b#(b',_)
| a' < 1 = if b' < 1 then compare (abs a') (abs b') else GT
| otherwise = if b' < 1 then LT else compare a' b'
rnd :: (RandomGen g) => Rand g Int
rnd = getRandomR (-100000,100000)
main = do
values <- evalRandIO (sequence (replicate (10000) rnd))
putStrLn (show $ least 5 "desc" values)
Assumption: M is the original array
Pesudocode
S = sort(M);
R = [];
sum = 0;
for(i=0, i < length(S); i++){
sum = sum + S[i];
if(sum < 1){
R.push(S[i]);
}else{
return R;
}
}
Can someone help me out with algorithm for solving linear equations in modular arithmetic (!). I need only the "smallest" solution. Smallest means lexicographically first.
Let's have this system:
3x1+2x2=3
4x1+3x2+1x3+2x4=4
Number next to x is index.
Matrix for this system where we use modulo 5 (0<=x<=p where p is our modulo) is
3 2 0 0 0 | 3
4 3 1 2 0 | 4
The smallest solution for this is (0,4,0,1,0). I have to write an algorithm which will give me that solution.
I was thinking about brute-force, because p<1000. But I dont how to do it, because in this situation in first row I have to x1=0 ... p-1 , then solve x2, in the second row i have to pick x3= 0 ... p-1. And solve x4. I have to do this until that system of equations hold. If I go from 0 .. p-1, then the first solution I get will be the smallest one.
PS:There can a lot of forms of matrix, like:
3 2 4 0 0 | 3
4 3 1 2 1 | 4
1 2 0 0 0 | 3
3 0 3 0 0 | 3
4 3 1 2 3 | 4
etc.
Sorry for my english, I am from asia.
Edit: I was thinking about how to determine which variables are parameters. But can't figure it out....
Ah well, what the heck, why not, here you go
#include <stdio.h>
#define L 2
#define N 5
#define MOD 5
static int M[L][N] =
{ { 3, 2, 0, 0, 0 }
, { 4, 3, 1, 2, 0 }
};
static int S[L] =
{ 3, 4
};
static void init(int * s)
{
int i;
for (i = 0; i < N; i++)
{
s[i] = 0;
}
}
static int next(int * s)
{
int i, c;
c = 1;
for (i = N-1; i >= 0 && c > 0; i--)
if ( (++s[i]) == MOD)
{
s[i] = 0;
}
else
{
c = 0;
}
return c == 0;
}
static int is_solution(int * s)
{
int i, j, sum;
for (i = 0; i < L; i++)
{
sum = 0;
for (j = 0; j < N; j++)
{
sum += M[i][j]*s[j];
}
if (sum % MOD != S[i])
{
return 0;
}
}
return 1;
}
int main(void)
{
int s[N];
init(s);
do
{
if (is_solution(s))
{
int i;
for (i = 0; i < N; i++)
{
printf(" %d", s[i]);
}
printf("\n");
break;
}
} while (next(s));
return 0;
}
You can treat this as a problem in linear algebra and Gaussian elimination mod p.
You are trying to find solutions of Mx = y mod p. Start with a square M by adding rows of 0'x = 0 if necessary. Now use Gaussian elimination mod p to reduce M, as far as possible, to upper triangular form. You end up with a system of equations such as
ax + by + cz = H
dy + ez = G
but with some zeros on the diagonal, either because you have run out of equations, or because all of the equations have zero at a particular column. If you have something that says 0z = 1 or similar there is no solution. If not you can work out one of possibly many solutions by solving from the bottom up as usual, and putting in z=0 if there is no equation left that has a non-zero coefficient for z on the diagonal.
I think that this will produce the lexicographically smallest answer if the most significant unknown corresponds to the bottom of the vector. The following shows how you can take an arbitrary solution and make it lexicographically smallest, and I think that you will find that it would not modify solutions produced as above.
Now look at http://en.wikipedia.org/wiki/Kernel_%28matrix%29. There is a linear space of vectors n such that Mn = 0, and all the solutions of the equation are of the form x + n, where n is a vector in this space - the null space - and x is a particular solution, such as the one you have worked out.
You can work out a basis for the null space by finding solutions of Mn = 0 much as you found x. Find a column where there is no non-zero entry on the diagonal, go to the row where the diagonal for that column should be, set the unknown for that column to 1, and move up the matrix from there, choosing the other unknowns so that you have a solution of Mn = 0.
Notice that all of the vectors you get from this have 1 at some position in that vector, 0s below that vector, and possibly non-zero entries above. This means that if you add multiples of them to a solution, starting with the vector which has 1 furthest down, later vectors will never disturb components of the solution where you have previously added in vectors with 1 low down, because later vectors always have zero there.
So if you want to find the lexicographically smallest solution you can arrange things so that you use the basis for the null space with the lexicographically largest entries first. Start with an arbitrary solution and add in null space vectors as best you can, in lexicographical order, to reduce the solution vector. You should end up with the lexicographically smallest solution vector - any solution can be produced from any other solution by adding in a combination of basis vectors from the null space, and you can see from the above procedure that it produces the lexicographically smallest such result - at each stage the most significant components have been made as small as possible and any alternatives must be lexicographically greater.