力扣刷题-数组


前言

本博客仅做学习笔记,如有侵权,联系后即刻更改

科普:


学习路线

参考文章

时间/空间复杂度

时间复杂度

时间复杂度考虑最坏时间复杂度

  • T(n) = O(f(n))
    f(n) 是算法代码执行的总步数,也叫操作数
  • O(logn)
    对于对数复杂度来说,不管是以 2、3 为底,通通记作 O(logn)
    在这里插入图片描述
  • 常见时间复杂度
    在这里插入图片描述

空间复杂度

在衡量代码的空间复杂度的时候,只关心运行过程中临时占用的内存空间

  • n 作为数据集大小,f(n) 指的是规模 n 所占存储空间的函数
    在这里插入图片描述

堆/栈

程序运行时所需的内存空间分为 固定部分,和可变部分
在这里插入图片描述

数组

在这里插入图片描述

知识点

for的增强型循环

  • 增强for循环遍历数组时使用的普通for循环,而遍历集合时使用的Iterator迭代器
  • 在使用增强型for循环不支持遍历时删除元素
  • 使用增强型for循环时,对遍历的集合需要做null判断,不然可能引发空指针异常。

快慢指针

  • 使用速度不同的指针(可用在链表、数组、序列等上面),来解决一些问题
  • 快指针 fast 指向当前要和 val 对比的元素,慢指针 slow 指向将被赋值的位置

滑动窗口

  • 一般就用在数组或者字符串上
  • 滑动:窗口可以按照一定的方向移动。
  • 窗口:窗口大小可以固定,也可以不固定,此时可以向外或者向内,扩容或者缩小窗口直至满足条件

模拟题

  • 模拟题本身不涉及算法,就是单纯根据题目所描述的模拟整个过程从而得到最后的结果

力扣704题-二分查找

确定区间为左闭右闭

  • 左节点可以等于右节点
  • middle要向前/后移动一位

数组的特点

  • 数组下标都是从0开始的
  • 数组内存空间的地址是连续的
class Solution {
    public int search(int[] nums, int target) {
        // 避免输入的target过大或过小
        if (target < nums[0] || target > nums[nums.length - 1]) 
            return -1;
         int left = 0,
         right = nums.length-1,
         middle;
         while(left <= right){
             middle = left + (right-left)/2;
             if(nums[middle] == target)
                return middle;
             else if(nums[middle] > target)
                 right = middle-1;
             else 
             	 left = middle+1;
         }
         return -1;
    }
}

相关题目

力扣35-搜索插入位置
class Solution {
    public int searchInsert(int[] nums, int target) {
        int len = nums.length -1;
        // 提前判断是否在区间内
        if(target < nums[0])
            return 0;
        else if(target > nums[len])
            return len+1;
        // 左闭右闭区间
        int left = 0, right = len, middle = 0;
        while(left <= right){
            middle = left + (right - left)/2;
            // target在右区间
            if(nums[middle] < target)
               left = middle+1;
            // target在左区间
            else if(nums[middle] > target)
              right = middle-1;
            else return middle; 
        }
        // 目标值插入数组中 
        return right+1;
    }
}
力扣34-在排序数组中查找元素的第一个和最后一个位置
class Solution {
    public int[] searchRange(int[] nums, int target) {
        int location = binarySearch(nums,target);

        if(location == -1){
            return new int[] {-1,-1};
        }
        // 确定左右边界
        int leftBorder =location ,rightBorder = location;
        while(leftBorder-1 >= 0 && nums[leftBorder-1] == nums[location]){
            leftBorder--;
        }
        while(rightBorder+1 < nums.length && nums[rightBorder+1] == nums[location]){
            rightBorder++;
        }
        return new int [] {leftBorder,rightBorder};

    }

// 二分查找
    public int binarySearch(int[] nums, int target){
        int len = nums.length;
        //  先判断是否在数组内
        if(nums.length == 0)
            return -1;
        else if(target < nums[0]) 
            return -1;
        else if(target > nums[len-1])
            return -1;
        // 左闭右闭
        int left = 0, right = len -1, middle = 0;
        while(left <= right){
            middle = left + (right-left)/2;
            if(target == nums[middle]){
                 return middle;
            }else if(target > nums[middle]){
                left = middle +1;
            }else {
                right = middle -1;
            }
        }
        return -1;
    }
}
力扣69-x的平方根
class Solution {
    public int mySqrt(int x) {
        int left = 0, right = x, middle = 0, ans = -1;
        while(left <= right){
            middle = left + (right - left)/2;
            if((long)middle*middle <= x){
                ans = middle;
                left = middle +1;
            }else 
            right = middle -1;
        }
         return ans;
    }
}
力扣367-有效的完全平方数
class Solution {
    public boolean isPerfectSquare(int num) {
        int left = 0, right = num, middle = 0;
        while(left <= right){
            middle = left + (right - left)/2;
            if((long)middle*middle == num){
                return true;
            }else if((long)middle*middle < num)
                left = middle+1;
            else right = middle -1;
        }
         return false;
    }
}

力扣27题-移除元素

移除元素

  • 是快慢指针的经典题目

暴力双层循环

class Solution {
    public int removeElement(int[] nums, int val) {
        int num = nums.length;
        for(int i=0; i<num; i++){
            if(nums[i] == val){
                for(int j=i; j<num-1; j++){
                    nums[j] = nums[j+1];
                }
                num--;
                i --;
            }
        }
        return num;
    }
}

快慢指针

