一 : 二维数组相关
链接 : 二维数组中的查找
1.题目
在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
[
[1,2,8,9],
[2,4,9,12],
[4,7,10,13],
[6,8,11,15]
]
给定 target = 7,返回 true。
给定 target = 3,返回 false。
2.解题
2.1思路分析
最常规的思路 , 当然是遍历这个二维数组 , 依次进行比较 , 判断target是否存在于数组中 . 这种做法时间复杂度比较高 , 而且没有用到题目中行和列的规律 , 不推荐 !
第二种思路 , 是利用二维数组的行列特点 . 查找的过程 , 本质是排除的过程 !
2.2代码实现
C++代码
以比较二维数组右上角为例 :
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
int i = 0;
int j = array[0].size()-1;
while(i<array.size() && j >= 0){
if(target < array[i][j]){
j--;//当前列排除
}
else if(target > array[i][j]){
i++;// 当前行排除
}
else{
return true;
}
}
return false;
}
};
java代码
以比较二维数组左下角为例 :
public class Solution {
public boolean Find(int target, int [][] array) {
int i = array.length -1;
int j = 0;
while(i>=0 && j<array[0].length){
if(target > array[i][j]){
j++;
} else if(target < array[i][j]){
i--;
} else {
return true;
}
}
return false;
}
}
二 : 数组理解,二分查找
链接 : 旋转数组的最小数字
2.1题目
有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。
2.2解题
2.2.1 思路分析
最常规的思路是 , 遍历数组 , 求出数组中的最小值即可 , 然而这种方法和旋转完全不沾边 . 我们注意到 , 旋转之后的数组会被分为两部分 , 前部和后部 , 以对数组[1,2,3,4,5]进行旋转为例 .
有一种特殊情况 , 就是数组旋转后 , 最中间的元素 = 最左边的元素 = 最右边的元素 .如下图所示 :
这种情况下比较少见 , 如果出现 , 特殊处理即可 , 可以通过线性探测的方式 , 找出最小元素 !
2.2.2代码实现
C++代码
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if(rotateArray.empty()) {
return 0;
}
int left = 0;
int right = rotateArray.size()-1;
int mid = 0;
while(rotateArray[left] >= rotateArray[right]){
if(right-left == 1){
mid = right;
break;
}
mid = left + ((right-left) >> 1);
if(rotateArray[mid] == rotateArray[left] &&
rotateArray[mid] == rotateArray[right]){
int result = rotateArray[left];
for(int i=left+1;i<right;i++){
if(result > rotateArray[i]){
result = rotateArray[i];
}
}
return result;
}
if(rotateArray[mid] >= rotateArray[left]){
left = mid;
}
else{
right = mid;
}
}
return rotateArray[mid];
}
};
java代码
import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] rotateArray) {
if(rotateArray.length==0) {
return 0;
}
int left = 0;
int right = rotateArray.length-1;
int mid = 0;
while(rotateArray[left] >= rotateArray[right]){
if(right-left == 1){
mid = right;
break;
}
mid = left + ((right-left) >> 1);
if(rotateArray[mid] == rotateArray[left] &&
rotateArray[mid] == rotateArray[right]){
int result = rotateArray[left];
for(int i=left+1;i<right;i++){
if(result > rotateArray[i]){
result = rotateArray[i];
}
}
return result;
}
if(rotateArray[mid] >= rotateArray[left]){
left = mid;
}
else{
right = mid;
}
}
return rotateArray[mid];
}
}
三 : 数组操作,排序思想的扩展使用
链接 :调整数组顺序使奇数位于偶数前面
2.1题目
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
2.2解题
2.2.1思路分析
我们一开始的想法 , 肯定是定义两个指针 , 一个指针i , 指向数组开始位置 ; 一个指针j , 指向数组结束位置 . i++ , 直到遇到偶数 ; j-- , 直到遇到奇数 ,根据"奇数在前 , 偶数在后的原则" , 对这两个数进行交换 . 但是 , 这样处理的结果并不能保证奇数和奇数,偶数和偶数之间的相对位置不变 .
所以我们的第二种思路是 , 从数组开头向后遍历 , 当遇到奇数时 , 开始三板斧 :
- 保存当前奇数的内容 ;
- 将当前奇数之前的内容整体向后移动一位 ;
- 将保存的奇数内容填充到数组前面 , 位置在已经排好位置的所有奇数的后一位 .
图示如下 :
2.2.2代码实现
C++代码
class Solution {
public:
void reOrderArray(vector<int> &array) {
int k = 0 ;//记录已经排好序的奇数个数
for(int i=0;i<array.size();i++){
if(array[i] & 1){//是奇数,&是取出最低位
int tmp = array[i];//先将当前奇数保存起来
int j = i;
while(j > k){
array[j] = array[j-1];
j--;
}
array[k++] = tmp;
}
}
}
};
java代码
import java.util.*;
public class Solution {
public void reOrderArray(int [] array) {
int k = 0 ;//记录已经排好序的奇数个数
for(int i=0;i<array.length;i++){
if((array[i] & 1) == 1){//是奇数,&是取出最低位
int tmp = array[i];//先将当前奇数保存起来
int j = i;
while(j > k){
array[j] = array[j-1];
j--;
}
array[k++] = tmp;
}
}
}
}
本课内容结束 !