int findByElement(int a[], int size, int key) {
for(int i = 0; i < size; i++)
if(a[i] == key) return i;
return -1;
}
int findByElement(int a[], int size, int key) {
for(int i = 0; i < size; i++)
if(a[i] >= key) return i;
return -1;
}
增加和删除元素是数组最基本的操作,看别人的代码非常容易,但是自己写的时候经常bug满天飞。能准确处理游标和边界等情况是数组算法题最基础重要的问题之一。所以务必自己亲手能写一个才可以,不要感觉挺简单就不写,其中涉及的问题在所有与数组有关的算法题中都会遇到。
将给定的元素插入到有序数组的对应位置中,我们可以先找位置,再将其后元素整体右移,最后插入到空位置上。这里需要注意,算法必须能保证在数组的首部、尾部和中间位置插入都可以成功。该问题貌似一个for循环就搞定了,但是如果面试直接让你写并能正确运行,我相信很多人还是会折腾很久,甚至直接会挂。因为自己写的时候会发现游标写size还是size-1,判断时要不要加等于等等,这里推荐一种实现方式。
int addByElementSequence(int a[], int size, int elem) {
if(size >= sizeof(a) / sizeof(a[0])) return -1;
int index = size;
for(int i = 0; i < size; i++) {
if(a[i] > elem) {
index = i;
break;
}
for(int i = size; i > index; i--) {
a[i] = a[i - 1];
}
a[index] = elem;
return index;
}
除了上面的方式,还可以一开始就从后向前一边移动一边对比查找,找到位置直接插入。从效率上看这样更好一些,因为只遍历了一次
int addByElementSequence(int a[], int size, int elem) {
if(size > sizeof(a) / sizeof(a[0])) return -1;
for(int i = size; i > 0; i--) {
if(a[i - 1] > elem) {
a[i] = a[i - 1];
} else {
a[i] = elem;
break;
}
}
return i;
}
对于删除,不能一边从后向前移动一边查找了,因为元素可能不存在。 所以要分为两个步骤,先从最左侧开始查是否存在元素,如果元素存在,则从该位置开始执行删除操作。
例如序列是 1 2 3 4 5 6 7 8 9 ,要删除5,则应先遍历,找到5,然后从5开始执行删除操作,也就是从6开始逐步覆盖上一个元素,最终将序列变成 1 2 3 4 6 7 8 9 [9]。
int removeByElement(int a[], int size, int key) {
int index = -1;
for(int i = 0; i < size; i++) {
if(a[i] == key) {
index = i;
break;
}
}
// 这里要从index + 1开始,否则会访问到不存在的地址
if(index != -1) {
for(int i = index + 1; i < size; i++) {
a[i - 1] = a[i];
}
size--;
}
return size;
}
LeetCode 896. 单调数列
如果数组是单调递增或单调递减的,那么它是 单调 的。
如果对于所有 i <= j,nums[i] <= nums[j],那么数组 nums 是单调递增的。 如果对于所有 i <= j,nums[i]> = nums[j],那么数组 nums 是单调递减的。
当给定的数组 nums 是单调数组时返回 true,否则返回 false。
bool isMonotonic(vector<int>& nums) {
bool inc = true, dec = true;
for(int i = 0; i < nums.size() - 1; ++i) {
if(nums[i] < nums[i + 1]) {
inc = false;
}
if(nums[i] > nums[i + 1]) {
dec = false;
}
}
return inc || dec;
}
LeetCode 35. 搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
int searchInsert(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1, ans = nums.size();
while(left <= right) {
int mid = (right - left) / 2 + left;
if(target <= nums[mid]) {
// 因为要按顺序插入,如果目标值小于或等于当前中间位置的值,
// 说明插入位置在当前中间位置的左侧或正好就是当前中间位置
ans = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return ans;
}