LeetCode Brushing Notes (6) - Primary Algorithms - Others

❤ 2021.11.17 ❤
Today's topic is:

number of bit 1

insert image description here
My thinking:
let’s compare one by one

int hammingWeight(uint32_t n) {
    
    
	int count = 0;
	for (int i = 0; i < 32; i++)
	{
    
    
		if ((n & 1) == 1)
			count++;
		n = n >> 1;
	}
	return count;
}

insert image description here
It should be noted here that the type uint32_t needs to include the library <stdint.h>.
Then I looked at the answer

int hammingWeight(uint32_t n) {
    
    
    int ret = 0;
    for (int i = 0; i < 32; i++) {
    
    
        if (n & (1 << i)) {
    
    
            ret++;
        }
    }
    return ret;
}

It probably means that he did not shift n, but shifted 1, and then counted, the principle is similar.
Then there is the advanced version.
insert image description here
In fact, I didn't understand it. . .

but! but! This question is actually more than that!
His function name gave a hint that
hammingweight
translates to "Hamming weight". I googled it
→→→ Hamming weight.
The standard solution to this question should be like this.
insert image description here

❤ 2021.11.18 ❤
Today's topic is:

Hamming distance

insert image description here
My thinking:
it's very simple!
Isn't it just adding an XOR before yesterday's question~

int hammingDistance(int x, int y) {
    
    
	int count = 0;
	unsigned int temp = x ^ y;
	for (int i = 0; i < 32; i++)
	{
    
    
		if (temp & 1)
			count++;
		temp = temp >> 1;	
	}
	return count;
}

insert image description here

After reading the answer, it is true, hahaha

❤ 2021.11.19 ❤
Today's topic is:

reverse the bits

insert image description here
My thinking:
The most direct way is probably to create a new number, then read the original number bit by bit and write it into the new number at the corresponding position, but this feels a bit silly, after all, not every bit Both need modification.
So I pondered for a while, and I think that the original number can be divided into half first, and the symmetrical comparison is whether it corresponds to whether it is the same. If it is the same, skip it. If it is different, invert the corresponding bit. The inversion operation is realized through XOR.

uint32_t reverseBits(uint32_t n) {
    
    
	for (int i = 0; i < 16; i++)
	{
    
    
		if (((n >> i) & 1) != ((n >> (31 - i)) & 1))	//判断对称的两位是否相同
			//如果对称的两位不同,则将n与一个除了对应两位为1,其余都为0的二进制数相异或,以达到对相应位取反的效果
			n = n ^ (((uint32_t)1 << i) | ((uint32_t)1 << (31 - i)));	
	}
	return n;
}

insert image description here
In the process of debugging, I encountered a problem.
insert image description here
I also encountered this problem yesterday, but I didn't think about it.
Looking at it now, this error is not triggered by every input. From the text description, when 1 is shifted to the left by 31 bits, it cannot be expressed in int.
So I added (uint32_t) to various places until I added him to the front of 1 before passing. It seems that the compiler treats the number as an int by default, and it passes after the modification.
In fact, I made a small mistake. I took i and 32-i as symmetrical positions at the beginning, so the whole result was skewed by one bit. Later, I thought it should be 31-i.
Let's look at the answer below.
The first one is the first violent method I thought of, and the second one is more powerful!
insert image description here
The general meaning is to exchange the adjacent two bits with each other first, and then exchange each other in groups of two, and so on.
insert image description here
I have to admire the heads of the big guys.

❤ 2021.11.24 ❤
Today's topic is:

Yang Hui Triangle


My thinking:
There should be no difficulty in the implementation process, so let's practice the dynamic allocation of two-dimensional arrays.

int** generate(int numRows, int* returnSize, int** returnColumnSizes) {
    
    
	*returnSize = numRows;
	int** result = (int*)malloc(sizeof(int*) * numRows);
	(*returnColumnSizes) = (int*)malloc(sizeof(int) * numRows);
	for (int i = 0; i < numRows; i++)
	{
    
    
		result[i] = (int*)malloc(sizeof(int) * (i + 1));
		(*returnColumnSizes)[i] = i + 1;
		for (int j = 0; j < i + 1; j++)
		{
    
    
			if (j == 0 || j == i)
				result[i][j] = 1;
			else
				result[i][j] = result[i - 1][j - 1] + result[i - 1][j];
		}
	}
	return result;
}

insert image description here
The main function is as follows

int main()
{
    
    
	int a = 3;
	int m;
	int* n;
	int** k = generate(a, &m, &n);
	for (int i = 0; i < m; i++)
	{
    
    
		printf("[");
		for (int j = 0; j < n[i]; j++)
		{
    
    
			printf("%d ", k[i][j]);
		}
		printf("]\n");
	}
}

