目录
-
多数元素
概念:多数元素是指在数组中出现次数大于【n/2】的元素。
e.g
给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。示例:
输入:nums = [3,2,3]
输出:3
int majorityElement(int* nums, int numsSize)
{
int i=0;
int most=nums[0];
int count=1;
for(i=1;i<numsSize;i++)
{
if(most==nums[i])
{
count++;
}
else
{
count--;
}
if(count==0)
{
most=nums[i];
coount=1;
}
}
return most;
解题思路:
摩尔投票法
- 将第一个元素假设为出现次数最多的元素,记为most,并标记count为1
- 遍历数组元素,如果元素与most相同则++,否则--
- 当count进行--时,如果count==0,重置most元素为nums[i],count为1
- 最后返回的most即为数组中出现次数大于【n/2】的元素
-
拓展
摩尔投票法使用条件:绝对众数确实存在
在一个集合中,如果一个元素的出现次数比其他所有元素的出现次数之和还多,那么就称它为这个集合的绝对众数。绝对众数的出现次数大于总元素数的一半。
过程:让我们把找到绝对众数的过程想象成一次选举。我们维护一个most,表示当前的候选人,然后维护一个count。对于每一张新的选票,如果它投给了当前的候选人,就把count加1,否则就把count减1。特别地,计票时如果count==0,我们可以认为目前谁都没有优势,所以新的选票投给谁,谁就成为新的候选人。
-
二分查找
概念:二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
e.g
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
提示:
1.你可以假设 nums 中的所有元素是不重复的。
2.n 将在 [1, 10000]之间。
3.nums 的每个元素都将在 [-9999, 9999]之间。
int search(int* nums, int numsSize, int target){
int left=0;
int right=numsSize-1;
while(left<=right)
{
int mid=(left+right)/2;
if(nums[mid]<target)
{
left=mid+1;
}else if(nums[mid]>target)
{
right=mid-1;
}else
{
return mid;
}
}
return -1;//target不存在
}
-
拓展
二分查找使用条件:
1.必须采用顺序存储结构。
2.必须按关键字大小有序排列。
过程:首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则查找前一子表,否则查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
-
闰年
闰年概念:普通年能被4整除且不能被100整除的为闰年;世纪年能被400整除的是闰年
e.g
打印1000年到2000年之间的闰年
int main()
{
int year = 0;
for(year=1000; year<=2000; year++)
{
if(((year%4==0)&&(year%100!=0))||(year%400==0))
{
printf("%d ", year);
}
}
return 0;
}
-
递归
概念:程序调用自身的编程技巧称为递归( recursion)。
递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接
调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量
e.g(1)
采用递归的方法逆序一个字符串的内容
void Reverse_str1(char* str)
{
int len = strlen(str);
char* p = str;
char* pa = str + len - 1;
//交换首尾元素
char tmp = *p;
*p = *pa;
*pa = '\0';
if(strlen(str+1)>=2)//交换的元素之间只剩1个或没有元素时,
Reverse_str1(str + 1);
*pa = tmp;
}
e.g(2)
用递归的方法模拟实现strlen函数
int my_strlen(char* str)
{
if (*str == '\0')
{
return 0;
}
else
{
return 1 + my_strlen(str + 1);
}
}
e.g(3)
写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和
int DigitSum(int n)//1729
{
if(n>9)
return DigitSum(n/10)+n%10;//前N-1位之和+第N位
else
return n;
}
拓展
递归的两个必要条件:
- 存在限制条件,当满足这个限制条件的时候,递归便不再继续。
- 每次递归调用之后越来越接近这个限制条件。
-
斐波那契数
概念:斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称“兔子数列”,其数值为:1、1、2、3、5、8、13、21、34……在数学上,这一数列以如下递推的方法定义:F(0)=1,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)。
e.g
有一种兔子,从出生后第3个月起每个月都生一只兔子,小兔子长到第三个月后每个月又生一只兔子。
例子:假设一只兔子第3个月出生,那么它第5个月开始会每个月生一只兔子。
一月的时候有一只兔子,假如兔子都不死,问第n个月的兔子总数为多少?
数据范围:输入满足:1≤n≤31
输入描述:
输入一个int型整数表示第n个月
输出描述:
输出对应的兔子总数
#include <stdio.h>
int main()
{
int n=0;
scanf("%d",&n);
int a=1;
int b=1;
int c=1;
if(n<=2)
{
c=1;
}
while(n>2)
{
a=b;
b=c;
c=a+b;
n--;
}
printf("%d\n",c);
}
注:如果使用递归算法来编辑程序,由于要进行大量重复的计算,会大大降低效率