算法

算法

  • 交换两个变量的值

  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);
    	}
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值