编程导航算法通关村第三关 | 爱不起的数组之数组基本操作

查找元素

  1. 根据值是否相等线性查找
int findByElement(int a[], int size, int key) {
	for(int i = 0; i < size; i++) 
		if(a[i] == key) return i;
	return -1;
}
  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;
}

你可能感兴趣的:(算法,java,数据结构)