• 算法训练---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;
            
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    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;
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    二 : 数组理解,二分查找

    链接 : 旋转数组的最小数字

    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];
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    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];
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    三 : 数组操作,排序思想的扩展使用

    链接 :调整数组顺序使奇数位于偶数前面

    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;
                }
            }
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    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;
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    本课内容结束 !

    在这里插入图片描述

  • 相关阅读:
    Eureka 概述与 Eureka Server 配置
    [PyTorch][chapter 60][强化学习-2-有模型学习2]
    Mockaroo - 在线生成测试用例利器
    VulnHub narak
    leetcode每日一题31
    服装ERP软件首要的好处都有哪些?
    意大利语专业,做翻译工作好不好
    【图形学】18 光照模型(三、镜面反射的Shader实现)
    Python 函数进阶-递归函数
    Django之路由层
  • 原文地址:https://blog.csdn.net/baijaiyu/article/details/126749804