剑指offer之数组(1)

剑指offer 刷题笔记–数组(1)

3 . 数组中重复的数字 难度:简单

题目规定长度为n的数组中所有元素的大小都在0~n-1这个范围内,所以查找重复元素的时候要充分利用这个条件。也就是说,在遍历数组的时候,我们将每个元素放到对应的数组下标中(如:nums[0]为2,那么我们就将0下标的元素与2下标的元素交换,此时nums[2]就为2),当遍历到一个下标为i的元素x(即x=nums[i]),并且nums[x] == x时,我们就找到了这个重复元素x。

class Solution {
    public int findRepeatNumber(int[] nums) {
        int i = 0;
        while(i < nums.length){
            if(i == nums[i]){
                i++;
                continue;
            }
            if(nums[i]  == nums[nums[i]])    return nums[i];
            int tmp = nums[i];
            nums[i] = nums[tmp];
            nums[tmp] = tmp;
        }
        return -1;
    }
}

11. 旋转数组的最小数字 难度:简单

查找数组中的数字,首选二分查找,时间复杂度O(logn)。

本题与寻常二分查找有所不同的是,在查找过程中遇到中间下标元素与边界元素相等的情况时,改为线性查找,此线性查找区间还是这一轮二分查找的区间[l,r],在这个区间中找到最小元素即可。

class Solution {
    public int minArray(int[] numbers) {
        int l = 0, r = numbers.length-1;
        while(l < r){
            int mid = (l + r)/2;
            if(numbers[mid] > numbers[r])   l = mid + 1;
            else if(numbers[mid] < numbers[r])   r = mid;
            else{
                //相等
                int x = l;
                for(int i = l;i < r; ++i){
                    if(numbers[i] < numbers[x])     x=i;
                }
                return numbers[x];
            }
        }
        return numbers[l];
    }
}

4. 二维数组中的查找 难度:中等

根据该二维数组的特点:每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。我们可以锁定该二维数组的右上角元素,每次将该元素与想要寻找的元素比较,如果matrix[i] [j]< target,就排除一行,如果matrix[i] [j] > target,就排除一列,以此可以很快找到想要的元素。

class Solution {
    public boolean findNumberIn2DArray(int[][] matrix, int target) {
        if(matrix == null || matrix.length == 0)   return false;
        int i = 0,j = matrix[0].length-1;
        while(i < matrix.length && 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;
    }
}

21. 调整数组顺序使得奇数位于偶数前面 难度:简单

用双指针遍历整个数组:左指针遇到偶数停下,右指针遇到奇数停下,交换左右指针指向的元素。重复这个过程直到两 指针相遇为止。

class Solution {
    public int[] exchange(int[] nums) {
        int l = 0, r = nums.length - 1;
        while(l < r){
            while(l < r && nums[l]%2 == 1)  l++;
            while(l < r && nums[r]%2 == 0)  r--;
            int tmp = nums[l];
            nums[l] = nums[r];
            nums[r] = tmp;
        }
        return nums;
    }
}

29. 顺时针打印矩阵 难度: 简单

关键在于设置左、右、上、下、边界来约束打印时的下标走向。每次打印完一行或者一列的时候,刷新边界值即可。当左右边界或者上下边界越界时打印结束。

class Solution {
    public int[] spiralOrder(int[][] matrix) {
        if(matrix.length == 0)  return new int[0];
        int l = 0;//左边界
        int r = matrix[0].length-1;//右边界
        int u = 0;//上边界
        int n = matrix.length-1;//下边界
        int[] res = new int[(r+1)*(n+1)];
        int x = 0;
        while(true){
            for(int i = l;i<=r;++i){
                res[x++] = matrix[u][i];
            }
            if(++u>n)   break;
            for(int i = u;i<=n;++i){
                res[x++] = matrix[i][r];
            }
            if(--r<l)   break;
            for(int i = r;i>=l;--i){
                res[x++] = matrix[n][i];
            }
            if(--n<u)   break;
            for(int i = n;i>=u;--i){
                res[x++] = matrix[i][l];
            }
            if(++l>r)   break;
        }
        return res;
    }
}

17. 打印从1到最大的n位数 难度:简单

只要求得最大的n位数就很简单:如最大的3位数为999=103-1

class Solution {
    public int[] printNumbers(int n) {
        int count = (int)Math.pow(10,n)-1;
       
        int[] res = new int[count];
        for(int i = 0;i<count;++i){
            res[i] = i+1;
        }
        return res;
    }
}

12.数组中的路径 难度:中等

方法:深度优先搜索+剪枝 通过构造一个深度优先搜索的方法,传递的参数有五个:二维字符数组board,该单词的字符数组ch,二维数组小标i,j,单词字符数组下标k。

剪枝:遇到这条路不可能走通的情况下(此元素与目标字符不同,此元素已经被访问),立刻返回。

class Solution {
    public boolean exist(char[][] board, String word) {
        char[] ch = word.toCharArray();

        for(int i = 0;i<board.length;++i){
            for(int j = 0;j<board[0].length;++j){
                if(dfs(board,ch,i,j,0)) 
                    return true;
               
            }
        }
        return false;
    }
    public boolean dfs(char[][] board,char[] word,int i,int j,int k){
        if(i<0 || j<0 || i>=board.length || j>=board[0].length || word[k] != board[i][j])   return false;
        if(k == word.length-1)  return true;
        char c =  board[i][j];
        board[i][j] = '\0';
        boolean res = dfs(board,word,i+1,j,k+1)||dfs(board,word,i-1,j,k+1)
        ||dfs(board,word,i,j+1,k+1) ||dfs(board,word,i,j-1,k+1);
        board[i][j] = c;
        return res;
    }
}

代码参考LeetCode作者:Krahets

  • 11
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值