第一章 数组part02

977. 有序数组的平方

  1. 暴力解法,就是直接在原数组中进行平方,然后进行排序。这里我采用了两种排序方法:一个是Arrays.sort函数,内部调用的是快速排序。另一个是手写的冒泡排序。前者时间复杂度为O(nlogn),后者是O(n^2)。
  2. 巧妙方法,就是利用数组最大值在原数组两边的特性,建立左右双指针,向中间遍历数组,将每次对比后的最大值存入新数组中。
class Solution {
    public int[] sortedSquares(int[] nums) {
        // for(int i = 0; i < nums.length; i++){
        //     nums[i] *=  nums[i];
        // }
        //一. Arrays工具类排序
        //Arrays.sort(nums);   

        //二. 冒泡排序
        // for(int i = 0; i < nums.length; i++){
        //     boolean flag = true;
        //     for(int j = 0; j < nums.length - 1 - i; j++){
        //         if(nums[j] > nums[j + 1]){
        //             int temp = 0;
        //             temp = nums[j];
        //             nums[j] = nums[j+1];
        //             nums[j+1] = temp;   
        //             flag = false;                 
        //         }
        //     }
        //     if(flag == true){
        //         break;
        //     }
        // }
        // return nums;

        int[] result = new int[nums.length];
        int left = 0;
        int right = nums.length - 1;
        int k = right;
        while(left <= right){//注意退出条件
            int left_num = nums[left] * nums[left];
            int right_num = nums[right] * nums[right];
            if(left_num <= right_num){
                result[k--] = right_num;
                right--;
            }else{
                result[k--] = left_num;
                left++;
            }
        }
        return result;
    }
}

209. 长度最小的子数组

思路:本质是拿双指针来实现滑动窗口。对左侧窗口何时添加、去除元素的细节比较难以把握,建议边debug边修改代码。针对其中的while循环,是大于还是大于等于,也考察了对代码的理解程度。
这里只提供本人思考的代码,卡尔哥的代码其实更加的简洁也易懂,他把操作窗口左侧的元素放入了while循环中,会更好理解点。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int left = 0;
        int right = 0;
        int sum = 0;
        int min = 100000;
        boolean flag = false;
        for(; right < nums.length; right++){
            sum += nums[right];
            if(sum >= target){
                flag = true;
                while(sum >= target){  
                    //当相等时也要进入循环,因为出循环后会默认增加前一个left元素,如果正好相等其实不用添加,
                    //所以要进入循环让left多向前一步,sum多加一个元素
                    sum -= nums[left++];  
                }
                sum += nums[--left];
                int len = right - left + 1;
                min = len < min ? len : min;
            }
        }
        if(flag){
            return min;
        }
        return 0;
    }
}

59. 螺旋矩阵 II

这里我找了两种解法:

  1. 利用方向向量来表示要移动的方向,每次加上方向向量的距离来移动,好理解
  2. 使用代码模拟出填充流程,比较难想出代码
class Solution {
    public int[][] generateMatrix(int n) {
        //1.采用方向向量的形式,这里使用的是传统的坐标
        int dx = 1;
        int dy = 0;

        int x = 0;
        int y = 0;

        int[][] nums = new int[n][n];  //int型默认为0
        
        for(int i = 1; i <= n * n; i++){
            nums[x][y] = i;

            int temp_x = (x - dy + n) % n;  //x和y向着向量方向移动,每次加1
            int temp_y = (y + dx + n) % n;  //防止负数取模,需要先加n,再取模
            if(nums[temp_x][temp_y] != 0){  //到头,也就是取模会取到第一次操作的数
                int temp = dy;
                dy = -dx;
                dx = temp;                  //交换dx、dy使得向量90度旋转。因为向量y负数表示向下,所以取负值
            }
            x -= dy;
            y += dx;
        }
        return nums;
    }
}
class Solution {
    public int[][] generateMatrix(int n) {
         int[][] nums = new int[n][n];
         int startx = 0;
         int starty = 0;
         int offset = 1;
         int loop = n / 2;
         int mid = n /2;
         int count = 1;
         int i;
         int j;
         while((loop--) > 0){
             i = startx;
             j = starty;

             for(j = starty;j < n - offset; j++){
                 nums[i][j] = count++;
             }

             for(i = startx;i < n - offset; i++){
                 nums[i][j] = count++;
             }

             for(;j > startx; j--){
                 nums[i][j] = count++;
             }

             for(;i > starty; i--){
                 nums[i][j] = count++;
             }

             startx++;
             starty++;
             offset++;
         }
         if ((n % 2)!=0) {
             nums[mid][mid] = count;
         }
         return nums;

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值