力扣刷题-数组


前言

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

科普:


学习路线

参考文章

时间/空间复杂度

时间复杂度

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

  • 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;
    }
}

总结

小小励志

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于力扣刷题C++常用操作,我可以给你一些常见的操作和技巧: 1. 使用 STL 容器和算法库:STL(Standard Template Library)是 C++ 标准库中的一个重要组成部分,包含了许多常用的容器和算法。在力扣刷题中,使用 STL 可以大大提高代码的效率和可读性。例如,vector 可以用来存储动态数组,sort 可以用来排序等等。 2. 使用 auto 关键字:auto 关键字可以自动推导变量类型,可以减少代码量和提高可读性。例如,auto x = 1; 可以自动推导出 x 的类型为 int。 3. 使用 lambda 表达式:lambda 表达式是 C++11 中引入的一种匿名函数,可以方便地定义一些简单的函数对象。在力扣刷题中,使用 lambda 表达式可以简化代码,例如在 sort 函数中自定义比较函数。 4. 使用位运算:位运算是一种高效的运算方式,在力扣刷题中经常会用到。例如,左移运算符 << 可以用来计算 2 的幂次方,右移运算符 >> 可以用来除以 2 等等。 5. 使用递归:递归是一种常见的算法思想,在力扣刷题中也经常会用到。例如,二叉树的遍历、链表的反转等等。 6. 使用 STL 中的 priority_queue:priority_queue 是 STL 中的一个容器,可以用来实现堆。在力扣刷题中,使用 priority_queue 可以方便地实现一些需要维护最大值或最小值的算法。 7. 使用 STL 中的 unordered_map:unordered_map 是 STL 中的一个容器,可以用来实现哈希表。在力扣刷题中,使用 unordered_map 可以方便地实现一些需要快速查找和插入的算法。 8. 使用 STL 中的 string:string 是 STL 中的一个容器,可以用来存储字符串。在力扣刷题中,使用 string 可以方便地处理字符串相关的问题。 9. 注意边界条件:在力扣刷题中,边界条件往往是解决问题的关键。需要仔细分析题目,考虑各种边界情况,避免出现错误。 10. 注意时间复杂度:在力扣刷题中,时间复杂度往往是评判代码优劣的重要指标。需要仔细分析算法的时间复杂度,并尽可能优化代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值