《剑指offer》每日分享三道题 -1 day

本文介绍了三种算法问题的解决方案:1) 杨氏矩阵查找元素,通过对比右上角元素缩小查找范围;2) 旋转数组中最小值的二分查找实现,处理特殊情况;3) 调整数组顺序使奇数位于偶数前面,分别提供改变和不改变相对位置的策略。这些算法思想在数组操作中具有广泛应用。
摘要由CSDN通过智能技术生成

《剑指offer》中都是必刷的题目,接下来我将会出一个系列的博文来带大家和我一样完成这一系列的题目。

1. 杨氏矩阵查找元素

首先给大家一个杨氏矩阵的示意图,如图所示:
在这里插入图片描述

一个二维数组从左到右,从上到下都是递增的
那么我们如何查找到一个数组元素是否存在呢?

大多数情况下,在数组元素并不是很多的情况下我们都会进行数组遍历从而确定。

接下来将会给大家呈现一种新的方法

1.首先我们需要清楚的一件事情就是:

*查找的过程就是排除的过程,一次过程排除的越多效率就越高

思路:跟右上角(左下角)的元素进行比较, 如果比右上角的元素大,就排除那一行;如果比右上角的元素小,就排除那一列。
临界条件:找到了或者排除到数组的形式已经不存在了。*

根据上面思路中的方法我们可以清楚地发现,每一个二维数组的右上角或者左下角都是它所在行和列的最大最小值,那么我们就可以和右上角或者左下角的元素进行大小的比对,从而不断缩小数组的大小,从而最终确定所要查找元素是否存在。

class Solution{
	public:
	bool Find(int target,vector<vector<int >>array){
		//声明i,j 来代表行和列
		int i=0;
		int j=array[0].size()-1;
		//我们选择从右上角的那个元素进行比较,所以在数组缩小的进行中,是i逐渐增加而j逐渐减小
		while(i<array[0].size()&&j>=0){
			if(target<array[i][j])
				j--;
			else if(target>a[i][j])
				i++;
			else
				return true;
		}
		//当跳出循环,说明数组中并不存在数组元素
		return false;
	}
};

2. 查找旋转数组中的最小值(二分查找实现)

首先来一张旋转数组的示意图

非递减序列(递增或者是存在数组元素相等)的前x个值旋转到后面
旋转之后形成两部分,这两部分都是非递减序列

在这里插入图片描述

思路:如果中间值大于左值,说明中间值属于前半部分,left=mid;
如果中间值小于左值,说明中间值在后半部分,right=mid;
终止条件: 1.左值等于中间值等于右值,那么得用遍历的方法
2.部分划分的过程中,左指针和右指针相邻,那么右指针就是最小值

class Solution{
	public:
	int minNumberInRotateArray(int[]array){
		//对于特殊情况的添加,都是在用例通过大多数之后,才想起来的
		//但是长几次记性之后就会想在最前面了,嗨嗨。
		if(array==NULL|| array.lenth==0)
			return 0;
		
		//二分查找实现的思路
		int left=0;
		int right=array.length-1;
		int mid=0;
		
		while(left<right){
			
			if(right-left==1){//当传来的数组是只有两个元素的时候
				mid=right;
				break;
			}
			//特殊情况,当数组中都是相等的元素的时候,二分查找的方式效率就已经很低了
			//这时采取遍历的方式效率就会更高
			if(array[left]==array[right]&&array[left]==array[mid]){
				int result=array[0];
				for(int i=0;i<array.lenth;i++){
					if(result>array[i]){
						result=array[i];
					}
				}
				return result;
			}
			//在最开始思路写代码的时候,确定最小值位置
			mid=(right+left)>>1;
			if(array[mid]>array[left]){
				left=mid;
			}
			else{
				right=mid;
			}
		}
		//在数组不断缩小进行精确定位时候,返回的就是最小值
		return array[mid];
	}
}

3. 调整数组顺序使得奇数位于偶数前面

那么在我们遇到一个救赎都存在的数组时,
让我们将奇数和偶数进行前后区分的时候,我们想到的方法都是什么呢?

1. 可以改变奇偶数在数组中的相对位置

我们可以采取快排中的一种思路,就是采用前后指针的思路,从前面后面同时开始,找到第一个奇数和偶数的时候,就将两个位置的奇偶数进行交换。

void reSort(int a[],int num){
	int left=0;
	int right=num-1;
	
	while(left<right){//当找到奇偶数时
		while(left<right&&(a[left]&1)){
		left++;
		}
		while(left<right&&!(a[right]&1)){
		right--;
		}
		//当找到奇偶数,为了避免指针的加减出现前后指针大小出现问题
		if(left<right)
		{
		int temp=a[left];
		a[left]=a[right];
		a[right]=temp;
		}
	}
	
}

2.不改变数组中元素的相对位置

那如何实现不改变数组中的相对位置呢?
当然你可以通过新数组再多重步骤实现,那么如何实现更高效率的算法呢?
我们可以采用前插的方式:

思路:遇到奇数的时候进行前插,并且将这个奇数之前的所有偶数向后挪动一位. 就是现在这个奇数之前,已经进行前插的奇数个数之后那些个偶数集体后移一位。

class Solution{
	public:
	void reOrderArray(int []array){
		if(array==NULL||array.length==0){
			return ;
		}
		
		int k=0;//
		for(int i=0;i<array.lenght;i++){
			if(array[i]&1==1){
				int temp=array[i];
				int j=i;
				while(j>k){ //不能=
					array[j]=array[j-1];
					j--;
				}
				//将奇数进行前插
				array[k++]=temp;
			}
		}
	}
}

4. 鸡汤来啦

在20左右的年纪,身处大学时代的我们,难免会感到前路迷茫而不知所措,在迷茫中,不知不觉的看着日子一天天过去。希望下面的句子能够给你指引:

“我不知道需要多少时间我才会取得辉煌,我只是想尽我所能去成为最出色的篮球运动员” —— 科比 布莱恩特

让我们不负韶华,一起成长!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值