Tuesday, December 13, 2011

maximum-subarray problem

 If we are given an array A, we now want to find the nonempty, contiguous subarray of A whose values have the largest sum. We call this contiguous subarray
the maximum subarray.

Clean way to illustrate basic algorithm design:
1:  brute force algorithm: O(n^3)
2: algorithm that reuses data: O(n^2)
3: divide-and-conquer algorithm: O(n *lgn)



divide-and-conquer algorithm:
need consider two factors:
1: termination condition
2: combination of left and right .

1: termination condition:
  if(size==1) return;

2: combination
    compare(left, right, combined);
    left and right can be obtained by recursion.
    combined is computed by array[i..mid]+array[mid+1...j];

   array[i..mid]: the max subarray beginning from mid. For example, suppose given  array[0..9]. mid=4; array[i..4] means the max of array[4], array[4,3], array[4,3,2], array[4,3,2,1], array[4,3,2,1,0].



------------------------------------------------------------
Non-recursion solution:
Knowing a maximum subarray of A[1..j], extend the answer to find a maximum subarray ending at index  by using the following observation: a maximum subarray of A[1..j] is either a maximum subarray of A[1..j] or a subarray A[1..j+1]. Determine a maximum subarray of the form A[1..j+1] in constant time based on knowing a maximum subarray ending at index j.



Wednesday, December 7, 2011

Introduction to Algorthms 3rd --P2.3.7

Describe aO(n *lg n)-time algorithm that, given a set S of n integers and another integer x, determines whether or not there exist two elements in S whose sum is exactly x.

This is the usual solution:
---------------------------------------------------------

Input: An array A and a value x.
Output: A boolean value indicating if there is two elements in A whose sum is x.
A ← SORT(A)
n ← length[A]
for i ← to n do
if A[i] 0 and B INARY-SEARCH(A, A[i] − x, 1, n) then
return true
end if
end for
return false
---------------------------------------------------------
My idea is to use merge sort.

x is sum of two numbers. then x/2 must be between those two numbers. in other words, if there are two numbers A and B whose sum is x, then A must be on the left of x and B must be on the right side of x.

The above idea cannot work. Because there is no way to determine how many elements should be chosen from left or right side of x/2.

Tuesday, December 6, 2011

Implementation of "strtok" in "string.h"

Some advice:
Never use this function. This function modifies its first
argument. The identity of the delimiting character is
lost. This function cannot be used on constant strings.
Usually, the following is how "strtok" is used.

char test[]="I Love You";
char *token;

token=strtok(test," ");
while(token!=NULL)
{
    cout<<token<<endl;
    token=strtok(NULL," ");
}

But the confusing part is why the 1st parameter of strtok can be NULL.
From http://www.cplusplus.com/reference/clibrary/cstring/strtok/, it states NULL means continuing to scan the left part of the original string.
If that is the case, how do you store the original string. For example, in while loop, how does the strtok know which string it is handling.

Delimiter-Characters at the beginning and end of str are skipped.

Useful implementation:http://clc-wiki.net/wiki/C_standard_library:string.h:strtok

Implementation of strtok:
http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/string/strtok.c?rev=1.6&content-type=text/x-cvsweb-markup



Explanation: http://bytes.com/topic/c/answers/810975-looking-implementation-strtok

The version above (with the truncated URL) is a rehash of the
implementation I wrote in 1988. Mine did not have a strtok_r()
(which is not even in C99, much less C89), and in any case it
would be better to put strtok_r() in a separate file.

The C99 "restrict" qualifiers are missing, and should be added
if you have a C99-based system (though most people do not).

These days it probably would be better, in some sense, to go ahead
and call strspn() and strcspn(), rather than writing them in-line
as I did. (When I wrote this, subroutine calls were relatively
expensive, and compilers never did any inline expansion, so we had
to do it by hand wherever it was profitable.)

The assignment:

s[-1] = 0;

writes a '\0' at s[-1], of course. If you mean "what does s[-1]
even *mean*", it means: "add -1 to the pointer in s, and then
follow the resulting pointer". Adding an integer to a pointer
moves "forward" by that number of objects, so adding -1 moves
"forward" negative-one "char"s, or in other words, moves backward
by one "char". Earlier we had:

c = *s++;

so s now points one "char" beyond the location that holds the
character stored in "c". Pictorially, suppose we call strtok()
with:

char buf[] = ",hello,/,world";
char *result;

result = strtok(buf, ",/");

When we enter strtok(), we have "s" pointing to &buf[0], which
contains a ',' character. The static variable "last" is initially
NULL, or is left over from a previous call to strtok(), but either
way we are not going to use it, and are soon going to overwrite
it.

The strtok() call then calls strtok_r(), passing s (&buf[0]), delim
(pointing to the ',' in the string ",/"), and &last. The strtok_r()
function begins with (I will update this code for C99 while writing
this; note this changes the name of the third argument to "lastp",
as I would have called the variable if I had written this):

char *strtok_r(char *restrict s, const char *restrict delim, char **lastp) {
const char *restrict spanp;
char c, sc;
char *restrict tok;

if (s == NULL && (s = *lastp) == NULL)
return NULL;

Since s is not NULL, we do not even look at *lastp, much less
return NULL. (However, if we call strtok() again later, passing
NULL for s, we *will* look at *lastp, i.e., strtok()'s "last",
at that point. This is how we will save a "sideways" result
for later strtok() calls. This is not a *good* way to do it;
see the BSD strsep() function for a better method.)

Next, we enter the ugly loop that simply implements strspn():

cont:
c = *s++;
for (spanp = delim; (sc = *spanp++) != '\0';) {
if (c == sc)
goto cont;
}

In this case, "delim" points to ",/" and "c" initially picks up
the ',' from &buf[0], leaving s pointing to &buf[1]. The inner
loop sets spanp to delim, then loops while seting sc (the "span
character") from *spanp++ until sc is '\0'. Because the
loop increments spanp each time, it will look at all the non-'\0'
characters in delim, i.e., ',' and '/' respectively, until
something happens. In this case, the "something" happens
right away: c==',' and sc==',', so c==sc, so we execute the
"goto cont" line and thus start the outer loop over again.

This time, c gets the 'h' from buf[1], and s winds up pointing
to the 'e' in buf[2]. Since c=='h', and the inner loop looks
for ',' and '/', we get all the way through the inner loop
without doing a "goto cont". This leaves c=='h' and exits the
outer loop.

(The outer loop logically should use something other than a
"goto", but more realistically, we could just replace the whole
thing with:

s += strspn(s, delim);
c = *s++;

The strspn() function counts the number of characters that are
in the "span set", up to the first one that is not in it. That
is, since s points to ",hello,/,world" and the span-set is ",/",
strspn() would return 1, and s += 1 would then advance over the
initial comma. If s pointed to ",/,hello", strspn() would
return 3, and s += 3 would advance over all three initial
characters.)

In any case, now that we have skipped leading "non-token"
characters, we are ready to look for tokens:

if (c == '\0') {
*lastp = NULL;
return NULL;
}

If there are no more tokens, we set *lastp to NULL (this is, I
think, allowed but not required by the C standard) and return NULL.
However, c=='h', so we do not do this, but instead plow on to the
trickiest, densest part of the code:

tok = s - 1;
for (;;) {
c = *s++;
spanp = delim;
do {
if ((sc = *spanp++) == c) {
[to be shown and explained in a moment]
}
} while (sc != '\0');
}
/* NOTREACHED */

Remember that s points one character *past* the beginning of
the token -- in this case, to the 'e' in "hello" -- because we
did "c = *s++". So we set tok to s-1, so that tok points to
the 'h' in "hello". We then enter the outer loop, which -- as
the comment notes -- really just implements strcspn().

For each trip through the outer loop, we look at the next character
of the proposed token, via "c = *s++" as before. In this case,
it first sets c to the 'e' in buf[2], leaving s pointing to buf[3]
(the first 'l').

The inner loop then runs through each character in "delim", putting
it in sc each time, checking to see whether c==sc. Since the two
delimiter characters are ',' and '/', and 'e' is neither a comma nor
a slash, this will not find them. But here is one of the tricky
bits: since "delim" is a C string, it ends with a '\0' character.
I want *all* the loops to stop if c=='\0'. Rather than putting
in a special test for c=='\0', I simply allow the inner loop to
test c against the '\0' that ends the delimiter string.

In other words, since delim points to {',', '/', '\0'}, I can let
sc take on all *three* of these "char"s, and compare c==sc each
time. I stop the inner loop only *after* both c!=sc *and* sc=='\0'.
So this allows me to test c=='\0' without writing a separate "if"
statement.

In any case, none of 'e', 'l', 'l', and 'o' are token-delimiters,
so eventually "c = *s++" sets c to ',', leaving s pointing to the
'/' in ",hello,/,world". This time the inner loop *does* find
a token-delimiter, and we get to the code inside the "if":

if (c == '\0')
s = NULL;
else
s[-1] = '\0';
*lastp = s;
return tok;

Here, we check to see if c=='\0' first. A '\0' ends the string --
meaning s points one past the end -- and the end of the string is
necessarily the end of the token. But it also means there cannot
possibly be any additional tokens. So we want to sent *lastp to
NULL, so that a future call to strtok() will return NULL. Setting
s to NULL and *lastp to s will accomplish that. (In this case,
since c==sc, we will also have sc=='\0'. That is, we found both
the end of the delimiter string *and* the end of the token. This
is OK; we do not care which "token-ending character" we found.)

In our case, though, c!='\0', because c==','. So we set s[-1] to
'\0'. Here s points to the '/' in buf[7], so this replaces the
',' in buf[6] with '\0'. (Remember, buf is initially set to
",hello,/,world", so buf[0] is ',', buf[1] is 'h', buf[2] is 'e',
buf[3] is 'l', buf[4] is 'l', buf[5] is 'o', buf[6] is ',', buf[7]
is '/', buf[8] is ',', buf[9] is 'w', and so on.) We leave s==&buf[7],
and set *lastp = s -- so now the variable "last" in strtok()
points to the '/' in buf[7].

Finally, we return "tok", which is &buf[1]. The contents of buf[]
have been modified slightly, and the static variable "last" in
strtok() points just past the first token, so that a later call to
strtok() can find more tokens.

Again, the two nasty loops can be replaced by strspn() -- which
will "span" (or skip over) initial delimiters -- and strcspn(),
which will span the "c"omplement of the delimiter-set, i.e., skip
over initial "non-delimiters". Since everything that is not
a delimiter is a token character, this will give us just what
we want -- and we can rewrite the entire thing as:

char *strtok(char *restrict s, const char *restrict delim) {
static char *last;
char *restrict tok;

/* pick up from previous stopping point, if told to do so */
if (s == NULL && (s = last) == NULL)
return NULL;

/* skip initial delimiters to find start of token */
tok = s + strspn(s, delim);

/* skip over non-delimiters to find end of token */
s = tok + strcspn(tok, delim);

/*
* Save state for next call, and return token. If there
* is no token, both *tok and *s will be '\0'. If there
* is one token that is ended with '\0', *s will be '\0'.
* (If there are trailing delimiters, we will skip them
* later.)
*/
last = *s == '\0' ? NULL : s + 1;
return *tok == '\0' ? NULL : tok;
}

This code is now short enough that we can just use a separate copy
for strtok_r(), if we like; or we can use the BSD-style "strtok is
a wrapper around strtok_r", which just needs the obvious changes
with "lastp".

It is also short enough to demonstrate that strtok() is not a
particularly useful function: you can call strspn() and strcspn()
yourself, and avoid the problems that eventually crop up with the
saved state in the static variable called "last" here.

Monday, December 5, 2011

Notes of Introduction to Algorithms (3rd Edition) --1

"In Place": Algorithm operates on the same inputs without using extra space, or use a constant number of extra space, which implies the inputs are the outputs after the algorithm is completed.

1: Insertion Sort (in place algorithm)
Inputs: an array of n elements: int inputs[n];
Outputs: an array of n elements inputs[n] following ascending order.

Idea: Suppose the first m (<n) elements have been sorted, the (m+1)th element is being sorted. Then insert (m+1)th element into an appropriate place in the first m elements. Therefore, after the insertion, the (m+1) elements are sorted as well.


int Insertion(int inputs[], int size)  
/*if array is passed as parameter, inputs should not have size with it: inputs[]; inputs[size] is not correct.*/
{
     for(int i=1;i<size;++i)
     {
          for(int j=0;j<i;++j)
          {
               if(inputs[i] < inputs[j])
               {
                  exchange(inputs[i],inputs[j]);
                  break;
               }
           }
      }
}

The internal loop can also be scanning from right to left:
          for(int j=i-1;j>-1;--j)
          {
               if(inputs[i] > inputs[j])
               {
                  exchange(inputs[i],inputs[j]);
                  break;
               }

           }

Complexity: O(n^2)