数组是在编程中非常常见的数据存储结构,主要有以下几个特点:
更多有关数组的理论基础可查阅:《代码随想录》数组理论基础
题目详细:LeetCode.704
注意:二分查找对数据样本有明确的要求,即数组中的元素是有序的,所以在今后遇到类似于“在有序的数据样本中查找某一目标数据”时,都可以优先尝试二分查找。
二分查找的关键点在于二分,顾名思义,就是在查找的过程中不断将数据集合一分为二,划分为两个区间,且仅在目标值可能存在的区间中继续进行划分,直到找到目标值或者无法继续划分(找不到目标值),其解题思路简单,类似于根据区间猜数字的小游戏。
Java解法:
class Solution {
public int search(int[] nums, int target) {
int l = 0, r = nums.length-1;
while(l < r){
int mid = l + (r-l)/ 2;
int cur_val = nums[mid];
if(target == cur_val){
return mid;
}else if(target > cur_val){
// 目标值大于当期mid坐标下的值,则表示目标值在比较大的区间范围内
l = mid + 1;
}else if(target < cur_val){
// 目标值小于当期mid坐标下的值,则表示目标值在较小的区间范围内
r = mid - 1;
}
}
return -1;
}
}
题目详细:LeetCode.27
注意:本题的难点在于,不能使用额外的数组空间,必须仅使用O(1) 额外空间
并原地修改
输入的数组。
由数组理论基础可知,数组占用的是一片连续的存储空间,所以在对数组进行插入/删除元素时,可能需要向后/向前移动一部分元素。
移除元素这一题的过程,就类似于对数组中某一元素进行删除操作,虽然用额外的数组空间能够非常简单地解答,但在实际应用时,如果数据量非常庞大,则会大大增加算法的空间复杂度。
不能使用额外的数组空间的要求,不仅是为了让我们更好的理解操作数组时对地址空间的影响,也是为了在实际应用中,能够更加效率地解决问题。
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:
- 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。
- 你不需要考虑数组中超出新长度后面的元素。
- 例如,函数返回的新长度为 2 ,即 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
通过示例可以得知:
相当于就是将需要移除的元素,全部移动到数组的尾部,然后输出记录的新的数组长度即可。
Java解法(模拟上述思路解题):
class Solution {
public int removeElement(int[] nums, int val) {
// 利用双指针,方便将需要移除元素往右边挪
// ans则记录用于移除元素后的新长度,每移除一个元素则-1
int l = 0, r = nums.length-1, ans = nums.length;
while(l <= r){
int l_val = nums[l], r_val = nums[r];
if(r_val == val){
// 判断右指针当前的元素是否需要被移除,因为需要移除的元素会被放在右边,所以当遇到需要移除的元素时,只需要将右指针左移一位即可,然后继续循环,直到右指针指向不需要移除的元素。
r--;
ans--;
continue; // very important !
}else if(l_val == val){
// 判断左指针当前的元素是否需要被移除,因为需要移除的元素会被放在右边,所以当遇到需要移除的元素时,需要将左指针的元素与右指针的元素进行交换(上面的if已经保证右指针此时指向的元素不需要被移除),接着将右指针左移一位即可。
nums[l] ^= nums[r];
nums[r] ^= nums[l];
nums[l] ^= nums[r];
r--;
ans--;
}
// 注意,当左右两个指针指向的元素都不需要被移除时,只需要移动左指针,因为右指针的主要作用是为了移除元素,而不是为了排查元素。
l++;
}
return ans;
}
}
开启护眼模式(简洁上述代码,并利用左指针来记录新数组的长度):
class Solution {
public int removeElement(int[] nums, int val) {
int l = 0, r = nums.length-1;
while(l <= r){
int l_val = nums[l], r_val = nums[r];
if(r_val == val){
r--;
continue;
}else if(l_val == val){
nums[l] ^= nums[r];
nums[r] ^= nums[l];
nums[l] ^= nums[r];
r--;
}
l++;
}
return l;
}
}
训练营的第一天,天气晴朗,积极向上又满怀期待,希望接下来的每一天都可以坚持下去,慢慢看到蜕变的自己。
每天都用一句诗来记录此刻的心情和结尾吧:
见兔而顾犬,未为晚也;亡羊而补牢,未为迟也。