【1】格式
格式問題
精確到xx位
> #include< iomanip >
> cout << fixed << setprecision(1) << 6.000;
: 按前置0的形式讀取和輸出數字:比如讀取 0005, 和將5輸出爲0005
> #include<iomanip>
> 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);
【2】別人家的代碼
一. 樹
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;i<len;i++)
{
char c = s[i];
if (dic[c]>idx)
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<vector<int>>& 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
algorithm中常用的現成算法:
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<int>::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;
18. 輸入:多行數據:每行數據之間空格間隔,
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
string line;
while(getline(cin,line))
{
int sum=0,x;
stringstream ss(line);
while(ss>>x)
{
sum+=x;
}
cout<<sum<<endl;
}
return 0;
}
19.
strlwr()將字符串變小寫
strupr()將字符串變大寫
strcmp()兩個參數只能是c字符串,不能是string類型,也可以用s.data()
20. C++容器類常用泛型函數總結
// count algorithm example
#include <iostream>
#include <algorithm>
#include <vector>
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<int> 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 <iostream>
#include <algorithm>
#include <vector>
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<int> myvector (myints,myints+4);
vector<int>::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 <iostream>
#include <algorithm>
#include <cctype>
#include <vector>
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<char> myvector (mychars,mychars+6);
vector<char>::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 <class T> const T& max ( const T& a, const T& b );
template <class T, class Compare>
const T& max ( const T& a, const T& b, Compare comp );
find_if()函數的例子:
// find_if example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
bool IsOdd (int i)
{
return ((i%2)==1);
}
int main () {
vector<int> myvector;
vector<int>::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 <class InputIterator>
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<T,Allocator>& 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<iterator,bool> insert ( const value_type& x );將元素x插入到set容器中返回pair對象,first元素爲指向插入的元素的迭代器,second元素爲指示插入成功與否的bool值
iterator insert ( iterator position, const value_type& x );將x插入
template <class InputIterator>
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<Key,Compare,Allocator>& 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 <iostream>
#include <string>
#include <algorithm>
#include <cstring>
using namespace std;
int main()
{
string s="Hello worLD";
transform(s.begin(),s.end(),s.begin(),::toupper);
cout<<s<<endl;
transform(s.begin(),s.end(),s.begin(),::tolower);
cout<<s<<endl;
return 0;
}
20.有權圖的單源最短路徑問題:
迪傑斯特拉 算法:
針對常見問題、疑惑給出的結論:
若路徑是按照遞增(非遞減)的
順序生成的,則:
1.真正的最短路必須只經過S中的頂點
2.每次從未收錄的頂點中選一個dist值最小的收錄(貪心)
3.增加一個v進入S,可能影響另外一個w的dist值。
而且針對第3點,還有一個重要的說明就是v如果能夠改變w
也有一個必要條件,就是v和w一定是鄰接點。
這樣編程就好編了。
dist[w] = min{dist[w],dist[v]+<v,w>的權重}。
22.倒計時一個月:
數據輸入範圍:
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 <cstring>
注意:
**對於初學者,只建議使用memset賦 0 或 -1;
如果要對數組賦其他數字,比如1,使用 fill()函數。
這裏已經試過了,的確賦其他值,比如 34 的時候,出錯了。
這裏一定要注意一下。**
**判斷字符是字母,數字,還是字母數字,以及大寫,小寫:**
2.cctype中還有其他函數,如:
isdigit() 用來判斷一個字符是否是數字。
isalnum() 用來判斷一個字符是否爲英文字母或數字,相當於 isalpha(c) || isdigit(c)
isalpha() 用來判斷一個字符是否是英文字母,相當於 isupper(c)||islower(c)
**構造函數有什麼用呢?**
初始化,就記住初始化就可以了。
#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
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>,雖然這個不是問題所在,
但是是一個好習慣。在 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
25.進制轉換:
**其他進制轉換爲 10 進制,用while()循環;
10 進制轉換爲 其他k進制,就是除k取餘法,用do {}while;**
26.單點測試的技巧:
巧妙地利用EOF , 算法筆記 P97
PAT B 的經典說反話 。
27.基本的排序算法:
1.選擇排序:
每次從未排序的序列中選擇最小的數,然後將其與未排序的序列第一個元素交換,
並與之前已經排好序的序列,自動形成有序序列。
貼到已排序的序列屁股後面。
2.歸併排序:
過程就是從2人小組/1人小組,N/2個小組,到四人小組,N/4個小組,一直到N人小組,1個小組。
歸併就是把兩個有序的序列合併爲一個有序的序列的過程。
總之算是分治與歸併的結合就是歸併排序,可以看下面的代碼: