双非本科准备秋招(3)——力扣数组

力扣算法题

1、27. 移除元素

审题很关键啊,读不懂题目或者一知半解都不要敲代码,思路比代码更重要,好好读读题意思也挺明显,让你返回一个len,代表移除完毕后的数组长度,要求数组下标为0到len-1的元素都是没删除的元素。

一开始思路也不是很清晰,感觉应该有比较巧妙的方法,最后也没想出来,弄了个新数组记录一下原数组保留的元素,然后copy到原数组,过了。

Arrays.copyOfRange([] original, int from, int to)

参数:
original:要拷贝的数组对象
from:为拷贝的开始位置(包含)
to:拷贝的结束位置(不包含)

public int removeElement(int[] nums, int val) {
        int ans = nums.length, j = 0;
        int[] temp = nums;
        for(int i = 0; i < nums.length; i++){
            if(nums[i] == val){
                ans--;
            }
            else{
                temp[j++] = nums[i];
            }
        }
        nums = Arrays.copyOfRange(temp, 0, ans);
        return ans;
    }

果然有更优雅的解决方法:

class Solution {
    public int removeElement(int[] nums, int val) {
        int len = nums.length, i = 0;
        while(i < len){
            if(nums[i] == val){
                nums[i] = nums[len-1];
                len--;
            }
            else{
                i++;
            }
        }
        return len;
    }
}

len代表最终数组长度,一开始等于原数组长度,遍历数组,每当遇到应该删除的元素,就把最后一个元素赋值给当前元素,然后减小len;否则,该元素就应该保留,i++。这样,后面的元素如果也是应该删除的元素就会一直删除,因为i一直不变。

2、977. 有序数组的平方

暴力:遍历一下再排个序,快排时间复杂度nlogn

public int[] sortedSquares(int[] nums) {
        // 遍历一下再排个序
        for(int i = 0; i < nums.length; i++){
            nums[i] = nums[i] * nums[i];
        }
        Arrays.sort(nums);
        return nums;
    }

还有一种双指针的解法:

观察nums数组,平方后最大值一定从两侧取,所以可以设置两个首尾指针,倒着添加到一个新数组中。i,j是首位指针,index记录新数组ans的下标。时间复杂度O(n)

class Solution {
    public int[] sortedSquares(int[] nums) {
        int i = 0, j = nums.length-1;
        int index = nums.length-1;
        int[] ans = new int[nums.length];

        while(index >= 0){
            if(nums[i]*nums[i] > nums[j]*nums[j]){
                ans[index--] = nums[i]*nums[i];
                i++;
            }
            else{
                ans[index--] = nums[j]*nums[j];
                j--;
            }
        }

        return ans;
    }
}

3、209. 长度最小的子数组

真的不想再暴力啦!

本题思路是如何把双层for循环优化成一个for循环,还是利用双指针,单层for循环的j代表尾指针,每次移动后都记录从i到j的和,如果和大于目标值,就更新ans,直到找到最小的ans。

public int minSubArrayLen(int target, int[] nums) {
        int i = 0, ans = Integer.MAX_VALUE, temp = 0;
        for(int j = 0; j < nums.length; j++){
            temp += nums[j];
            System.out.println(temp);
            while(temp >= target){
                ans = (j-i+1)<ans ? (j-i+1) : ans;
                temp -= nums[i];
                i++;
            }
        }
        return ans==Integer.MAX_VALUE?0:ans;
    }

4、59. 螺旋矩阵 II

记得之前刷刘汝佳紫书就有这个题,叫蛇形矩阵,这种题属于模拟题,但是一定要充分考虑边界问题,自己搞了一个小时才搞出来,主要是思路太不清晰了。

以4*4举例,一开始我是这么找的,边界判断的稀碎

四条边可以统一用这种左闭右开的找法,这样就能在每一圈的循环中统一判断四个边的各种情况,而不是外圈判断好了,内圈又出问题了。

如下代码,cnt代表填充的数字。因为每圈都要缩小,所以定义了一个变量t,用来控制边界。(一开始忘记每次循环令t++,找了半个小时bug)。

内圈四个for循环则是用来填充上、右、下、左的值。仔细找找其中的规律,写出来并不难。

最后判断n是不是奇数,是奇数要把中间手补上。

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] a = new int[n][n];
        int i = 0, j = 0, t = 1, cnt = 1;
        for(int r = 0; r < n/2; r++){
            for(j = r; j < n-t; j++){
                System.out.println("1r: " + r + " j: " + j);
                a[r][j] = cnt++;
                System.out.println("a[r][j]: " + a[r][j]);
            }
            for(i = r; i < n-t; i++){
                System.out.println("2r: " + r + " i: " + i);
                a[i][j] = cnt++;
                System.out.println("a[i][j]: " + a[i][j]);
            }
            for(; j >= t; j--){
                System.out.println("3r: " + r + " j: " + j);
                a[i][j] = cnt++;
                System.out.println("a[i][j]: " + a[i][j]);
            }
            for(; i >= t; i--){
                System.out.println("4r: " + r + " i: " + i);
                a[i][j] = cnt++;
                System.out.println("a[i][j]: " + a[i][j]);
            }
            t++;
        }
        if(n%2==1) a[n/2][n/2] = n*n;
        return a;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值