The first program I wrote was like this

int** generate1(int numRows, int* returnSize, int** returnColumnSizes) {
    
    
	int n = 1;
	for (int i = 1; i <= numRows; i++)
	{
    
    
		n *= i;
	}
	*returnSize = numRows;
	int** result = (int**)malloc(sizeof(int) * n);
	(*returnColumnSizes) = (int*)malloc(sizeof(int) * numRows);
	for (int i = 0; i < numRows; i++)
	{
    
    
		result[i] = (int*)malloc(sizeof(int) * (i + 1));
		(*returnColumnSizes)[i] = i + 1;
		for (int j = 0; j < i + 1; j++)
		{
    
    
			if (j == 0 || j == i)
				result[i][j] = 1;
			else
				result[i][j] = result[i - 1][j - 1] + result[i - 1][j];
		}
	}
	return result;
}

The test can pass in VS, but when submitted on leetcode, an error will be reported. It will appear when the number of layers is 1 and 2,
insert image description here
but it will be fine when the number of layers is greater than or equal to 3. Look at the error message is probably the illegal access to memory or something.
At first I thought that the array was out of bounds, but after commenting out the array operation, an error was reported, so I was sure it was a memory allocation problem.
What I use here is to allocate memory according to the factorial of the number of layers. Later, I found that the error should be accumulation, but after the modification, an error is still reported.
So after thinking about it, I located the problem on the malloc instruction.
For the memory allocation of two-dimensional arrays, I basically learned the method from the previous binary tree sequence traversal question. There may be some misunderstandings in my understanding.
I have always felt that a two-dimensional array needs to allocate enough memory space for the entire array at one time, and then store the data, but after reading some other people's programs, the correct way should be to first allocate the memory of the pointer of each row, and then give each row Each allocates memory.
After modification, it finally passed, but why there is no problem with writing in this way before and why an error is reported only when the number of layers is 1 and 2, and there is no problem with other numbers, it is still not clear. . .
But it should be very simple if you use the vector container of c++ to do it.

❤ 2021.11.26 ❤
Today's topic is:

valid brackets

insert image description here
My thinking:
Isn't this just a stack!
It just so happens that I haven't written the operation of the stack in the C language, so let's do it here.
First, I create a node structure, one data member and one pointer member like ordinary linked list nodes, and then create a stack structure, with two pointer members pointing to the top of the stack and the bottom of the stack. The stack is empty when the top and bottom pointers point to the same value.
I think there can be only one pointer on the top of the stack. When the pointer is a null pointer, the stack is empty, which saves an empty node. But since it can be done, let's do it first

struct LNode {
    
    
	char data;
	struct LNode* next;
};
typedef struct LNode LNode;

struct Stack {
    
    
	struct LNode* top;
	struct LNode* bottom;
};
typedef struct Stack Stack;

Then I will no longer write the operation function of the stack, and operate directly in the function. The process is that if it is a left semi-bracket, it will be pushed into the stack, and if the right semi-bracket is the corresponding left semi-bracket, it will be checked if the top of the stack is the corresponding left semi-bracket.

bool isValid(char* s) {
    
    
	Stack* S = (Stack*)malloc(sizeof(Stack));
	LNode* L = (LNode*)malloc(sizeof(LNode));
	L->data = 0;
	S->bottom = L;
	S->top = L;
	int i = 0;
	while (s[i] != 0)
	{
    
    
		if (s[i] == '(' || s[i] == '[' || s[i] == '{')
		{
    
    
			LNode* p = (LNode*)malloc(sizeof(LNode));
			p->data = s[i];
			p->next = S->top;
			S->top = p;
			i++;
		}
		else
		{
    
    
			if (s[i] == ')')
			{
    
    
				if (S->top->data != '(')
					return false;
				else
				{
    
    
					LNode* t;
					t = S->top;
					S->top = S->top->next;
					free(t);
					i++;
				}
			}
			else if (s[i] == ']')
			{
    
    
				if (S->top->data != '[')
					return false;
				else
				{
    
    
					LNode* t;
					t = S->top;
					S->top = S->top->next;
					free(t);
					i++;
				}
			}
			else
			{
    
    
				if (S->top->data != '{')
					return false;
				else
				{
    
    
					LNode* t;
					t = S->top;
					S->top = S->top->next;
					free(t);
					i++;
				}
			}
		}
	}
	if (S->top != S->bottom)
		return false;
	return true;
}

