代码随想录算法训练营day01(数组理论基础, 二分查找, 移除元素)

一.数组理论基础

数组

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

注意:

1.数组下标都是从0开始的

2.数组的元素不能删,只能覆盖

二维数组

在C++中二维数组在地址空间上是连续的

在java中二维数组的每一行头结点的地址随机,后续结点连续

在这里插入图片描述

704.二分查找

https://leetcode.cn/problems/binary-search

注意:1.数组下标从0开始,到nums.length-1结束

2.二分查找要求无重复元素有序数组

3.“左闭右闭”和“左闭右开”的区别

1.左闭右闭,left和right可相等

 [left,right]int right = nums.length - 1while(left<=right)  
  ③right=mid-1;
class Solution {  
     public int search(int[] nums, int target) {  
         while(target < nums[0] || target > nums[nums.length-1])  
             return -1;  
         //左闭右闭  
         int left = 0, right = nums.length - 1;  
         while(left<=right){  
             int i=(left+right)/2;  
             if(nums[i]<target)//target比中间数大  
                 left=i+1;  
             else if(nums[i]>target)target比中间数小  
                 right=i-1;  
             else  
                 return i;  
         }  
         return -1;  
     }  
  }

2.左闭右开,则left和right不可相等

[left,right)  
  ①int right = nums.length  
  ②while(left<right)  
  ③right=mid;
class Solution {  
     public int search(int[] nums, int target) {  
         while(target < nums[0] || target > nums[nums.length-1])  
             return -1;  
         //左闭右开  
         int left = 0, right = nums.length ;  
         while(left<right){  
             int i=(left+right)/2;  
             if(nums[i]<target)//target比中间数大  
                 left=i+1;  
             else if(nums[i]>target)target比中间数小  
                 right=i;  
             else  
                 return i;  
         }  
         return -1;  
     }  
  }

35.搜索插入位置

https://leetcode.cn/problems/search-insert-position

注意点:1.时间复杂度要求为O(logn),因此需要使用二分查找

2.在数组中,未找到时,返回left or right+1

3.target不在范围内的情况可以不用考虑

1.左闭右闭

//思路:二分查找,找到则输出下标,找不到则输出left-1

  class Solution {  
     public int searchInsert(int[] nums, int target) {  
         //target不在范围  
         if(target <= nums[0])  
             return 0;  
         if(target > nums[nums.length -1])  
             return nums.length;  
         int left=0,right=nums.length -1;  
         while(left <= right){  
             int mid= (left+right)/2;  
             if(nums[mid]<target)  
                left=mid+1;   
             else if(nums[mid]>target)  
                 right=mid-1;  
             else  
                 return mid;  
         }  
          return left;  
     }  
  }

2.左闭右开

class Solution {  
     public int searchInsert(int[] nums, int target) {  
         int left=0,right=nums.length ;  
         while(left < right){  
             int mid= (left+right)/2;  
             if(nums[mid]<target)  
                left=mid+1;   
             else if(nums[mid]>target)  
                 right=mid;  
             else  
                 return mid;  
         }  
          return left;  
     }  
  }

27. 移除元素

https://leetcode.cn/problems/remove-element

注意点:1.数组元素不能删除,只能覆盖(循环覆盖,即自带一层循环)

2.数组移除元素=覆盖掉目标元素+数组缩短被移除元素的个数

1.暴力解,两次循环

  // 时间复杂度:O(n^2)  
  // 空间复杂度:O(1)  
  class Solution {  
     public int removeElement(int[] nums, int val) {  
         int length =nums.length;   
         for(int i=0;i<length;i++){  
             if(nums[i]==val){  
                for(int j=i+1;j<length;j++)  
                     nums[j-1]=nums[j];  
                  i--;  
                  length--;  
             }  
         }  
         return length;          
     }  
  }

2.快慢指针法

在这里插入图片描述

基础思想(自己根据动图想的):

①快慢指针位置相同时,一起移动,慢指针遇到val即停;

②快指针继续向前,当快慢指针位置不同时,快指针往回覆盖;快指针遇到val时,返回到慢指针位置

进阶思想(根据书上算法分析的):

①仅快指针遍历,当快指针不等于val时,给慢指针赋值

②是“虚拟数组法”的进阶。只不过在“虚拟数组法”中,当指针不等于val时,给另外一个数组赋值,而该算法赋值给同一个数组,从而实现了所谓的“覆盖”

  
  class Solution {  
     public int removeElement(int[] nums, int val) {  
         int length =nums.length;   
         int slowIndex = 0;  
         for(int fastIndex = 0 ;fastIndex < length;fastIndex++){  
             if(nums[fastIndex]!=val){//如果快指针位置的值和val不同,快指针给慢指针位置赋值  
                 nums[slowIndex]=nums[fastIndex];  
                 slowIndex++;  
             }  
         }  
         return slowIndex;  
     }  
  }

3.相向双指针方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值