代码随想录训练营第二天|数组

977.有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

示例:

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]

思路:

  1. 暴力解法:直接遍历乘法后排序
  2. 双指针:从示例中会发现两边平方后大中间最小,选择双指针从两边向中间遍历,反向生成新的数组。
    /**
     * 双指针
     * 定义一个新数组和A数组一样的大小,让k指向result数组终止位置。
     *
     * 如果A[i] * A[i] < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
     *
     * 如果A[i] * A[i] >= A[j] * A[j] 那么result[k--] = A[i] * A[i]; 。
     */
    public class Solusion {
    
        public static int[] sortedSquares(int[] nums) {
            int left = 0;
            int right = nums.length -1;
            int[] result = new int[nums.length];
            int index = result.length -1;
            while (left <=right){ //此处小于等于是因为若等于就停止循环,会有一个数没有取到
                if (nums[left] * nums[left] > nums[right] * nums[right]){
                    result[index--] = nums[left] * nums[left];
                    ++left; //前进一位
                }else { //此处包含了=是因为等于的时候娶那边都可以
                    result[index--] = nums[right] * nums[right];
                    --right;//减少一位
                }
            }
            return result;
        }
    
      
    
    }

解题: 

//暴力解法
public class Solusion {

    public  int[] sortedSquares(int[] nums) {
        int[] new_nums = new int [nums.length];
        for (int i = 0; i < nums.length; i++) {
            new_nums[i] = nums[i] * nums[i];
        }
        Arrays.sort(new_nums);
        return new_nums;
    }

}
//快排:每次将基准点归位,分而治之,二分思想,然后进行递归

public class QuickSort implements IArraySort {

    @Override
    public int[] sort(int[] sourceArray) throws Exception {
        // 对 arr 进行拷贝,不改变参数内容
        int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);

        return quickSort(arr, 0, arr.length - 1);
    }

    private int[] quickSort(int[] arr, int left, int right) {
        if (left < right) {
            int partitionIndex = partition(arr, left, right);
            quickSort(arr, left, partitionIndex - 1);
            quickSort(arr, partitionIndex + 1, right);
        }
        return arr;
    }
    //每次找到基准值,进行分区。
    private int partition(int[] arr, int left, int right) {
        // 设定基准值(pivot)
        int pivot = left;
        int index = pivot + 1;
        for (int i = index; i <= right; i++) {
            if (arr[i] < arr[pivot]) {
                swap(arr, i, index);
                index++;
            }
        }
        swap(arr, pivot, index - 1);
        return index - 1;
    }

    private void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

}

209.长度最小的子数组 

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

示例:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组

思路:

  1. 暴力解法:双层for循环,找到最小的长度
  2. 移动窗口:所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果.

         想要使用一个for循环代替两个for循环做的事情,就应该想到遍历的数字代表的应该是窗口的起始位置,还是终止位置,若是起始位置,那么终止的位置难免也需要遍历,又变成了暴力解法,所以只能是表示终止位置。那么滑动窗口的起始位置如何移动呢? 首先需要考虑三个问题:

  • 窗口是什么?
  • 如何移动窗口的起始位置?
  • 如何移动窗口的结束位置?

窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。

窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。

窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。

解题:

/**
 * 暴力解法:双层for循环,找到最小长度
 */

public class Solusion {

    public static int minSubArrayLen(int target, int[] nums) {
        int n = nums.length;
        if (n == 0){
            return 0;
        }
        int ans = Integer.MAX_VALUE;
        for (int i = 0; i < n; i++) {
            int sum = 0; //每次从新的位置遍历,查找最小长度数组。
            for (int j = i; j < n; j++) {
                sum += nums[j];
                if (sum >=target){
                    ans = Math.min(ans,j-i+1);
                    break; //因为我们是想找到最小的数组长度
                }
            }

        }
        return ans == Integer.MAX_VALUE ? 0 : ans;
    }


}
class Solution {

    // 滑动窗口
    public int minSubArrayLen(int s, int[] nums) {
        int start = 0;
       int sum =0;
       int result = Integer.MAX_VALUE;//用最大值先去比较确定最小值
       int subLength =0;
       int size = nums.length;
        for (int i = 0; i < size; i++) {
            sum +=nums[i];
            while (sum >= target){//窗口定义及窗口移动条件
                subLength = i - start +1; //窗口大小
                result = result < subLength ? result:subLength;//每次取到最小值
                sum-=nums[start++];//移动后减去起始位置移动对应值
            }
        }
        return result == Integer.MAX_VALUE? 0 : result; //没有进去while循环的情况
}

59.螺旋矩阵II

思路:坚持循环不变量原则

        每转一圈,可以左闭右开,这样才不会重复,不会乱。

        

解题: 

class Sulotion{
public  int[][] generateMatrix(int n) {
        int loop = 0;  // 控制循环次数,也间接控制每次循环的该减少的偏移量
        int[][] res = new int[n][n];
        int start = 0;  // 每次循环的开始点(start, start)
        int count = 1;  // 定义填充数字
        int i, j;

        while (loop++ < n / 2) { // 判断边界后,loop从第一圈开始
            // 模拟上侧从左到右,i不变,j增加到n-loop
            for (j = start; j < n - loop; j++) {
                res[start][j] = count++;
            }

            // 模拟右侧从上到下,j不变,i从0增加到n-loop
            for (i = start; i < n - loop; i++) {
                res[i][j] = count++;
            }

            // 模拟下侧从右到左,i不边,j减小到
            for (; j >= loop; j--) {
                res[i][j] = count++;
            }

            // 模拟左侧从下到上,j不变,i减小到
            for (; i >= loop; i--) {
                res[i][j] = count++;
            }
            start++;
        }

        if (n % 2 == 1) {
            res[start][start] = count;
        }

        return res;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值