class Solution {
    public int removeElement(int[] nums, int val) {
        int slow = 0;
        int fast = 0;
        for(; fast<nums.length; fast++){
            if(nums[fast] != val){
                nums[slow] = nums[fast];
                slow++;
            }
        }
        return slow;
    }
}

双向指针

class Solution {
    public int removeElement(int[] nums, int val) {
        int left = 0;
        int right = nums.length -1;
        while(left <= right){
            // 找左边等于val的元素
            while(left <= right && nums[left] != val)
                left ++;
            // 找右边不等于val的元素
            while(left <= right && nums[right] == val)
                right --;
            if(left < right)
                nums[left ++] = nums[right --]; 
        }
        return left;
    }
}

相关题目

力扣26-删除有序数组中的重复项
class Solution {
    public int removeDuplicates(int[] nums) {
        if(nums == null || nums.length == 0) return 0;
        int slowIndex = 0, fastIndex = 0;
        while(fastIndex < nums.length){ 
            if(nums[fastIndex] != nums[slowIndex]){
                if(fastIndex - slowIndex > 1)
                    nums[slowIndex+1] = nums[fastIndex];
                slowIndex ++;
            }
            fastIndex ++;
        }
        return slowIndex +1;        
    }
}
力扣283-移动零
class Solution {
    public void moveZeroes(int[] nums) {
        int slowIndex = 0;
        for(int fastIndex = 0; fastIndex < nums.length; fastIndex++){
            if(nums[fastIndex] != 0)
                nums[slowIndex++] = nums[fastIndex];
        }
        for(int i = slowIndex; i < nums.length; i++){
            nums[i] = 0;
        }
    }
}
力扣844-比较含退格的字符串

使用栈实现退格

class Solution {
    public boolean backspaceCompare(String s, String t) {
       return resolveStr(s).toString().equals(resolveStr(t).toString());
    }
    public StringBuilder resolveStr(String s){
        StringBuilder sta = new StringBuilder();
        for(char ch : s.toCharArray())
            if(ch != '#')
                 sta.append(ch);
            else if(sta.length() > 0) 
                sta.deleteCharAt(sta.length() -1);
        return sta;
    }
}

双指针从后往前

class Solution {
    public boolean backspaceCompare(String S, String T) {
        int sSkipNum = 0; // 记录S的#数量
        int tSkipNum = 0; // 记录T的#数量
        int i = S.length() - 1;
        int j = T.length() - 1;
        while (true) {
            // 从后向前遍历S
            while (i >= 0) {
                // 如果为#,计数加一 
                if (S.charAt(i) == '#') sSkipNum++;
                else {
                    // #的计数不为零,要过一轮
                    if (sSkipNum > 0) sSkipNum--;
                    // 直到#的个数为0,跳出和T的字符比对
                    else break;
                }
                i--;
            }
            while (j >= 0) { 
                if (T.charAt(j) == '#') tSkipNum++;
                else {
                    if (tSkipNum > 0) tSkipNum--;
                    else break;
                }
                j--;
            }

            // 先检验 S 或者 T 是否遍历到头了
            if (i < 0 || j < 0) break; 
            // 检验跳出时的字符是否相同,不同则可以跳出最外层循环,返回false
            if (S.charAt(i) != T.charAt(j)) return false;
            i--;j--;
        }
        // 说明S和T同时遍历完毕
        if (i == -1 && j == -1) return true;
        return false;
    }
};

力扣977题-有序数组平方排序

双指针法来解决,left 指向下标 0,right 指向下标 n - 1

class Solution {
    public int[] sortedSquares(int[] nums) {
       int right = nums.length-1, left = 0;
       int array[] = new int [nums.length];
       int pos = nums.length-1;

       while(left <= right){
           nums[left] = Math.abs(nums[left]);
           nums[right] = Math.abs(nums[right]);
           if(nums[left] > nums[right])
               array[pos--] = (int)Math.pow(nums[left++], 2);
            else {
                array[pos--] = (int)Math.pow(nums[right--], 2);
            }
       } 
       return array;
    }
}

力扣209题-长度最小子数组

滑动窗口

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int right=0, left=0, sum=0, num=Integer.MAX_VALUE;
        for(; right<nums.length;){
            sum += nums[right++];
            while(sum >= target){
                num = Math.min(num, right-left);
                sum -= nums[left++];
            }
        }
        return num == Integer.MAX_VALUE ? 0 : num;
    }
}

力扣59题-螺旋矩阵

  • 题目解析
    这是一道模拟题,难度中等,面试出现频率极高

  • 时空复杂度分析
    矩阵大小为 n²,需要全部遍历且填充,所以时间复杂度为 O(n²)
    此外额外维护了一个大小为 n² 的结果矩阵,所以空间复杂度为 O(n²)

class Solution {
    public int[][] generateMatrix(int n) {
        int w[][]= new int [n][n];
        int s=0,x=n-1,z=0,r=n-1;
        int sum=1,i;
        while(sum <= n*n){
            for(i=z; i<=r; i++)
            w[s][i] = sum++;
            s++; 
            for(i=s; i<=x; i++)
            w[i][r] = sum++;
            r--;
            for(i=r; i>=z; i--)
            w[x][i] = sum++;
            x--;
            for(i=x; i>=s; i--)
            w[i][z] = sum++;
            z++;
        }
        return w;
    }
}

总结

小小励志

有些事你现在不做,一辈子都不会做了。
如果你想做一件事,全世界都会为你让路。
《搭车去柏林》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值