【Leecode笔记】第十九周(1.11-1.17) 数组专题

【第一题】三个数的最大乘积

在这里插入图片描述

分析:注意注意!有负数出没!!
方法1:
1.最小的两个负数相乘,再乘以最大的正数,得出sum1;
2.直接让三个最大的正数相乘,得出sum2;
3.比较sum1和sum2,返回更大的那个。

时间主要消耗在了这个排序上面。

方法二:线性扫描(找最小的两个数和最大的三个数)

//执行用时:12 ms, 在所有 Java 提交中击败了69.75% 的用户
//内存消耗:39.8 MB, 在所有 Java 提交中击败了71.82% 的用户
class Solution {
    public int maximumProduct(int[] nums) {
        if(nums.length == 3){return nums[0] * nums[1] * nums[2];}
        Arrays.sort(nums);
        int sum1 = 0,sum2 = 0;
        sum2 = nums[nums.length-1] * nums[nums.length-2] * nums[nums.length-3];
        sum1 = nums[0] * nums[1] * nums[nums.length-1];
        return Math.max(sum1,sum2);
    }
}
//执行用时:2 ms, 在所有 Java 提交中击败了99.19% 的用户
//内存消耗:39.8 MB, 在所有 Java 提交中击败了67.07% 的用户
public class Solution {
    public int maximumProduct(int[] nums) {
        int min1 = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE;
        int max1 = Integer.MIN_VALUE, max2 = Integer.MIN_VALUE, max3 = Integer.MIN_VALUE;
        for (int n: nums) {
            if (n <= min1) {
                min2 = min1;
                min1 = n;
            } else if (n <= min2) {     // n lies between min1 and min2
                min2 = n;
            }
            if (n >= max1) {            // n is greater than max1, max2 and max3
                max3 = max2;
                max2 = max1;
                max1 = n;
            } else if (n >= max2) {     // n lies betweeen max1 and max2
                max3 = max2;
                max2 = n;
            } else if (n >= max3) {     // n lies betwen max2 and max3
                max3 = n;
            }
        }
        return Math.max(min1 * min2 * max1, max1 * max2 * max3);
    }
}

【第二题】存在连续三个奇数的数组

在这里插入图片描述

分析:双指针,遍历一遍,判断过的数没必要再判断。

//执行用时:0 ms, 在所有 Java 提交中击败了100.00% 的用户
//内存消耗:38.1 MB, 在所有 Java 提交中击败了61.66% 的用户
class Solution {
    public boolean threeConsecutiveOdds(int[] arr) {
        if(arr.length < 3){return false;}
        int i = 0,count =0;
        for(i = 0;i < arr.length;i++){
            if(arr[i] % 2 == 0){
                //System.out.println("even:"+arr[i]);
                count = 0;
            }else{
                count++;
                if(count == 3){
                    return true;
                }
                //System.out.println("odd:"+arr[i]);
            }  
        }
        return false;
    }
}

【第三题】汇总区间

在这里插入图片描述

分析:意思就是,每一组连续的数是一个区间,假如中间缺失了一个数字,就得另外划分区间
在这里插入图片描述
方法一:相邻两元素相减看是不是为1即可。(双指针和二分查找的边界是真的难扣,一顿操作猛如虎,提交击败百分五)
在这里插入图片描述

方法二:双指针的改进;

//执行用时:9 ms, 在所有 Java 提交中击败了29.32% 的用户
//内存消耗:36.9 MB, 在所有 Java 提交中击败了46.01% 的用户
class Solution {
    public List<String> summaryRanges(int[] nums) {
        ArrayList<String> list = new ArrayList<>();
        if(nums.length == 0){return list;}
        if(nums.length ==1){
            list.add(nums[0]+"");
            return list;
        }
        int i = 0,j = 1;
        while(i < nums.length && j< nums.length){
            if(nums[j] - nums[i] == (j-i)){
                j++;
            }else{
                if(j-i == 1){
                    list.add(nums[i]+"");
                    i = j;
                    if(j < nums.length-1){
                        j++;
                    }else{
                        break;
                    }
                }
                if(j - i > 1){
                    list.add(nums[i]+"->"+nums[j-1]);
                    i = j;
                    if(j < nums.length-1){
                        j++;
                    }else{
                        break;
                    }
                }
            }
        }
        //第一种情况
        if(j==i){
            list.add(nums[i]+"");
        }
        //第二种情况
        if(j - i>1){
            list.add(nums[i]+"->"+nums[j-1]);
        }
        return list;
    }
}
//执行用时:0 ms, 在所有 Java 提交中击败了100.00% 的用户
//内存消耗:36.4 MB, 在所有 Java 提交中击败了94.54% 的用户
class Solution {
    public List<String> summaryRanges(int[] nums) {
        List<String> ret = new ArrayList<String>();
        int i = 0;
        int n = nums.length;
        while (i < n) {
            int low = i;
            i++;
            while (i < n && nums[i] == nums[i - 1] + 1) {
                i++;
            }
            int high = i - 1;
            StringBuffer temp = new StringBuffer(Integer.toString(nums[low]));
            if (low < high) {
                temp.append("->");
                temp.append(Integer.toString(nums[high]));
            }
            ret.add(temp.toString());
        }
        return ret;
    }
}

【第四题】种花问题

在这里插入图片描述

分析:看有连续几个0,另外还得考虑封口的0还是不封口的0
在这里插入图片描述
要考虑一个元素的两边分别是什么。

【第五题】翻转图像

在这里插入图片描述

分析:先逆序翻转,再0,1翻转。(一遍AC,大人的快乐就这么简单)

//执行用时:0 ms, 在所有 Java 提交中击败了100.00% 的用户
//内存消耗:38.7 MB, 在所有 Java 提交中击败了43.60% 的用户
class Solution {
    public int[][] flipAndInvertImage(int[][] A) {
        for(int i = 0;i < A.length;i++){
            A[i] = reverse(A[i]);
            for(int j = 0;j < A[i].length;j++){
                if(A[i][j] == 0){
                    A[i][j] = 1;
                }else{
                    A[i][j] = 0;
                }
            }
        }
        return A;
    }
    public int[] reverse(int[] nums){
        int i = 0,j = nums.length-1;
        while(i < j){
            int temp = nums[j];
            nums[j] = nums[i];
            nums[i] = temp;
            i++;
            j--;
        }
        return nums;
    }
}

【第六题】最富有客户的资产总量

在这里插入图片描述

分析:一次AC(要做点重拳出击的题才能增强自信)

//执行用时:0 ms, 在所有 Java 提交中击败了100.00% 的用户
//内存消耗:38.3 MB, 在所有 Java 提交中击败了16.33% 的用户
class Solution {
    public int maximumWealth(int[][] accounts) {
        int max = 0;
        for(int i = 0;i < accounts.length;i++){
            int sum = 0;
            for(int j = 0;j < accounts[i].length;j++){
                sum+=accounts[i][j];
            }
            max = Math.max(sum,max);
        }
        return max;
    }
}

【第七题】找出井字棋的获胜者

在这里插入图片描述

【第八题】统计好三元组

在这里插入图片描述

【第九题】数组序号转换

在这里插入图片描述

分析:首先去重是个大问题,去完重排序,然后排序后将数组下标对应数组元素即可。
去重:https://blog.csdn.net/u010680097/article/details/52353369

方法一:列表去重+哈希映射;
方法二:

//居然超时了
class Solution {
    public int[] arrayRankTransform(int[] arr) {
        int[] ret = new int[arr.length];
        if(arr.length == 0){return ret;}
        if(arr.length == 1){ret[0] = 1;return ret;}

        ArrayList<Integer> list = new ArrayList<>();
        Map<Integer,Integer> map = new HashMap<>();
        for(int i = arr.length-1;i >=0;i--){
            if(!list.contains(arr[i])){
                list.add(arr[i]);
            }
        }
        Collections.sort(list);
        for(int i = list.size()-1;i >= 0;i--){
            map.put(list.get(i),i+1);
        }
        for(int j = 0;j < arr.length;j++){
            ret[j] = map.get(arr[j]);
        }
        return ret;
    }
}
//直接用哈希表
//执行用时:27 ms, 在所有 Java 提交中击败了77.86% 的用户
//内存消耗:48.1 MB, 在所有 Java 提交中击败了74.67% 的用户
class Solution {
    public int[] arrayRankTransform(int[] arr) {
        //学到了,还可以直接克隆
        int[] temp = arr.clone();
        Arrays.sort(temp);
        HashMap<Integer,Integer> map = new HashMap<>();
        int n = temp.length;
        int count = 1;
        for(int i = 0;i < n;i++){
            if(map.get(temp[i]) == null){
                map.put(temp[i],count);
                count++;
            }
        }
        for(int i = 0;i < n;i++){
            arr[i] = map.get(arr[i]);
        }
        return arr;
    }
}
//数组去重后排序+二分+桶排序
class Solution {
    public int[] arrayRankTransform(int[] arr) {
        int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
        for (int num : arr) {
            if (num < min) min = num;
            if (num > max) max = num;
        }
        
        int[] count = new int[max - min + 1];
        for (int num : arr)
            count[num - min] = 1;
        
        int[] preSum = new int[count.length + 1];
        for (int i = 1; i < preSum.length; i++)
            preSum[i] = preSum[i - 1] + count[i - 1];
        
        int[] ans = new int[arr.length];
        int index = 0;
        for (int num : arr) 
            ans[index++] = preSum[num - min] + 1;
        
        return ans;
    }
}

【第十题】至少是其他数字两倍的最大数

在这里插入图片描述

分析:
方法一:【排序版】首先将数组排序,找到最大的整数.然后看第二大的数的两倍是否小于等于它即可。
方法二:【不排序版】

//执行用时:2 ms, 在所有 Java 提交中击败了16.56% 的用户
//内存消耗:36.4 MB, 在所有 Java 提交中击败了43.50% 的用户
class Solution {
    public int dominantIndex(int[] nums) {
        if(nums.length == 1){return 0;}
        int[] temp = nums.clone();
        Arrays.sort(temp);
        int max = temp[nums.length-1];
        int index = 0;
        int j = nums.length-2;
        while(temp[j] == max){
            j--;
        }
        if(temp[j] * 2 <= max){
            for(int i = 0;i < nums.length;i++){
                if(nums[i] == max){
                    index = i;
                    return i;
                }
            }
        }
        return -1;
    }
}
//执行用时:0 ms, 在所有 Java 提交中击败了100.00% 的用户
//内存消耗:36.3 MB, 在所有 Java 提交中击败了50.31% 的用户
class Solution {
    public int dominantIndex(int[] nums) {
        int max = Integer.MIN_VALUE;
        int index = 0;
        for(int i = 0;i < nums.length;i++){
            if(nums[i] > max){
                max = nums[i];
                index = i;
            }
        }
        for(int i = 0;i < nums.length;i++){
            if(i != index && nums[i]!=max){
                if(nums[i]*2 > max){
                    return -1;
                }
            }
        }
        return index;
    }
}

【第十一题】斐波那契数

在这里插入图片描述

分析:
方法一:递归;
方法二:非递归。

//递归大法好
class Solution {
    public int fib(int n) {
        if(n == 1||n == 0){return n;}
        else{
            return fib(n-1) + fib(n-2);
        }
    }
}
//执行用时:0 ms, 在所有 Java 提交中击败了100.00% 的用户
//内存消耗:35.2 MB, 在所有 Java 提交中击败了29.73% 的用户
class Solution{
    public int fib(int n){
        if(n == 1||n == 0){return n;}
        int[] ret = new int[n+1];
        ret[0] = 0;
        ret[1] = 1;
        int cur = 2;
        while(cur <= n){
            ret[cur] = ret[cur - 1] +  ret[cur - 2];
            cur++;
        }
        return ret[n];
    }
}

【第十二题】缀点成线

在这里插入图片描述

分析:注意转double!

//执行用时:0 ms, 在所有 Java 提交中击败了100.00% 的用户
//内存消耗:38.1 MB, 在所有 Java 提交中击败了52.96% 的用户
class Solution {
    public boolean checkStraightLine(int[][] coordinates) {
        if(coordinates.length == 2){return true;}
        double a = 0,b = 0;
        
        if((coordinates[1][0] - coordinates[0][0])!=0){
            a = (double)(coordinates[1][1] - coordinates[0][1])/(coordinates[1][0] - coordinates[0][0]);
            b = (double)(coordinates[1][0] * coordinates[0][1] - coordinates[0][0] * coordinates[1][1])/(coordinates[1][0] - coordinates[0][0]);
        }else{
            for(int i = 2;i < coordinates.length;i++){
                if(coordinates[i][0]!=coordinates[0][0]){
                    return false;
                }
            }
            return true;
        }
        for(int i = 2;i < coordinates.length;i++){
            if(coordinates[i][1] != coordinates[i][0] * a + b){
                return false;
            }
        }
        return true;
    }
}

【第十三题】数组的度

在这里插入图片描述

分析:首先要知道哪个元素出现次数最多,其次要知道该元素首次出现的下标first以及最后一次出现的下标last。
last - first +1即为返回值。

【第十四题】寻找数组的中心索引

在这里插入图片描述

分析:首先求出所有元素的总和,然后以数组的每个元素nums[i]作为中心索引,只需要试探nums[i]左边的元素之和是否等于( sum-nums[i] )/2即可,假如小于,那么继续往下设置中心索引,假如大于,直接返回-1。
(注意注意注意!!有负数出没!!)

方法二:leftsum == sum - leftsum - nums[i];只需要在累加的时候顺便判断即可,这样的话,只需要一层for循环

//一顿操作猛如虎,提交超越百分五。
//执行用时:648 ms, 在所有 Java 提交中击败了5.09% 的用户
//内存消耗:39.3 MB, 在所有 Java 提交中击败了34.38% 的用户
class Solution {
    public int pivotIndex(int[] nums) {
        if(nums.length == 0 || nums.length == 2){return -1;}
        if(nums.length == 1){return 0;}

        double sum = 0;
        for(int i : nums){
            sum =(double)sum + i;
        }
        for(int j = 0;j < nums.length;j++){
            double total = 0;
            for(int k = 0;k < j;k++){
                total =(double)total + nums[k];
            }
            if(total == (double)(sum - nums[j])/2){
                return j;
            }
            // if(total > 0 && total > (double)(sum - nums[j])/2){
            //     return -1;
            // }
            // if(total < 0 && total < (double)(sum - nums[j])/2){
            //     return -1;
            // }
            //System.out.println(total);
        }
        return -1;
    }
}
//执行用时:1 ms, 在所有 Java 提交中击败了100.00% 的用户
//内存消耗:39.1 MB, 在所有 Java 提交中击败了59.60% 的用户
class Solution {
    public int pivotIndex(int[] nums) {
        int sum = 0, leftsum = 0;
        for (int x: nums) sum += x;
        for (int i = 0; i < nums.length; ++i) {
            if (leftsum == sum - leftsum - nums[i]) return i;
            leftsum += nums[i];
        }
        return -1;
    }
}

【第十五题】等价多米诺骨牌的数量

在这里插入图片描述

分析:

【第十六题】特殊数组的特征值

在这里插入图片描述

分析:

//执行用时:2 ms, 在所有 Java 提交中击败了29.21% 的用户
//内存消耗:36 MB, 在所有 Java 提交中击败了78.70% 的用户
class Solution {
    public int specialArray(int[] nums) {
        Arrays.sort(nums);
        for(int i = 0;i < 1000;i++){
            for(int j = 0;j < nums.length;j++){
                if(nums[j] >= i){
                    //System.out.println(i + " "+j+" "+(nums.length-j));
                    if((nums.length - j) == i){
                        return i;
                    }else{
                        break;
                    }
                }
            }
        }
        return -1;
    }
}
//执行用时:1 ms, 在所有 Java 提交中击败了93.73% 的用户
//内存消耗:36.3 MB, 在所有 Java 提交中击败了52.87% 的用户
class Solution {
    public int specialArray(int[] nums) {
        Arrays.sort(nums);
        if(nums[0] >= nums.length)//length个值
            return nums.length;
        for (int i = 1; i <= nums.length; i++) {
            if((nums[nums.length -i] >= i && nums[nums.length -i-1] < i ))
                return i;
        }
        return -1;
    }
}

【第十七题】珠玑妙算

在这里插入图片描述

分析:猜中——>相应位置的字母相同;伪猜中——>字母存在,但是位置错了。
双指针:确定是否猜中;桶:确定伪猜中的次数;

【第十八题】最长连续递增序列

在这里插入图片描述

分析:

//执行用时:1 ms, 在所有 Java 提交中击败了99.79% 的用户
//内存消耗:39.2 MB, 在所有 Java 提交中击败了48.68% 的用户
class Solution {
    public int findLengthOfLCIS(int[] nums) {
        if(nums.length == 0 || nums.length == 1){return nums.length;}
        int max = 1,count = 1;
        
        for(int i = 1;i < nums.length;i++){
            if(nums[i] > nums[i-1]){
                count++;
            }else{
                max = Math.max(max,count);
                count = 1;
            }
        }
        max = Math.max(max,count);
        return max;
    }
}

【第十九题】将每个元素替换为右侧最大元素

在这里插入图片描述

分析:从右往左开始。不断比较得出最大值

//执行用时:3 ms, 在所有 Java 提交中击败了32.65% 的用户
//内存消耗:39.9 MB, 在所有 Java 提交中击败了18.08% 的用户
class Solution {
    public int[] replaceElements(int[] arr) {
        int[] ret = new int[arr.length];
        ret[arr.length - 1] = -1;
        int max = arr[arr.length -1];
        for(int i = arr.length -2;i>=0;i--){
            //System.out.println(max);
            ret[i] = Math.max(arr[i+1],max);
            max = Math.max(arr[i+1],max);
        }
        return ret;
    }
}

【第二十题】数组拆分I

在这里插入图片描述

分析:按照顺序从小到大排序,然后每两个一组,不断加上组内min,最后计算总和。
方法二:计数排序.(没咋看懂) https://leetcode-cn.com/problems/array-partition-i/solution/shu-zu-chai-fen-i-by-leetcode/

//执行用时:14 ms, 在所有 Java 提交中击败了36.73% 的用户
//内存消耗:40.8 MB, 在所有 Java 提交中击败了12.39% 的用户
class Solution {
    public int arrayPairSum(int[] nums) {
        if(nums.length == 2){return Math.min(nums[0],nums[1]);}
        int sum = 0;
        Arrays.sort(nums);
        for(int i = 0;i < nums.length;i+=2){
            sum += Math.min(nums[i],nums[i+1]);
        }
        return sum;
    }
}
public class Solution {
    public int arrayPairSum(int[] nums) {
        int[] arr = new int[20001];
        int lim = 10000;
        for (int num: nums)
            arr[num + lim]++;
        int d = 0, sum = 0;
        for (int i = -10000; i <= 10000; i++) {
            sum += (arr[i + lim] + 1 - d) / 2 * i;
            d = (2 + arr[i + lim] - d) % 2;
        }
        return sum;
    }
} 

作者:LeetCode
链接:https://leetcode-cn.com/problems/array-partition-i/solution/shu-zu-chai-fen-i-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

【第二十一题】玩筹码

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会为你介绍Python中的数组。 在Python中,数组是一种存储元素的数据结构。与列表不同,数组是固定大小的,且元素类型必须相同。 要使用数组,需要先导入array模块。下面是一个创建数组的示例: ```python import array as arr # 创建一个整数类型的数组 a = arr.array('i', [1, 2, 3, 4, 5]) # 打印数组 print(a) ``` 在上面的示例中,我们使用了`array`模块创建了一个整数类型的数组,并初始化了它。要注意的是,第一个参数是一个字符,用于指定数组元素的类型。在本例中,我们使用了`i`,表示整数类型。 除了整数类型之外,还有其他类型可以使用,如`f`表示浮点数,`d`表示双精度浮点数,`b`表示布尔类型等。 在数组中,可以使用索引来访问元素,如下所示: ```python import array as arr # 创建一个整数类型的数组 a = arr.array('i', [1, 2, 3, 4, 5]) # 访问数组中的第一个元素 print(a[0]) # 修改数组中的第二个元素 a[1] = 6 # 打印数组 print(a) ``` 在上面的示例中,我们使用了索引`0`来访问数组中的第一个元素,使用索引`1`来修改数组中的第二个元素。 除了使用索引来访问和修改元素外,还可以使用循环来遍历数组中的所有元素,如下所示: ```python import array as arr # 创建一个整数类型的数组 a = arr.array('i', [1, 2, 3, 4, 5]) # 遍历数组中的所有元素 for i in a: print(i) ``` 在上面的示例中,我们使用了`for`循环来遍历数组中的所有元素,并打印每个元素的值。 这就是Python中数组的基本用法。希望对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值