一、数组类算法(力扣刷题)-Java (二分查找、移除元素、有序数组的平方、长度最小的子数组、螺旋矩阵 II)

一、数组类算法

  • 数组下标都是从0开始的;数组内存空间的地址是连续的
  • 数组的元素是不能删的,只能覆盖
    c++中的二维数组在地址空间上是连续的,Java中二维数组程序员无法看到真实地址,每一行头节点的地址是没有规则的
    Java二维数组排列方式

1、(704)二分查找

坚持根据查找区间的定义来做区间边界处理,区间的定义就是不变量,循环不变量原则当题目的前提是有序数组且无重复元素,则可以考虑使用二分法
(1)如果有区间是左闭右闭,即[left,right]

public static int search(int[] nums, int target) {
    int size = nums.length;
    int med;
    int i = 0, j = size-1;
    while (i<=j){   // 当left==right,区间[left, right]依然有效,所以用 <=
        //med = (i+j)/2;  //要注意每次循环改变med的值;为了避免i+j会溢出,采用 i+(j-1)/2
        med = i+(j-i)/2;
        if (target == nums[med]){
            break;
        }else if (target < nums[med]){
            j = med-1;
        }else {
            i = med+1;
        };
    }
    return -1;
}

(2)如果区间是左闭右开,即[left,fight)
注意每一次确定meddle的位置,要右移一位

int middle = left + ((right - left) >> 1);

2、(27)移除元素

巧用双指针思想:通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

public static int removeElement1(int[] nums, int val) {
    int len = nums.length;
    int i = 0;
    for (int x:nums) {
        if (x == val)
            len--;
        else
            nums[i++] = x;
    }
    return len;
}

3、(977)有序数组的平方

(1)暴力法:冒泡两个for循环
注意两个for循环的限定范围

public static int[] sortedSquares1(int[] nums) {
    int m,n;
    int temp;
    for(int i=0;i<nums.length;i++){
        nums[i] = nums[i]*nums[i];
    }
    for (m=0;m<nums.length-1;m++)
        for (n=0;n<nums.length-m-1;n++)
            if (nums[n]>nums[n+1]){
                temp = nums[n];
                nums[n] = nums[n+1];
                nums[n+1] = temp;
            }
    return nums;
}

(2)双指针法
因为初始数组是有序的,所以平房之后最大的数只可能出现在数组的两头,用两个指针对两头的数组元素进行比较,选择大的尾插一个新的数组即可
ps:偶然发现debug用来调试数组算法的错误,真是不要太舒服,善用debug

public static int[] sortedSquares2(int[] nums){
    int[] temp;
    int k=nums.length-1,i=0,j=nums.length-1;
    temp = new int[k+1];
    while (i != j){
        if (nums[i]*nums[i] > nums[j]*nums[j]){
            temp[k--] = nums[i]*nums[i];
            ++i;
        }else {
            temp[k--] = nums[j]*nums[j];
            --j;
        }
    }
    temp[k] = nums[j]*nums[j];
    return temp;
}

4、(209)长度最小的子数组

(1)暴力法:直接两个for循环,即可遍历所有长度的子数组情况;

public static int minSubArrayLen1(int target, int[] nums) {
    int result_len = 10000; //最终的当前最短子数组长度
    int sum;    //子数组的和
    int len;    //每次记录的当前最短子数组长度
    for (int i=0;i<nums.length;i++) {
        sum = 0;
        for (int j=i;j<nums.length;j++){
            sum += nums[j];
            if (sum >= target){
                len = j-i+1;
                result_len = result_len<len?result_len:len; //每次更新最短子数组的长度
                break;
            }
        }
    }
    if (result_len > nums.length)
        return 0;
    else
        return result_len;
}

(2)滑动窗口法:

public static int minSubArrayLen2(int target, int[] nums){
    int result = Integer.MAX_VALUE; //最终的当前最短子数组长度
    int sum = 0;    //子数组的和
    int len = 0;    //每次记录的当前最短子数组长度
    int i = 0;  //滑动窗口的起始位置
    for (int j=0;j<nums.length;j++){    //滑动窗口的终止位置
        sum += nums[j];
        while (sum >= target){
            len = (j-i)+1;
            result = result<len ? result:len; //每次更新最短子数组的长度
            sum -= nums[i++];
        }
    }
    return result == Integer.MAX_VALUE ? 0:result;
}

5、(59)螺旋矩阵 II

坚持循环不变量原则,模拟顺时针画矩阵的过程,从左上到右上,从右上到右下,从右下到左下,从左下到左上。(范围界定保持一致)
要注意画每条边的时候,要注意保持长度一致;另外注意奇数和偶数n的区别

public static int[][] generateMatrix(int n) {
    int res[][] = new int[n][n];  //定义一个二维数组
    int startx = 0,starty = 0;  //循环的起始位置
    int loop = n/2; //循环的圈数
    int mid = n/2;  //矩阵最中间的值
    int count = 1;  //每个方格赋值数据
    int offset = 1; //每循环一圈 控制每条边的长度
    int i,j;    //控制for循环的变量
    while ((loop--) > 0){
        i = startx;
        j = starty;

        //从左上到右上
        for (;j < n+starty-offset;j++){
            res[i][j] = count++;
        }
        //从右上到右下
        for (;i < n+startx-offset;i++){
            res[i][j] = count++;
        }
        //从右下到左下
        for (;j > starty;j--){
            res[i][j] = count++;
        }
        //从左下到左上
        for (;i > startx;i--){
            res[i][j] = count++;
        }
        //第二圈从(1,1)开始 循环罔替
        ++startx;
        ++starty;

        //更新第二圈以后的边长控制变量,因为前一次循环每条边都用去了两个方格
        offset += 2;
    }
    //如果n为奇数,则最中间只有一个数字
    if (n%2 == 1){
        res[mid][mid] = count;
    }
    return res;
}

刷题顺序按照代码随想录推荐
其他算法题解,敬请期待!
只为记录自己刷题过程,有问题欢迎探讨!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值