首页 > 其他分享 >经典数据结构题目-数组

经典数据结构题目-数组

时间:2024-01-14 23:56:17浏览次数:26  
标签:题目 target nums int mid length 数组 数据结构 指针

704. 二分查找

  • 解决思路

    • 基于数组有序的特性,取其中一个值进行比较,即可淘汰该值左边或右边的元素,缩小搜索的区间
    • 使用两指针标记需要遍历的区间,取中间值进行比较,淘汰左边或右边元素,不断移动缩小遍历的区间,即可查到
  • 代码

    public int search(int[] nums, int target) {
            int l = 0;
            int r = nums.length - 1;
            while(l <= r){  // 注意点一
                int mid = l + (r-l)/2;
                if(nums[mid] > target){
                    r = mid - 1; // 注意点二
                }else if(nums[mid] < target){
                    l = mid + 1;
                }else{
                    return mid;
                }
            }
            return -1; 
        }
    
  • 注意点

    • 核心注意点:避免漏检元素
    • 注意点一:while条件中选择 l <= r 还是 l < r ,取决于 r 的取值;当 r = num.length时,l 不能 <= r,可能会溢出
    • 注意点二:当选择 l < r 的判断时,while中每次搜索的区间为 [l,r) 。当num[mid] > target时,r = mid,不能mid-1。因为r所指向的元素在进入第二次循环时,是不会再与target比较,会导致漏检
    • 时间复杂度 O(logN) 。总共需要遍历 log2N次,忽略常数2。
  • 扩展

    • 当元素可重复时,如何定位到与target相等的最小索引

    • public static int search(int[] nums, int target) {
              int l = 0;
              int r = nums.length - 1;
              while(l <= r){
                  int mid = l + (r-l)/2;
                  if(nums[mid] >= target){
                      // 等于target的时候 右指针继续移动,继续寻找最左边的一个
                      // 如果已达最左的一个,再循环左指针会移动,最终会大于r,取到最左的
                      r = mid - 1;
                  }else if(nums[mid] < target){
                      l = mid + 1;
                  }
              }
              // 会存在找不到与target相等的情况
              if(nums.length == l || nums[l] != target){
                  return -1;
              }
              return l;
          }
      

80. 删除有序数组中的重复项 II

  • 解决思路

    • 使用快慢指针遍历,快指针用于判断是否与上一个元素重复,慢指针用于记录下最终有效的数字
    • 快指针判断为不重复,慢指针记下来,同时向前移动一位
  • 代码

        public int removeDuplicates(int[] nums) {
            // 只允许元素出现一次的情况
            int k = 1;
            int fast = k;
            int slow = k; // 注意点一
            while(fast < nums.length){
                if(nums[fast] != nums[fast-k]){ // 注意点二
                    nums[slow] = nums[fast];
                    slow++;
                }
                fast ++;
            }
            return slow;
        }
    
  • 注意点

    • 核心注意点:理清快慢指针分别的作用
    • 注意点一:快慢指针的起始位置,k <= nums.length时,可以初始化快慢指针在k的位置开始遍历
    • 注意点二:判断元素是否超过k个重复,因为数组有序,如果当前元素等于前k个位置的元素,说明超过了
  • 同类型题目

977. 有序数组的平方

  • 解决思路

    • 非递减顺序。即递增但可以重复
    • 使用双向指针,比较两指针指向元素的绝对值,绝对值大的计算平方添加进结果数组
  • 代码

     public int[] sortedSquares(int[] nums) {
            int[] res = new int[nums.length];
            int l = 0;
            int r = nums.length-1;
            int index = nums.length - 1;
            while(l <= r){
                if(Math.abs(nums[l]) > Math.abs(nums[r])){
                    res[index] = (int)Math.pow(nums[l],2);
                    l++;
                }else{
                    res[index] = (int)Math.pow(nums[r],2);
                    r--;
                }
                index --;
            }
            return res;
        }
    
  • 注意点

    • 这里空间复杂度为O(1),不是O(n),因为空间复杂度是计算非答案占用的空间
  • 扩展

    • 想再节省空间的话,可以比较两个数的平方后,进行交换,右指针一直往前移即可

    • public int[] SortedSquares(int[] nums) {
          int left = 0;
          int right = nums.length-1;
          int leftR = 0, rightR = 0;
          while(right >= 0){
            leftR = nums[left]*nums[left];
            rightR = nums[right]*nums[right];
            // 左指针的平方比较大,交换到数组的后面来
            if(leftR >= rightR){
              nums[left] = nums[right];
              nums[right] = leftR;
            }else{
              nums[right] = rightR;
            }
            right--;
          }
          return nums;
      }
      

