算法通关村-不简单的数组增删改查

不简单的数组增删改查-(算法通关村第三关青铜挑战)


  • 初始化数组最基本的方式是循环赋值:

  •   for(int i = 0; i < arr.length; i++){
          arr[i] = i;
      }
    
  • 但是这种方式在面试题中一般不行,因为很多题目会给定若干测试数组让你都能测试通过,例如给你两个数组 [0,1,2,3,5,6,8] 和 [1,4,5,6,7,9,10]。那这时候该如何初始化呢?显然不能用循环了,可以采用下面的方式:

  •   int[] arr = new int[]{0,1,2,3,5,6,8};
      int[] nums = {2, 5, 0, 4, 6, -10};
    
  • 如果要测试第二组数据,直接将其替换就行。创建数组时大小就是元素的数量,是无法在插入元素的,如果需要增加新元素就不能这么用了。

查找一个元素

  •   /**
           * 
           * @param arr 要查找的数组
           * @param size 已经存放的元素个数
           * @param key 待查找的元素
           * @return
           */
          public static int findByElement(int[] arr, int size, int key){
              for(int i = 0; i < size; i++){
                  if(arr[i] == key){
                      return i;
                  }
              }
              return -1;
          }
    
  • 还有一种很常见的情况,如果数组是递增的,此时查找时如果相等或者当前位置元素比目标值更大就停下了。你是否可以修改上面的代码来实现这个功能?

  •   public static int findByElement2(int[] arr, int size, int key){
              for(int i = 0; i < size; i++){
                  if(arr[i] > key){
                      System.out.println("key not exists in arr[]");
                  }else if(arr[i] == key){
                      return i;
                  }
              }
              return -1;
          }
    

增加一个元素

  •   /**
           * 
           * @param arr
           * @param size 数组已经储存的元素数量,从1开始编号
           * @param element 待插入的元素
           * @return
           */
          public static int addByElementSequence(int[] arr, int size, int element){
              //判断size > arr.length
              if(size >= arr.length){
                  return -1;
              }
              int index = size;//新元素插入位置索引
              for(int i = 0; i < size; i++){
                  if(element < arr[i]){
                      index = i;
                      break;
                  }
              }
              //元素后移
              for(int j = size; j > index;j--){
                  arr[j] = arr[j-1];
              }
              arr[index] = element;
              return index;
          }
    

删除一个元素

  • 例如序列是1 2 3 4 5 6 7 8 9,要删除5,则应先遍历,找到5,然后从5开始执行删除操作,也就是从6开始逐步覆盖上一个元素,最终将序列变成1 2 3 4 6 7 8 9[9]。

  •    /**
           * 
           * @param arr 数组
           * @param size 数组已经储存的元素数量,从1开始编号
           * @param key 删除目标值
           * @return
           */
          public int removeByElement(int[] arr, int size, int key){
              int index= -1;
              for(int i = 0; i < size; i++){
                  if(arr[i] == key){
                      index = i;
                      break;
                  }
              }
              if(index != -1){
                  for(int j = index + 1; j < size; j++){
                      arr[j-1] = arr[j];
                  }
                  size--;
              }
              return size;
          }
    

单调数组问题

  • LeetCode896: 判断一个给定的数组是否为单调数组。

  • 在 i 和 i+1 位置出现了 nums[i] > nums[i+1],而在另外一个地方 j 和 j+1 出现了 nums[j] < nums[j+1],那就说明不是单调。

  •   public boolean isMonotonic(int[] nums){
              boolean incr = true, decr = true;
              int n = nums.length;
              for(int i = 0; i < n-1; i++){
                  if(nums[i] > nums[i+1]){
                      incr = false;
                  }
                  if(nums[i] < nums[i+1]){
                      decr = false;
                  }
              }
              return incr || decr;
          }
    

数组合并问题

  • LeetCode88: 给你两个按非递减顺序排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n,分别表示 nums1 和 nums2 中的元素数目。请你合并 nums2 到 nums1 中,使合并后的数组同样按非递减顺序排列。

  • 最终合并的数组储存在数组 nums1 中,nums1 的初始长度为 m+n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0应忽略。nums2 的长度为n。

  • 例子1:
    输入:nums1 = [1, 2, 3, 0, 0, 0],m = 3,nums2 = [2, 5, 6],n = 3
    输出:[1, 2, 2, 3, 5, 6]
    解释:合并 [1, 2, 3,] 和 [2, 5, 6] 的结果是 [1, 2, 2, 3, 5, 6]
  • 对于有序数组的合并,一种简单的方法是先将B直接合并到A的后面,然后再对A排序。(没技术含量)。

  •    public void merge1(int[] nums1, int nums1_len, int[] nums2, int nums2_len){
              for(int i = 0; i < nums2_len; i++){
                  nums1[nums1_len + i] = nums2_len;
              }
              Arrays.sort(nums1);
          } 
    
  • 比较好的方式是从后向前插入,A和B的元素数量是固定的,所以排序后最远位置一定是A和B元素都最大的那个,依次类推,每次都找最大的那个从后向前填就可以了。

  •   public void merge(int[] nums1, int nums1_len, int[] nums2, int nums2_len){
              int i = nums1_len + nums2_len -1;
              int len1 = nums1_len-1, len2 = nums2_len-1;
              while(len1 >= 0 && len2 >= 0){
                  if(nums1[len1] <= nums2[len2]){
                      nums1[i--] = nums2[len2--];
                  }else if(nums1[len1] > nums2[len2]){
                      nums1[i--] = nums1[len1--];
                  }
              }
              //假如数组 A 或 B 还有剩余元素
              while(len2 != -1){
                  nums1[i--] = nums2[len2--];
              }
              while(len1 != -1){
                  nums1[i--] = nums1[len1--];
              }
          }
    
  • 16
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

种一棵树leng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值