算法训练---Day1

一 : 二维数组相关

链接 : 二维数组中的查找

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-- , 直到遇到奇数 ,根据"奇数在前 , 偶数在后的原则" , 对这两个数进行交换 . 但是 , 这样处理的结果并不能保证奇数和奇数,偶数和偶数之间的相对位置不变 .

所以我们的第二种思路是 , 从数组开头向后遍历 , 当遇到奇数时 , 开始三板斧 :

  1. 保存当前奇数的内容 ;
  2. 将当前奇数之前的内容整体向后移动一位 ;
  3. 将保存的奇数内容填充到数组前面 , 位置在已经排好位置的所有奇数的后一位 .

图示如下 :

在这里插入图片描述

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;
            }
        }
    }
}

本课内容结束 !

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值