数组中元素的插入和查找算法探究

news2024/12/28 5:49:11

数组的查找

线性查找

概念

线性查找也叫顺序查找,这是最基本的一种查找方法,从给定的值中进行搜索,从一端开始逐一检查每个元素,直到找到所需元素的过程。

元素序列的排列可以有序,也可以无序。

代码实现

public class Test01 {
	public static void main(String[] args) {
		//线性查找
		
		int[] arr = {45, 62, 15,62, 78, 30};
		
		int index = sequentialSearch01(arr, 62);
		System.out.println("指定元素首次出现的下标位置:" + index);
		
		List<Integer> indexList = sequentialSearch02(arr, 62);
		System.out.println("指定元素出现的下标位置的集合:" + Arrays.toString(indexList.toArray()));
	}
	
	/**
	 * 顺序查找
	 * 返回指定元素首次出现的下标位置
	 */
	public static int sequentialSearch01(int[] arr,int value){
		for (int i = 0; i < arr.length; i++) {
			if(arr[i] == value){
				return i;
			}
		}
		return -1;
	}
	
	/**
	 * 顺序查找
	 * 返回指定元素出现的下标位置的集合
	 */
	public static List<Integer> sequentialSearch02(int[] arr,int value){
		List<Integer> list = new ArrayList<>();
		for (int i = 0; i < arr.length; i++) {
			if(arr[i] == value){
				list.adds(i);
			}
		}
		return list;
	}
}

二分法查找

概念

二分查找(Binary Search)算法,也叫折半查找算法。

当要从一个序列中查找一个元素的时候,二分查找是一种非常快速的查找算法。

二分查找是针对有序数据集合的查找算法,如果是无序数据集合就遍历查找。

二分查找之所以快速,是因为它在匹配不成功的时候,每次都能排除剩余元素中一半的元素。因此可能包含目标元素的有效范围就收缩得很快,而不像顺序查找那样,每次仅能排除一个元素。

原理

比如有一个有序表数组[1,3,5,7,9,11,13,15,17,19,21],它是按照从小到大的顺序来进行排列的,现在需要在该有序表中查找元素19,步骤如下:

  1. 首先设置两个指针low和high,分别指向数据集合的第一个数据元素1(位序为0)和最后一个数据元素21(位序为10)。

然后把整个数据集合长度分成两半,并用一个指针指向它们的临界点,所以定义指针mid指向了中间元素11(位序5),也就是说mid=(high+low)/2,其中high和low都代表所指向的元素的位序,如下图:

在这里插入图片描述

  1. 接着,将mid所指向的元素(11)与待查找元素(19)进行比较。

因为19大于11,说明待查找的元素(19)一定位于mid和high之间。所以继续折半,则low = mid+1,而mid = (low+high)/2,结果如下图:

在这里插入图片描述

  1. 接着,又将mid所指向的元素(17)与待查找元素(19)进行比较,由于19大于17,所以继续折半,则low = mid+1,而mid = (low+high)/2,结果如下图:
    在这里插入图片描述
  1. 最后,又将mid所指向的元素(19)与待查找元素(19)进行比较,结果相等,则查找成功,返回mid指针指向的元素的位序。

如果查找的元素值不是19,而是20,那么在最后一步之前还得继续折半查找,最后出现的情况如下图:

在这里插入图片描述

代码实现

public class Test01 {
	public static void main(String[] args) {
		//二分法查找

		int[] arr = {1,2,3,4,5,6,7,8,9,11,11,11,11,11,11};

		int index = binarySearch01(arr, 11);
		System.out.println("指定元素出现的下标位置:" + index);

		List<Integer> indexList = binarySearch02(arr, 11);
		System.out.println("指定元素出现的下标位置的集合:" + Arrays.toString(indexList.toArray()));

		index = recursionbinarySearch01(arr, 0, arr.length-1, 11);
		System.out.println("递归方式 - 指定元素出现的下标位置:" + index);

		indexList = recursionbinarySearch02(arr, 0, arr.length-1, 11);
		System.out.println("递归方式 - 指定元素出现的下标位置的集合:" + Arrays.toString(indexList.toArray()));
	}

