【leetcode之旅】 数组 - 关于数组【简单】部分的总结

通过这么久的坚持,终于把数组中的【简单】部分的题目做完了,做了这么多,也该来一次小小的总结。

通过数组的练习,了解了这一类题的常用思路和方法

1.使用多重循环一步步遍历求解

2.将数组存入Map中,然后利用map中的方法进行解答

3.双指针法,定义两个索引,对数组进行遍历

4.有时从头往后遍历不能解决问题,那么可以尝试从后往前进行遍历

5.在【66.加一问题】中将每位数通过相除(/)判断是否进位,通过取余(%)给每位数对应的值,

在遇到进位问题时,可以考虑使用这种方法

6.分治算法来解决问题,通过将一个大的问题分成很多个小块,然后每个小块负责各自的功能

7.在遇到【53.最大子序和】这类问题时,可以通过边累加边判断,在 求和之后的值 和 求和之前的值  之间取较大/小的值

8.在遇到搜索问题时,请首先考虑二分查找,如果不行,再考虑普通的搜索方式

9.遇到移除元素时,不一定要真正的删除,可以将其替换掉

10.大家可能觉得将【杨辉三角】【杨辉打印II】出来可能有点难度,可以换个角度思考问题,不需要第一步就将杨辉三角的结构和数据都对应上你可以先将杨辉三角初始化,将结构构建出来,然后再将对应的值进行替换。

对于构建结构,可以使用List<List<Integer>>进行构建

对于数据替换,可以先初始化为1,然后通过上一层之和,求出下一层的值,然后对其进行修改赋值。

11.对于盈利问题时【121.买股票的最佳时机】【122.买卖股票的最佳时机II】,

对于只能买卖一次的情况:可以先进行判断是否继续,继续下去是盈利还是亏损,记录每次的利润将其和目前求得的利润 取最大值。

对于可以买卖多次的情况: 判断下一次的值是否比这次的大,如果大,直接相减,将差值进行累加。

12.在进行查找时,我们可以对已经查找到的值做一个标记,使其表示已存在,在【448.找出所有数组消失的数】中,将已经存在的值标记为负数,然后将1-n不为负数的值输出

13.【求第三大的数】,或者求第二大的数,模板如下:

for (int i = 0; i < nums.length; i++) {
   if (nums[i] > max){
       thirdMax = secondMax;
       secondMax = max;
       max = nums[i];
    }else if (nums[i] > secondMax && nums[i] < max){
       thirdMax = secondMax;
       secondMax = nums[i];
    }else if (nums[i] > thirdMax && nums[i] < secondMax){
       thirdMax = nums[i];
    }
}

将赋值最大值max之前先将之前的max赋值给第二大的值secondMax

赋值第二大的值secondMax之前先将之前的secondMax赋值给第三大的值

14.数组移动问题:

向前移动:举例:【283.移动零


/**
 * 前移
 * @param nums
 * @param index
 */
public static void move(int[] nums,int index){
    for (int i = index + 1; i < nums.length; i++) {
        nums[i - 1] = nums[i];
    }
}

向后移动:

从后面开始遍历,nums[i] = nums[i - 1]

15. 利用异或求解(^),一个数连续异或两个相同的数,得到的结果为其本身,例如:1 ^ 2 ^ 2 = 1,案例:【268.缺少数字

16. 利用%可以防止重复移动【189. 旋转数组

17. Set集合在数组去重方面,会有奇效

18.注意map.put()方法是有返回值的,如果key值不存在,则返回null,如果存在,则返回上一个key值【219. 存在重复元素II

19. 在【169.求众数】的时候,很多人想到的是将其出现的个数计算出来,其实不需要,只需给每个值进行统计,当某个值相同时则count++,否则count--,当count=0时,对下一个值进行统计(注意:这种方法适用于数组中一定存在众数的情况)。

20. 从两边搜索比每次从头开始的速度要快很多

22. 【566.重塑数组】中,为了防止数组越界,利用int类型相除,小于必为0,取余小于必为本身的方法,对索引值进行了限定

public static int[][] matrixReshape(int[][] nums, int r, int c) {
    int n = nums.length,m = nums[0].length;
    if (r * c != n*m){
        return nums;
    }
    int[][] res = new int[r][c];
    for (int i = 0; i < r * c; i++) {
        res[i/c][i%c] = nums[i/m][i%m];
    }
    return res;
}

23. 可以利用map中 jdk1.8的新特性map.getOrDefault(),统计数组中每个值出现的个数

Map的新方法getOrDefault(Object,V)允许调用者在代码语句中规定获得在map中符合提供的键的值,否则在没有找到提供的键的匹配项的时候返回一个“默认值”。

24. 可以多多利用三元运算符

25. 【697.求数组的度】中需要统计数组的度(即出现次数最多的值开始索引与结束时索引差的长度),以及随时更新重复数的索引,以及保存第一次出现改值的索引,使用了Map<Integer,int[]>来存储

26. 【 695.岛屿的最大面积】中使用递归求岛屿的面积,当计算了一个值,就将其置为0,递归的算法就是判断其周围有没有1,如果有继续递归,如果没有,则直接返回0

27. 多多利用公式,使其更容易理解【888.公平的糖果交换

28.多多利用中间值和最终值进行比较,【849.到最近的人的最大距离

29.看清题型,并觉得最终的输出类型以及使用的数据结构

30. 在【746.使用最小花费爬楼梯】时,有时数组需要进行扩容然后进行判断,在原数组无法选择最后走出的路径时

31.最后一点总结,不要钻牛角尖,这样会浪费你的很多时间!!!

喜欢本文的话,可以关注一下公众号,每天定时更新一篇学习日记,让我们一起成长!

 

 

 

  • 44
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 26
    评论
题目描述:给定一个非负整数数组nums和一个整数m,你需要将这个数组分成m个非空的连续子数组。设计一个算法使得这m个子数组中的最大和最小。 解题思路: 这是一个典型的二分搜索题目,可以使用二分查找来解决。 1. 首先确定二分的左右边界。左边界为数组中最大的值,右边界为数组中所有元素之和。 2. 在二分搜索的过程中,计算出分割数组的组数count,需要使用当前的中间值来进行判断。若当前的中间值不够分割成m个子数组,则说明mid值偏小,将左边界更新为mid+1;否则,说明mid值偏大,将右边界更新为mid。 3. 当左边界小于等于右边界时,循环终止,此时的左边界即为所求的结果。 具体步骤: 1. 遍历数组,找到数组中的最大值,并计算数组的总和。 2. 利用二分查找搜索左右边界,从左边界到右边界中间的值为mid。 3. 判断当前的mid值是否满足题目要求,若满足则更新右边界为mid-1; 4. 否则,更新左边界为mid+1。 5. 当左边界大于右边界时,循环终止,返回左边界即为所求的结果。 代码实现: ```python class Solution: def splitArray(self, nums: List[int], m: int) -> int: left = max(nums) right = sum(nums) while left <= right: mid = (left + right) // 2 count = 1 total = 0 for num in nums: total += num if total > mid: total = num count += 1 if count > m: left = mid + 1 else: right = mid - 1 return left ``` 时间复杂度分析:二分搜索的时间复杂度为O(logN),其中N为数组的总和,而遍历数组的时间复杂度为O(N),因此总的时间复杂度为O(NlogN)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值