LeetCode日记——【数据结构】数组与矩阵专题

  题1:移动0

LeetCode题号:283

难度:Easy

题目描述:

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

示例:

输入: [0,1,0,3,12]
输出: [1,3,12,0,0]

代码:

class Solution {
    public void moveZeroes(int[] nums) {
        int cnt = 0;
        for(int num:nums){
            if(num!=0){
                nums[cnt++]=num;
            }
        }
        while (cnt < nums.length) {
            nums[cnt++] = 0;
        }
    }
}

分析:

设置一个计数值cnt来统计数组中非0的元素的个数。

遍历整个数组,遇到不是0的数,就将nums[cnt]位置设为该数,然后计数值cnt++。

遍历完整个数组后,cnt即为非0元素的个数。然后我们从索引cnt开始(因为数组下标从0开始)把数组的后部分都设置为0即可。

 

  题2:重塑矩阵

LeetCode题号:556

难度:Easy

题目描述:

在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据。

给出一个由二维数组表示的矩阵,以及两个正整数r和c,分别表示想要的重构的矩阵的行数和列数。

重构后的矩阵需要将原始矩阵的所有元素以相同的行遍历顺序填充。

如果具有给定参数的reshape操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

示例 1:

输入:
nums =
[[1,2],
[3,4]]
r = 1, c = 4
输出:
[[1,2,3,4]]
解释:
行遍历nums的结果是 [1,2,3,4]。新的矩阵是 1 * 4 矩阵, 用之前的元素值一行一行填充新矩阵。

代码:

class Solution {
    public int[][] matrixReshape(int[][] nums, int r, int c) {
        int or = nums.length;
        int oc = nums[0].length;
        if(or*oc!=r*c) return nums;
        int[][] newnums = new int[r][c];
        int index = 0;
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                newnums[i][j] = nums[index / oc][index % oc];
                index++;
            }
        }
        return newnums;        
    }
}

分析:

核心在于,设置双重循环遍历新数组的每个位置,然后利用nums[index/oc][index%oc]为newnums[i][j]赋值。

 

  题3:最大连续1的个数

LeetCode题号:485

难度:Easy

题目描述:

给定一个二进制数组, 计算其中最大连续1的个数。

示例 1:

输入: [1,1,0,1,1,1]
输出: 3
解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 3。

代码:

class Solution {
    public int findMaxConsecutiveOnes(int[] nums) {
        int count=0,max=0;
        for(int num:nums){
            count=num==0?0:++count;
            max=Math.max(max,count);
        }
        return max;
    }
}

 分析:

这道题思想挺经典的,一定要会!!

遍历所有元素:遇到1,count计数,遇到0,count清零。无论1还是0,每遍历元素,更新一下max值为max(max,count)

 

 

  题4:有序矩阵查找

 LeetCode题号:240

 难度:Medium

 题目描述:

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性:

每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
示例:

现有矩阵 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。

代码:

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        if(matrix==null||matrix.length==0||matrix[0].length==0) return false;
        int m = matrix.length, n = matrix[0].length;
        int r=0,c=n-1;
        while(r<m && c>=0){
            if (target==matrix[r][c]) return true;
            else if (target<matrix[r][c]) c--;
            else r++;        
        }
        return false;        
    }
}

 分析:

 从右上角的元素开始查找,若比target大,左移一位,若比target小,下移一位。

 

  题5:有序矩阵中第k小的元素

 LeetCode题号:378

 难度:Medium

 题目描述:

给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。
请注意,它是排序后的第 k 小元素,而不是第 k 个不同的元素。

 示例:

matrix = [
[ 1, 5, 9],
[10, 11, 13],
[12, 13, 15]
],
k = 8,

返回 13。

  

   题6:错误的集合

 LeetCode题号:645

 难度:Easy 

题目描述:

集合 S 包含从1到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个元素复制了成了集合里面的另外一个元素的值,导致集合丢失了一个整数并且有一个元素重复。

给定一个数组 nums 代表了集合 S 发生错误后的结果。你的任务是首先寻找到重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。

示例 1:

输入: nums = [1,2,2,4]
输出: [2,3]

代码:

class Solution {
    public int[] findErrorNums(int[] nums) {
        int n = nums.length;
        int[] count = new int[n];
        int repeat = 0, blank = 0;
        for(int num:nums){
            count[num-1]++;             
        }
        for(int i=0;i<n;i++){
            if (count[i]==2) repeat = i;
            if (count[i]!=2 && count[i]!=1) blank = i;
        }
        int[] result = new int[2];
        result[0] = repeat+1;
        result[1] = blank+1;
        return result;
    }
}

 分析:

