算法:数组 #241126

46 阅读3分钟

算法:数组理论(二)

有序数组的平方

题目链接: leetcode#977

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

题目的前置条件为非递减顺序的有序数组,不难看出,平方后新数组的最大值必在数据的两侧,可以使用双指针的方法,分别指向数组两侧,进行大小比较,将平方后较大值的元素放到新数组末端(平方值从大往小的找),随后移动指针(移动平方结果大的指针,移动方向为靠近数组中间因为我们是从大往小的找),之后继续进行下一个最大值查找。

	public int[] sortedSquares(int[] nums) {
        int[] res = new int[nums.length]; // 返回结果
        int left=0;// 左边指针
        int right=nums.length-1; // 右边指针
        int targetInsertIdx = res.length-1; //新数组需要添加的下标,从大往小找
        while(left <= right) {
            int leftVal = nums[left] * nums[left]; // 左指针对应的值
            int rightVal = nums[right] * nums[right]; // 右指针对应的值
            if (leftVal >= rightVal) {
                res[targetInsertIdx] = leftVal; // 如果左边大,新数组赋值左指针向内部移动
                left++;
            } else {
                res[targetInsertIdx] = rightVal; // 如果右边大,新数组赋值右指针向内部移动
                right--;
            }
            targetInsertIdx--; // 需要插入的下标往前移动,因为后面的数据会逐步减小
        }
        return res;
    }

长度最长子数组

题目链接: leetcode#209

给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

按照常规理解,我们只需要找到所有和>=s的子数组就可以,随后找到这些子数组中长度最小的,这需要我们枚举出所有的子数组,时间复杂度会很高(O(n2)O(n^2)) (for循环两次)

滑动窗口:如果我们在遍历数组的过程中,使用两个指针,两个之间的元素为我们需要观察的子数组,遍历时,可以不断调节两个指针使得子数组和满足>=s,这样我们只需要进行一次遍历即可

我们定义两个指针,左、右,如何调节指针?重新理一下题目,子数组和>=s&&最短子数组长度,由此,如果子数组和不满足条件,则子数组的元素需要增加,所以左指针不移动,右边指针移动,如果当前子数组和已经满足,因为我们要找最短的,所以碰到满足条件的,就可以尝试缩小子数组则左的指针往后移,随后重复上面的判断,继续往下找,就可以完成这道题目

public int minSubArrayLen(int target, int[] nums) {
    int res = Integer.MAX_VALUE;
    int left = 0; // 左
    int right = 0; // 右
    int sum = 0; // 子数组和
    for (; right < nums.length; right++) {
        sum += nums[right];
        while (sum >= target) { // 尝试缩小滑动窗口
            res = Math.min(res, (right-left+1));
            sum -= nums[left++]; // 注意sum记得回退
        }
    }
   return Objects.equals(Integer.MAX_VALUE, res) ? -0 : res;
}

螺旋矩阵 II

题目链接: leetcode#59

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 描述

注意边界,选择左开右闭的方式

public int[][] generateMatrix(int n) {
    int[][] nums = new int[n][n];
    int loop = 1; // 记录循环层数
    int i,j; // 下标
    int count = 1; // 从1->n
    int x = 0;
    int y = 0;
    while(loop <= n/2) {
        for(j=y; j<n-loop; j++) { // n-loop注意边界
            nums[x][j] = count++;// 左->右
        }
        for (i=x; i<n-loop; i++) { // n-loop注意边界
            nums[i][j] = count++;// 上->下
        }
        for (; j>y; j--) { // 左闭
            nums[i][j] = count++; // 右->左
        }
        for (; i>x; i--) {
            nums[i][j] = count++;// 下->上
        }
        loop++;
        x++;
        y++;
    }
    // 如果n是单数,这中间位置需要特殊处理下
    if(n % 2 == 1) {
        nums[x][y] = count++;
    }
    return nums;
}