【剑指offer刷题】查找算法

本文记录了在LeetCode上刷《剑指offer》中关于查找算法的题目,包括顺序查找、二分查找、哈希查找的应用,并通过实例解析了二维数组查找、旋转数组找最小数、唯一字符查找以及排序数组中查找数字等问题。通过这些算法的实践,旨在提升算法基础和编程能力。
摘要由CSDN通过智能技术生成

记录在Leetcode刷《剑指offer》的笔记,希望提高自己的算法基础和编程水平。这一篇文章刷的是查找算法的题目集合,在CSDN做一下记录,随时更新,一起学习吧。

如果顺序查找耗时间比较多,则重点考虑使用二分查找或者哈希查找算法。

刷题链接:https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/59bx1r/

1. 剑指 Offer 03. 数组中重复的数字

  • 题目
    在这里插入图片描述

  • 提交答案

思路:利用计数排序的思路,先遍历一遍,找出序列中的最大值,然后创建一个数组。每个数组元素存放的是对应位置的数据个数。

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        int myMax = 0;
        for(int i = 0; i < nums.size(); i++)
        {
            myMax = max(myMax, nums[i]);
        }
        vector<int> myVec(myMax + 1, 0);
        for(int i = 0; i < nums.size();i++)
        {
            if(myVec[nums[i]] == 0) myVec[nums[i]]++;
            else return nums[i];
        }
       return -1;
    }
};
  • 题目解析
    思路:哈希解法。必须要掌握的一种方法。
class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        unordered_map<int, bool> map;
        for(int num : nums) {
            if(map[num]) return num;//已经有一个数据了
            map[num] = true;
        }
        return -1;
    }
};

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

  • 题目
    在这里插入图片描述
  • 提交答案

思路:两层循环,遇到大于target的值就跳至下一行。

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

思路:从左下角开始遍历。
当 matrix[i][j] > target 时,执行 i-- ,即消去第 i 行元素;
当 matrix[i][j] < target 时,执行 j++ ,即消去第 j 列元素;
当 matrix[i][j] = target 时,返回 true,代表找到目标值。

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

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

  • 题目
    在这里插入图片描述

  • 提交答案

思路:倒序查找,直到找到比当前值大的数字。

class Solution {
public:
    int minArray(vector<int>& numbers) {
        for(int i = numbers.size() - 1; i >= 0; i--)
        {
            int j = i - 1;
            if( j < 0) break;
            if(numbers[j] > numbers[i]) return numbers[i];
        }
        return numbers[0];
    }
};
  • 题目解析

思路:二分查找

class Solution {
public:
    int minArray(vector<int>& numbers) {
        int i = 0, j = numbers.size() - 1;
        while (i < j) {
            int m = (i + j) / 2;
            if (numbers[m] > numbers[j]) i = m + 1;
            else if (numbers[m] < numbers[j]) j = m;
            else j--;
        }
        return numbers[i];
    }
};

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

  • 题目
    在这里插入图片描述
  • 提交答案

思路:这里考察哈希表,不过哈希表的值需要设定一个结构体类型,分别存储字符出现的顺序和次数。

struct Mystruct
{
    int arr;//次序
    int count;//计数
};
class Solution {
public:
    char firstUniqChar(string s) {
        if(s.size() == 0) return ' ';
        int arr = 0;//次序
        map<char, Mystruct> myMap;
        for(int i = 0; i < s.size(); i++)
        {
            myMap[s[i]].count++;
            if(myMap[s[i]].count ==  1)//首次出现
            {                
                myMap[s[i]].arr = arr;
                arr++;//下次
            }
        }
        arr = 100;
        char tmp = ' ';
        for(auto x : myMap)
        {
            if(x.second.count == 1 && arr > x.second.arr) 
            {
                arr = x.second.arr;
                tmp = x.first;
            }
        }
        return tmp;
    }
};
  • 题目解析

思路:题目解析中运用了vector配合unordered_map进行实现。

class Solution {
public:
    char firstUniqChar(string s) {
        vector<char> keys;
        unordered_map<char, bool> dic;
        for(char c : s) {
            if(dic.find(c) == dic.end())
                keys.push_back(c);
            dic[c] = dic.find(c) == dic.end();
        }
        for(char c : keys) {
            if(dic[c]) return c;
        }
        return ' ';
    }
};

5. 剑指 Offer 53 - I. 在排序数组中查找数字

  • 题目
    在这里插入图片描述
  • 提交答案

思路:考察二分查找。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        if(nums.size() == 0)return 0;
        int L = 0;
        int H = nums.size() - 1;
        int mid = (L + H)/2;
        //二分查找
        while(L <=H)
        {
            if(target == nums[mid])break;
            else if(target > nums[mid]) {L = mid +1;}
            else H = mid - 1;
            mid = (L + H)/2;
        }
        
        if(nums[mid] != target) return 0;
        int count  = 0;
        int i = 0;
        cout<<nums[mid];
        while(mid + i < nums.size())//找右边
        {
            if( nums[mid + i] == target)
            {
                count++;
                i++;
            } 
            else break;
        }
        i = 1;
        while(mid - i >= 0)//找左边
        {
           if( nums[mid - i] == target)
            {
                count++;
                i++;
            } 
            else break;
        }
        return count;
    }
};
  • 题目解析

思路:也是二分查找,只不过变形了一下,如果相等的时候不退出来,等到搜索到边界的时候才退。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        // 搜索右边界 right
        int i = 0, j = nums.size() - 1;
        while(i <= j) {
            int m = (i + j) / 2;
            if(nums[m] <= target) i = m + 1;
            else j = m - 1;
        }
        int right = i;
        // 若数组中无 target ,则提前返回
        if(j >= 0 && nums[j] != target) return 0;
        // 搜索左边界 right
        i = 0; j = nums.size() - 1;
        while(i <= j) {
            int m = (i + j) / 2;
            if(nums[m] < target) i = m + 1;
            else j = m - 1;
        }
        int left = j;
        return right - left - 1;
    }
};

6. 剑指 Offer 53 - II. 0~n-1 中缺失的数字

  • 题目
    在这里插入图片描述
  • 题目解析

思路:二分查找

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int i = 0, j = nums.size() - 1;
        while(i <= j) {
            int m = (i + j) / 2;
            if(nums[m] == m) i = m + 1;
            else j = m - 1;
        }
        return i;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

非晚非晚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值