LeetCode - 요소 제거

머리말

질문: 배열 nums 및 값 val이 주어지면 값이 val과 동일한 모든 요소를 ​​제자리에서 제거하고 제거된 배열의 새 길이를 반환해야 합니다. 추가 배열 공간을 사용하지 마십시오. O(1) 추가 공간만 사용하고 입력 배열을 제자리에서 수정해야 합니다. 주제 링크

다음과 같은 솔루션이 있으며, 그 중 일부는 주제의 요구 사항을 충족하지 않는 것으로 표시되며 글은 단지 아이디어를 제공하기 위한 것입니다. 내가 틀렸다면 정정해주세요!

1. 폭력적인 해결책

전체 배열을 반복하고 val과 같은 요소가 발견될 때마다 배열에서 제거됩니다. 전체 배열을 순회할 때까지 새 배열 길이가 반환됩니다.
여기에 이미지 설명 삽입
암호:

//暴力求解
int removeElement(int* nums, int numsSize, int val) {
    
    
	int i = 0;
	while (i < numsSize)
	{
    
    
		if (nums[i] == val)
		{
    
    
			for (int j = i; j < numsSize - 1; j++) //把后面的元素往前移动进行覆盖,就相当于删除val元素
			{
    
    
				nums[j] = nums[j + 1];
			}
		}
		else
			i++;
	}
	return numsSize; //返回新数组的长度
}

시간 복잡도는 O (n 2 ) O(n^2)O ( n2 ), 공간 복잡도는O(1) O(1)( 1 ) .
주제의 요구 사항을 충족하지만 효율성이 너무 낮습니다.

2. 임시 공간 만들기

임시 배열을 만들고 원래 배열의 val과 같지 않은 요소를 임시 배열에 복사하고 마지막으로 임시 배열을 다시 원래 배열에 복사합니다.
여기에 이미지 설명 삽입

암호:

//创建临时空间
int removeElement(int* nums, int numsSize, int val) {
    
    
	int* tmp = (int*)malloc(sizeof(int) * numsSize);
	if (tmp == NULL) //这个判断其实也可以省略,在本题中。
	{
    
    
		perror("malloc fail\n");
		return;
	}
	int count = 0;
	int i = 0;
	for (i = 0; i < numsSize; i++)
	{
    
    
		if (nums[i] != val)
		{
    
    
			tmp[count] = nums[i];
			count++;
		}
	}
	for (i = 0; i < count; i++)
	{
    
    
		nums[i] = tmp[i]; 
	}
	free(tmp);//释放临时空间,这题中可以不用把tmp置为NULL
	return count;
}

이 질문에서 임시 배열의 메모리를 해제한 후에는 tmp 포인터를 사용하거나 NULL로 설정할 필요가 없습니다. 함수의 끝에서 이 포인터는 소멸되고 더 이상 존재하지 않으므로 댕글링 포인터 문제가 없습니다.
시간 복잡도는 O(n) O(n)O ( n ) , 공간 복잡도는O(n) O(n)( ) .
첫 번째 유형과 비교하여 효율성은 향상되었지만 공간 복잡도는 주제의 요구 사항을 충족하지 않습니다.

3. 더블 포인터 방식

이중 포인터 방식의 기본 개념은 느린 포인터와 빠른 포인터를 유지하는 것으로, 빠른 포인터는 전체 배열을 순회하는 데 사용되며 느린 포인터는 필요한 요소의 위치를 ​​가리키는 데 사용됩니다. 보존. 빠른 포인터가 삭제해야 하는 요소를 만나면 빠른 포인터는 계속 앞으로 이동하고 느린 포인터는 유지해야 하는 요소를 만날 때까지 변경되지 않고 느린 포인터의 위치에 복사되고 느린 포인터는 1비트 앞으로 이동합니다.
여기에 이미지 설명 삽입
암호:

int removeElement(int* nums, int numsSize, int val){
    
    
    int src=0;
    int dest=0;
    while(src<numsSize)
    {
    
    
        if(nums[src]!=val)
        {
    
    
            nums[dest++]=nums[src++];
        }
        else
        {
    
    
            src++;
        }
    }
    return dest; //返回长度
}

시간 복잡도는 O(n) O(n)O ( n ) , 공간 복잡도는O(1) O(1)( 1 ) .
가장 좋은 솔루션은 시간 효율적일 뿐만 아니라 공간도 절약하는 이중 포인터 방법이라는 것을 알 수 있습니다!

오늘의 알고리즘 공유는 여기까지입니다!

여기에 이미지 설명 삽입

추천

출처blog.csdn.net/qq_69218005/article/details/130180919