LeetCode刷题 | 977. 有序数组的平方、209. 长度最小的子数组、59. 螺旋矩阵 II

977. 有序数组的平方

 

 暴力排序

        最直观的想法,莫过于:每个数平方之后,排个序,美滋滋,代码如下:

Java:

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

        return nums;
    }
}

Golang:

func sortedSquares(nums []int) []int {
    ans := make([]int, len(nums))
    for i, v := range nums{
        ans[i] = v * v
    }
    sort.Ints(ans)
    return ans
}

双指针法

        数组其实是有序的, 只不过负数平方之后可能成为最大数了。

那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。

此时可以考虑双指针法了,i指向起始位置,j指向终止位置。

定义一个新数组result,和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]; 。

class Solution {
    public int[] sortedSquares(int[] nums) {
        int l = 0;
        int r = nums.length - 1;
        int[] res = new int[nums.length];
        int j = nums.length - 1;
        while(l <= r){
            if(nums[l] * nums[l] > nums[r] * nums[r]){
                res[j--] = nums[l] * nums[l++];
            }else{
                res[j--] = nums[r] * nums[r--];
            }
        }
        return res;
    }
}

209. 长度最小的子数组

暴力解法

        两个for循环,然后不断的寻找符合条件的子序列,时间复杂度是O(n^2)。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int result = Integer.MAX_VALUE;
        int length = 0;
        int sum = 0;
        int k = 1;
        for(int i = 0;i < nums.length;i ++){
            sum = 0;
            for(int j = i;j < nums.length;j ++){
                sum += nums[j];
                if(sum >= target){
                    length = j - i + 1;
                    result = result < length ? result : length;
                    break;
                }
            }
        }
        return result == Integer.MAX_VALUE ? 0 : result;
    }
}
//代码最终超时了。。

滑动窗口

在本题中实现滑动窗口,主要确定如下三点:

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

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

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

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

解题的关键在于 窗口的起始位置如何移动,如图所示:

可以发现滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。

Java:

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        //滑动窗口
        int left = 0;
        int sum = 0;
        int result = Integer.MAX_VALUE;
        for(int right = 0;right < nums.length;right ++){
            sum += nums[right];
            while(sum >= target){
                result = Math.min(result,right - left + 1);
                sum -= nums[left++];
            }
        }
        return result == Integer.MAX_VALUE ? 0 : result;
    }
}

Golang:

func minSubArrayLen(target int, nums []int) int {
    if len(nums) == 0{
        return 0
    }

    start, end := 0, 0
    sum := 0
    ans := math.MaxInt32
    for end < len(nums){
        sum += nums[end]
        for sum >= target{
            sum -= nums[start]
            ans = min(ans, end - start + 1)
            start ++
        }
        end ++
    }
    if ans == math.MaxInt32{
        return 0
    }
    return ans
}

func min(x, y int) int{
    if x < y{
        return x
    }
    return y
}

59. 螺旋矩阵 II

不涉及算法,模拟顺时针画矩阵的过程:

  • 填充上行从左到右
  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上

由外向内一圈一圈这么画下去。

Java:

class Solution {
    public int[][] generateMatrix(int n) {
        int loop = 0;
        int[][] res = new int[n][n];
        int start = 0;
        int count = 1;
        int i,j;

        while(loop++ < n/2){
            //上侧从左到右 左闭右开
            for(j = start;j < n - loop;j ++){
                res[start][j] = count ++;
            }

            //右侧从上到下 上闭下开
            for(i = start;i < n - loop;i ++){
                res[i][j] = count ++;
            }

            //下侧从右到左 右闭左开
            for(;j >= loop;j --){
                res[i][j] = count ++;
            }

            //左侧从下到上 下闭上开
            for(;i >= loop;i --){
                res[i][j] = count ++;
            }

            start ++;
        }

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

 Golang:

type pair struct{ x, y int }
var dirs = []pair{{0, 1}, {1, 0}, {0, -1}, {-1, 0}} // 右下左上

func generateMatrix(n int) [][]int {
    matrix := make([][]int , n)
    for i := range matrix{
        matrix[i] = make([]int, n)
    }
    row, col, dirIdx := 0, 0, 0
    for i := 1; i <= n*n; i++ {
        matrix[row][col] = i
        dir := dirs[dirIdx]
        if r, c := row+dir.x, col+dir.y; r < 0 || r >= n || c < 0 || c >= n || matrix[r][c] > 0 {
            dirIdx = (dirIdx + 1) % 4 // 顺时针旋转至下一个方向
            dir = dirs[dirIdx]
        }
        row += dir.x
        col += dir.y
    }
    return matrix
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值