leetcode数组刷题总结

文章目录

      • 理论基础
    • 704.二分查找
      • 二分查找系列题目
        • 153. 寻找旋转排序数组中的最小值
        • 33. 搜索旋转排序数组 *****
        • 35.搜索插入位置
        • 34.在排序数组中查找元素的第一个和最后一个位置
        • 69.x的平方根
        • 367.有效的完全平方数
    • 27.移除元素 (双指针)
        • 26.删除排序数组中的重复项
        • 283.移动零
        • 844.比较含退格的字符串
        • 977.有序数组的平方
    • 209.长度最小的子数组(最小滑动窗口)
      • 滑动窗口模板总结
      • ==相关题目==
        • 904.水果成篮(最大滑动窗口)
        • 76. 最小覆盖子串
        • 1004. 最大连续1的个数 III
        • 3. 无重复字符的最长子串
    • 59.螺旋矩阵Ⅱ(模拟题目,考察代码能力)
      • ==相关题目==
        • 54.螺旋矩阵
        • 剑指Offer 29.顺时针打印矩阵

理论基础

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

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

704.二分查找

leetcode数组刷题总结_第1张图片
大家写二分法经常写乱,主要是因为对区间的定义没有想清楚,区间的定义就是不变量。要在二分查找的过程中,保持不变量,就是在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;
    }
}

二分查找系列题目

153. 寻找旋转排序数组中的最小值

leetcode数组刷题总结_第2张图片

class Solution {
   //二分查找寻找数组的最小值
   public int findMin(int[] nums) {
       int left = 0;
       int right = nums.length - 1;
       while(left<right){
           int mid = (left + right)/2;
           if(nums[mid]>nums[right]){
               left = mid + 1;
           }else{
               right = mid;
           }
       }
       return nums[right];
   }
}

33. 搜索旋转排序数组 *****

leetcode数组刷题总结_第3张图片

class Solution {
    public int search(int[] nums, int target) {
        //在局部有序中使用二分查找
        int len = nums.length;
        if(len==0) return -1;
        if(len==1) return nums[0]==target?0:-1;
        int left = 0;
        int right = len - 1;
        while(left<=right){
            int mid = (left+right)/2;
            if(nums[mid] == target){
                return mid;
            }
            if(nums[0]<=nums[mid]){//左边有序
                if(nums[0]<=target && nums[mid]>target){//左闭右闭,左区间必须取等
                    right = mid - 1;

                }else{
                    left = mid + 1;  
                }
            }else{
                if(nums[mid]<target && target<=nums[right]){//同理 左闭右闭
                    left = mid + 1;
                }else{
                    right = mid - 1;
                }
            }
        }
        return -1;
    }
}

35.搜索插入位置

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

69.x的平方根

367.有效的完全平方数


27.移除元素 (双指针)

leetcode数组刷题总结_第4张图片
leetcode数组刷题总结_第5张图片

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.删除排序数组中的重复项

leetcode数组刷题总结_第6张图片
双指针,慢指针指向新数组的元素,快指针用来遍历。只有当快慢指针不同时,进行元素复制。相同的话就进行指针的移动

class Solution {
    public int removeDuplicates(int[] nums) {
        if(nums.length == 1){
            return 1;
        }
        int slow = 0;
        int fast = 1;
        while(fast<nums.length){
            if(nums[slow] == nums[fast]){
                fast++;
            }else{
                nums[slow+1] = nums[fast];
                slow++;
                fast++;
            }
        }
        return slow+1;
    }
}

283.移动零

844.比较含退格的字符串

977.有序数组的平方

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

leetcode数组刷题总结_第7张图片
窗口内是什么?
如何移动窗口的起始位置?
如何移动窗口的结束位置?

  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. 最小覆盖子串

leetcode数组刷题总结_第8张图片

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.螺旋矩阵Ⅱ(模拟题目,考察代码能力)

leetcode数组刷题总结_第9张图片
模拟画圆圈,注意区间统一就好

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.顺时针打印矩阵

你可能感兴趣的:(算法题,leetcode,算法,职场和发展,java,学习)