算法分析(四):删除排序数组中的重复项

97 阅读2分钟

这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

前言

解法

  • 这道题很简单,意思就是一个数组分成两个部分,左边的部分和大于右边的部分和,找出这个界限,当然还有个问题可能界限在数组两边,例子里有写。

  • 一开始我的想法收到的双指针的影响,想要在左右两边都设置一个指针然后开始累加,后面想想有界限在数组两端这种情况就很麻烦。

  • 然后通过题解,我理解了这个解法

  • 第一步,首先将数组都加起来,设置为sum

  • 第二步,将索引0设置为界限,左边total加上这个界限,跟sum比,如果相等就返回,不相等就接着遍历,并且,total加上数组 的值,sum减去数组的值 在这里插入图片描述

  • 第三步,当两边相等,返回索引 在这里插入图片描述

  • 第四步,如果遍历完成返现没有相对应的数字,就返回-1

  • 这道题算是入门,有一丝丝前缀和的味道,这道题还是相当简单的,不说了上代码


class Solution {
    public int pivotIndex(int[] nums) {
    	//累加
        int sum = Arrays.stream(nums).sum();
        //左边
        int total = 0;
        int l = nums.length;
        //循环遍历
        for(int i=0;i<l;i++){
            //加上当下的索引
            total += nums[i];
            if(total == sum){
                return i;
            }
            //减去当下的索引
            sum -= nums[i];
        }
        //没有合适的返回
        return -1;
    }
}

空间优化

  • 甚至可以不使用额外空间。
  • 先求一遍总和 total,再使用 sum 记录当前遍历位置的左侧总和。
  • 对于中心索引必然有:sum = total - sum - nums[i] (左边值 = 右边值)

代码:


class Solution {
    public int pivotIndex(int[] nums) {
        int n = nums.length;
        int total = 0, sum = 0;
        // 我们的 nums 处理不涉及并行操作,使用循环要比 Arrays.stream 快
        // total = Arrays.stream(nums).sum(); 
        for (int i = 0; i < n; i++) total += nums[i];
        for (int i = 0; i < n; i++) {
            if (sum == total - sum - nums[i]) return i;
            sum += nums[i];
        }
        return -1;
    }
}
  • 时间复杂度:对数组进行线性扫描。复杂度为 O(n)O(n)
  • 空间复杂度:O(1)O(1)

总结

题目相当简单,但是很多难的算法都是从简单到复杂的,又一个循序渐进的过程,如果还想深入可以去看看变式,加油吧。