TIPS
1. 我们都知道,地址,指针这两者是完全等价的概念,但是有微小的差别。地址的话是不能够修改的(比如说数组名++就是违法的),而指针的话可以++与--。
2. 以后一旦在代码里面看到字符char类型的,眼睛里面默认就要把它想象成ASCII码,比如定义
int arr['10']是完全正确的,那个字符10说白了,在计算机里面就是一个数字罢了。
3.
4.
题目1 (有关于函数调用,递归与参数问题)
答案:“suieue”
经验总结:
1. 函数调用传递参数的时候,一定一定要注意是传值调用还是传址调用。一定一定要特别明确:如果是传值调用,那么形参就是实参的一份临时拷贝(它们名字可能一模一样极具迷惑性,但是无论如何也掩盖不了临时拷贝的事实),也正是因为当传值调用时形参与实参的关系是临时拷贝,所以现在假设我有一个函数,一旦进入到其调用函数的内部,里面各种五花八门的变换对于我本函数接下来代码语句的数据等将不会有任何影响。
2. 那么接下来回到这道题目,有人可能就要问,这不是传址调用吗?没错,确实是传址调用。那是你要知道的是:传址调用确实是在函数的内部与外部建立了联系,但不要偷换概念,那个的意思在于可以通过指针解引用然后进行修改啊运算啊等等然后等到调用函数跳出来后,之前那些"修改痕迹"还是被保留下来,"持续发挥着影响"。但是,当传址调用时,我在调用函数里面的参数指针也是新的指针(虽然名字可能与原来指针相同,但两者是完全不搭嘎的东西,只不过一开始都指向同一空间而已),里面新指针的变化,对于本函数来说没有任何影响
3. ++与--都是有副作用的。
4. 字符char的话,其实我们也都知道,它在计算机里面也属于整型,因为它本质上就是ACSII码而已。虽然看起来花里胡哨的。
寻找数组的中心下标
题目链接:https://leetcode.cn/problems/find-pivot-index/
题目:
代码1:
//弱智暴力解法
int pivotIndex(int* nums, int numsSize)
{
int i = 0;
int j1 = 0;
int j2 = 0;
for (i = 0; i < numsSize; i++)
{
int sum_left = 0;
int sum_right = 0;
for (j1 = 0; j1 <= (i - 1); j1++)
{
sum_left += *(nums + j1);
}
for (j2 = (i + 1); j2 < numsSize; j2++)
{
sum_right += *(nums + j2);
}
if (sum_left == sum_right)
{
return i;
}
}
return -1;
}
代码2:
//稍微动点脑子的做法
int pivotIndex(int* nums, int numsSize)
{
int i = 0;
int j = 0;
int sum_right = 0;
for (j = 1; j < numsSize; j++)
{
sum_right += *(nums + j);
}
int sum_left = 0;
for (i = 0; i < numsSize; i++)
{
if (i > 0)
{
sum_left += *(nums + i - 1);
sum_right -= *(nums + i);
}
if (sum_left == sum_right)
{
return i;
}
}
return -1;
}
代码3:
int pivotIndex(int* nums, int numsSize)
{
int i=0;
int total=0;
for (i=0;i<numsSize;i++)
{
total+=*(nums+i);
}
//
int sum_left=0;
for (i=0;i<numsSize;i++)
{
if (2*sum_left==total-*(nums+i))
{
return i;
}
sum_left+=*(nums+i);
}
return -1;
}
经验总结:
1. 这个才是真正经过推敲过的代码。运行的效率会高很多。我们需要慢慢改正优化,把痤的代码完善起来。
2. 也就是说,如果有时候能通过数学推演得出一个表达式那就最好不过了,像这道题:sum_right=total-nums[ i ]-sum_left这个表达式如果脑海中知晓的话,在等于sum_left,就可以省事很多.
字符串不同字符个数统计(桶排序思想)
题目链接:https://www.nowcoder.com/practice/eb94f6a5b2ba49c6ac72d40b5ce95f50?tpId=37&&tqId=21233&rp=1&ru=/ta/huawei&qru=/ta/huawei/question-ranking
题目:
代码:
#include <stdio.h>
#include <string.h>
int main()
{
int i=0;
int arr1[128]={0};
int count=0;
//
char arr[500]={0};
scanf("%s",arr);
int sz=strlen(arr);
//
for (i=0;i<sz;i++)
{
int num=arr[i];
arr1[num]=1;
}
//
for (i=0;i<=127;i++)
{
if (arr1[i]==1)
{
count++;
}
}
printf("%d\n",count);
return 0;
}
经验总结:
1. 桶排序的精髓在于:
1. 把待排序的数字与新数组(全为0)的下标联系起来。
2. 联系起来之后在对应下标的数组元素里面放入1作为标记。
2. 桶排序就相当于把一堆数字放进一个新桶(就是元素全为0的数组)里面去,把数字与数字的下标对应起来,到时候再打印下标。如果有多个相同的数字,但没有办法,无论如何对到新数组的下标都只有一个,因此,桶排序算法有去重的功能
3. 以后一旦在代码里面看到字符char类型的,眼睛里面默认就要把它想象成ASCII码,就是整形
数组多数元素(众数)的查找
(排序法,随机法,分治递归法,摩尔投票法)
题目链接:https://leetcode.cn/problems/majority-element/
题目:
代码1:
int majorityElement(int* nums, int numsSize)
{
int i=0;
int j=0;
for (i=0;i<numsSize-1;i++)
{
for (j=0;j<=(numsSize-(i+2));j++)
{
if (*(nums+j)>*(nums+j+1))
{
int tmp=*(nums+j);
*(nums+j)=*(nums+j+1);
*(nums+j+1)=tmp;
}
}
}
return *(nums+(numsSize/2));
}
经验总结:
1. 如果将数组所有元素先单调递增或者单调递减排序,发现排序后的数组的下标为n/2的那个元素一定是众数。
2. 有时候在解题目的时候,可以对那个无序数组先进行排序,这样就可能可以使某些特征展现在新的有序数组里面。
代码2:
#include <stdlib.h>
#include <time.h>
int majorityElement(int* nums, int numsSize)
{
srand((unsigned int)time(NULL));
while(1)
{
int a = rand()%numsSize;
int count=0;
int i=0;
for (i=0;i<numsSize;i++)
{
if (*(nums+a)==*(nums+i))
{
count++;
}
}
if (count>numsSize/2)
{
return *(nums+a);
}
}
}
经验总结:
这也不失为一种方法
代码3:
int majorityElement(int* nums, int numsSize)
{
if (numsSize>=2)
{
int a=majorityElement(nums,numsSize/2);
int b=majorityElement(nums+numsSize/2,numsSize-numsSize/2);
if (a==b)
{
return a;
}
else
{
int i=0;
int count_a=0;
for (i=0;i<numsSize;i++)
{
if (*(nums+i)==a)
{
count_a++;
}
}
return count_a>numsSize/2?a:b;
}
}
else
{
return *nums;
}
}
经验总结:
1. 分治即“分而治之”,
1. “分”指的是将一个大而复杂的问题划分成多个性质相同但是规模更小的子问题。
2. 子问题继续按照这样划分,直到问题可以被轻易解决。
3. “治”指的是将子问题单独进行处理。经过分治后的子问题,需要将解进行合并才能得到原问题的解,因此整个分治过程经常用递归来实现。
2. 递归我们是学过的。
1. 明确这个函数的功能,有时候功能是返回东西,有时候是进行某个操作(如打印等等)
2. 明确整个过程,并且分拆过程,其中某个过程必须得是与母过程性质结构类型一模一样。
3. 在使用函数递归的时候,最好是能够求出像数列的递推公式一样的这么一个表达式。
4. 回顾整个过程,添加限制条件,限制条件最好是控制那个与母过程一模一样的子过程
3 要明白的是:如果a是数组的众数,那如果把数组分成两个部分,那么a至少是其中一部分的众数。这两个数组部分有各自的众数,如果它们相等,那把这个数就是数组的众数,如果不相等的话,那么就去判断其中一个看是不是。
代码4:
int majorityElement(int* nums, int numsSize)
{
int force=0;
int people=0;
int i=0;
for (i=0;i<numsSize;i++)
{
if (people==0)
{
force=*(nums+i);
people+=1;
}
else if (*(nums+i)==force)
{
people+=1;
}
else
{
people-=1;
}
}
return force;
}
经验总结:
求数组的众数时摩尔投票法是一个特别管用好使且新奇的方法lol