关于leetcode中对数组O(1)空间消耗操作的几道题

这篇博客探讨了在LeetCode中处理数组问题时如何实现O(1)空间消耗的操作,重点讲解了如何删除数组中的重复元素。通过使用头尾指针或双指针策略,可以在不改变数组顺序的情况下达到题目要求,如Remove Duplicates from Sorted Array题目所示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

其实这几道题在leetcode中都是比较容易的,但是如果刚开始不理解题意的话可能就会进入陷阱。

整数数组中的几个操作如下面所示,无非是怎样进行数组元素的的交换。

Remove Element

Given an array and a value, remove all instances of that value in place and return the new length.

The order of elements can be changed. It doesn't matter what you leave beyond the new length.

这道题是删除一个整数数组中的与给定元素相同的元素。题目提示可以将原有元素的顺序打乱,最后返回的是数组的长度

同时不能有其他的空间消耗。

其实我当初的思路还是很简单的:

我是用一个头指针,一个尾指针分别从两端开始,每一次如果前面的元素出现了elem,那么从尾指针当前位置

向前找到第一个出现的非elem的元素进行交换,这样的时间复杂度是O(m)其中m是非elem的个数,但是代码的实现上稍显复杂:

/*---------------------O(m)时间消耗,O(1)空间消耗-------------------------------------*/
//首尾两个指针,向中间扫描。用后面元素向前面元素进行替换,会改变元素的位置
//By Lingtao 2015/04/21
int removeElement(int A[], int n, int elem) {
	int length = 0;
	int head = 0, tail = n - 1;
	while (head <= tail)
	{
		if (A[head] == elem)
		{
			while (tail > head)
			{
				if (A[tail] != elem)
				{
					swap(A[head], A[tail]);
					length++;
					break;
				}
				tail--;
			}
		}
		else
			length++;
		head++;
	}
	cout << endl;
	return length;
}

//下面的代码不用改变数组元素的顺序,但是需要进行o(n)的时间度,即需要对整个元素进行扫描一次。

简洁了许多。

int removeElement2(int A[], int n, int elem) {
	int count = 0;
	for (int i = 0; i<n; i++)
		if (A[i] != elem)
			swap(A[i], A[count++]);
	return count;
}

其实,对于这种问题,解法二才是最正宗的解法,两个point一前一后,一个用来遍历数组,一个用来记录有效元素的位置。下面这道题依然是类似的题目:

Remove Duplicates from Sorted Array

 

Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length.

这里面要求数组元素的顺序是不能变的。那么就可以采用一中的方法。

仍然是两个指针:

int removeDuplicates(int A[], int n) {
	if (n == 0 || n==1)
		return n;
	int count = 1;
	for (int i = 1; i < n; i++)
	{
		if (A[i - 1] == A[i])
			continue;
		else
		{
			A[count] = A[i];
			count++;
		}
	}
	return count;
}

未完待续。


### LeetCode 上使用 C 语言处理二维数组的相关问与解法 在 LeetCode 中,涉及二维数组的问通常会测试编程者对矩阵操作的理解以及优化算法的能力。以下是针对 C 语言实现二维数组相关问的一个典型例子及其解决方案。 #### 示例目:设置零矩阵 给定一个 `m x n` 的矩阵,如果某个元素为 0,则将其所在的行和列的所有元素都设为 0。此问可以通过额外的空间来解决,也可以通过原地标记的方式减少空间复杂度。 ##### 方法一:使用辅助数组标记行列 这种方法利用两个辅助数组分别记录哪些行和列需要被置零。其间复杂度为 \(O(m \times n)\),而空间复杂度为 \(O(m + n)\)[^1]。 ```c void setZeroes(int** matrix, int matrixSize, int* matrixColSize){ int m = matrixSize; int n = *matrixColSize; bool* row = (bool*)calloc(m, sizeof(bool)); bool* col = (bool*)calloc(n, sizeof(bool)); // 记录需要清零的行和列 for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (matrix[i][j] == 0) { row[i] = true; col[j] = true; } } } // 将对应的行和列置零 for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (row[i] || col[j]) { matrix[i][j] = 0; } } } free(row); free(col); } ``` 上述方法虽然简单易懂,但由于引入了额外的存储开销,在某些情况下可能不满足最优解的要求。 ##### 方法二:原地修改策略 为了进一步降低空间复杂度至常量级别 (\(O(1)\)),可以采用一种更巧妙的方法——利用矩阵的第一行和第一列表示其他位置的状态标志位[^3]。 具体做法如下: - 使用第一个单元格作为特殊状态指示器; - 如果某行/列存在零值,则将对应首元标注为真(true); - 最后再依据这些标记完成最终更新过程即可。 由于该方案无需开辟新的内存区域保存中间数据结构,因此极大地节省了资源消耗。 --- ### § 相关问 § 1. 如何用动态规划求解编辑距离? 2. 在二维网格中寻找路径有哪些常见技巧? 3. 基于双指针技术如何高效移除指定数值元素? 4. 对于含有重复项的大规模整型序列,怎样快速定位目标值的位置区间? 5. 实现一个函数判断输入字符串能否由另一个字符串重新排列成回文串形式吗 ?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值