2008年7月8日
#
Source Code
The key point is that we should generate the palindromes instead of enumerating all the numbers and checking if each one of them is palindrome. Since the number<=10^8, we only need to generate 10^4 palindromes. This is a great performance boost comparing to 10^8.
Lession Learned:
1. To generate palindrome, there is no need to enumerate range for each digit. We may just try [0, 9999]. I never think of this.
2. We should balance between performance and code complexity. For example, generating palindromes can boost performance a lot. However, I also tried to filter numbers<a or >b as special cases, but this performance care increases my code compexity a lot. I may just checking this after completing the numbers.
3. It seems that I am the only one use the DFS for this problem because I hate hard-coding.
4. During enumerating through an array, always use sizeof(arr)/sizeof(item_size) as upper limit. This will save you a lot of time during refactoring.
5. How to implement the "atoi":
int atoi(char str[], int len)
{
assert(arr!=NULL);
assert(len>0);
int number=0;
for(int j=0;j<len;j++)
{
number*=10;
number+=(str[j]-'0');
}
return number;
}
2008年7月6日
#
Source Code
This problem requires us to search all the possible paths. For every level i, the i+1 level has searching choices: f(i+1)=2*f(i). So, for R rows, the final level paths are O(2^R). This calculation paths number is not acceptable for computer since R can be 1000. We need some way to reduce the paths.
Then, we see the insight. We find that for level i, there should be i paths for decisions. For item (i, j), we can filter other paths to it and just keep one current max sum path. This is just the dynamic programming. We have paths 1+2+3...+R = O(R^2) paths, which is acceptable for calculation now.
Lesson Learned:
1. The difference between dynamic programming and brute-force searching is that there may be some redundant states during the searching. That is, the searching tree has many nodes that are the same node coming from other parent nodes. So, the tree nodes numbers are not that large if we filter the redundant nodes. So, we can dynamically judge in the middle state to filter a lot of search paths. This will greatly improve the searching boundaries.
2. Set code copying operation as an alarm.
3. While looping through a 2-d array, we'd better use indexing varialbe names "row", "item" instead of "i", "j" for readability reason.
4. Always assert the index range before using the index to access array items.
2008年7月3日
#
Source Code
Lesson Learned:
1. Just as the sorting, searching algorithms, the sequence search(O(N)) < binary search(O(logN)) < bitmap algorithm(O(1)).
2. To boost performance a program, the most possible bottleneck is the nested loops. For deep nested loops, the time is: d1*d2*d3...(di stands for the loop count of level i). So, we should optimize at different levels to boost the whole nested loops performance.
For example, we first caculate the MaxB(using fomular a+(N-1)*b <=p^2+q^2 ) for variable "b" in level1; then, we pre-calculate the possible value array for variable "a" in level2("a" must be in the square array set. Note: this greatly cuts level2 loop count). Then, we check if the a+(N-1)*b exceeds the max square value to filter even more level2 values(This at least cuts the level2 loop by half). Finally, in the level3, we use the bitmap search for optimization.
2008年6月29日
#
Source Code
Lesson Learned:
1. The pseudocode programming is the most important part. Once this part is done correctly, coding is trivial.
2. For the multiply and add math operations, if the oprands are not too large, it is more convenient and efficient to store them in a single integer instead of in an array. However, if they exceed the int value range(which is called large intergers), using an array is necessary.
3.
Simple Algorithm Pattern: Moving an array backward one position should start from the last item instead of the first item.
4.
Simple Algorithm Pattern(Big integer array add operation):
int advanceVal=0;
for(int i=0;i<len;i++)
{
int addVal = b1[i]+b2[i]+advanceVal;
c[i] = addVal%10;
advanceVal = addVal/10;
}
c[len]=advanceVal;
2008年6月28日
#
Source code
Lession Learned: This is the first non-trivial Gready Algorithm I wrote. It costs a bit of time for me to get it right. For non-trivial algorithm, the pseudocode design&check is really the crucial part.
1. In the complex loop&algorithm, it is helpful to use "Assert" to assist debugging.
2. In the complex algorithm, always verify if the logic is correct after writting one code statement. The logic must keep clear!
3. Don't make quick assumption, for example, "If the input data is sorted...". This is the second time I made wrong assumption.

4. Check the edge condition again. Do remember to spend some time to check the input data's edge condition. It worths the time!
Source Code
Lesson Learned:
This program algorithm is simple. However, I still meet one problem: edge condition(N, M both are zero). After writting the pseudocode, I should always check algorithm for the edge conditions of the input parameters. This is just a small effect, but helps to eliminate high risk bugs!
2008年6月22日
#
2008年6月21日
#
2008年6月14日
#