	/**
	 * 有序的数组中查找某个元素出现的下标位置
	 * 不使用递归的二分查找
	 * 返回出现的下标位置
	 */
	public static int binarySearch01(int[] arr,int val){

		int low = 0;
		int high = arr.length-1;

		while(low <= high){
			int mid = (low + high)/2;

			if(val > arr[mid]){
				//目标在右侧
				low = mid+1;
			}else if(val < arr[mid]){
				//目标在左侧
				high = mid-1;
			}else{
				return mid;
			}
		}
		return -1;
	}

	/**
	 * 有序的数组中查找某个元素首次出现的下标位置
	 * 不使用递归的二分查找
	 * 返回下标集合
	 */
	public static List<Integer> binarySearch02(int[] arr,int val){

		int low = 0;
		int high = arr.length-1;

		while(low <= high){
			int mid = (low + high)/2;

			if(val > arr[mid]){
				//目标在右侧
				low = mid+1;
			}else if(val < arr[mid]){
				//目标在左侧
				high = mid-1;
			}else{
				// 定义放置索引下标的集合
				List<Integer> list = new ArrayList<>();
				// 将首次查找的位置放入集合
				list.add(mid);

				// 判断是否还有重复值
				int index = mid + 1;
				while(index < arr.length){
					if(arr[index] == val){
						list.add(index);
					}else{
						break;
					}
					index++;
				}
				index = mid-1;
				while(index >= 0){
					if(arr[index] == val){
						list.add(index);
					}else{
						break;
					}
					index--;
				}
				return list;
			}
		}
		return null;
	}

	/**
	 * 有序的数组中查找某个元素出现的下标位置
	 * 使用递归的二分查找
	 * 返回出现的下标位置
	 */
	public static int recursionbinarySearch01(int[] arr,int low,int high,int val){

		if(val < arr[low] || val > arr[high] || low > high){
			return -1;
		}

		int mid = (low + high)/2;

		if(val > arr[mid]){
			//目标在右侧
			return recursionbinarySearch01(arr, mid+1, high, val);
		}else if(val < arr[mid]){
			//目标在左侧
			return recursionbinarySearch01(arr, low, mid-1, val);
		}else{
			return mid;
		}
	}
	
	/**
	 * 有序的数组中查找某个元素首次出现的下标位置
	 * 使用递归的二分查找
	 * 返回下标集合
	 */
	public static List<Integer> recursionbinarySearch02(int[] arr,int low,int high,int val){

		if(val < arr[low] || val > arr[high] || low > high){
			return null;
		}

		int mid = (low + high)/2;

		if(val > arr[mid]){
			//目标在右侧
			return recursionbinarySearch02(arr, mid+1, high, val);
		}else if(val < arr[mid]){
			//目标在左侧
			return recursionbinarySearch02(arr, low, mid-1, val);
		}else{
			// 定义放置索引下标的集合
			List<Integer> list = new ArrayList<>();
			// 将首次查找的位置放入集合
			list.add(mid);

			// 判断是否还有重复值
			int index = mid + 1;
			while(index < arr.length){
				if(arr[index] == val){
					list.add(index);
				}else{
					break;
				}
				index++;
			}
            
			index = mid-1;
			while(index >= 0){
				if(arr[index] == val){
					list.add(index);
				}else{
					break;
				}
				index--;
			}
			return list;
		}
	}
}

优缺点

优点:速度快,不占空间,不开辟新空间

缺点:必须是有序的数组,数据量太小没有意义

插值查找

概念

从折半查找中可以看出,折半查找的查找效率还是不错的。可是为什么要折半呢?为什么不是四分之一、八分之一呢?

打个比方,在牛津词典里要查找“apple”这个单词,会首先翻开字典的中间部分,然后继续折半吗?肯定不会,对于查找单词“apple”,我们肯定是下意识的往字典的最前部分翻去,而查找单词“zero”则相反,我们会下意识的往字典的最后部分翻去。

所以在折半查找法的基础上进行改造就出现了插值查找法,也叫做按比例查找。所以插值查找与折半查找唯一不同的是在于mid的计算方式上,它的计算方式为:

int mid = low + (high - low) * (val- arr[low]) / (arr[high] - arr[low])

这样就能快速定位目标数值所在的索引,比二分查找可以更快速实现查找。

自适应获取mid,也就是自适应查找点。

代码实现

