剑指offer刷题记录

剑指offer

T03:数组中重复的数字

找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例 1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
限制:
2 <= n <= 100000

解决本题重点是,需要时间O(n),空间O(1)。采用原地解法。考虑到n长的数组所有数字都在0~n-1,关键思路为:
遍历数组,尽可能通过交换把元素放在其对应下标的地方。如果发现待交换的目标重复了则返回。
在这里注意一个特例,[3,4,2,0,0,1],如果交换完直接i++的话会忽略换完以后的元素。所以换完还要继续考虑当前元素。
(不过这样的时间复杂度是否不同?anyway这真的不是一道easy……)

class Solution {
public:
    void swap(vector<int>& nums,int a_index,int b_index){
        int tmp = nums[a_index];
        nums[a_index]=nums[b_index];
        nums[b_index]=tmp;
    }
    int findRepeatNumber(vector<int>& nums) {
        //原地交换,把数放在下标上
        int i=0;
        while(i<nums.size()){
            if(nums[i]==i){
                i++;
                continue;
            }
            if(nums[i]==nums[nums[i]]) return nums[i];
            swap(nums,i,nums[i]);
        }
        return -1;
    }
};

T04:二维数组二分查找

在一个 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 withinRange(int r,int c,vector<vector<int>>& matrix){
        if(r<0 || r>=matrix.size() || c<0 || c>=matrix[0].size()) return false;
        return true;
    }
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        int n = matrix.size();
        if(n==0) return false;
        int m = matrix[0].size();
        int r = 0,c = m-1;
        while(withinRange(r,c,matrix)){
            if(matrix[r][c]==target) return true;
            if(matrix[r][c]>target){
                c--;
                continue;
            }else{
                r++;
                continue;
            }
        }
        return false;
    }
};

T10 青蛙跳台阶

dp[i]=dp[i-1]+dp[i-2]

T11 旋转数组的最小数

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [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

二分查找:
注意一些特例:

  • 正常:[3,4,5,1,2]
  • 容易想到:[2,2,2,2,2]
  • 扑街:[2,1,2,2,2]

这里比较的元素都是numbers[r]

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

T12:矩阵图中求单词

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。
image
示例 1:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true
示例 2:
输入:board = [["a","b"],["c","d"]], word = "abcd"
输出:false

主要思路就是dfs深度搜索,为了防止循环查找,需要用vis数组记录是否访问过。每次查找失败后,要回退vis数组。
为了方便回退,需要把vis数组带在dfs参数里。

class Solution {
public:
    vector<int> dx = {-1,0,0,1};
    vector<int> dy = {0,-1,1,0};
    bool flag = false;
    void dfs(vector<vector<char>>& board,vector<vector<bool>>& vis,int x,int y,int cur_word,string word){
        if(flag || x<0 || y<0 || x>=board.size() || y>=board[0].size()) return;
        if(vis[x][y]) return;
        if(board[x][y]!=word[cur_word]) return;
        vis[x][y]=true;
        if(cur_word==word.length()-1){
            flag=true;
            return;
        }else{
            for(int i=0;i<4;i++){
                dfs(board,vis,x+dx[i],y+dy[i],cur_word+1,word);
            }
            if(!flag) vis[x][y]=false;
        }
    }
    bool exist(vector<vector<char>>& board, string word) {
        int n = board.size();
        int m = board[0].size();
        vector<vector<bool>> vis(n,vector<bool>(m,false));
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(flag) return true;
                dfs(board,vis,i,j,0,word);
            }
        }
        return flag;
    }
};
posted @ 2021-09-24 11:38  达达达达达  阅读(54)  评论(2)    收藏  举报