格式问题
精确到xx位
> #include< iomanip >
> cout << fixed << setprecision(1) << 6.000;
: 按前置0的形式读取和输出数字:比如读取 0005, 和将5输出为0005
> #include
> int a;
> cin >> a; //enter 05;
> cout << setfill('0') << setw(4) << a;
ACMer的常用宏
常用操作
> #define rep(i,j,k) for (int i=j ; i<=k ; i++)
> #define per(i,j,k) for (int i=j ; i>=k ; i--)
> #define mp(i,j) make_pair(i,j)
> #define pb push_back
> #define ff first
> #define ss second
> typedef long long LL;
样例测试方法
使用fstream的方法:先把测试用例复制进txt中,然后代码中将txt路径和txt名载入到文件输入流中,把这个“流”对象当输入用
freopen("C:\\Users\\chenzhuo\\Desktop\\in.txt","r",stdin);
一. 树
1)求二叉树的高度(Maximum Depth of Binary Tree)
// LeetCode, Maximum Depth of Binary Tree
// 时间复杂度O(n),空间复杂度O(logn)
class Solution {
public:
int maxDepth(TreeNode *root) {
if (root == nullptr) return 0;
return max(maxDepth(root->left), maxDepth(root->right)) + 1;
}
};
2)判断二叉树是否对称(Symmetric Tree)
// LeetCode, Symmetric Tree
// 递归版,时间复杂度O(n),空间复杂度O(logn)
class Solution {
public:
bool isSymmetric(TreeNode *root) {
return root ? isSymmetric(root->left, root->right) : true;
}
bool isSymmetric(TreeNode *left, TreeNode *right) {
if (!left && !right) return true; // 终止条件
if (!left || !right) return false; // 终止条件
return left->val == right->val // 三方合并
&& isSymmetric(left->left, right->right)
&& isSymmetric(left->right, right->left);
}
};
3)二叉树-> 链表(Flatten Binary Tree to Linked List)
// LeetCode, Flatten Binary Tree to Linked List
// 递归版2
// @author 王顺达(http://weibo.com/u/1234984145)
// 时间复杂度O(n),空间复杂度O(logn)
class Solution {
public:
void flatten(TreeNode *root) {
flatten(root, NULL);
}
private:
// 把root 所代表树变成链表后,tail 跟在该链表后面
TreeNode *flatten(TreeNode *root, TreeNode *tail) {
if (NULL == root) return tail;
root->right = flatten(root->left, flatten(root->right, tail));
root->left = NULL;
return root;
}
};
二. 字符串
1)最长无重复字符子串(Longest Substring Without Repeating Characters)
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int ans = 0;
int dic[256];
memset(dic,-1,sizeof(dic));
int len = s.size();
int idx = -1;
for (int i=0;iidx)
idx = dic[c];
ans = max(ans,i-idx);
dic[c] = i;
}
return ans;
}
};
三. 数组
1)数组中所有数字出现两次,只有一个出现一次,求出它(Single Number)
// LeetCode, Single Number
// 时间复杂度O(n),空间复杂度O(1)
class Solution {
public:
int singleNumber(int A[], int n) {
int x = 0;
for (size_t i = 0; i < n; ++i)
x ^= A[i];
return x;
}
};
2)顺时针旋转二维数组90度(Rotate Image)
// LeetCode, Rotate Image
// 思路1,时间复杂度O(n^2),空间复杂度O(1)
class Solution {
public:
void rotate(vector>& matrix) {
const int n = matrix.size();
for (int i = 0; i < n; ++i) // 沿着副对角线反转
for (int j = 0; j < n - i; ++j)
swap(matrix[i][j], matrix[n - 1 - j][n - 1 - i]);
for (int i = 0; i < n / 2; ++i) // 沿着水平中线反转
for (int j = 0; j < n; ++j)
swap(matrix[i][j], matrix[n - 1 - i][j]);
}
};
3)排序数组去重(Remove Duplicates from Sorted Array)
// LeetCode, Remove Duplicates from Sorted Array
// 时间复杂度O(n),空间复杂度O(1)
class Solution {
public:
int removeDuplicates(int A[], int n) {
if (n == 0) return 0;
int index = 0;
for (int i = 1; i < n; i++) {
if (A[index] != A[i])
A[++index] = A[i];
}
return index + 1;
}
};
4)两个排序数组,求中位数(Median of Two Sorted Arrays)
// LeetCode, Median of Two Sorted Arrays
// 时间复杂度O(log(m+n)),空间复杂度O(log(m+n))
class Solution {
public:
double findMedianSortedArrays(int A[], int m, int B[], int n) {
int total = m + n;
if (total & 0x1)
return find_kth(A, m, B, n, total / 2 + 1);
else
return (find_kth(A, m, B, n, total / 2)
+ find_kth(A, m, B, n, total / 2 + 1)) / 2.0;
}
private:
static int find_kth(int A[], int m, int B[], int n, int k) {
//always assume that m is equal or smaller than n
if (m > n) return find_kth(B, n, A, m, k);
if (m == 0) return B[k - 1];
if (k == 1) return min(A[0], B[0]);
//divide k into two parts
int ia = min(k / 2, m), ib = k - ia;
if (A[ia - 1] < B[ib - 1])
return find_kth(A + ia, m - ia, B, n, k - ia);
else if (A[ia - 1] > B[ib - 1])
return find_kth(A, m, B + ib, n - ib, k - ib);
else
return A[ia - 1];
}
};
1.http://blog.csdn.net/hacker00011000/article/details/51298294
2.http://blog.csdn.net/nk_test/article/details/48912763
1.binary_search() 确定容器中是否存在某个元素
2.equal() 确定两个集合中的所有元素皆相同。
3.lower_bound() 从头到尾,查找第一个大于或者等于所列元素的值的位置
用法,参考下面的min_element();
4.upper_bound() 从头到尾,查找第一个大于所列元素的值的位置
5.make_heap( ) 创建一个堆并以序列的形式输出
6.max() 返回两个元素间的较大者
7.max_element() 返回序列中的最大值
8.min() 返回两个元素中的较小者
9.min_element() 返回序列中的最小值
int a[]={1,4,66,43,2,56,443,23,234,4};
int b= min_element(a,a+7)-a;
int c= max_element(a,a+7)-a;
如果想取值的话,直接加*
: *max_element(a,a+n)
10.mismatch() 查找两个序列中的第一个不相同的位置
11.pop_heap() 从一个堆中移除一个最大的元素
12.push_heap() 添加一个元素至堆
13.reverse() 将给定序列反转顺序,范围。
14.sort() 将序列升序排序
15.sort_heap() 将堆转变为有序序列
16.swap() 交换两个对象的值
17.unique() 移除连续的重复元素
注意连续两个字,也就是说明了要先进性排序操作
为什么呢?
因为unique函数并没有把重复的元素删掉,他只是把那些重复的元素移动
到了本序列的末尾,
返回值是不重复序列的位置指针。
所以如何显示不重复序列呢?
1.一种方法是直接将不重复序列指针 it 到 vector.end()
对此阶段进行 删除
用erase()函数
erase(it,vector.end());
2.直接将vector.begin 到不重复序列尾的 位置指针 it 将元素输出来
即,
vector::iterator it=a.begin();
while(it!= unique(a.begin(),a.end()))
{
cout<<*it<<" ";
it++;
}
VECTOR_STRING::iterator iNameTor;
iNameTor = unique(vecNames.begin(), vecNames.end());
cout << "after unique(), contents are:" << endl;
printVec(vecNames);
cout << "unique return a iterator, point to the first Duplicate element " << endl;
cout << iNameTor - vecNames.begin() << endl << endl;
vecNames.erase(iNameTor, vecNames.end()); //删除重复元素
cout << "after erase(), contents are:" << endl;
#include
#include
#include
using namespace std;
int main()
{
string line;
while(getline(cin,line))
{
int sum=0,x;
stringstream ss(line);
while(ss>>x)
{
sum+=x;
}
cout<
strlwr()将字符串变小写
strupr()将字符串变大写
strcmp()两个参数只能是c字符串,不能是string类型,也可以用s.data()
// count algorithm example
#include
#include
#include
using namespace std;
int main () {
int mycount;
// counting elements in array:
int myints[] = {10,20,30,30,20,10,10,20}; // 8 elements
mycount = (int) count (myints, myints+8, 10);
cout << "10 appears " << mycount << " times.\n";
// counting elements in container:
vector myvector (myints, myints+8);
mycount = (int) count (myvector.begin(), myvector.end(), 20);
cout << "20 appears " << mycount << " times.\n";
return 0;
}
find()函数的一个例子:
InputIterator find ( InputIterator first, InputIterator last, const T& value );
// find example
#include
#include
#include
using namespace std;
int main () {
int myints[] = { 10, 20, 30 ,40 };
int * p;
// pointer to array element:
p = find(myints,myints+4,30);
++p;
cout << "The element following 30 is " << *p << endl;
vector myvector (myints,myints+4);
vector::iterator it;
// iterator to vector element:
it = find (myvector.begin(), myvector.end(), 30);
++it;
cout << "The element following 30 is " << *it << endl;
return 0;
}
find_first_of()的例子
// find_first_of example
#include
#include
#include
#include
using namespace std;
bool comp_case_insensitive (char c1, char c2) {
return (tolower(c1)==tolower(c2));
}
int main () {
int mychars[] = {'a','b','c','A','B','C'};
vector myvector (mychars,mychars+6);
vector::iterator it;
int match[] = {'A','B','C'};
// using default comparison:
it = find_first_of (myvector.begin(), myvector.end(), match, match+3);
if (it!=myvector.end())
cout << "first match is: " << *it << endl;
// using predicate comparison:
it = find_first_of (myvector.begin(), myvector.end(),
match, match+3, comp_case_insensitive);
if (it!=myvector.end())
cout << "first match is: " << *it << endl;
return 0;
}
reverse()实现逆转
reverse_copy()实现逆转,不改变原来的字符串
sort()
unique()
erase()
repalce()
replacse_copy()
不改变原来的字符串或者是容器的内容
strlwr()将字符串变小写
strupr()将字符串变大写
strcmp()两个参数只能是c字符串,不能是string类型,也可以用s.data()
template const T& max ( const T& a, const T& b );
template
const T& max ( const T& a, const T& b, Compare comp );
find_if()函数的例子:
// find_if example
#include
#include
#include
using namespace std;
bool IsOdd (int i)
{
return ((i%2)==1);
}
int main () {
vector myvector;
vector::iterator it;
myvector.push_back(10);
myvector.push_back(25);
myvector.push_back(40);
myvector.push_back(55);
it = find_if (myvector.begin(), myvector.end(), IsOdd);
cout << "The first odd value is " << *it << endl;
return 0;
}
map容器的操作:
begin()返回指向第一个元素的迭代器
end()返回指向最后一个元素的迭代器
rbegin()返回指向最后一个元素的迭代器
rend()返回指向第一个元素的迭代器
empty()测试map容器是不是空的
size()返回容器的大小
max_size()返回容器最大的容量,这个是相对于内存来讲的
insert()向容器中插入元素
erase(it)删除容器当中it指向的元素,it为迭代器
erase('c')删除容器中键值为'c'的元素
eras(it, mymap.end())删除容器中it和mymap.end()之间的元素,它们两个都是迭代器
foo.swap(bar)交换容器foo和bar中的元素
clear()清空容器
find('b')返回指向键值为'b'的的迭代器,没有的话就指向end()
count('c')查找键值为'c'的元素,在map中返回0或者1,0表示没有这个键值,1表示有,但是在mutimap中就是这个键值出现的次数
lower_bound('b')返回指向键值为'b'的迭代器,当没有这个键值时就返回空的迭代器
upper_bound('b')返回指向键值为'b'的下一个元素的迭代器,没有的话就返回空的迭代器
vector容器的操作:
begin()返回指向第一个元素的迭代器
end()返回指向最后一个元素的迭代器
rbegin()返回指向最后一个元素的迭代器
rend()返回指向第一个元素的迭代器
size()返回容器的元素的个数
max_size()返回容器的最大的元素的个数
resize()重新调整容器的容量,无论原来的容量是大于还是小于后来的恶容量都可以
myvector.resize(5);将容器的容量调整为5,如果变短了就直接删除多余的元素,长了就用0将剩余的空间填满
myvector.resize(8,100);将容器的容量调整8,并将多出来的位置用100表示
myvector.resize(12);将容器的容量调整为12,多出的空间用0填充
capacity()返回这个容器在内存空间中最多的连续空间
empty()测试这个容器是不是空的
reserve()重新调整容器的capacity
at(i)返回位置为i处得元素的引用,当超出容器的最后一个位置就抛出一个异常
front()返回第一个元素的引用
back()返回最后一个元素的引用
void assign ( InputIterator first, InputIterator last );将迭代器first和迭代器last之间的元素付给调用这个方法的容器
void assign ( size_type n, const T& u );将n个u付给容器
push_back()在容器的末尾添加元素
pop_back()删除容器最后面的一个元素
iterator insert ( iterator position, const T& x );在迭代器position的前面插入元素x
void insert ( iterator position, size_type n, const T& x );在position的前面插入n个x
template
void insert ( iterator position, InputIterator first, InputIterator last );将迭代器first和last之间的元素插入到position前面
iterator erase ( iterator position );删除迭代器position指向的元素
iterator erase ( iterator first, iterator last );删除迭代器first和last之间的元素,不包括last指向的元素
void swap ( vector& vec );交换两个容器的元素
void clear ( );清空容器当中的元素
set容器(只存储值不相同的元素,并且按照从小到大的顺序排列)
iterator begin ();返回指向set容器第一个元素的迭代器
iterator end ();返回指向容器最后一个元素的迭代器
reverse_iterator rbegin();返回指向容器最后一个元素的迭代器
reverse_iterator rend();返回指向容器第一个元素的迭代器
bool empty ( ) const;测试容器是否为空
size_type size() const;计算容器当中元素的个数
size_type max_size () const;计算容器的最大容量
pair insert ( const value_type& x );将元素x插入到set容器中返回pair对象,first元素为指向插入的元素的迭代器,second元素为指示插入成功与否的bool值
iterator insert ( iterator position, const value_type& x );将x插入
template
void insert ( InputIterator first, InputIterator last );将first与last只见到恶元素插入到容器中
void erase ( iterator position );删除position位置处得元素
size_type erase ( const key_type& x );删除值为x的元素
void erase ( iterator first, iterator last );删除迭代器first和last之间的元素
void swap ( set& st );交换两个set容器的元素
void clear ( );清空set容器
容器迭代器的操作
stack栈的操作:
bool empty ( ) const;测试栈是不是空的返回1表示空0表示非空
size_type size ( ) const;返回当前栈的元素的个数
value_type top ( );返回当前的栈顶元素,不删除这个元素
const value_type top ( ) const;返回栈顶元素的const引用
void push ( const T& x );将当前的元素x入栈
void pop ( );删除栈顶元素
queue队列的操作:
bool empty ( ) const;测试当前队列是不是空,0表示空,1表示非空
size_type size ( ) const;队列的元素的个数
value_type& front ( );返回队首元素的引用
const value_type front ( ) const;返回队首元素的const值
value_type& back ( );返回队尾元素的引用
const value_type& back ( ) const;返回队尾元素的const值
void push ( const T& x );将x入队列
void pop ( );删除队首元素
string类型的应用
string.c_str() 返回的是const char*而非char *,如果想返回char *的话可以这样写:char * a = (char*)string.c_str();
strtok()函数很好用,分割字符串
还有一个大优势,就是容器之间可以直接赋值。
或许还有其他的操作符被重载了,这个看具体情况。
set:
就是数学意义上的集合——每个元素最多只出现一次。
字符大小写转换函数:
tolower(char c)函数,tolower()函数的参数是字符类型。
toupper(char c)函数,toupper()函数的参数也是字符类型。
字符串大小写转换:
c中,包含ctype.h头文件
strlwr()将字符串变小写
strupr()将字符串变大写
strcmp()两个参数只能是c字符串,不能是string类型,也可以用s.data()
c++,中,tolower()、toupper()配合transform()函数
编程:
1.下面的编程 是改变发生在原字符串S上。
#include
#include
#include
#include
using namespace std;
int main()
{
string s="Hello worLD";
transform(s.begin(),s.end(),s.begin(),::toupper);
cout<
迪杰斯特拉 算法:
针对常见问题、疑惑给出的结论:
若路径是按照递增(非递减)的
顺序生成的,则:
1.真正的最短路必须只经过S中的顶点
2.每次从未收录的顶点中选一个dist值最小的收录(贪心)
3.增加一个v进入S,可能影响另外一个w的dist值。
而且针对第3点,还有一个重要的说明就是v如果能够改变w
也有一个必要条件,就是v和w一定是邻接点。
这样编程就好编了。
dist[w] = min{dist[w],dist[v]+的权重}。
数据输入范围:
int 记住绝对值在10^9 范围以内的整数都可以定义为 int 。
long long 记住 在10^10 ~10^18 范围以内的整数都可以定义为 long long 。
long long bignum = 123456789012345LL;
需要 加 LL 。
见 《算法笔记》 P8.、
如果数组大小较大,大概10^6 级别,则需要将其定义在主函数的外面,
否则会使程序异常退出。
**不使用 float ,都使用 double .**
**无穷大INF的定义:**
const int INF = (1<<30)-1;
const int INF = 0x3fffffff;
**常用数学函数:**
fabs(double x)
:对double类型变量取绝对值。
floor(double x)
: 对double 类型变量向下取整
ceil(double x)
: 对double 类型变量向上取整
pow(double x,double y)
: 求 x^y
sqrt(double x)
: 对double 类型变量求算术平方根。
log(double x)
: 对double 类型变量求以自然对数为底的对数。
round(double x)
: 对double 类型变量x进行四舍五入。
**对冒泡排序的简单思考:**
从数组 前到后 遍历,交换 -》》》沉底算法;
从数组 后到前 遍历,交换 -》》》冒泡算法。
memset():
--对数组中的每一个元素赋一个相同的值。
包含头文件 #include
注意:
**对于初学者,只建议使用memset赋 0 或 -1;
如果要对数组赋其他数字,比如1,使用 fill()函数。
这里已经试过了,的确赋其他值,比如 34 的时候,出错了。
这里一定要注意一下。**
**判断字符是字母,数字,还是字母数字,以及大写,小写:**
2.cctype中还有其他函数,如:
isdigit() 用来判断一个字符是否是数字。
isalnum() 用来判断一个字符是否为英文字母或数字,相当于 isalpha(c) || isdigit(c)
isalpha() 用来判断一个字符是否是英文字母,相当于 isupper(c)||islower(c)
**构造函数有什么用呢?**
初始化,就记住初始化就可以了。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
struct Point{
int x;
Point(){
}
};
int main()
{
Point a;
return 0;
}
**永远保持有一个默认的空的构造函数,这样我们在声明一个
自定义类型变量的时候,就可以不必初始化**。详见 算法笔记》P73.
sscanf()和sprintf()
:流输入输出函数,这个东西很有用,尤其是sscanf,可以实现一次性的多个分割:
比如:
将字符数组str中的内容按 "%d:%lf,%s"的格式
写到int型变量n、double型变量db、char型数组变量str2中。
sscanf(str,"%d:%lf,%s",&n,&db,&str2);
相对应的反操作:
sprintf(str,"%d:%lf,%s",n,db,str2);
补充内容:
1.cin、cout P74
2.浮点数的比较 P75
const double eps=1e-8;
#define Equ(a,b) ( (fabs( (a)-(b) )) <(eps) )
3.圆周率
const double PI=acos(-1.0);
4.复杂度 P78
**刚才在做题过程中调试发现问题,结果是因为pow()函数。**
首先你应该知道,需要使用 pow 函数,
你需要加上 #include,虽然这个不是问题所在,
但是是一个好习惯。在 math.h 中,或者查阅相关 C 语言的手册,
你会发现,pow 函数的原型是 double pow( double, double ),
查函数的原型也是一个好习惯;所以你知道了,传入 pow 函数的应该是一个浮点数。
**在极个别奇葩编译器中,因为浮点数的表示问题,
10 会被表示为 9.99999999999,所以 10 的 4 次方就是 9999.9999……,
double 转成 int 的时候截断,所以剩下了 9999。不过,**
据说这个极个别的情况只在一些低版本的 mingw 中才存在,
详细问题可以看算法笔记 P87 对应codeup的 6170 部分A+B
**其他进制转换为 10 进制,用while()循环;
10 进制转换为 其他k进制,就是除k取余法,用do {}while;**
巧妙地利用EOF , 算法笔记 P97
PAT B 的经典说反话 。
1.选择排序:
每次从未排序的序列中选择最小的数,然后将其与未排序的序列第一个元素交换,
并与之前已经排好序的序列,自动形成有序序列。
贴到已排序的序列屁股后面。
2.归并排序:
过程就是从2人小组/1人小组,N/2个小组,到四人小组,N/4个小组,一直到N人小组,1个小组。
归并就是把两个有序的序列合并为一个有序的序列的过程。
总之算是分治与归并的结合就是归并排序,可以看下面的代码: