【PAT】總結

【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個小組。
歸併就是把兩個有序的序列合併爲一個有序的序列的過程。
總之算是分治與歸併的結合就是歸併排序,可以看下面的代碼:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章