【PAT】总结

15 篇文章 0 订阅

【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个小组。
归并就是把两个有序的序列合并为一个有序的序列的过程。
总之算是分治与归并的结合就是归并排序,可以看下面的代码:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值