# Practice in C
###### tags: `linux2020` `c language`
## leetCode (EASY): 104. Maximum Depth of Binary Tree [[link]](https://leetcode.com/problems/maximum-depth-of-binary-tree/)
Given a binary tree, find its maximum depth.
The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.
**Note**: A leaf is a node with no children.
**Example**:
Given binary tree `[3,9,20,null,null,15,7]`,
```
3
/ \
9 20
/ \
15 7
```
My code right-behind have ***time limit exceeded*** problem which is really ***bad example*** for recursive funtion.
```cpp=
int countDepth(struct TreeNode* root){
if((root->left != NULL)&&(root->right!=NULL)){
if(countDepth(root->left) > countDepth(root->right)){//<--WHICH IS REALLY BAD
return countDepth(root->left)+1; //<--WHICH IS REALLY BAD
}
else{
return countDepth(root->right)+1; //<--WHICH IS REALLY BAD
}
}
else if((root->left == NULL)&&(root->right!=NULL)){
int sum = countDepth(root->right);
return sum + 1;
}
else if((root->left != NULL)&&(root->right==NULL)){
int sum = countDepth(root->left);
return sum + 1;
}
else{
return 0;
}
}
```
You should always catch your return value(from function) when function are recursing itself. The **better answer** is like the code below:
```cpp=
int countDepth(struct TreeNode* root){
if((root->left != NULL)&&(root->right!=NULL)){
int left = countDepth(root->left);//<--WHICH IS GOOD EXAMPLE
int right = countDepth(root->right);//<--WHICH IS GOOD EXAMPLE
if(left > right){//<--WHICH IS GOOD EXAMPLE
return left+1;//<--WHICH IS GOOD EXAMPLE
}
else{
return right+1;//<--WHICH IS GOOD EXAMPLE
}
}
else if((root->left == NULL)&&(root->right!=NULL)){
int sum = countDepth(root->right);
return sum + 1;
}
else if((root->left != NULL)&&(root->right==NULL)){
int sum = countDepth(root->left);
return sum + 1;
}
else{
return 0;
}
}
```
This movement can save lots of excuting time, make your program **run faster**.
---
## C programing skill 0
### Call by address in C
```cpp=
void myfunc(int* value){
*value = 777;
}
int main(){
int num = 0;
myfunc(&num);
printf("%d",num);
return 0;
}
```
Guess what? Yeee~ You got **777**. The part need to point out is that `&` mark can extract the pointer address for `num`.
---
## leetCode (MEDIUM): 338. Counting Bits [[link]](https://leetcode.com/problems/counting-bits/)
Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1's in their binary representation and return them as an array.
**Example 1**:
```
Input: 2
Output: [0,1,1]
```
**Example 2**:
```
Input: 5
Output: [0,1,1,2,1,2]
```
> When I solve this problem in **C language on LeetCode**, I encounting a ERROR:
> ``` ==29== ERROR:AddressSanitizer: heap-buffer-overflow on address...```
> The reason why this error heppend is the [rule of AddressSanitizer](https://blog.csdn.net/zhangpeterx/article/details/88775434). Thus, the best way to fix this error is change your ```<=```,```>=``` mark to ```<```,```>``` in all your for loop and carefully check your dynamic memory have any overflow or not. [Reference](https://blog.csdn.net/lym940928/article/details/89678727)
Anyway, my solution is:
```cpp=
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* decToBin(int num, int* mSize){
int i=0;
int *arr1 = malloc(sizeof(int)*num);
while(num>0){
arr1[i] = num%2;
i = i + 1;
num = num/2;
}
int *arr2 = malloc(sizeof(int)*i);
int k = 0;
for(;i>0;i--){
arr2[k] = arr1[i-1];
k=k+1;
}
*mSize = k;
free(arr1);
return arr2;
}
int countBinary(int* arr,int mSize){
int i = 0;
int count =0;
for(;i<mSize;i++){
if(arr[i]==1){
count ++ ;
}
}
return count;
}
int* countBits(int num, int* returnSize){
*returnSize = num+1;
int i = 0;
int mySize=0;
int *ansArray = malloc(sizeof(int)*(num+1));
for(;i<(num+1);i++){
int* myBinary = decToBin(i,&mySize);
int countNum = countBinary(myBinary,mySize);
ansArray[i] = countNum;
}
return ansArray;
}
```
As you can see, my code is very simple, but **it is little bit longer**, compare to those code which also have good performance from the Leetcode website like:
```cpp=
int* countBits(int num, int *returnSize){
num++;
*returnSize = num;
int* arr = (int*)malloc(sizeof(int)*num);
arr[0] = 0;
for(int i = 1; i < num; i++){
arr[i] = (i&1)? arr[i>>1]+1 : arr[i>>1];
}
return arr;
}
```
How can I improve my code like this one? Learn the skill below:
---
## C programing skill 1
### Question mark in C
e.g.
```cpp=
x == 3 ? x++ : x--;
```
Do you know what those code means? It actually means:
```cpp=
if (x == 3) {
x++;
}
else {
x--;
}
```
Assume that you already have the code below:
```cpp=
int* countBits(int num, int *returnSize){
num++;
*returnSize = num;
int* arr = (int*)malloc(sizeof(int)*num);
arr[0] = 0;
for(int i = 1; i < num; i++){
if(arr[i] == i&1){
arr[i/2]+1;
}
else{
arr[i/2];
}
}
return arr;
}
```
You can use this question mark skill and turn it to:
```cpp=
int* countBits(int num, int *returnSize){
num++;
*returnSize = num;
int* arr = (int*)malloc(sizeof(int)*num);
arr[0] = 0;
for(int i = 1; i < num; i++){
arr[i] = (i&1)? arr[i>>1]+1 : arr[i>>1];
}
return arr;
}
```
Cool~ right?
### NULL pointer
```cpp=
int *testCase = 0;
printf("%p %s\n",testCase,testCase);
testCase = NULL;
printf("%p %s",testCase,testCase);
```
The output is:
```
0000000000000000 (null)
0000000000000000 (null)
```
Yes, for pointer, zero is equals to null.
### The length of array
```cpp=
char* ss = "0123456789";
sizeof(ss)// 結果 4 ===》ss 是指向字元串常量的字元指針,sizeof 獲得的是一個指針的之所占的空間,應該是長整型的,所以是 4。
sizeof(*ss)// 結果 1 ===》*ss 是第一個字元 其實就是獲得了字元串的第一位 '0' 所占的內存空間,是 char 類型的,占了 1 位
strlen(ss)//結果 10 ===》 如果要獲得這個字元串的長度,則一定要使用 strlen。strlen 用來求字元串的長度;而 sizeof 是用來求指定變量或者變量類型等所占內存大小。
```
### Preparing fxxk hard by valgrind
```cpp=
int main(){
char* inputArr = malloc(sizeof(char)*101);
int len = strlen(inputArr); //the problem caused by strlen
printf("The length of char array before input is :%d",len);
printf("\nSister, you better wake up and input string : ");
fgets(inputArr,100,stdin);
//fputs(inputArr,stdout);
len = strlen(inputArr);
printf("\nThe length of char array after input is :%d\n",len);
int i =0;
for(;i<len;i++)
printf(" %c",inputArr[i]);
printf("Show again : %s",inputArr);
free(inputArr);
return 0;
}
```
**Result** :
```
The length of char array before input is :0
Sister, you better wake up and input string : I hate myself for not putting enough effort in coding.
The length of char array after input is :55
I h a t e m y s e l f f o r n o t p u t t i n g e n o u g h e f f o r t i n c o d i n g .
Show again : I hate myself for not putting enough effort in coding.
```
Sure, you can compile and run it as usual, but you heard that sound of memory leaking? I heard it this time. Then, I check my @#$% code with valgrind and get one error named **jump or move depends on uninitialised value(s)**. Great !
```
$ valgrind --leak-check=full --log-file=vglog --track-origins=yes ./a.out
$ cat valgrind
```
```
==5737== Memcheck, a memory error detector
==5737== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5737== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==5737== Command: ./a.out
==5737== Parent PID: 18796
==5737==
==5737== Conditional jump or move depends on uninitialised value(s)
==5737== at 0x4C32CF9: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5737== by 0x10884B: main (in /home/huang/JserV/JserV_practice/arrayToTree/a.out)
==5737== Uninitialised value was created by a heap allocation
==5737== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5737== by 0x10883B: main (in /home/huang/JserV/JserV_practice/arrayToTree/a.out)
==5737==
==5737==
==5737== HEAP SUMMARY:
==5737== in use at exit: 0 bytes in 0 blocks
==5737== total heap usage: 3 allocs, 3 frees, 2,149 bytes allocated
==5737==
==5737== All heap blocks were freed -- no leaks are possible
==5737==
==5737== For counts of detected and suppressed errors, rerun with: -v
==5737== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
```
To slove this, I know the two ways I can choose.
1. Do not using **strlen** to the **NULL-string**.
2. Using **calloc** instand of the **malloc**, because calloc set the initialised value (0) for every space you declared.
**Result 1.**
```cpp=
int main(){
char* inputArr = malloc(sizeof(char)*101);
// int len = strlen(inputArr);
// printf("\nThe length of char array is :%d",len);
printf("\nSister, you better wake up and input string: ");
fgets(inputArr,100,stdin);
fputs(inputArr,stdout);
int len = strlen(inputArr);
printf("\nThe length of char array is :%d",len);
int i =0;
for(;i<len;i++)
printf("\nwhat %c",inputArr[i]);
printf("\n%s",inputArr);
free(inputArr);
return 0;
}
```
**Result 2.**
```cpp=
int main(){
char* inputArr = calloc(101,sizeof(char));
int len = strlen(inputArr);
printf("\nThe length of char array is :%d",len);
printf("\nSister, you better wake up and input string: ");
fgets(inputArr,100,stdin);
fputs(inputArr,stdout);
len = strlen(inputArr);
printf("\nThe length of char array is :%d",len);
int i =0;
for(;i<len;i++)
printf("\nwhat %c",inputArr[i]);
printf("\n%s",inputArr);
free(inputArr);
return 0;
}
```
```
---
==6041== All heap blocks were freed -- no leaks are possible
==6041==
==6041== For counts of detected and suppressed errors, rerun with: -v
==6041== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
```
Yeah, 0 errors. World piece... peace of cake? My english suck...
### The type size never remember in my tiny brain
| Type | 32-bits System| 64-bits System|
| -------- | -------- | -------- |
| int | | 4 bytes |
| char | | 1?
I told you I never remember.
> [name=Huang Yu Hsuan] [time=Tue, Mar 3, 2020 1:14 AM]