引言
开始学习算法,准备从《图解算法》这本书开始入门,写的确实通俗易懂、生动有趣,很适合算法入门。可惜的是书中的代码都是使用python来实现的,作为一名Java门下走(菜)狗,准备在学习的过程中,将书中的python代码用Java实现一遍,同时也会记录一些学习过程中的笔记。
第一章 算法简介
1.2 二分查找
二分查找就是一个“对半砍”的查找方式,简单粗暴的每次直接查询当前列表的中间部分,但只能在列表有序时才管用。
方法binary_search
用于接收一个有序数组和一个元素。如果指定的元素包含在数组中,这个方法将返回其位置。你将跟踪要在其中查找的数组部分——开始时为整个数组。
首先,我们需要两个属性low和high(名字可以随意)来跟踪要查找的列表部分:
如果猜测的数字太大了,我们就需要修改high的值,调整我们下一次猜测的范围(猜测小了就修改low的值):
直到low和high的范围缩小到只包含一个值。
Python2.7实现二分查找代码:
def binary_serch(list, item):
# low和high用于跟踪要在其中查找的列表部分,索引low~high就是我们要查找得到范围
low = 0 #数组索引从0开始
high = len(list)-1 #数组的最后一个索引=数组长度-1
while low <= high:
# 每一次都检查中间的元素
mid = (low + high) / 2 # 如果(low + high)不是偶数,Python自动将mid向下取整
guess = list[mid]
if guess == item:
return mid
# 如果猜的数字大了,就相应的修改high,小了就修改low
if guess > item:
high = mid - 1
else:
low = mid + 1
retuen None
my_list = [1, 3, 5, 7, 9]
print binary_serch(my_list, 3) # => 1
print binary_serch(my_list, -1) # => None
Java实现二分查找代码:
/**
* 最基础的二分查找
* 《图解算法》1.2Java版
*/
public class BinarySearch {
public static void main(String[] args) {
int[] arry = {-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10};
BinarySearch lin = new BinarySearch();
Integer res = lin.binarySearch(arry,-5);
if (res == null){
System.out.println("数组中不存在该元素");
}else {
System.out.println("数组中存在item这个元素,它在数组的索引为" + res);
}
}
/**
*
* @param arry 数组
* @param item 被猜的答案
* @return
*/
public Integer binarySearch(int[] arry, int item){
int low = 0;
int high = arry.length - 1;
while (low <= high){
int mid = (low + high) / 2;
int guess = arry[mid];
if (guess > item){
high = mid - 1;
}else if (guess < item){
low = mid + 1;
}else if (guess == item){
return mid;
}
}
return null;
}
}
第二章 选择排序
2.3 选择排序
选择排序就是多次遍历当前队列,每次遍历选出最大或者最小的元素,再插入一个新的队列,直到原本的队列每一个元素都添加到了新的队列当中,则排序完成。算法速度为 O ( n 2 ) O(n^2) O(n2)。
假设我们需要对下图的歌单按照播放次数进行排序
那么首先,我们可以先遍历一遍这个列表,找出其中播放次数最多的乐队,并且将这个乐队添加到一个新的列表中。
再次这样做,找出播放量第二的乐队。
继续这样重复,就能获得一个有序列表。
示例代码Python版
先创建一个findSmallest()
函数,用于找出数组中的最小元素
def findSmallest(arr):
smallest = arr[0] # smallest存储当前最小的值
smallest_index = 0 # smallest_index存储当前最小元素的索引
for i in range(1, len(arr)):
if arr[i] < smallest: #当arr[i]小于smallest,就将arr[i]的值赋给smallest,此时smallest又是当前的最小值,直到与整个数组进行比较,smallest就是最小值
smallest = arr[i]
smallest_index = i
return smallest_index
现在就可以拿这个函数来编写排序算法啦~
def selectionSort(arr): ←------对数组进行排序
newArr = []
for i in range(len(arr)):
smallest = findSmallest(arr) ←------找出数组中最小的元素,并将其加入到新数组中
newArr.append(arr.pop(smallest))
return newArr
print selectionSort([5, 3, 6, 2, 10])
示例代码Java版
不同于之前的二分查找,选择排序的Java实现和python实现有很大的不同,因为Java中并没有pop()
函数(用于移除列表中的一个元素)。
但这并不意味着Java就没法实现选择排序,让我们来换一个角度来思考问题:python中我们是通过新建一个列表,将旧列表的元素一个一个移动到新列表中完成排序,那我们能不能就在原有的列表内部直接调整位置来完成排序呢?
当然是可以滴,首先默认列表的最小元素是smallest
,最小元素索引是smallest_index
。最开始它们为列表的第一个值arry[0]
,也就是5(但实际上5并不是这个列表的最小值,所以还要后续的比较)
然后让我们进行一次循环来不断比较,在比较过程中,每当发现比smallest
更小的值,就将这个值赋值给smallest
,保证smallest
是当前的最小值,当列表遍历一次后,我们就能得到列表的最小值。
获得最小值后,将当前的最小值和列表的第一个值(也就是arry[0])交换位置,再将默认最小值设置为arry[1],继续上一步的操作,从arry[1]开始循环找到最小值,并且将最小值和列表的第二个值交换位置(arry[1]),直至将整个列表排序完成。
示例代码Java版
import java.util.Arrays;
public class SelectionSort {
public static void main(String[] args) {
// 需要排序的数组
int[] arry = {5, 3, 6, 2, 0};
// 进行选择排序,并返回一个已经排序好的数组
selecctionSort(arry);
// 输出已经排序好的数组
System.out.println("数组排序完毕:"+Arrays.toString(arry));
}
/**
*
* @param arry
* @return
*/
public static int[] selecctionSort(int[] arry){
//第一层循环,控制交换位置的次数
for (int i = 0; i < arry.length - 1 ; i++){
int smallest = arry[i]; //本次交换的假定最小值
int smallest_index = i; //本次交换假定最小值的索引位置
//第二层循环,遍历数组,确定最小值
for (int j = i + 1; j < arry.length; j++){
if (arry[j] < smallest){
smallest = arry[j];
smallest_index = j;
}
}
//再把确定的最小值换到假定最小值的位置
int temp = arry[i];
arry[i] = smallest;
arry[smallest_index] = temp;
System.out.println("第" + (i+1) + "次交换位置结果:" + Arrays.toString(arry));
}
return arry;
}
}
运行结果:
最后更新时间:2022-1-11(更新中ing…)
第三章 递归
程序调用自身的编程技巧称为递归( recursion)。
书中使用了在嵌套的箱子中找钥匙🔑来解释递归:
- 仔细检查盒子A=>在盒子A中发现了盒子B和C,进入盒子B
- 检查盒子B=>在盒子中发现了盒子D,进入盒子D
- 检查盒子D=>里面什么也没有,是一个空的,return null到盒子B
- 返回盒子B=>除了空盒子D外什么也没有,return null到盒子A
- 搜索盒子C=>找到钥匙