分治(CSP考前总复习)

一、分治

分治法是算法常用的解题方法之一,是将一个大的问题拆分为若干小的问题。二分法就是常用的分治法。

可以采用分治法解决的一些问题:

1.二分查找

2.合并排序(归并排序)

3.快速排序

4.快速幂

5.汉诺塔

1.二分查找

二分查找对要查找的序列有两个要求:

​ 一是该序列必须是有序的(即该序列中的所有元素都是按照大小关系排好序的,升序和降序都可以)

​ 二是该序列必须是顺序存储的。

例题:二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

思路:

1、先确定中间位置:

    middle = (left+right)/2;

2、将待查找得值与nums[middle]的值相比较。若相等,则查找成功并返回该位置,否则须确定新确定查找区间,继续查找。

3、如果nums[middle] 的值大于待查找的值,则证明在nums[middle]~nums[right]中所有的值都大于待查找的值,令right=middle,在nums[left]到nums[middle]中查找。

4、当left>right时,证明nums中没有要查找的值,跳出循环,返回-1。

2.归并排序

归并排序是基于递归实现的,归并排序是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法的一个非常典型的应用。将数据分为a,b两组,再将a,b各自再分成两组,以此类推,当每一组都只有一个数据时,认为这个小小组已经达到了有序,再将相邻两个小小组依次合并。

例题:排序数组

给你一个整数数组 nums,请你将该数组升序排列。

示例 1:

输入:nums = [5,2,3,1]
输出:[1,2,3,5]

思路:

1、将数组进行拆分,利用递归的方法,将数组拆分成一个个单独的元素。

2、依次对数组进行合并,依次比较数组内的元素,将较小的元素先加入新的数组,依次往下比较,如果一个数组内的值已经全都加入新数组,将另一个数组的剩下的值依次加入新数组。

3、将额外的空间覆盖掉原来的空间。

3.快速排序

快速排序,基于冒泡排序移动换位思想——通过遍历,判断每个数并放置在数组合适的位置。快速排序可能是应用最广泛的排序算法,适用于各种不同的输入数据且在一般应用中比其他排序都要快的多。

排序方式:

1、选定一个值,一般是数值的第一个值

2、进行分区,将该值与数组后面的数据依次进行比较,将比它小的值都放在左边,比它大的值都放在右边。

3、采用递归的方法,对该值左右区间的数组依次再进行分区操作,直到每个区间只剩一个值。

例题:最小的k个数

输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

示例 1:

输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]

思路:

1、选取一个基数

2、设置i,j两个指针,分别从左右两边向中间进行查找,先使j移动,当遇到arr[j]小于基数时,移动i,当遇到arr[i]大于基数时,将arr[i]与arr[j]互换位置,保证比基数小的值在左边,比基数大的值在右边

3、当i>=j的时候,跳出循环,将基数与i指针所在的位置交换数值

4、当i>k时,证明最小的k个数在0~(i-1)之间,在该区间查找最小的k个数

5、当i<k时,证明比基数大的一些数也是最小的k个数,在比基数大的值中间属于最小的k个数的值

6、当i==k时,返回最小的k个数。

4.快速幂

例题:Pow(x, n)

实现 pow(x, n) ,即计算 x 的整数 n 次幂函数(即,xn )。

示例 1:

输入:x = 2.00000, n = 10
输出:1024.00000

思路:

1、声明数据类型为long的b,将n赋值给它

2、当b为负数时,先将b转化为正数运算,x=1/x,b=-b

3、将b除以2,如果余数为一,将res=res*x,x等于x的平方,因为最后结果永远等于x的b次幂乘res,当b=0时,最后结果等于1乘res,即res

5.汉诺塔

例题:汉诺塔问题

在经典汉诺塔问题中,有 3 根柱子及 N 个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时受到以下限制:
(1) 每次只能移动一个盘子;
(2) 盘子只能从柱子顶端滑出移到下一根柱子;
(3) 盘子只能叠在比它大的盘子上。

请编写程序,用栈将所有盘子从第一根柱子移到最后一根柱子。

你需要原地修改栈。

示例1:

输入:A = [2, 1, 0], B = [], C = []
输出:C = [2, 1, 0]

思路:

假设A柱有n个盘子

1、B柱与C柱替换,新的C柱就是B柱。

2、将A柱上的n-1个盘子移到新C柱上,实际上都移到了B柱上。

3、将B柱与C柱换回来。

4、将A柱上的最后一个盘子移到C柱上,这个盘子不用再移动,将它和C柱看成一个整体。

5、将B柱与A柱互换位置,B柱成为新的A柱。

6、将B柱看出A柱重复1~5步,直到盘子完全移到C上。

分治和递归:

递归和分治本身就不是同一种东西,递归是敲代码的技巧之一,分治是算法的思想之一,两者没关系。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值