Java刷题——代码随想录Day2

代码随想录Day2

数组

有序数组的平方

力扣977.有序数组的平方

这个题,一开始就猛猛偷懒了。关键代码直接用Arrays.sort()代替。

在IDEA中重新尝试了自己熟知的几个小排序算法:

  • 选择排序

  • 冒泡排序

  • 快速排序

public class Main {
    public static void main(String[] args) {
        int[] nums={-4,-1,0,3,10};
        for(int i=0;i<nums.length;i++){
            nums[i]*=nums[i];
        }
        quickSort(nums,0,nums.length-1);
        for(int i=0;i<nums.length;i++){
            System.out.print(nums[i]+" ");
        }


    }
    static void seleSort(int[] nums){
        /*
        选择排序的思想是每轮找到最小的值,并放到“最前”
         */
        for(int i=0;i<nums.length;i++){  //分别找能放到当前i位置 最小的元素
            for(int j=i+1;j<nums.length;j++){ //每一轮把“最小的值”放到前面之后,下一轮前面已放过去的就没必要遍历了,所以是j=i+1
                if(nums[j]<nums[i]){
                    int temp=nums[i];
                    nums[i]=nums[j];
                    nums[j]=temp;
                }
            }
        }
    }
    static void maopaoSort(int[] nums){
        //冒泡排序其实是每轮把最大的“石头” 沉入到最下面
        for(int i=0;i<nums.length-1;i++){  //一共有nums.length个元素,每轮沉1个石头,那么只需要遍历nums.length-1轮 结果就出来了
            //j的界限是变化的,每一轮不一样,比如第一轮最大的放到了最后,那么第二轮就只需要遍历到倒数第二个数就行了
            for(int j=0;j<nums.length-1-i;j++){
                if(nums[j]>nums[j+1]){
                    int temp=nums[j];
                    nums[j]=nums[j+1];
                    nums[j+1]=temp;
                }
            }

        }
    }
  //快速排序
    static void quickSort(int[]nums,int left,int right){
        if(left>right)
            return;
        int i=left;
        int j=right;
        int pivot=nums[left];//pivot用来记录基准值,这里就用nums[left]来指定
        while(i<j){
            while(i<j && nums[j]>=pivot){  //每次从右边往左走,直到找到小于基准值的数
                j--;
            }
            while(i<j && nums[i]<=pivot){//每次从左边往右走,直到找到大于基准值的数
                i++;
            }
            if(i<j){
                int temp=nums[i];
                nums[i]=nums[j];
                nums[j]=temp;
            }
        }
        nums[left]=nums[i];  //把“相交的数”放到最左边
        nums[i]=pivot;        //最初始的基准数放到中间
        quickSort(nums,left,i-1);//递归
        quickSort(nums,i+1,right);

    }
}

补充: 以上的排序方式,即便是快排,其时间复杂度也是O(nlogn),达不到进阶的O(n)时间复杂度。

明天学习一下此题别的解法

长度最小的子数组

力扣209长度最小的子数组

根据题目的提示: 时间复杂度要为 O(n),脑海中第一时间就想到整个数组只能遍历一次。那么就使用了快慢指针(提交过后看题解才知道原来这个叫做滑动窗口)。

在数据结构方面入手,其实滑动窗口本质上有点类似于队列。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int sum=0;
        for(int i=0;i<nums.length;i++){
            if(nums[i]==target) //反正遍历了  顺带判断一下也无所谓
                return 1;
            sum+=nums[i];
        }
        if(sum<target)
            return 0;
        //上面已经排除了target直接存在于nums中 以及 target根本不可能存在于nums中的情况
        //并且上面同样也已经排除了nums.length==1的情况
        sum=0;
        int numsLen=nums.length;
        int outLen=nums.length+1;  //默认把要调用的outlen调整至比nums.length还大
        int slow=0;
        int fast=0;
         while(slow<numsLen){
            if(sum<target){    
                if(fast==numsLen)  //这个时候,快指针已经越界,说明不能再添加元素
                    break;
                else{
                    sum+=nums[fast];
                    fast++;
                }  
            }
            else{     //sum大于等于target的情况
                outLen=(fast-slow)<outLen?(fast-slow):outLen;  //获取较小值
                sum-=nums[slow];   
                slow++;
            }
        }
        if(outLen==nums.length+1)
            return 0;
        else
            return outLen;
    }
}

补充: 看了Carl哥的讲解视频之后,感觉他的方法更加简洁明了,并且理解上也更容易。自己在IDEA中复现了一下代码。如下所示:

public static void main(String[] args) {
        int[] nums={2,3,1,2,4,3};
        System.out.println(result(nums,7));

    }
    static int result(int[] nums,int target){
        int slow=0;
        int fast=0;
        int outLen=nums.length+1;
        int sum=0;
        for(fast=0;fast<nums.length;fast++){
            sum+=fast;
            while(sum>=target){
                outLen=(fast-slow+1)<outLen?(fast-slow+1):outLen;
                sum-=nums[slow];
                slow++;
            }
        }
        if(outLen>nums.length)
            return 0;
        else
            return outLen;
    }

个人理解:

  • 对于我个人而言,复现的时候最怕出现边界情况,即当fast指针到了最右边的时候,此时程序该如何运行?

    • 当fast指针到达最右边(即fast==nums.length-1)时,此时只要sum>=target,那么slow指针就会一直往右走,直到sum<target,并最后跳出整个大循环。

螺旋矩阵

力扣59螺旋矩阵

螺旋矩阵的代码,再一次强调了循环不变量的概念。

  • 正因为是循环,个人理解,一个好的循环,它应当是每次循环它的“界限”是定的。下方代码为左闭右开[ )
public static void main(String[] args) {
        int n=4;
        int[][] nums=new int[n][n];
        int loop=1;
        int startX=0;
        int startY=0;
        int i=0,j=0;
        int number=1;
        //对于n*n的二维数组  每循环一圈(一圈指的是四周),纵向看,高度就会少2,每一个loop少2  所以loop<=n/2
        //我这里loop的初始值是从1开始的,因为发现如果从1开始的话 loop也就能同步运用到下方for循环之中了
        while(loop<=n/2){
            //循环不变量!—— 对于循环来说,我们希望每次循环它的“界限”是一定的。这里采用左闭右开[ ) 的原则
            //即每一条边的最后一个元素,交给下一个循环去处理,当做其第一个元素。

            for(j=startY;j<n-loop;j++){   //第一条边  最上面的
                nums[startX][j]=number++;
            }
            for(i=startX;i<n-loop;i++){ //第二条边  最右边的
                nums[i][j]=number++;
            }
            for(;j>startY;j--){   //第三条边,最下面的
                nums[i][j]=number++;
            }
            for(;i>startX;i--){
                nums[i][j]=number++;//第四条边,最左边的
            }
            startX++;
            startY++;
            loop++;
        }
        if(n%2==1){
            nums[n/2][n/2]=number;
        }
        for(i=0;i<n;i++){
            for(j=0;j<n;j++){
                System.out.print(nums[i][j]+"      ");
            }
            System.out.println();
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值