数组是非常基础的数据结构,关于数组算法的题目一般在思维上不难,但是仍要自己动手实现才能发现细节问题

数组是存放在连续内存空间上的相同类型数据的集合

  • 数组下标是从0开始的
  • 不同于链表,数组内存地址是连续的
  • 数组的元素不能进行删除,只能覆盖
  • 如删除中间元素需把后面的所有元素向前做移动操作

要求

704. 二分查找 - 力扣(LeetCode)

给定一个n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下标,否则返回-1

示例:

  1. 输入: nums = [-1,0,3,5,9,12], target = 9
  2. 输出: 4
  3. 解释: 9 出现在 nums 中并且下标为 4
  4. 输入: nums = [-1,0,3,5,9,12], target = 2
  5. 输出: -1
  6. 解释: 2 不存在 nums 中因此返回 -1

解法

暴力解法

for循环遍历数组,找出数组中的target值并返回下标,不做过多解释

  1. class Solution {
  2. public int search(int[] nums, int target) {
  3. for(int i = 0; i < nums.length; i++){
  4. if(nums[i] == target){
  5. return i;
  6. }
  7. }
  8. return -1;
  9. }
  10. }

二分查找

题目提到数组按照升序排列,并且数组中无重复元素,这些都是使用二分查找的前提条件

利用数组排列,每次取值选取中间下标的值快速缩短查找范围

  1. class Solution {
  2. public int search(int[] nums, int target) {
  3. // 避免当 target 小于nums[0] nums[nums.length - 1]时多次循环运算
  4. if (target < nums[0] || target > nums[nums.length - 1]) {
  5. return -1;
  6. }
  7. int left = 0;
  8. int right = nums.length - 1;
  9. int middle = (left + right) / 2;
  10. // int middle = left + (right - left >> 1); 防止left+right溢出
  11. while(left <= right){
  12. //思考终止条件 left < right 以及 nums[middle] != target是否可行,可以试着写下不同解法
  13. if(nums[middle] == target){
  14. return middle;
  15. }else if(nums[middle] < target){
  16. left = middle + 1;
  17. middle = (left + right) / 2;
  18. }else{
  19. right = middle - 1;
  20. middle = (left + right) / 2;
  21. }
  22. }
  23. return -1;
  24. }
  25. }

学有余力的同学可以分析一下最优情况、最坏情况、一般情况下的时间、空间复杂度