[C language.oj question brush] Find the element that appears once in the integer array ##{Idea+C source code}

Table of contents

Overview 

Question 1

 Question 2

Solve problems

Question 2

Idea one:

Limitations: 

Idea two:

Question 1

Idea one:

 Limitations:

 Idea 2:

Expand


Overview 

Question 1


 Only two numbers in an array appear once, and all other numbers appear twice.

Write a function to find these two numbers that appear only once.

For example:

The elements of the array are: 1, 2, 3, 4, 5, 1, 2, 3, 4, 6

Only 5 and 6 appear once. Find 5 and 6.


 Question 2


 Only one number in an array appears once, and all other numbers appear twice.

Write a function to find these two numbers that appear only once.

For example:

The elements of the array are: 1, 2, 3, 4, 5, 1, 2, 3, 4,

Only 5 appears once. Find 5


 Before solving question 1, we first solve question 2 as a warm-up, which is more conducive to solving question 1 and subsequent expansion.

Solve problems

Question 2

Idea one:

        Loop traversal, take an element in the array and traverse the array until an element that is the same as it is found;

        This element cannot be himself.

        The output does not have paired elements.

Implementation source code:



int main()
{
	int arr[] = {1,2,3,4,5,1,2,3,4};
	int sz = sizeof(arr)/sizeof(arr[0]);
	for(int i = 0;i < sz;i++)//遍历数组,用arr[i]去找arr[j],每一个arr[i] 都要遍历一边数组
	{
		int f = 0;
		for(int j = 0;j < sz;j++)
		{
			if((i != j) && arr[i] == arr[j])//找到的arr[i]不能是arr[i]本身,所以限制i != j
			{
				f = 1;
				break;
			}
		}
		if(f == 0)
		{
			printf("%d ",arr[i]);
		}
	}
	return 0;
}
Limitations: 

        The idea and method are easy to think about and simple, but the amount of code is large;

        After calculation, the time complexity of the traversal algorithm is O(N^2)

Idea two:

 Refer to the characteristics of the XOR operation:

Homologous 0, Dissimilar 1, So
        1 ^ 1 = 0
        0 ^ 0 = 0
        1 ^ 0 = 1

We can infer an important characteristic of XOR -> reflexivity: A ^ B ^ B = A 

From this, we can create an integer variable initialized to 0, recorded as (int tem = 0), let tem XOR each element in the array, and the result is only one element ret;

Implementation source code:


int main()
{
	int arr[] = {1,2,3,4,5,1,2,3,4};
	int sz = sizeof(arr)/sizeof(arr[0]);
	int ret = 0;
	for(int i = 0;i < sz;i++)
	{
		ret ^= arr[i];
	}
	printf("%d",ret);
	return 0;
}

The amount of code in the second idea has been greatly reduced. After calculation, the time complexity is O(N), which has greatly improved the efficiency.

Question 1

Only two numbers in an array appear once, and all other numbers appear twice.

Write a function to find these two numbers that appear only once.

We found that: Question 1 has more requirements. There are two numbers that only appear once. How to solve it?

Idea one:

        Loop traversal, take an element in the array and traverse the array until an element that is the same as it is found;

        This element cannot be himself;

        The output does not have paired elements.

Implementation source code:


int main()
{
	int arr[] = {1,2,3,4,5,1,2,3,4,6};
	int sz = sizeof(arr)/sizeof(arr[0]);
	for(int i = 0;i < sz;i++)
	{
		int f = 0;
		for(int j = 0;j < sz;j++)
		{
			if((i != j) && arr[i] == arr[j])
			{
				f = 1;
				break;
			}
		}
		if(f == 0)
		{
			printf("%d ",arr[i]);
		}
	}
	return 0;
}

Is it the same as the source code of question 2? Why is this happening? Since question 2 does not XOR all the elements on a variable, but compares and traverses them one by one, and outputs the individual ones that meet the requirements, the elements are easy to separate.

From another perspective -> If we still use the XOR method to combine all elements, the result will be the XOR value of two separate elements, which is difficult to separate.

 Limitations:

The traversal method has its own advantages, but after calculation, the time complexity of the traversal algorithm is O(N^2), which needs to be speeded up.

 Idea 2:

The XOR method is not easy to separate. We can divide the two numbers that appear once into two different arrays, and then perform the XOR operation separately. Wouldn't that be great?

(1) First, through an XOR operation, the repeated elements will be offset, and the final result is equivalent to the XOR value of two single-occurring elements;
2) By XOR According to the Or rule, if a certain binary bit of the XOR value of two elements is 1, it means that the values ​​of the two elements at that binary bit are different (one is 0, the other is 1), and find one of them that satisfies the condition ( is the binary bit of 1).

(3) According to the binary bits found in (2), the original array can be divided into two parts. Two separate elements are in two parts respectively, and the same repeated elements will also be divided into the same part (because of their corresponding The values ​​of the binary bits are the same);

(4) Perform the XOR operation again on the two parts, which is equivalent to eliminating the even repetition problem, and finally you can get two separate elements.

Replenish:

        (Generally speaking, the XOR value of two non-zero elements != 0, then the binary bit of this XOR value must have 1)

          The binary bit we are looking for can be the rightmost binary bit. We can achieve it by ret &((~ret) + 1)

          Suppose N is 001010110000

Operation binary result
N 001010110000
~N 110101001111
(~N)+1 110101010000
N&((~N)+1) 000000010000

Implementation source code:



#include<stdio.h>
int search(int arr[],int sz)//此函数用于求得数组中的所有元素的异或
{
	int result = 0;
	for(int i = 0;i < sz;i++)
	{
		result ^= arr[i];
	}
	return result;//其实就是5^6^0=5^6
}
int main1()
{
	int arr[] = {1,2,3,4,5,1,2,3,4,6};
	int sz = sizeof(arr)/sizeof(arr[0]);
	int ret = search(arr,sz);
	
	int bit_ret = ret &((~ret) + 1);//操作:取得二进制最右侧的1
	
	int arr1[50] = {0};//存储
    int arr2[50] = {0};
	int c1 = 0;//计数
	int c2 = 0;
	for(int i = 0;i < sz;i++)
	{
		
		if((arr[i] & bit_ret) != 0)
		{
			arr1[c1] = arr[i];//不同
			c1++;
		}
		else
		{
			arr2[c2] = arr[i];//相同
			c2++;
		}
	}
	printf("%d\n",search(arr1,c1));
	printf("%d\n",search(arr2,c2));
	return 0;
}

 The time complexity is still O(N), and the efficiency is still high.


Expand

        The traversal algorithm can handle any number of single elements, but some time needs to be sacrificed.

        The XOR algorithm is an efficient algorithm, but it requires multiple groupings and recursion.


Finished~


Reprinting without the author's consent is prohibited

Guess you like

Origin blog.csdn.net/2301_79465388/article/details/134575094