IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【剑指Offer】查找算法(1) -> 正文阅读

[数据结构与算法]【剑指Offer】查找算法(1)

今天的题开始考研算法了,题目变得有意思了许多,其中第二题的数组反转是很经典的一类例题,值得细细琢磨。

剑指 Offer 04. 二维数组中的查找

在一个n* m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

示例:

现有矩阵 matrix 如下:

[
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
]

给定 target = 5,返回 true

给定 target = 20,返回 false

限制:

0 <= n <= 1000
0 <= m <= 1000

解法一(暴力查找)

class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        if(matrix.size() == 0)return false;
        int n = matrix.size(), m = matrix[0].size();
        for(int i = 0; i < n; ++ i){
            for(int j = 0; j < m; ++ j){
                if(matrix[i][j] == target){
                    return true;
                }
                if(matrix[i][j] > target){
                    break;
                }
            }
        }
        return false;
    }
};

算法思路:

在普通矩阵查找的基础上,逐行逐列遍历,因为行和列都有单调性,所以每一行在遍历时如果发现该元素已经大于目标值时则不必继续在这一行查询,由于单调性可以跳过这一行直接到下一行查询。这虽然用到了行递增条件,但没用到列递增这个条件,这种解法能过,但还能继续优化。

解法二(优化成线性查找)

class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        if(matrix.size() == 0)return false;
        int n = matrix.size(), m = matrix[0].size();
        if(m == 0)return false;
        int x = 0, y = m - 1;
        while(x < n && y >= 0){
            if(matrix[x][y] == target)return true;
            else if(matrix[x][y] > target)y --;
            else x ++;
        }
        return false;
    }
};

算法思路:

这次不从左上角出发,改成从右上角出发,遇到一个元素如果相同则返回true,大于目标值则左移,小于目标值则下移,当xy坐标有一越界时则返回false。下面证明一下正确性:

  • 左移(反证):假设存在目前遍历的位置在(x, y),假设此时目标值位于现在位置的右下方(x1, y1),因为遍历过程只有左移和下移,此时目标值被忽略。

    因为(x1, y1)(x, y)右下方,因此存在(x1, y)(x, y)同行,(x1, y1)同列,由题目条件可得matrix[x1][y] >matrix[x][y]matrix[x1][y]<matrix[x1][y1],当便利店到达(x1, y)时由条件得此时应该下移而不是左移,因此假设不成立。

  • 下移:与左移同理,用反证法就可以证明。

第一题结果

剑指 Offer 11. 旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2][1,2,3,4,5] 的一个旋转,该数组的最小值为1。

示例 1:

输入:[3,4,5,1,2]
输出:1

示例 2:

输入:[2,2,2,0,1]
输出:0
class Solution {
public:
    int minArray(vector<int>& numbers) {
        int n = numbers.size(), ans = min(numbers[0], numbers[n - 1]);
        int l = 0, r = n - 1;
        while(l < r){
            int mid = (l + r) / 2;
            if(numbers[mid] < numbers[r]){
                r = mid;
            }else if(numbers[mid] > numbers[r]){
                l = mid + 1;
            }else r --;
        }
        return numbers[l];
    }
};

算法思路:

将一个有序序列反转变成两个序列,两个序列依旧有序,我们称两个序列为AB,前为A,后为BA可以为空,B不能为空,这道题的主要思路就是将B数组用二分法收缩,收缩到个数为1,得到结果。定义头尾指针l, r, 每次二分都会得到一个mid,当numbers[mid] < numbers[r]时,此时midBr前移到mid;当numbers[mid]>numbers[r]时,此时midA中,l后移到mid+1;当numbers[mid]==numbers[r]时,两种情况都有可能,解决的方法是r前移一位,理由是:

  • 假设此时midAr前移一位,假设B此时长度只有1r前移完长度变为0,此时变成一个有序序列,二分查找依旧可以解决问题;如果B长度大于1r前移对求B中最小值无影响。
  • 假设此时midBr前移一位,假设B此时长度只有1,此种情况只有整个序列都相等,此时r前移对结果也没影响;如果B长度大于1r前移对求B中最小值无影响。

因此通过二分的方法很快就能求出结果。

第二题结果

剑指 Offer 50. 第一个只出现一次的字符

在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。

示例 1:

输入:s = "abaccdeff"
输出:'b'

示例 2:

输入:s = "" 
输出:' '

限制:

0 <= s 的长度 <= 50000
class Solution {
public:
    char firstUniqChar(string s) {
        // unordered_map<char, int> mp;
        int mp[26] = {0};
        for(auto w : s){
            mp[w - 'a'] ++;
        }
        for(auto w : s){
            if(mp[w - 'a'] == 1)return w;
        }
        return ' ';
    }
};

算法思路:

这一题就比较简单了,直接hash就可以解决,因为只有小写字母,所以开一个26大小的数组就可以存储。
第三题结果

【剑指Offer】系列:
【剑指Offer】栈
【剑指Offer】链表
【剑指Offer】字符串
【剑指Offer】查找算法

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-09-14 13:36:45  更:2021-09-14 13:37:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 12:12:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码