剑指offer 打卡计划 | 每天进步一点点 | 第一天

121 阅读2分钟

image-20220402205617479.png 一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

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

思路

(原地交换) O(n) 首先遍历一遍数组,如果存在某个数不在0到n-1的范围内,则返回-1。

下面的算法的主要思想是把每个数放到对应的位置上,即让nums[i] = i

从前往后遍历数组中的所有数,假设当前遍历到的数是 nums[i]=x,那么:

如果x != i && nums[x] == x,则说明 x 出现了多次,直接返回x即可;如果nums[x] != x那我们就把 x交换到正确的位置上,即 swap(nums[x], nums[i]),交换完之后如果nums[i] != i,则重复进行该操作。由于每次交换都会将一个数放在正确的位置上,所以swap操作最多会进行 n 次,不会发生死循环。 循环结束后,如果没有找到任何重复的数,则返回-1

时间复杂度分析: 每次swap操作都会将一个数放在正确的位置上,最后一次swap会将两个数同时放到正确位置上,一共只有 n 个数和 n 个位置,所以swap最多会进行 n−1次。所以总时间复杂度是 O(n)。

 class Solution {
 public:
     int findRepeatNumber(vector<int>& nums) {
         for(int i = 0; i < nums.size(); i++){
             while(nums[i] != nums[nums[i]]) swap(nums[i], nums[nums[i]]);
             if(nums[i] != i) return nums[i];
         }
         return -1;
     }
 };

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

(单调性扫描) O(n+m)

m x n矩阵 matrix中我们可以发现一个性质:对于每个子矩阵右上角的数xx左边的数都小于等于xx下边的数都大于x

图片.png

因此我们可以从整个矩阵的右上角开始枚举,假设当前枚举的数是 x

  • 如果 x 等于target,则说明我们找到了目标值,返回true
  • 如果 x小于target,则 x左边的数一定都小于target,我们可以直接排除当前一整行的数;
  • 如果x 大于target,则 x 下边的数一定都大于target,我们可以直接排序当前一整列的数;

排除一整行就是让枚举的点的横坐标加一,排除一整列就是让纵坐标减一。当我们排除完整个矩阵后仍没有找到目标值时,就说明目标值不存在,返回false

具体过程如下:

  • 1、初始化i = 0, j = matrix[0].size() - 1
  • 2、如果matrix[i][j] == target,返回true
  • 3、如果matrix[i][j] < targeti++,排除一行。
  • 4、如果matrix[i][j] > targetj--,排除一列。
  • 5、如果出界还未找到target,则返回false

c++代码

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

时间复杂度分析: 每一步会排除一行或者一列,矩阵一共有 n 行,m 列,所以最多会进行 n+m 步。所以时间复杂度是 O(n+m)。

剑指 Offer 05. 替换空格

思路

(线性扫描) O(n)

这个题在C++里比较好做,我们可以从前往后枚举原字符串:

  • 1、如果遇到空格,则在string类型的答案中添加 "%20"
  • 2、如果遇到其他字符,则直接将它添加在答案中;

时间复杂度分析: 原字符串只会被遍历常数次,所以总时间复杂度是 O(n)。

c++代码

 class Solution {
 public:
     string replaceSpace(string s) {
         string res;
         for(int i = 0; i < s.size(); i++){
             if(s[i] == ' ') res += "%20";
             else res += s[i];
         }
         return res;
     }
 };