第一个完全自己写出来的代码!!我太苦了...

应用的是桶排序的思想,count数组中下标表示数字-1,元素的值表示该数字出现的次数。应该是有一个2,一个null,其他都为1。

然后把2的下标+1和null的下标+1记录下来返回即可。

 

  题7:寻找重复数

 LeetCode题号:287

 难度:Medium

题目描述:

给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

示例 1:

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

代码:

class Solution {
    public int findDuplicate(int[] nums) {
        int n =nums.length-1;
        int[] count = new int[n];
        for(int num:nums){
            if(count[num-1]>0) return num;
            count[num-1]++;
        }
        return 0;
    }
}

分析:

设置一个计数数组,把每个元素的个数记录下来,如果个数大于1,则该数就是重复的数。

 

  题8:优美的排列ii

 LeetCode题号:667

 难度:Medium

题目描述:

给定两个整数 n 和 k,你需要实现一个数组,这个数组包含从 1 到 n 的 n 个不同整数,同时满足以下条件:

① 如果这个数组是 [a1, a2, a3, ... , an] ,那么数组 [|a1 - a2|, |a2 - a3|, |a3 - a4|, ... , |an-1 - an|] 中应该有且仅有 k 个不同整数;.

② 如果存在多种答案,你只需实现并返回其中任意一种.

示例 1:

输入: n = 3, k = 1
输出: [1, 2, 3]
解释: [1, 2, 3] 包含 3 个范围在 1-3 的不同整数, 并且 [1, 1] 中有且仅有 1 个不同整数 : 1

 

 

  题10:托普利兹矩阵

 LeetCode题号:766

 难度:Easy

题目描述:

如果矩阵上每一条由左上到右下的对角线上的元素都相同,那么这个矩阵是 托普利茨矩阵 。

给定一个 M x N 的矩阵,当且仅当它是托普利茨矩阵时返回 True。

示例 1:

输入:
matrix = [
  [1,2,3,4],
  [5,1,2,3],
  [9,5,1,2]
]
输出: True
解释:
在上述矩阵中, 其对角线为:
"[9]", "[5, 5]", "[1, 1, 1]", "[2, 2, 2]", "[3, 3]", "[4]"。
各条对角线上的所有元素均相同, 因此答案是True。

代码:

class Solution {
    public boolean isToeplitzMatrix(int[][] matrix) {
        for (int i = 0; i < matrix[0].length; i++) {
            if (!check(matrix, matrix[0][i], 0, i)) {
                return false;
        }
    }
    for (int i = 0; i < matrix.length; i++) {
        if (!check(matrix, matrix[i][0], i, 0)) {
            return false;
        }
    }
    return true;
    }
    private boolean check(int[][] matrix, int expectValue, int row, int col) {
        if (row >= matrix.length || col >= matrix[0].length) {
           return true;
        }
        if (matrix[row][col] != expectValue) {
            return false;
        }
        return check(matrix, expectValue, row + 1, col + 1);
    }
}

分析:

check方法验证某一条对角线的数是否都等于expectValue,若是,返回true,否则返回false。

写两组循环,第一组循环验证右上三角的所有对角线,循环次数为第一个元素的个数,即矩阵列数。

第二组循环验证左下三角的所有对角线,循环次数为矩阵元素的个数,即矩阵行数。

 

  题12:分隔数组

LeetCode题号:769

 难度:Medium

题目描述:

数组arr是[0, 1, ..., arr.length - 1]的一种排列,我们将这个数组分割成几个“块”,并将这些块分别进行排序。之后再连接起来,使得连接的结果和按升序排序后的原数组相同。

我们最多能将数组分成多少块?

示例 1:

输入: arr = [4,3,2,1,0]
输出: 1
解释:
将数组分成2块或者更多块,都无法得到所需的结果。
例如,分成 [4, 3], [2, 1, 0] 的结果是 [3, 4, 0, 1, 2],这不是有序的数组。

代码:

class Solution {
    public int maxChunksToSorted(int[] arr) {
        if(arr==null) return 0;
        int ret = 0;
        int right = arr[0];
        for(int i=0;i<arr.length;i++){
            //right记录当前遍历到的最大的数
            right = Math.max(arr[i],right);
            //当前最大的数就是当前遍历到的下标,计数++
            if (right == i) ret++;
        }
            return ret;
    }
}

分析:

right变量记录当前遍历到的最大的数,若最大的数刚好等于当前下标,则计数++。

 

posted @ 2020-06-15 22:07  菅兮徽音  阅读(221)  评论(0编辑  收藏  举报