LeetCode数组类知识点&题型总结

参考博主charlotte的总结,记录自己的刷题过程。她真的很棒~https://github.com/huxiaoman7/leetcodebook

https://mp.weixin.qq.com/s?__biz=MzI0OTQwMTA5Ng==&mid=2247483819&idx=1&sn=071731261441f702f429ae9fc1b98b84&chksm=e9935bccdee4d2da68f0a62830c23daba65fe81c42f4f04f0f5358f1b76bcf144b70f3b4a30d&token=1778626027&lang=zh_CN#rd

数组

什么是数组

​ 我们知道常用的数据存储方式有两种:顺序存储和非顺序存储。顺序存储就是把数据存储在一块连续的空间内。数组(array)就是典型的顺序存储,而链表就是典型的非顺序存储。

​ 数组通常用于存储一系列相同类型的数据。当我们在创建数组时,会在内存中划分出一块连续的内存用于存储数据,插入数据时,会将数据按顺序存储在这块连续的内存中,读取时通过访问数组的索引迅速取出。数组名就是一个指针,指向这段内存的起始地址。通过数组的类型,编译器知道在访问下一个元素的时候需要在内存中后移多少个字节。由于数组在存储时是顺序存储的,存储数据的内存也是连续的,所以数组在读取数据时比较容易,随机访问速度快,但是插入和删除就比较费劲了。读取可以直接根据索引,插入和删除则比较耗时,插一个数据需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其中,如果想删除一个元素,同样需要移动大量元素去掉被移动的元素。所以如果需求是快速访问数据,很少或者几乎不插入和删除元素,数组是一个不错的选择。

​ 最常见的有一维数组和二维数组,稍微复杂一点的是多维数组和动态数组。在c++中,STL提供了Vector,在Java中,Collection集合中提供了ArrayList和Vector,对于Python而言,内置的List就是一个动态指针数组。当列表中没有空间存储新的元素时,列表会动态地改变大小以容纳新的元素,每次改变大小时,会预留一部分空间以降低改变大小的频率。

类别

  • 1.无序数组

    • 概念:未经过排序的数组
    • 优点:插入快
    • 缺点:查找慢,删除慢,大小固定
  • 2.有序数组

    • 概念:数组中的元素是按照一定规则排列的。

    • 优点:查找效率高。根据元素值查找时可以使用二分查找,效率比无序数组高很多,在数据量大的时候尤其明显。对于leetcode中很多查找元素类的题目,如果没有事先说明是有序数组,可以事先对数组进行排序,再进行查找,二分法或其他方法都可以。

    • 缺点:插入和删除较慢。插入元素时,首先判断该元素的小标,然后对该小标之后的所有元素后移以为才能进行插入,所以有序数组比较适合查找频繁,而插入删除操作较少的情况。

      复杂度 有序数组 无序数组
      查找复杂度 O(logn) O(n)
      插入复杂度 O(n) O(1)
  • 3.如何权衡

    • 根据需求性能判断:对于插入时性能要求高而对查询的要求不高或者插入操作远多于查询操作时,选择无序数组;相反,如果对查询性能要求较高或者查询操作量大时,则选择有序数组。
    • 根据数据量判断:数据量小且可预知,查询速度比插入速度更重要使用有序数组;数据量大且不可知,插入速度比查询速度更重要使用无序数组。

 

题型总结

【一维数组】

1.K-Sum

​ 这类题目通常会给定一个数组和一个值,让求出这个数组中两个/三个/K个值的和等于这个给定的值target。leetcode第一题就是two-sum,对于这类题目,首先看题目要求的时间复杂度和空间复杂度是什么,其次看有没有限制条件,如要求不能有重复的子数组或者要求按照升序/降序排列等。解法如下:

1.暴力解法:最常见,但是通常会超时,只能作为备选,

2.hash-map:建立一个hash-map循环遍历一次即可

3.two-pointers:定位两个指针根绝和的大小来移动另外一个。这里设定的指针个数根据题目中K的个数来定。3Sum中可以设定3个指针,固定两个,移动另一个。

Java

  /*hash-map*/
  class Solution {
      public int[] twoSum(int[] numbers, int target) {
          int[] result = new int[2];
          HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
          for (int i = 0;i<numbers.length;i++){
          if (map.containsKey(target-numbers[i])){
              result[0]=map.get(target-numbers[i]);
              result[1]= i+1;
          }
          map.put(numbers[i],i+1);       
      }
          return result;
      }
  }

Leetcode中包含该类型的题目:

序号 题目 难度 代码
1 Two Sum easy python、java、c++
167 Two Sum II-Input array is sorted easy python、java、c++
15 3Sum medium python、java、c++
16 3Sum Closet medium python、java、c++
259 3Sum Smaller medium python、java、c++
18 4Sum medium python、java、c++

题解:

1. 使用hashmap遍历中存储对应的数值(target-nums[i]),但是因为不能使用某元素两次,所以要先判断是否存在所需要的key再添加该元素。

167. 双指针。一个指向头元素,一个指向尾元素。如果和大于target就向前移动尾指针,如果小于target就向后移动头指针,直到和为目标值或者头

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值