Art of Programming contest chapters:1-4
Table of Contents
- 1. 学习算法注意点
- 2. 一些规则
- 3. C字符串处理函数(部分)
- 4. 基础数据结构
Mathematics
- Prime Number
- Big Integer
- Permutation
- Number Theory
- Factorial
- Fibonacci
- Sequences
- Modulus
Dynamic Programming
- Longest Common Subsequence
- Longest Increasing Subsequence
- Edit Distance
- 0/1 Knapsack
- Coin Change
- Matrix Chain Multiplication
- Max Interval Sum
Graph
- Traversal
- Flood Fill
- Floyed Warshal
- MST
- Max Bipertite Matching
- Network Flow
- Aritculation Point
Sorting
- Bubble Sort
- Quick Sort
- Merge Sort (DAndC)
- Selection Sort
- Radix Sort
- Bucket Sort
Searching
- Complete Search, Brute Force
- Binary Search (DAndC)
- BST
Simulation
- Josephus
String Processing
- String Matching
- Pattern Matching
Computational Geometry
- Convex Hull
AdHoc
- Trivial Problems
1 学习算法注意点
- Proof of algorithm correctness (especially for Greedy algorithms)
- Time/Space complexity analysis for non recursive algorithms.
- For recursive algorithms, the knowledge of computing recurrence relations and analyze them: iterative method, substitution method, recursion tree method and finally, Master Theorem
- Analysis of randomized algorithm which involves probabilistic knowledge, e.g: Random variable, Expectation, etc.
- Amortized analysis.
- Output-sensitive analysis, to analyze algorithm which depends on output size, example: O(n log k) LIS algorithm, which depends on k, which is output size not input size.
2 一些规则
- Biggest built in data structure "long long" is 263-1: 9*1018 (up to 18digits)
- If you have k nested loops running about n iterations each, the program has O(n*k)
complexity
- If your program is recursive with b recursive calls per level and has l levels, the
program O(b*l) complexity
- Bear in mind that there are n! permutations and 2n subsets or combinations of n
elements when dealing with those kinds of algorithms
- The best times for sorting n elements are O(n log n)
- DP algorithms which involves filling in a matrix usually in O(n3)
- In contest, most of the time O(n log n) algorithms will be sufficient.
3 C字符串处理函数(部分)
- strdup()The library function strdup() is similar to strcpy(), except that strdup()performs its own memory allocation for the destination string with a call tomalloc().
Using strdup() to copy a string with automatic memory allocation.
The prototype for strdup() is
char *strdup( char *source );
/* The strdup() function. */ #include <stdlib.h> #include <stdio.h> #include <string.h> char source[] = "The source string."; main() { char *dest; if ( (dest = strdup(source)) == NULL) { fprintf(stderr, "Error allocating memory."); exit(1); } printf("The destination = %s\n", dest); return(0); } The destination = The source string.
- strchr()The strchr() function finds the first occurrence of a specified character ina string.
The prototype is
char *strchr(char *str, int ch);strchr函数从左到右寻找字符ch,直到找到ch或者"\0",如果ch找到就返回指向ch的指针,如果找不到,就返回NULL
/* Searching for a single character with strchr(). */ #include <stdio.h> #include <string.h> main() { char *loc, buf[80]; int ch; /* Input the string and the character. */ printf("Enter the string to be searched: "); gets(buf); printf("Enter the character to search for: "); ch = getchar(); /* Perform the search. */ loc = strchr(buf, ch); if ( loc == NULL ) printf("The character %c was not found.", ch); else printf("The character %c was found at position %d.\n", ch, loc-buf); return(0); } Enter the string to be searched: How now Brown Cow? Enter the character to search for: C The character C was found at position 14.
- strcspn()The library function strcspn() searches one string for the first occurrenceof any of the characters in a second string.原型如下:
sizet strcspn(char *str1, char *str2);
这个函数从str1寻找str2中任意一个字符第一次出现的位置,如果找到了,就返回str1的偏移量,如果没找到,就返回str1字符创的长度。
看例子:
/* Searching with strcspn(). */ #include <stdio.h> #include <string.h> main() { char buf1[80], buf2[80]; size_t loc; /* Input the strings. */ printf("Enter the string to be searched: "); gets(buf1); printf("Enter the string containing target characters: "); gets(buf2); /* Perform the search. */ loc = strcspn(buf1, buf2); if ( loc == strlen(buf1) ) printf("No match was found."); else printf("The first match was found at position %d.\n", loc); return(0); } Enter the string to be searched: How now Brown Cow? Enter the string containing target characters: Cat The first match was found at position 14.
- strstr()This function searches for the first occurrence of one string withinanother, and it searches for the entire string, not for individualcharacters within the string.原型如下:char *strstr(char *str1, char *str2);这应该是最有用的了,如果在str1里头找到str2,返回指针,若没找到,返回NULL,如果str2的长度为0,那么返回str1。
例子如下:
/* Searching with strstr(). */ #include <stdio.h> #include <string.h> main() { char *loc, buf1[80], buf2[80]; /* Input the strings. */ printf("Enter the string to be searched: "); gets(buf1); printf("Enter the target string: "); gets(buf2); /* Perform the search. */ loc = strstr(buf1, buf2); if(loc== NULL) printf("No match was found.\n"); else printf("%s was found at position %d.\n", buf2, loc-buf1); return(0);} Enter the string to be searched: How now brown cow? Enter the target string: cow Cow was found at position 14.
- atoi() atol() atof()原型如下:int atoi(char *ptr);long atol(char *ptr);double atof(char *str);
String value Returned by atoi() "157" 157 "-1.6" -1 "+50x" 50 "twelve" 0 "x506" 0 atol和atoi类似,只是返回longatof如下
String Value Returned by atof() "12" 12.000000 "-0.123" -0.123000 "123E+3" 123000.000000 "123.1e-5" 0.001231
4 基础数据结构
一共有五种基础数据结构:数组,链表,栈,队列和双向队列。
- 数组
数组是最有用的数据结构,事实上,这种数据结构也是在竞赛中最常使用的。先看看优点:如果下表已知,搜索元素非常快,O(1)的复杂度,非常适合循环/迭代.除此之外,数组常常被用来实现其他的数据结构,比如栈,队列,哈希表。然而,最简单的数据结构并不意味着高效,在有些时候,数组也并不高效。并且,在标准数组中,它的大小事给定的。如果你实现不知道输入的大小,更好的作法应该是使用vector(一个可变大小的数组)。数组的插入操作很慢,在未排序的数组中搜索数据也很慢,删除操作要移动几乎所有的元素。
- 可变大小的数组 vector
#include <stdio.h> #include <vector> #include <algorithm> using namespace std; void main() { // just do this, write vector<the type you want, // in this case, integer> and the vector name vector<int> v; // try inserting 7 different integers, not ordered v.push_back(3); v.push_back(1); v.push_back(2); v.push_back(7); v.push_back(6); v.push_back(5); v.push_back(4); // to access the element, you need an iterator... vector<int>::iterator i; printf("Unsorted version\n"); // start with 'begin', end with 'end', advance with i++ for (i = v.begin(); i!= v.end(); i++) printf("%d ",*i); // iterator's pointer hold the value printf("\n"); sort(v.begin(),v.end()); // default sort, ascending printf("Sorted version\n"); for (i = v.begin(); i!= v.end(); i++) printf("%d ",*i); // iterator's pointer hold the value printf("\n"); }
- 链表为了解决数组插入删除不高效的问题,引出了链表,除此之外数组不能变大小(vector变大小也比较慢)。链表的插入删除非常快,但是链表的副作用是,当一个节点被删除的时候,会浪费内存,之所以会这样是因为被删除的节点只是被标记为"已删除",这些被浪费的内存只有被垃圾回收期清理了才能使用(取决于编译器/操作系统)。链表通常由数据和指针组成,查找数据得从头往后挨个找。STL中的链表:
#include<stdio.h> #include<list> using namespace std; list<int>l; list<int>::iterator i; void print(){ for(i=l.begin();i!=l.end();i++) printf("%d ",*i); printf("\n"); } void main() { l.push_back(3);l.push_back(1); l.push_back(2); l.push_back(7); l.push_back(6); l.push_back(5); l.push_back(4); l.push_back(7); print(); l.sort(); print(); l.remove(3); print(); l.unique(); //删除重复的元素 print(); i=l.begin(); i++; l.insert(i,1,10);//插入1个'10' print(); }
- 栈一个只允许在顶部插入和删除的数据结构,这种行为叫后进先出。重要的栈操作:
- push(C++ STL:push())
给栈顶部添加新元素
- pop(C++ STL:pop())
得到并移除栈顶部元素
- peek(C++ STL:top())
得到栈顶元素,但不删除
- IsEmpty(C++ STL:empty())
测试栈是否为空
栈的一些应用场合:
- 计算机世界中真实的栈:递归,调用过程等等
- 测试回文(虽然使用队列和栈检查回文是很笨的方法)
- 翻转输入数据(也是一个笨的方法)
- 测试括号匹配
- 后缀计算
- 转换数学表达式:前缀,中缀或是后缀
STL实现的STACK
#include<iostream> #include<stack> using namespace std; void main() { stack<int>s; s.push(3); s.push(1); s.push(2); s.push(7); s.push(6); s.push(5); s.push(4); while (!s.empty()) { printf("%d ",s.top()); s.pop(); } printf("\n");} }
- push(C++ STL:push())
- 队列一个只允许从后插入数据,从前删除数据的数据结构,这种行为叫做先进先出,和真实世界的队列一样。重要的队列操作:
- enqueue(C++ STL:push())
给队列末尾添加新元素
- dequeue(C++ STL:pop())
得到并移除队列顶部元素
- peek(C++ STL:top())
得到队列顶部元素,但不删除
- IsEmpty(C++ STL:empty())
测试队列是否为空
#include<iostream> #include<queue> using namespace std; void main(){ queue<int>q; q.push(3); q.push(1); q.push(2); q.push(7); q.push(6); q.push(5); q.push(4); while(!q.empty()){ printf("%d ",q.front()); q.pop(); } printf("\n"); }
- enqueue(C++ STL:push())
- 可变大小的数组 vector