标签:题目,target,nums,int,mid,length,数组,数据结构,指针
From: https://www.cnblogs.com/gg12138/p/17964478

相关文章

  • 经典数据结构题目-链表
    链表707.设计链表解题思路参考官方的单向链表,设置一个成员变量作为虚拟头节点,一个成员变量size保存有效节点数代码publicMyLinkedList(){size=0;head=newListNode(0);}publicintget(intindex){if(index<0||index>=size){retur......
  • 后缀数组 SA 学习笔记
    后缀数组SA学习笔记后缀数组处理字符串后缀排名,公共子串类问题十分优秀,可以在部分情况下替代后缀自动机(SAM),本文主要讲解后缀数组的实现过程和部分例题。正文定义后缀:从\(i\)开始到字符串结束的一个特殊子串,本文用\(suf(i)\)表示从\(i\)开始的后缀。后缀数组SA:SA是......
  • java中数组和字符串
    数组数组的声明方式:类型[]变量;数组的创建方式:new类型[数组长度]数组的简单声明并且赋值//声明一个数组,它的长度是3String[]arrs=newString[3];arrs[0]="张三";arrs[1]="李四";//访问数组的值System.out.println(arrs[0]);输出的是张三//获取当前数组的长......
  • 超级简单的后缀数组(SA)笔记!!
    超级简单的后缀数组(SA)!!(未完)前言这里选择当一手标题党。由于刚学完这个字符串算法,本人字符串算法又比较薄弱,好不容易这一次在晚修看各种资料看得七七八八,决定趁脑子清醒的时候记录下来。免得自己不久后忘了后又要痛苦地再看各种资料。希望这篇博客能帮到你。前置知识:RMQ问题......
  • 用数组作为函数参数来实现冒号排序函数
    define_CRT_SECUNRE_NO_WARNINGS1include<stdio.h>voidbubble_sort(intarr[],intsz){inti=0;for(i=0;i<sz;i++)//冒泡的次数{intflag=1;//假设这一趟排序已经有序intj=0;for(j=0;j<sz-1-i;j++){if(arr[j]>arr[j+1]){inttmp......
  • P52 数组中出现次数超过一半的数字
    题目链接:方法一:若数组中有数字的出现次数超过数组长度的一半(绝对众数),则将该数组排序后中间位置的数一定就是该数。classSolution{public:intmoreThanHalfNum_Solution(vector<int>&nums){sort(nums.begin(),nums.end());intn=nums.size();......
  • [刷题技巧] LeetCode238. 除自身以外数组的乘积
    题目描述思路:前缀/后缀乘积数组构造除自身以外数组的左边前缀乘积构造除自身以外数组的右边后缀乘积然后对应位置相乘方法一:classSolution{publicint[]productExceptSelf(int[]nums){intn=nums.length;//前缀乘积数组:leftProduct[i]表......
  • 数组
    数组介绍数组可以存放多个同一类型的数据。数组也是一种数据类型,是引用类型。数组的快速入门//1.double[]表示是double类型的数组,数组名hens//2.{3,5,1,3.4,2,50}表示数组的值/元素,依次表示数组的//第几个元素//double[]hens={3,5,1,3.4,2,50,7.8......
  • [刷题班] LeetCode1480. 一维数组的动态和
    题目描述思路:前缀和前缀和数组(prefixSum)的构造方法一:classSolution{publicint[]runningSum(int[]nums){int[]preSum=newint[nums.length];preSum[0]=nums[0];for(inti=1;i<nums.length;i++){preSum[i]......
  • js 合并、复制和修改定型数组
    定型数组同样使用数组缓冲来存储数据,而数组缓冲无法调整大小。因此,下列方法不适用于定型数组:concat()pop()push()shift()splice()unshift()不过,定型数组也提供了两个新方法,可以快速向外或向内复制数据:set()和subarray()。set()从提供的数组或定型数组中把值复制到当前定型数组......