leetcode数组刷题总结

理论基础

数组是存放在连续内存空间上的相同类型数据的集合。

数组下标都是从0开始的。
数组内存空间的地址是连续的

704.二分查找

在这里插入图片描述
大家写二分法经常写乱,主要是因为对区间的定义没有想清楚,区间的定义就是不变量。要在二分查找的过程中,保持不变量,就是在while寻找中每一次边界的处理都要坚持根据区间的定义来操作,这就是循环不变量规则。
(左闭右闭)

class Solution {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        if (target < nums[0] || target > nums[right]){
            return -1;
        }
        while (left <= right){
            int mid = (left + right) / 2;
            if (target > nums[mid]){
                left = mid + 1;
            }
            if (target < nums[mid]){
                right = mid - 1;
            }
            if(target == nums[mid]){
                return mid;
            }
        }
        return -1;
    }
}

二分查找系列题目

35.搜索插入位置

34.在排序数组中查找元素的第一个和最后一个位置

69.x的平方根

367.有效的完全平方数


27.移除元素 (双指针)

在这里插入图片描述
在这里插入图片描述

class Solution {
    public int removeElement(int[] nums, int val) {
        int slow = 0;
        for (int fast = 0; fast < nums.length; fast++){
            if(nums[fast] != val){
                nums[slow] = nums[fast];
                slow += 1;
            }
        }
        return slow;
//双指针遍历到非val的值 slow+1
    }
}

相关题目推荐

26.删除排序数组中的重复项

283.移动零

844.比较含退格的字符串

977.有序数组的平方

209.长度最小的子数组(最小滑动窗口)

在这里插入图片描述
窗口内是什么?
如何移动窗口的起始位置?
如何移动窗口的结束位置?

  1. 窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
  2. 窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。
  3. 窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int result = Integer.MAX_VALUE;//定义无穷大
        int left = 0;
        int right = 0;
        int sum = 0;
        while (right<nums.length){
            sum = sum + nums[right];
            while (sum>=target){
                result = Math.min(result,right-left+1);
                sum = sum - nums[left];
                left++;
            }
            right++;
        }
        if (result==Integer.MAX_VALUE){return 0;}
        return result;
    }
}

滑动窗口模板总结

最小滑动窗口

while j < nums.length:
    判断[i, j]是否满足条件
    while 满足条件:
        不断更新结果(注意在while内更新!)
        i += 1 (最大程度的压缩i,使得滑窗尽可能的小)
    j += 1

最大滑动窗口

while j < nums.length:
    判断[i, j]是否满足条件
    while 不满足条件:
        i += 1 (最保守的压缩i,一旦满足条件了就退出压缩i的过程,使得滑窗尽可能的大)
    不断更新结果(注意在while外更新!)
    j += 1

区别

最大滑窗是在迭代右移右边界的过程中更新结果,而最小滑窗是在迭代右移左边界的过程中更新结果

相关题目

904.水果成篮(最大滑动窗口)

class Solution {
    //哈希表+最大滑动窗口
    public int totalFruit(int[] fruits) {
        int left = 0;
        int right = 0;//左右边界
        int result = 0;//最终结果
        int count = 0;//水果类别个数
        Map<Integer,Integer> map = new HashMap<>();//哈希表为 水果种类:个数
        for (int i=0;i<fruits.length;i++){
            map.put(fruits[i],0);
        }
        while(right<fruits.length){
            //1. 判断是否有当前水果(不存在的话类别加1) 其放入果篮当中 更新map
            if (map.get(fruits[right])==0){
                count++;//没有当前水果,种类要加1
            }
            map.put(fruits[right],map.get(fruits[right])+1);//放入果篮 key:水果类别,value:在原来的个数基础上加1
            // 2. 看当前水果种类是否大于2
            while (count>2){
                //判断第一种类别的水果个数是否为1(等于1的话 类别减去1) 更新map
                if (map.get(fruits[left])==1){
                    count--;
                }
                map.put(fruits[left],map.get(fruits[left])-1);
                left++;//左边界左移
            }
            result = Math.max(result,right-left+1);
            right++;
        }
        return result;
    }
}

76. 最小覆盖子串

在这里插入图片描述

class Solution {
    //最小滑窗
    public String minWindow(String s, String t) {
        if(s.length() == 0 || s == null || t.length() == 0 || t == null){
            return "";//特殊情况
        }
        int left = 0;
        int right = 0;
        int start = 0;//记录最终结果
        int size = Integer.MAX_VALUE;//记录字符串的大小
        int count = t.length();//需要的数
        int[] need = new int[128];//记录需要的字符个数
        for(int i=0;i<t.length();i++){
            need[t.charAt(i)]++;
        }

        while(right<s.length()){
            char c = s.charAt(right);//取字符
            if(need[c]>0){//需要这个字符
                count--;
            }
            need[c]--;//入窗口
            //当count==0,进行处理
            if(count == 0){
                while(left<right && need[s.charAt(left)]<0){//need元素小于0 说明他不是t所需要的
                    need[s.charAt(left)]++;
                    left++;
                } 
                //记录最大值
                if(right-left+1<size){
                    size = right - left + 1;
                    start = left;
                }
                //need>=0的情况了
                need[s.charAt(left)]++;
                left++;
                count++;//与前面区别
            }
            //更新右边界
            right++;
        }
        return size == Integer.MAX_VALUE ? "" : s.substring(start,start+size);

    }
}

1004. 最大连续1的个数 III

3. 无重复字符的最长子串

59.螺旋矩阵Ⅱ(模拟题目,考察代码能力)

在这里插入图片描述
模拟画圆圈,注意区间统一就好

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] result = new int[n][n];
        int loop = 0;//循环次数
        int i,j; //遍历的坐标
        int start = 0;//开始坐标 x和y相同
        int count = 1;

//1.循环画圈
        //边界全部采取左闭右开
        while (loop < n/2){
            //1.1 从左到右
            for (j = start;j < n-loop-1;j++){
                result[start][j] = count;
                count++;
            }
            // 1.2 从上到下
            for (i = start;i < n - loop-1;i++){
                result[i][j] = count;
                count++;
            }
            // 1.3 从右到左
            for (;j>loop;j--){
                result[i][j] = count;
                count++;
            }
            for(;i>loop;i--){
                result[i][j] = count;
                count++;
            }
            start++;
            loop++;
        }
//2.奇数个中间有点     
        if (n % 2 == 1){
            result[start][start] = count;
        }
        return result;
    }
}

相关题目

54.螺旋矩阵

剑指Offer 29.顺时针打印矩阵


版权声明:本文为studyForMokey原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。