public class Test01 {
	public static void main(String[] args) {
		//插值查找
		
		int[] arr = {1,2,3,4,5,6,7,8,9,11,11,11,11,11,11};

		int index = insertSearch01(arr, 11);
		System.out.println("指定元素出现的下标位置:" + index);

		List<Integer> indexList = insertSearch02(arr, 11);
		System.out.println("指定元素出现的下标位置的集合:" + Arrays.toString(indexList.toArray()));

		index = recursionInsertSearch01(arr, 0, arr.length-1, 11);
		System.out.println("递归方式 - 指定元素出现的下标位置:" + index);

		indexList = recursionInsertSearch02(arr, 0, arr.length-1, 11);
		System.out.println("递归方式 - 指定元素出现的下标位置的集合:" + Arrays.toString(indexList.toArray()));
	}

	/**
	 * 有序的数组中查找某个元素出现的下标位置
	 * 不使用递归的二分查找
	 * 返回出现的下标位置
	 */
	public static int insertSearch01(int[] arr,int val){

		int low = 0;
		int high = arr.length-1;

		while(low <= high){
			
			int mid = low + (high - low) * (val - arr[low])/(arr[high] - arr[low]);

			if(val > arr[mid]){
				//目标在右侧
				low = mid+1;
			}else if(val < arr[mid]){
				//目标在左侧
				high = mid-1;
			}else{
				return mid;
			}
		}
		return -1;
	}

	/**
	 * 有序的数组中查找某个元素首次出现的下标位置
	 * 不使用递归的二分查找
	 * 返回下标集合
	 */
	public static List<Integer> insertSearch02(int[] arr,int val){

		int low = 0;
		int high = arr.length-1;

		while(low <= high){
			int mid = low + (high - low) * (val - arr[low])/(arr[high] - arr[low]);

			if(val > arr[mid]){
				//目标在右侧
				low = mid+1;
			}else if(val < arr[mid]){
				//目标在左侧
				high = mid-1;
			}else{
				// 定义放置索引下标的集合
				List<Integer> list = new ArrayList<>();
				// 将首次查找的位置放入集合
				list.add(mid);

				// 判断是否还有重复值
				int index = mid + 1;
				while(index < arr.length){
					if(arr[index] == val){
						list.add(index);
					}else{
						break;
					}
					index++;
				}
				index = mid-1;
				while(index >= 0){
					if(arr[index] == val){
						list.add(index);
					}else{
						break;
					}
					index--;
				}
				return list;
			}
		}
		return null;
	}

	/**
	 * 有序的数组中查找某个元素出现的下标位置
	 * 使用递归的二分查找
	 * 返回出现的下标位置
	 */
	public static int recursionInsertSearch01(int[] arr,int low,int high,int val){

		if(val < arr[low] || val > arr[high] || low > high){
			return -1;
		}

		int mid = low + (high - low) * (val - arr[low])/(arr[high] - arr[low]);

		if(val > arr[mid]){
			//目标在右侧
			return recursionInsertSearch01(arr, mid+1, high, val);
		}else if(val < arr[mid]){
			//目标在左侧
			return recursionInsertSearch01(arr, low, mid-1, val);
		}else{
			return mid;
		}
	}
	
	/**
	 * 有序的数组中查找某个元素首次出现的下标位置
	 * 使用递归的二分查找
	 * 返回下标集合
	 */
	public static List<Integer> recursionInsertSearch02(int[] arr,int low,int high,int val){

		if(val < arr[low] || val > arr[high] || low > high){
			return null;
		}

		int mid = low + (high - low) * (val - arr[low])/(arr[high] - arr[low]);

		if(val > arr[mid]){
			//目标在右侧
			return recursionInsertSearch02(arr, mid+1, high, val);
		}else if(val < arr[mid]){
			//目标在左侧
			return recursionInsertSearch02(arr, low, mid-1, val);
		}else{
			// 定义放置索引下标的集合
			List<Integer> list = new ArrayList<>();
			// 将首次查找的位置放入集合
			list.add(mid);

			// 判断是否还有重复值
			int index = mid + 1;
			while(index < arr.length){
				if(arr[index] == val){
					list.add(index);
				}else{
					break;
				}
				index++;
			}
			index = mid-1;
			while(index >= 0){
				if(arr[index] == val){
					list.add(index);
				}else{
					break;
				}
				index--;
			}
			return list;
		}
	}
}