insert image description here
I still encountered some problems during the debugging process.
At the beginning, the statement I popped out of the stack was written like this. As follows,
I allocated memory space to the temporary pointer t, and then freed the node that fell out of the stack first, and then freed the temporary node. , but the error is reported as follows. What's even more amazing is that this error only occurs when more than a pair of parentheses are entered. After
insert image description here
analysis, I found that the temporary pointer does not actually need to allocate memory. . . (I'm stupid), you only need to release the memory of the node it points to, and it will be released together with the function as a local variable.
However, I saw such an article in the process of looking for information. Although it has little to do with my problem, it is more meaningful for learning
→→→ leetcode error: ERROR: AddressSanitizer: attempting double-free on 0x7fa0cd690800 in thread T0: …

In addition, I didn't judge whether the stack is empty at the end of the loop at first, so I reported an error in the following input.
insert image description here
My first thought was to judge whether the loop variable is even at the end of the loop, but I encountered this situation again. . .
insert image description here
Well, it was later changed to judge whether the stack is empty.

Then I read the answer and felt that although the idea was similar, my code was too verbose compared to the answer.
The answer uses the array as the storage space of the stack, and directly stores the right parenthesis corresponding to the left parenthesis in the stack, and then directly judges whether they are equal, which is very useful for reference. I will type it myself first.

bool isValid(char* s) {
    
    
	int n = strlen(s);
	char* c = (char*)malloc(sizeof(char) * n);
	int top = 0;
	int i = 0;
	char ch;
	while (s[i])
	{
    
    
		if (s[i] == ')')	//如果数组中为右括号返回对应的左括号,如果左括号则返回0
			ch = '(';
		else if (s[i] == ']')
			ch = '[';
		else if (s[i] == '}')
			ch = '{';
		else
			ch = 0;
		if (ch)
		{
    
    
			if (top == 0)	//判断栈是否为空,为空false
				return false;
			if (ch != c[top - 1])	//判断返回的括号和栈顶储存括号是否一致,不一致false,一致则出栈。因为top指向新元素,所以栈顶实际是top-1
				return false;
			else
			{
    
    
				top--;
				i++;
			}
		}
		else
		{
    
    
			c[top] = s[i];	//入栈
			top++;
			i++;
		}
	}
	if (top != 0)	//判断栈是否为空(是否存入的左括号都出栈成功)
		return false;
	return true;
}

insert image description here
Although I typed it myself, it is based on the idea of ​​the answer. The strange thing is that it is also 5.6MB why the ranking is different. .

❤ 2021.11.29 ❤
Today's topic is

missing number

insert image description here
My thinking:
This is very simple, the most brainless method is to sort first and then traverse.
For advanced use of hash tables, this topic is relatively simple, and it should be feasible to use arrays instead of hash tables.

int missingNumber(int* nums, int numsSize) {
    
    
	int* hash = (int*)malloc(sizeof(int) * (numsSize + 1));
	int j = 0;
	for (int i = 0; i < numsSize + 1; i++)
		hash[i] = 0;
	for (int i = 0; i < numsSize; i++)
		hash[nums[i]]++;
	while (hash[j] != 0)
		j++;
	return j;
}

insert image description here
It feels okay, although it has been used three times, but after reading the answer, I still feel that I am really too young. . .
First of all, the method of sorting first and then traversing only needs to traverse twice, so it seems that my method is quite useless. . .
Then there is the mathematical method, use the summation formula to first find the sum of n numbers, then subtract the given number, and the last remaining number is the missing number, um. . .
However, I think the most interesting method is to use the bitwise XOR method. According to the principle of bitwise XOR, the numbers that are XORed twice will be shielded, so after two traversals, first XOR the numbers from 0 to n Once, and then XOR with the given number again, the last remaining number is the missing number.
What if I write the traversal process as one?

int missingNumber(int* nums, int numsSize) {
    
    
	int temp = 0;
	for (int i = 0; i < numsSize; i++)
	{
    
    
		temp ^= i;
		temp ^= nums[i];
	}
	temp ^= numsSize;
	return temp;
}

But this result is not as fast as my cycle three times,
insert image description here
which is quite strange.

I encountered a problem in the process of debugging, that is, the number passed in is the length of the array, and there is actually one element missing in the array, which means that 1 needs to be added when traversing. I didn’t pay attention at first and then debugged The result is always wrong, and then I want to use the online debugging method to monitor variables, but my variables are dynamic arrays, and by default only the value of the first element can be displayed. I checked the information and found the method, which is to use "Quick Watch" function, and then set the number of elements of the array in the window. as follows

→→→ Use quick monitoring in vs to check the value of elements in the dynamic array (check the value of the elements in the new array)

Ah, the primary algorithm is done. (Actually, it’s not because I haven’t done it before...)

Guess you like

Origin blog.csdn.net/ooorczgc/article/details/121387659