int arr[2][3] = {{1,2,3},{4,5,6}}
// 首先将二维数组arr看作元素是arr[0],arr[1]的一维数组
arr // 二维数组arr的起始地址
arr[i] // 第i行一维数组的数组名,代表该一维数组的首元素地址,即第一个元素arr[i][0]的地址 =*(arr+i)
arr[i]+j // 代表arr[i][j]的地址,即&(arr[i][j])
*(arr[i]+j) // 代表arr[i][j]
arr[i][j] // 代表arr[i][j]
arr+i // 代表二维数组中第i行数组的地址
*(arr+i) // 即arr[i],第i行第0列的地址
*(arr+i)+j // 即&(arr[i][j])
*(*(arr+i)+j) // 即arr[i][j]
如果难以理解,可以看看在一维数组中的情况:
int arr[3]={1,2,3}
arr[1] // 代表了a[1]的值,即2
arr+1 // 代表了a[1]的地址,即&a[1]
*(arr+1) // 代表了a[1]的值,即2
题目链接:二分查找
如果这道题目的名字不是二分查找,那么拿到题目一个最直接的思路就是for
循环暴力求解。
class Solution {
public:
int search(vector<int>& nums, int target) {
for(int i=0; i<nums.size(); i++){
if(nums[i] == target){
return i;
}
}
return -1;
}
};
再一看,输入的数组是有序的,同时数组中还没有重复元素,再结合题目二分查找,便也可轻易地想到实用二分法来查找元素。自己在纸上画画,有一个二分法的伪代码。
二分法的具体实现要关注两个点:
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
while (left <= right){
int mid = left + (right - left) / 2;
if (nums[mid] == target){
return mid;
}
else if (nums[mid] < target){
left = mid + 1;
}
else if (nums[mid] > target){
right = mid - 1;
}
}
return -1;
}
};
题目链接:移除元素
在看完题目说明后。首先是得删除掉数组中的目标元素(在数组中删除元素本质是后继元素的覆盖),然后返回的是剩余元素的长度。使用for
循环,如果当前元素等于目标元素,则: 将后续的所有元素向前移动一位(这里又要使用一个for循环),同时数组长度减一,for
循环的i
也减一(因为数组已经移动,当前位置的元素是之前的下一个位置的元素,还没有经过if
判断)。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int n = nums.size();
for(int i=0; i<n; i++){
if(nums[i] == val){
for(int j=i+1; j<n; j++){
nums[j-1] = nums[j];
}
n--;
i--;
}
}
return n;
}
};
这道题不看解析想不到要用双指针法,对于什么是双指针法,现在浅显的认识也就是要有两个东西来进行处理,之前的for
循环都是使用一个东西来遍历。
双指针法就是得要有两个东西来对数组进行处理,直观解释一下过程。
变量fast
,也就是快指针,用来遍历要处理的数组;变量slow
,也就是慢指针,用来对新数组的下标进行计数。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slow = 0;
for(int fast = 0; fast<nums.size(); fast++){
if(nums[fast] != val){
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
};