斐波那契查找

概念

斐波那契查找也叫做黄金分割法查找。

斐波那契查找也是二分查找的一种提升算法,通过运用黄金比例的概念在数列中选择查找点进行查找,提高查找效率。同样地,斐波那契查找也属于一种有序查找算法。

原理

对于斐波那契数列:1、1、2、3、5、8、13、21、34、55、89……(也可以从0开始),前后两个数字的比值随着数列的增加,越来越接近黄金比值0.618。

比如元素个数为89的有序列表。89在斐波那契数列中是34和55相加所得。

把元素个数为89的有序列表分成:前55个数据元素组成的前半段和34个数据元素组成的后半段。那么前半段元素个数和整个有序表长度的比值接近黄金比值0.618,而前后两段长度的比值也接近黄金比值0.618。

假如要查找的元素在前半段,那么继续按照斐波那契数列来看,55 = 34 + 21,所以继续把前半段分成前34个数据元素的前半段和后21个元素的后半段,继续查找,如此反复,直到查找成功或失败。这样斐波那契数列就被应用到查找算法中了。

总长度=f[k],

前半段长度=f[k-1],后半段长度=f[k-2]

在这里插入图片描述

有序列表的元素个数不是斐波那契数列中的数字时该如何处理呢?

当有序表的元素个数不是斐波那契数列中的某个数字时,需要把有序列表的长度补齐,让它成为斐波那契数列中的一个数值。

如果不是补齐,而是将多余的截掉是否可行?把原有序列表截断肯定是不可行的,因为可能把要查找的目标值截掉。

每次取斐波那契数列中的某个值时(f[k]),都会进行-1操作,这是因为数组下标从0开始。

代码实现


public class Test01 {
	public static void main(String[] args) {
		
		int[] arr = {1,13,25,37,49,51,62,68,70,80,80};
		
		List<Integer> fiboSearchList = fiboSearchList(arr, 80);
		System.out.println(Arrays.toString(fiboSearchList.toArray()));
	}
	
	public static List<Integer> fiboSearchList(int[] arr, int val) {
		
		int low = 0;
		int high = arr.length-1;
		
		// 斐波那契的索引下标。数组长度的数值在斐波那契数列中对应的索引下标
		int[] fiboArray = getFiboArray(10);//[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
		
		// 斐波那契的索引下标。数组长度的数值在斐波那契数列中对应的索引下标
		int k = 0;
		// 斐波那契的索引下标。数组长度的数值在斐波那契数列中对应的索引下标
		while(arr.length > fiboArray[k]){
			k++;
		}
		System.out.println("k = " + k);//6
		System.out.println("fiboArray = " + Arrays.toString(fiboArray));//[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
		
		// 利用Java工具类Arrays 构造新数组并指向 数组 arr[]
		int[] temp = Arrays.copyOf(arr, fiboArray[k]);
		System.out.println("temp=" + Arrays.toString(temp));
        //[1, 13, 25, 37, 49, 51, 62, 68, 70, 80, 80, 0, 0]
		
		//对新构造的数组进行元素补充,补充为最高位的数值
		for (int i = high+1; i < temp.length; i++) {
			temp[i] = arr[high];
		}
		System.out.println("补充数值的temp=" + Arrays.toString(temp));
        //[1, 13, 25, 37, 49, 51, 62, 68, 70, 80, 80, 80, 80]
		
		while(low <= high){
			
			//数列左侧有f[k-1]个元素
			int mid = low + fiboArray[k-1] - 1;
			
			if(val < temp[mid]){
				// 目标值小于mid所在元素,在左侧查找
				high = mid-1;
				
				/*全部元素=前部元素+后部元素
                 * f[k]=f[k-1]+f[k-2]
                 * 因为左侧有f[k-1]个元素,所以可以继续拆分f[k-1]=f[k-2]+f[k-3]
                 * 即在f[k-1]的前部继续查找 所以k-=1
                 * 即下次循环 mid=f[k-1-1]-1
                 */
				k-=1;
			}else if(val > temp[mid]){
				// 目标值大于mid所在元素,在右侧查找
				low = mid+1;
				
				/*全部元素=前部元素+后部元素
                 * f[k]=f[k-1]+f[k-2]
                 * 因为右侧有f[k-2]个元素,所以可以继续拆分f[k-2]=f[k-3]+f[k-4]
                 * 即在f[k-2]的前部继续查找 所以k-=2
                 * 即下次循环 mid=f[k-1-2]-1
               	 */
				k -= 2;
				
			}else{
				
				// 定义放置索引下标的集合
				ArrayList<Integer> list = new ArrayList<>();
				list.add(mid);
				
				int index = mid+1;
				while(index < arr.length){
					if(arr[index] == val){
						list.add(index);
						index++;
					}else{
						break;
					}
				}
				index = mid-1;
				while(index > 0){
					if(arr[index] == val){
						list.add(index);
						index--;
					}else{
						break;
					}
				}
				return list;
			}
		}
		return null;
	}
	
