阿龙的剑指学习笔记---3.11

2.4 算法和数据操作

  1. 排序和查找是重点,重点掌握二分查找,归并排序,快速排序。

  2. 递归和循环两种方式看要求,或和面试官讨论。

  3. 查找有顺序查找、二分查找、哈希表查找、二叉排序树查找等。需随时能够完整正确写出二分查找的算法。

  4. 排序有插入排序、冒泡排序、归并排序、快速排序等,需要比较其之间的优劣、特点。随时能够完整正确写出快速排序的算法。

  5. 快速排序
     分治法排序的一种算法,即把大问题化为小问题。算法思路是选取一个基准,把比他大的放在他右边,小的放左边,再对左右分别进行同样方法的排序。
     网上常规的方法是每次以第一个数为基准,如下图。在这里插入图片描述

    class L_QuickSort{
    private:
    	static int partition(int input[], int left, int right)
    	{
    		if (input == nullptr || left > right || left < 0 || right < 0)
    			throw new std::exception("Invalid Input/n");
    		//取第一个为基准
    		int base = input[left];
    
    		while (left < right)
    		{
    			while (left < right && input[right] >= base)
    				right--;
    			input[left] = input[right];
    
    			while (left < right && input[left] <= base)
    				left++;
    			input[right] = input[left];
    		}
    		input[left] = base;
    		return left;
    	}
    public:
    	static void quickSort(int inputArr[], int start, int end)
    	{
    		if (inputArr == nullptr || start > end || start < 0 || end < 0)
    			throw new std::exception("Invalid Input/n");	
    		int div = partition(inputArr, start, end);
    		if (div - start > 1)
    			quickSort(inputArr, start, div - 1);
    		if (end - div > 1)
    			quickSort(inputArr, div + 1, end);
    	}
    };
    

     剑指上的做法则更还原本算法的精髓,最开始的基准是随机取的,然后将以这个数字将数组分为大于和小于的两部分,在对这两部分继续递归。
     重点在于分块partition函数的算法

    static int patition(int data[], int start, int end)
    	{
    		if (data == nullptr || start > end || start < 0 || end < 0)
    			throw new std::exception("Invalid Input/n");
    		//随机选一个start-end范围内的数字作为基准
    		int index = (rand() % (end - start + 1)) + start;
    		//将这个数字先放到最后,对前面的数字进行分块
    		mySwap(&data[index], &data[end]);
    		//small代表比标准小的最后一个数字,即小的与大的之间的分界
    		int small = start - 1;
    		//从头到尾循环,将比标准大的数字放在后面,小的放在前面,small表示其交界处的位置
    		for (index = start; index < end; ++index){
    			if (data[index] < data[end]){
    				++small;
    				if (index != small)
    					mySwap(&data[index], &data[small]);
    			}
    		}
    		//最后把标准与small+1,即第一个比标准大的数字交换,完成前面都是小的,后面都是大的
    		mySwap(&data[small+1], &data[end]);
    		return small + 1;
    	}
    //排序主函数与上面类似。
    
  6. 二分查找算法的应用,实际问题能想到。

  7. 一般情况下使用递归代码更简单,但开销也会大,时间效率低,还有可能出现栈溢出的错误,要看情况使用。

  8. 斐波那契数列:
    表达式为: F(n) = F(n-1) + F(n-2), F(0)=0, F(1)=1.
     可以使用递归和非递归,如果数字很大,建议使用非递归循环算法(从小到大开始加)。

  9. 斐波那契数列的应用
    例如:
     有一段楼梯有10级台阶,规定每一步只能跨一级或两级,要登上第10级台阶有几种不同的走法?
    例如:
    在这里插入图片描述
    都可以以斐波那契数列数列来解决。

  10. 位运算:
    与&、或|、取反~、异或^,左移、右移。
    左移右边补0,左边丢弃。右移复杂一些,右移右边丢弃,左边补符号,如果正数则补0,负数补1。

  11. 位运算应用:二进制数中1的个数。
    常规算法1:
     取这个数左移,统计最低位的1的个数,直到变成0。但负数时会遇到问题。
    常规2:
     取一个i=1,把这个数右移,统计1的个数,但 效率比较低,因为32位的int则要移32次。
    变通算法:
      发现将一个数减1再与自己相位与,则会把最右边的1变成0。比如1001&1000=1000;1100&1011=1000。
     这样,只要做这个操作直到变成0,统计次数即可。
     一些二进制的题可能会用到统计1的个数来解决,此时要想到此算法。

  12. 要注意边界条件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值