算法

来源:互联网 发布:企业局域网监控软件 编辑:程序博客网 时间:2024/05/29 18:57

算法

  • 交换两个变量的值

  1. 诡异法
    void swap(int *a , int *b)   10, 8{*a = *a ^ *b;    //*a = 110 ^ 100 = 010*b = *b ^ *a;    //*b = 100 ^ 010 = 110*a = *a ^ *b;    //*a = 010 ^ 110 = 100}

  2. 变量法(使用第三个变量)
    void swap(int *a , int *b)   10, 8{int temp  = *a;   *a = *b;    *b = temp;    }

  3. 加减法
    void swap(int *a , int *b)   10, 8{*a = *b - *a; *b = *b - *a; *a = *b + *a;  }

  • 直接插入排序

  • template <typename T>void insertSort(T * a, int n){for (int i=1; i<n; i++){T t = a[i];for (int j =i-1; j>=0 && t<a[j]; j--){a[j+1] = a[j];}a[j+1] = t;}}


  • 冒泡排序

  • template <typename T>void bubbleSort(T * a, int n){for(int i=n; i>=0; i--){for(int j = 0; j<i; j++){if(a[j] > a[j+1])swap(a[j], a[j+1]);}}}


  • 选择排序

  • template <typename T>void selectionSort(T * a, int n){for(int i = 0; i<n-1; i++){int min = i;for (int j = i+1; j<n; j++){if(a[j] < a[min]){min = j;}}swap(a[i], a[min]);}}

  • 求一亿以内素数表,结果放在一个足够大的int数组中,要求程序速度越快越好,一亿以内素数个数为5761455个

  • int CompositeNumFilterV3(int n){int i, j;//素数数量统计int count = 0;// 分配素数标记空间,明白+1原因了吧,因为浪费了一个flag[0] char* flag = (char*)malloc(n + 1);memset(flag, 0, n+1);// 干嘛用的,请仔细研究下文 int mpLen = 2 * 3 * 5 * 7 * 11 * 13;char magicPattern[2 * 3 * 5 * 7 * 11 * 13]; // 奇怪的代码,why,思考无法代劳,想!  for (i = 0; i < mpLen; i++){magicPattern[i++] = 1;magicPattern[i++] = 0;magicPattern[i++] = 0;magicPattern[i++] = 0;magicPattern[i++] = 1;magicPattern[i] = 0;}for (i = 4; i <= mpLen; i += 5)magicPattern[i] = 0;for (i = 6; i <= mpLen; i += 7)magicPattern[i] = 0;for (i = 10; i <= mpLen; i += 11)magicPattern[i] = 0;for (i = 12; i <= mpLen; i += 13)magicPattern[i] = 0;  // 新的初始化方法,将2,3,5,7,11,13的倍数全干掉   // 而且采用memcpy以mpLen长的magicPattern来批量处理  int remainder = n%mpLen;char* p = flag + 1;char* pstop = p + n - remainder;while (p < pstop){memcpy(p, magicPattern, mpLen);p += mpLen;}if (remainder > 0){memcpy(p, magicPattern, remainder);}flag[2] = 1;flag[3] = 1;flag[5] = 1;flag[7] = 1;flag[11] = 1;flag[13] = 1;    // 从17开始filter,因为2,3,5,7,11,13的倍数早被kill了   // 到n/13止的,哈哈,少了好多吧 int stop = n / 13;for (i = 17; i <= n; i++){// i是合数,请歇着吧,因为您的工作早有您的质因子代劳了   if (0 == flag[i]) continue;// 从i的17倍开始过滤  int step = i * 2;for (j = i * 17; j <= n; j += step){flag[j] = 0;}}// 统计素数个数 for (i = 2; i <= n; i++){if (flag[i]) {count++;}}// 因输出费时,且和算法核心相关不大,故略   // 释放内存,别忘了传说中的内存泄漏  free(flag);return count;}


  • string类重载

  • class MyString  {  public:      //三个重载的构造函数        MyString();      MyString(const char* str);      MyString(const MyString& str);      //析构函数        ~MyString();        //重载运算符        MyString& operator = (const MyString& str);      char&  operator[](int index);//访问下标      friend ostream& operator << (ostream& out, const MyString& str); //重载输出操作符        friend istream& operator >> (istream& in, MyString& str); //重载输入操作符        friend MyString operator + (const MyString& str1, const MyString& str2); //重载加号操作符,注意返回引用不行      friend MyString operator += (MyString& str1, const MyString& str2); //重载+=操作符        friend bool operator == (const MyString& str1, const MyString& str2);   //重载相等操作符        friend bool operator != (const MyString& str1, const MyString& str2);   //重载不相等操作符      private:      char* p;      int len;  };  //默认构造函数,初始化为空串    MyString::MyString()  {      len = 0;      p = new char[len + 1];      p[0] = '\0';  }    //构造函数,用一个字符串初始化    MyString::MyString(const char* str)  {      len = strlen(str);      p = new char[strlen(str) + 1];      strcpy_s(p, strlen(str) + 1, str);  }    //拷贝构造函数,用另外一个string初始化    MyString::MyString(const MyString& str)  {      len = str.len;      p = new char[strlen(str.p) + 4];      strcpy_s(p, strlen(str.p) + 1, str.p);  }    //析构函数    MyString::~MyString()  {      delete[] p;  }    //重载赋值操作符( = )    MyString& MyString::operator = (const MyString& str)  {      if (this->p == str.p)      {          return *this;      }      delete[] p;      len = str.len;      p = new char[len + 1];      strcpy_s(p, len + 1, str.p);      return *this;  }    //重载输出操作符( << )    ostream& operator << (ostream& out, const MyString& str)  {      out << str.p;      return out;  }    //重载输入操作符( >> )    istream& operator >> (istream& in, MyString& str)  {      in >> str.p;      return in;  }    //重载加号操作符( + )    MyString operator + (const MyString& str1, const MyString& str2)  {      MyString str;      delete[] str.p;      str.len = str1.len + str2.len;      str.p = new char[str.len + 1];      strcpy_s(str.p, str.len + 1, str1.p);      strcat_s(str.p, str.len + 1, str2.p);      return str;  }    //重载相加赋值操作符( += )    MyString operator += (MyString& str1, const MyString& str2)  {      str1 = str1 + str2;      return str1;  }    //重载相等操作符    bool operator == (const MyString& str1, const MyString& str2)  {      if (strcmp(str1.p, str2.p) == 0)      {          return true;      }      return false;  }    //重载不相等操作符    bool operator != (const MyString& str1, const MyString& str2)  {      if (strcmp(str1.p, str2.p) == 0)      {          return false;      }      return true;  }    //重载下标([])  char&  MyString::operator[](int index)  {      return p[index];  }  


  • 遍历树求和,递归与非递归

  1. 递归
    typedef struct _node{_node *m_child[2] = {0};int m_data = 11;}Node;int getSum_1(Node * root){int sum = 0;if (NULL != root->m_child[0]){sum += getSum_1(root->m_child[0]);}if (NULL != root->m_child[1]){sum += getSum_1(root->m_child[1]);}sum += root->m_data;return sum;}

  2. 非递归
    int getSum_2(Node * root){int sum = 0;stack <Node *> s;Node *p = root;while (p != NULL || !s.empty()){while (p != NULL){sum += p->m_data;s.push(p);p = p->m_child[0];}if (!s.empty()){p = s.top();s.pop();p = p->m_child[1];}}return sum;}

  • 数字转字符串

  • #include <sstream>std::string int_to_string(int i){std::ostringstream stream;stream << i;return stream.str();}

  • 字符串转数字

  • #include <sstream>int string_to_int(std::string str){std::istringstream stream;int i=0;stream.str(str);stream >> i;return i;}


  • 怎样速度最快地删除vector中的任意元素

  •    // 这里移除的算法复杂度是O(1),将待删除元素与最后一个元素交换再pop_back      int idx=0;      if (static_cast<size_t>(idx) == ve1.size()-1)      {          ve1.pop_back();      }      else      {         iter_swap(ve1.begin()+idx, ve1.end()-1);         ve1.pop_back();      }  

  • 判断回文

  • int fun(int low, int high, char *str, int length){if (length == 0 || length == 1)return    1;if (str[low] != str[high])return    0;return fun(low + 1, high - 1, str, length - 2);}int pan_duan_hui_wen(){char    str[] = "aaabaaa";int     length = strlen(str);//返回1代表是, 0代表不是  std::cout << fun(0, length - 1, str, length) << std::endl;return 0;}


  • 中序遍历

  • typedef struct TreeNode {    int data;    struct TreeNode *left;    struct TreeNode *right;    struct TreeNode *parent;} TreeNode; void middle_order(TreeNode *Node) {    if(Node != NULL) {        middle_order(Node->left);        printf("%d ", Node->data);        middle_order(Node->right);    }} 调用时: middle_order(Root); //Root为树的根


  • 两条双向链表,去除链表中共有的元素

遍历list1, 对于其中的每个元素,将其插入到哈希表(map)中。然后遍历list2, 对于其中的每个元素,在哈希表(map)中进行查找。如果元素已经存在于哈希表(map)中,删除list2中元素与map中指针指向list1中元素。

  • 假设A上台阶,一次可以跨1层,2层或3层,问A上50层台阶,有多少种走法?假设A上台阶,一次可以跨1层,2层,3层.. 或m层,问A上n层台阶,有多少种走法?其中,m和n都是正整数,并且 m <= n, m <= 10, n <= 50请编程解决这个问题,并详细说明解题思路。

https://my.oschina.net/spance/blog/229477

  • 请设计一套对n个字符进行全排列的算法。
    如果对该算法输出全排列顺序分别标记序号,从1到n!
    那么,给出low, high,能否不算出所有排列,而直接输出第low个到第high个的排列方式。
    请写出示例代码,并详细说明解题思路。
  • 一栋楼有N层,要去每一层的人数分别为p[1], p[2], ...,p[n],如果电梯只停1次,问停哪一层,可以让所有人走的楼层最少。
    如果走路上一层楼耗费的能量为k1, 走路下一层楼消耗的能量为k2,坐电梯上一层楼消耗的能量为k3,问停哪一层,可以让所有人消耗能量最少
    请编程解决这个问题,并详细说明解题思路。

  • 如何将大量有序数据(例如有100万条有序节点的vector),快速添加到map中去

使用unordered_map。 
unordered_map和map类似,都是存储的key-value的值,可以通过key快速索引到value。不同的是unordered_map不会根据key的大小进行排序,
存储时是根据key的hash值判断元素是否相同,即unordered_map内部元素是无序的,而map中的元素是按照二叉搜索树存储,进行中序遍历会得到有序遍历。
所以使用时map的key需要定义operator<。而unordered_map需要定义hash_value函数并且重载operator==。但是很多系统内置的数据类型都自带这些,
那么如果是自定义类型,那么就需要自己重载operator<或者hash_value()了。

虽然都是map,但是内部结构大大的不同哎,map的内部结构是R-B-tree来实现的,所以保证了一个稳定的动态操作时间,查询、插入、删除都是O(logN),最坏和平均都是。而unordered_map如前所述,是哈希表。顺便提一下,哈希表的查询时间虽然是O(1),但是并不是unordered_map查询时间一定比map短,因为实际情况中还要考虑到数据量,而且unordered_map的hash函数的构造速度也没那么快,所以不能一概而论,应该具体情况具体分析。

  • memcpy实现

  • void *Memcpy(void *dst, const void *src, size_t size){    char *psrc;    char *pdst;     if(NULL == dst || NULL == src)    {        return NULL;    }     if((src < dst) && (char *)src + size > (char *)dst) // 自后向前拷贝    {        psrc = (char *)src + size - 1;        pdst = (char *)dst + size - 1;        while(size--)        {            *pdst-- = *psrc--;        }    }    else    {        psrc = (char *)src;        pdst = (char *)dst;        while(size--)        {            *pdst++ = *psrc++;        }    }     return dst;}


  • 删除vector/queue所有偶数项,并打印出删除的项

  1. 使用正向迭代器
    void erase(vector<int> &v){    for(vector<int>::iterator vi=v.begin();vi!=v.end();)    {        if(*vi % 2 == 0)        {            cout << "Erasing " << *vi << endl;            vi = v.erase(vi);        }        else ++vi;    }}

  2. 使用逆向迭代器
    void erase2(vector<int> &v){    for(vector<int>::reverse_iterator ri=v.rbegin();ri!=v.rend();)    {        if(*ri % 2 == 0)        {            cout << "Erasing " << *ri << endl;            v.erase((++ri).base()); //erase()函数期待的是正向iterator,故而这里要调            //用base()函数将逆向iterator转换为正向的        }        else ++ri;    }}

  • 删除map/list所有偶数项,并打印出删除的项

  1. 使用正向迭代器
    void erase(map<int,int> &m){    for(map<int,int>::iterator mi=m.begin();mi!=m.end();)    {        if(mi->second % 2 == 0)        {            cout << "Erasing " << mi->second << endl;            m.erase(mi++);        }        else ++mi;    }}

  • 不借助任何库函数,将字符串反转,并不改变单词次序。如:I am a Student.  操作后输出:Student a am I.

  • void FlipSentence(char *start, char *end) //把字符串翻转  {char* pstart = start;char* pend = end;char temp;while (pstart < pend){temp = *pstart;*pstart = *pend;*pend = temp;pstart++;pend--;}}void FlipWord(char *p) //在字符串中找出单词 ,并将各个单词用方法一将其翻转 {while (*p != '\0'){char *pst = p;while (*p != '\0' && *p != ' '){p++;}FlipSentence(pst, p - 1);//把每一个单词看作句子对待p++;}}int zi_fu_chuan_fan_zhuan(){char p[30] = "i am a student";int len = strlen(p);printf("原字符串为 : %s\n", p);printf("翻转后的字符串为 :");FlipSentence(p, p + len - 1);FlipWord(p);std::cout << p << std::endl;return 0;}


  • 分别输入两个空间中两个矩形的左上角坐标x,y,以及宽(width)高(height), 如果两个矩形有相交,输出相交的矩形左上角,右下角坐标,x1,y1,x2,y2
    例如: 键盘输入: 0,0,100,100
    20,20,100,40
    输出: 20,20,100,60   

  • 模拟实现乘法运算
    A*B = C,A和B最大值为9999. 要求输出如下
    1234
    * 121
    --------------
    1234
    2468
    1234
    = --------------
    14 9 3 1 4
  • 设计一个KString类,让它具备如下特性:
    1) KString str1 = "Hello";
    2) KString str2 = str1;
    3) str += "world";在执行
    1)之后,str1 的内容是 "Hello";在执行 2)之后,str2 的内容是 "Hello"; 但是str2内部未给"Hello"分配新空间;在执行 3)之后,str2 的内容是 "Helloworld", str1的内容是"Hello"而未改变

  • 快速排序

  • int partition(int * a, int p, int r){int x = a[r];int i = p-1;for (int j = p; j<r; j++){if(a[j] <= x){if (i != j){   swap(a[i], a[j]);}}}swap(a[i+1], a[r]);return i+1;}void quickSort(int * a, int p, int r){if(p < r){int q = partition(a, p, r);quickSort(a, p, q-1);quickSort(a, q+1, r);}}
3 0