	public static int[] getFiboArray(int maxSize){
		
		int[] fiboArray = new int[maxSize];
		
		fiboArray[0] = 1;
		fiboArray[1] = 1;
		
		for (int i = 2; i < fiboArray.length; i++) {
			fiboArray[i] = fiboArray[i-1] + fiboArray[i-2];
		}
		return fiboArray;
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1367983.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vulhub中的Apache HTTPD 换行解析漏洞(CVE-2017-15715)详解

Apache HTTPD 换行解析漏洞&#xff08;CVE-2017-15715&#xff09; 1.cd到CVE-2017-15715 cd vulhub/httpd/CVE-2017-15715 2.运行docker-compose build docker-compose build 3.运行docker-compose up -d 4.查看docker-compose ps 5.访问 出现这个表示安装成功 6.漏洞复现…

16-20.Python语言进阶

Python语言进阶 重要知识点 生成式&#xff08;推导式&#xff09;的用法 prices {AAPL: 191.88,GOOG: 1186.96,IBM: 149.24,ORCL: 48.44,ACN: 166.89,FB: 208.09,SYMC: 21.29 } # 用股票价格大于100元的股票构造一个新的字典 prices2 {key: value for key, value in prices…

Github 2024-01-09Python开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2024-01-09统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Python项目10Jupyter Notebook项目1 Payloads All The Things - 有用的Web应用程序安全负载和绕过列表 创建…

Unity 编辑器篇|(二)GenericMenu自定义弹出式菜单

目录 1. 前言2. Scene视图添加自定义菜单3. Hierarchy视图添加自定义菜单4. Project视图添加自定义菜单5. Game视图添加自定义菜单 1. 前言 GenericMenu 是 Unity 中的一个强大的类&#xff0c;用于创建和管理自定义上下文菜单&#xff08;也称为弹出菜单&#xff09;。可以使…

Django配置日志系统的最佳实践

概要 日志是跟踪应用行为、监控错误、性能分析和安全审计的重要工具。在Django框架中&#xff0c;合理配置日志系统可以帮助开发者有效管理项目运行过程中的关键信息。本文将详细介绍Django日志系统的最佳实践。 日志系统概述 Django使用Python的 logging 模块来实现日志系统…

苹果快捷指令在哪?详细使用教程送给大家!

快捷指令是苹果公司推出的一个实用功能&#xff0c;然而&#xff0c;可能还有很多新手用户不知道苹果快捷指令在哪。其实&#xff0c;快捷指令中心是iOS系统自带的应用&#xff0c;它一般就位于手机的主屏幕中。今天&#xff0c;小编将针对此问题来给大家分享一下有关苹果快捷指…

虚拟机Linux硬盘扩容

扩容前(20G)&#xff1a; 扩容后(60G)&#xff1a; 步骤&#xff1a; 1. 点击 虚拟机 -> 设置 -> 硬件 -> 硬盘(SCSI) -> 扩展(E)... -> 输入想要扩容大大小 -> 扩展(E) 2. 运行虚拟机&#xff0c;查看根目录属于那个文件系统&#xff0c;我的是 /dev/sda1…

前端八股文(网络篇)一

目录 1.Get和Post的请求的区别 2.常见的HTTP请求头和响应头 3.常见的HTTP请求方法 4.HTTP与HTTPS协议的区别 5.对keep-alive的理解 6.页面有多张图片&#xff0c;HTTP是怎样的加载表现&#xff1f; 7.HTTP请求报文是什么样的&#xff1f; 8.HTTP响应报文是什么样&#x…

【数据结构】数据结构中应用题大全(完结)

自己在学习过程中总结了DS中几乎所有的应用题&#xff0c;可以用于速通期末考/考研/各种考试。很多方法来源于B站大佬&#xff0c;底层原理本文不做过多介绍&#xff0c;建议自己研究。例题大部分选自紫皮严书。pdf版在主页资源 一、递归时间/空间分析 1.时间复杂度的分析 设…

与AI合作 -- 写一个modern c++单例工厂

目录 前言 提问 bard给出的答案 AI答案的问题 要求bard改进 人类智能 AI VS 人类 前言 通过本文读者可以学到modern C单例模式工厂模式的混合体&#xff0c;同时也能看到&#xff1a;如今AI发展到了怎样的智能程度&#xff1f;怎样让AI帮助我们快速完成实现头脑中的想法&…

如何下载和处理Sentinel-2数据

Sentinel-2是欧洲空间局&#xff08;ESA&#xff09;Copernicus计划中的一组地球观测卫星&#xff0c;主要用于提供高分辨率的光学遥感数据。Sentinel-2卫星组成了一个多光谱成像系统&#xff0c;可用于监测地球表面的陆地变化、植被覆盖、水域和自然灾害等。它具有以下特性&am…

2019年认证杯SPSSPRO杯数学建模A题(第一阶段)好风凭借力,送我上青云全过程文档及程序

2019年认证杯SPSSPRO杯数学建模 纸飞机在飞行状态下的运动模型 A题 好风凭借力&#xff0c;送我上青云 原题再现&#xff1a; 纸飞机有许多种折法。世界上有若干具有一定影响力的纸飞机比赛&#xff0c;通常的参赛规定是使用一张特定规格的纸&#xff0c;例如 A4 大小的纸张…

java 体育明星管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web 体育明星管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysq…

JQuery异步加载表格选择记录

JQuery异步加载表格选择记录 JQuery操作表格 首先在页面中定义一个表格对象 <table id"insts" class"table"><thead><tr><th>列1</th><th>列2</th><th>例3</th><th></th></tr>…

世微AP2400 DC-DC降压恒流IC12-80V 9V/3A LED电动摩托车灯驱动芯片方案

1&#xff0c;做一款三功能LED车灯驱动方案 AP2400 是一款 PWM 工作模式,率、外围简单、外驱功率管&#xff0c;适用于 输入的降压 LED 恒流驱动芯片。外驱 MOS&#xff0c;大输出电流可达 6A。AP2400 可实现三段功能切换&#xff0c;通过 MODE1/2/3 切换三种功能模式&#xff…

群辉安装gitea

群辉安装gitea 安装giteagitea容器配置 安装gitea gitea容器配置

​安全可靠测评结果公告(2023年第1号)

安全可靠测评主要面向计算机终端和服务器搭载的中央处理器&#xff08;CPU&#xff09;、操作系统以及数据库等基础软硬件产品&#xff0c;通过对产品及其研发单位的核心技术、安全保障、持续发展等方面开展评估&#xff0c;评定产品的安全性和可持续性&#xff0c;实现对产品研…

Opencv实验合集——实验八:相机校准

1.定义 首先&#xff0c;我们来理解一下怎么从相机的角度去看一张图片&#xff0c;就好比如你用眼睛作为相机来进行摄影&#xff0c;但是比摄影机强的是&#xff0c;你是怎么摄影图片之后再将它矫正出现在你眼前&#xff0c;将歪歪扭扭的图片变成一张在你眼前是一张直的图片 为…

孩视宝、飞利浦、书客护眼台灯怎么样?多方位深度测评对比

台灯是我们日常生活中比较常见的一种桌面照明工具&#xff0c;不管是大人用于工作&#xff0c;还是小孩用于学习、阅读&#xff0c;都离不开它。不过我们也要注意&#xff0c;如果使用一款不合格的台灯&#xff0c;时间长了也会影响我们的眼睛健康&#xff0c;尤其是青少年学生…

类别型特征的编码方法

机器学习模型中除了决策树等少数模型能直接处理字符串形式的类别型特征输入外&#xff0c;逻辑回归、支持向量机等模型的输入必须是数值型特征才能在矩阵上执行线性代数计算&#xff0c;所以参加计算的特征必须是数值型的&#xff0c;对于非数值型的特征需要进行编码处理。对于…